feat: downgrading + special opponents!

battler is you x2
This commit is contained in:
DaInfLoop 2024-06-24 20:56:44 +01:00
parent b5cea8ee2e
commit d2dbb53d69
2 changed files with 314 additions and 41 deletions

294
index.js
View file

@ -8,10 +8,12 @@ const sql = postgres({
username: 'haroon'
})
const SpecialOpponents = require('./opponents/special');
const BeginnerOpponents = require('./opponents/beginner');
const AllOpponents = [
...BeginnerOpponents
...(SpecialOpponents.map(x => ({ ...x, rank: 'SPECIAL' }))),
...(BeginnerOpponents.map(x => ({ ...x, rank: 'BEGINNER' }))),
]
const app = new App({
@ -309,16 +311,24 @@ app.view("chooseopponent", async (ctx) => {
"type": "input",
"element": {
"type": "static_select",
"options": BeginnerOpponents.map(opponent =>
({
"text": {
"type": "plain_text",
"text": `${opponent.name} // ${opponent.stats.health + opponent.stats.min + opponent.stats.max} Battle Power`,
"emoji": true
},
"value": opponent.rawId
})
),
"options": AllOpponents.filter(op => op.rank == rank).map(opponent => {
const battlePower = ((opponent) => {
if (opponent.stats.health instanceof Function) {
return opponent.stats.health(user) + opponent.stats.min(user) + opponent.stats.max(user)
} else {
return opponent.stats.health + opponent.stats.min + opponent.stats.max
}
})(opponent);
return {
"text": {
"type": "plain_text",
"text": `${opponent.name} // ${battlePower} Battle Power`,
"emoji": true
},
"value": opponent.rawId
}
}),
"action_id": "opponents"
},
"label": {
@ -327,7 +337,7 @@ app.view("chooseopponent", async (ctx) => {
"emoji": true
}
},
...( canRankUp ? [
...(canRankUp ? [
{
type: 'divider',
},
@ -417,6 +427,69 @@ app.view("chooseopponent-BEGINNER", async (ctx) => {
await sql`UPDATE users SET battlemessage = ${`https://hackclub.slack.com/archives/${channelId}/p${msg.ts.replace('.', '')}`} WHERE slack_id = ${userId};`
})
app.view("chooseopponent-SPECIAL", async (ctx) => {
await ctx.ack();
const channelId = ctx.view.private_metadata;
const userId = ctx.context.userId;
const slackUser = (await ctx.client.users.info({ user: userId })).user.profile;
const opponent = SpecialOpponents.find(o => o.rawId == Object.values(ctx.payload.state.values)[0].opponents.selected_option.value);
const player = await initializeUser(userId);
await sql`UPDATE users
SET playerhealth = ${player.health},
playermin = ${player.mindmg},
playermax = ${player.maxdmg},
currentOpponent = ${opponent.rawId},
opponenthealth = ${opponent.stats.health(player)},
opponentmin = ${opponent.stats.min(player)},
opponentmax = ${opponent.stats.max(player)}
WHERE slack_id = ${userId};`
const msg = await ctx.client.chat.postMessage({
channel: channelId,
text: `${slackUser.display_name_normalized} started a battle against ${opponent.name}.`,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: opponent.intro.replaceAll("{player}", slackUser.display_name_normalized)
},
"accessory": {
"type": "image",
"image_url": opponent.image,
"alt_text": opponent.name
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Continue",
"emoji": true
},
"value": userId,
"action_id": "continue"
}
]
}
]
});
await sql`UPDATE users SET battlemessage = ${`https://hackclub.slack.com/archives/${channelId}/p${msg.ts.replace('.', '')}`} WHERE slack_id = ${userId};`
})
async function checkButton(ctx) {
await ctx.ack();
@ -486,7 +559,7 @@ async function playerLoss(ctx) {
UPDATE users
SET spoints = ${user.spoints - 1},
cshards = ${user.cshards - 5},
defeats = ${user.defeats + 1}
losses = ${user.losses + 1}
WHERE slack_id = ${ctx.context.userId};
`
@ -832,20 +905,20 @@ app.action('viewaction-opponent', checkButton, async (ctx) => {
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${slackUser.display_name_normalized}_*\n\n\`\`\`NO DAMAGE\`\`\``
} else {
const damage = Math.floor(Math.random() * (user.opponentmax - user.opponentmin + 1)) + user.opponentmin;
await sql`UPDATE users SET opponenthealth = ${user.opponenthealth - damage} WHERE slack_id = ${ctx.context.userId};`
await sql`UPDATE users SET playerhealth = ${user.playerhealth - damage} WHERE slack_id = ${ctx.context.userId};`
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${slackUser.display_name_normalized}_*\n\n\`\`\`${damage.toLocaleString()} DAMAGE\`\`\``
}
} else if (user.playerdefense == 'Weak') {
if (Math.random() < 0.25) {
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${lackUser.display_name_normalized}_*\n\n\`\`\`NO DAMAGE\`\`\``
} else {
const damage = Math.floor(Math.random() * (user.playermax - user.playermin + 1)) + user.playermin;
await sql`UPDATE users SET opponenthealth = ${user.opponenthealth - damage} WHERE slack_id = ${ctx.context.userId};`
const damage = Math.floor(Math.random() * (user.opponentmax - user.opponentmin + 1)) + user.opponentmin;
await sql`UPDATE users SET playerhealth = ${user.playerhealth - damage} WHERE slack_id = ${ctx.context.userId};`
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${slackUser.display_name_normalized}_*\n\n\`\`\`${damage.toLocaleString()} DAMAGE\`\`\``
}
} else {
const damage = Math.floor(Math.random() * (user.playermax - user.playermin + 1)) + user.playermin;
await sql`UPDATE users SET opponenthealth = ${user.opponenthealth - damage} WHERE slack_id = ${ctx.context.userId};`
const damage = Math.floor(Math.random() * (user.opponentmax - user.opponentmin + 1)) + user.opponentmin;
await sql`UPDATE users SET playerhealth = ${user.playerhealth - damage} WHERE slack_id = ${ctx.context.userId};`
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${slackUser.display_name_normalized}_*\n\n\`\`\`${damage.toLocaleString()} DAMAGE\`\`\``
}
break;
@ -1020,7 +1093,7 @@ function getTimeDifference(date1, date2) {
app.command('/daily', async (ctx) => {
await ctx.ack();
const [ cooldown ] = await sql`SELECT * FROM cooldowns WHERE slack_id = ${ctx.context.userId};`
const [cooldown] = await sql`SELECT * FROM cooldowns WHERE slack_id = ${ctx.context.userId};`
const user = await initializeUser(ctx.context.userId)
const slackUser = (await ctx.client.users.info({ user: ctx.context.userId })).user.profile;
@ -1065,7 +1138,7 @@ app.command('/daily', async (ctx) => {
app.command('/weekly', async (ctx) => {
await ctx.ack();
const [ cooldown ] = await sql`SELECT * FROM cooldowns WHERE slack_id = ${ctx.context.userId};`
const [cooldown] = await sql`SELECT * FROM cooldowns WHERE slack_id = ${ctx.context.userId};`
const user = await initializeUser(ctx.context.userId)
const slackUser = (await ctx.client.users.info({ user: ctx.context.userId })).user.profile;
@ -1110,7 +1183,7 @@ app.command('/weekly', async (ctx) => {
app.command('/monthly', async (ctx) => {
await ctx.ack();
const [ cooldown ] = await sql`SELECT * FROM cooldowns WHERE slack_id = ${ctx.context.userId};`
const [cooldown] = await sql`SELECT * FROM cooldowns WHERE slack_id = ${ctx.context.userId};`
const user = await initializeUser(ctx.context.userId)
const slackUser = (await ctx.client.users.info({ user: ctx.context.userId })).user.profile;
@ -1324,8 +1397,179 @@ app.view('upgrade', async (ctx) => {
}
})
; (async () => {
await app.start(process.env.PORT);
app.command('/downgrade', async (ctx) => {
await ctx.ack();
console.log('⚡️ Bolt app is running!');
})();
const user = await initializeUser(ctx.context.userId);
await ctx.client.views.open({
trigger_id: ctx.body.trigger_id,
view: {
"private_metadata": ctx.payload.channel_id,
"type": "modal",
"callback_id": "downgrade",
"title": {
"type": "plain_text",
"text": "Downgrade your stats",
"emoji": true
},
"submit": {
"type": "plain_text",
"text": "Downgrade",
"emoji": true
},
"close": {
"type": "plain_text",
"text": "Never mind",
"emoji": true
},
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": `*Battle Builder:* Helloooo <@${ctx.context.userId}>! You're downgrading today huh? No problem! What would you like to... Erm... Downgrade?-`
}
},
{
"block_id": "select",
"type": "input",
"element": {
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Choose a statistic...",
"emoji": true
},
"options": [
{
"text": {
"type": "plain_text",
"text": "Health // 30 Creation Shards" + (user.cshards < 30 ? " :lock:" : ""),
"emoji": true
},
"value": "health"
},
{
"text": {
"type": "plain_text",
"text": "Min Damage // 40 Creation Shards" + (user.cshards < 40 ? " :lock:" : ""),
"emoji": true
},
"value": "mindmg"
},
{
"text": {
"type": "plain_text",
"text": "Max Damage // 50 Creation Shards" + (user.cshards < 50 || user.mindmg + 5 == user.maxdmg ? " :lock:" : ""),
"emoji": true
},
"value": "maxdmg"
}
],
"action_id": "downgrade-modal"
},
"label": {
"type": "plain_text",
"text": "What would you like to downgrade?",
"emoji": true
}
}
]
}
})
});
app.view('downgrade', async (ctx) => {
const user = await initializeUser(ctx.context.userId);
const { selected_option } = ctx.view.state.values['select']['downgrade-modal'];
if (selected_option.value == "health" && user.cshards < 30) {
return await ctx.ack({
response_action: 'errors',
errors: {
'select': "You don't have enough creation shards to downgrade your health!"
}
});
} else if (selected_option.value == "mindmg" && user.cshards < 40) {
return await ctx.ack({
response_action: 'errors',
errors: {
'select': "You don't have enough creation shards to downgrade your minimum damage!"
}
});
} else if (selected_option == "maxdmg" && user.mindmg + 5 == user.maxdmg) {
return await ctx.ack({
response_action: 'errors',
errors: {
'select': "You need to downgrade your minimum damage first!"
}
});
} else if (selected_option.value == "maxdmg" && user.cshards < 50) {
return await ctx.ack({
response_action: 'errors',
errors: {
'select': "You don't have enough creation shards to downgrade your maximum damage!"
}
});
}
await ctx.ack();
if (selected_option.value == "health") {
await sql`UPDATE users SET spoints = ${user.spoints + 5}, health = ${user.health - 1}, cshards = ${user.cshards - 30} WHERE slack_id = ${ctx.context.userId};`
await ctx.client.chat.postEphemeral({
channel: ctx.view.private_metadata,
user: ctx.context.userId,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `*Battle Builder:* Yayyy <@${ctx.context.userId}>! Your health has been successfully decreased!\n\n\`\`\`HEALTH DECREASED (${user.health} > ${user.health - 1})\`\`\``
}
}
]
})
} else if (selected_option.value == "mindmg") {
await sql`UPDATE users SET spoints = ${user.spoints + 10}, mindmg = ${user.mindmg - 1}, cshards = ${user.cshards - 40} WHERE slack_id = ${ctx.context.userId};`
await ctx.client.chat.postEphemeral({
channel: ctx.view.private_metadata,
user: ctx.context.userId,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `*Battle Builder:* Yayyy <@${ctx.context.userId}>! Your minimum damage has been successfully decreased!\n\n\`\`\`MIN DAMAGE DECREASED (${user.mindmg} > ${user.mindmg - 1})\`\`\``
}
}
]
})
} else if (selected_option.value == "maxdmg") {
await sql`UPDATE users SET spoints = ${user.spoints + 15}, maxdmg = ${user.maxdmg - 1}, cshards = ${user.cshards - 50} WHERE slack_id = ${ctx.context.userId};`
await ctx.client.chat.postEphemeral({
channel: ctx.view.private_metadata,
user: ctx.context.userId,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: `*Battle Builder:* Yayyy <@${ctx.context.userId}>! Your maximum damage has been successfully decreased!\n\n\`\`\`MAX DAMAGE DECREASED (${user.maxdmg} > ${user.maxdmg - 1})\`\`\``
}
}
]
})
}
})
; (async () => {
await app.start(process.env.PORT);
console.log('⚡️ Bolt app is running!');
})();

29
opponents/special.js Normal file
View file

@ -0,0 +1,29 @@
module.exports = [
{
"rawId": "battler",
"name": "Battler",
"stats": {
health: (user) => user.health * 2,
min: (user) => user.mindmg * 2,
max: (user) => user.maxdmg * 2
},
"image": "https://cdn.discordapp.com/attachments/1108683335347212389/1118840155109851167/Battler_Closeup.png?ex=667a9318&is=66794198&hm=4ee29c3ef2691c56a92ae77744be00b5526fbb271788b6afa1eabd268beaf23a&",
"intro": `*_A glowing white portal appears as Battler dramatically storms out. He is heading directly for {player}_*
*Battler*: Greetings {player}. I would like to assume you are looking for an opponent, are you not?
*{player}*: How do you know my name... And who are you!?
*Battler*: I am you, but better.
*{player}*: What? Are you from the future or something?
*Battler*: Precisely. I am you, but stronger.
*{player}*: Wait but if you're me from the future then how am I supposed to beat you!?
*Battler*: Battler's Mentality #8. Never give up.
*{player}*: What does that even mean!?
*Battler*: Good luck {player}. However, don't feel bad if you are defeated. After all, I am you... X2.
*{player}*: ...`,
"chances": {
"attack": 0.65,
"defend": 0.175,
"item": 0.175
}
}
]