feat: downgrading + special opponents!
battler is you x2
This commit is contained in:
parent
b5cea8ee2e
commit
d2dbb53d69
280
index.js
280
index.js
|
@ -8,10 +8,12 @@ const sql = postgres({
|
||||||
username: 'haroon'
|
username: 'haroon'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const SpecialOpponents = require('./opponents/special');
|
||||||
const BeginnerOpponents = require('./opponents/beginner');
|
const BeginnerOpponents = require('./opponents/beginner');
|
||||||
|
|
||||||
const AllOpponents = [
|
const AllOpponents = [
|
||||||
...BeginnerOpponents
|
...(SpecialOpponents.map(x => ({ ...x, rank: 'SPECIAL' }))),
|
||||||
|
...(BeginnerOpponents.map(x => ({ ...x, rank: 'BEGINNER' }))),
|
||||||
]
|
]
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
|
@ -309,16 +311,24 @@ app.view("chooseopponent", async (ctx) => {
|
||||||
"type": "input",
|
"type": "input",
|
||||||
"element": {
|
"element": {
|
||||||
"type": "static_select",
|
"type": "static_select",
|
||||||
"options": BeginnerOpponents.map(opponent =>
|
"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": {
|
"text": {
|
||||||
"type": "plain_text",
|
"type": "plain_text",
|
||||||
"text": `${opponent.name} // ${opponent.stats.health + opponent.stats.min + opponent.stats.max} Battle Power`,
|
"text": `${opponent.name} // ${battlePower} Battle Power`,
|
||||||
"emoji": true
|
"emoji": true
|
||||||
},
|
},
|
||||||
"value": opponent.rawId
|
"value": opponent.rawId
|
||||||
})
|
}
|
||||||
),
|
}),
|
||||||
"action_id": "opponents"
|
"action_id": "opponents"
|
||||||
},
|
},
|
||||||
"label": {
|
"label": {
|
||||||
|
@ -327,7 +337,7 @@ app.view("chooseopponent", async (ctx) => {
|
||||||
"emoji": true
|
"emoji": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
...( canRankUp ? [
|
...(canRankUp ? [
|
||||||
{
|
{
|
||||||
type: 'divider',
|
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};`
|
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) {
|
async function checkButton(ctx) {
|
||||||
await ctx.ack();
|
await ctx.ack();
|
||||||
|
|
||||||
|
@ -486,7 +559,7 @@ async function playerLoss(ctx) {
|
||||||
UPDATE users
|
UPDATE users
|
||||||
SET spoints = ${user.spoints - 1},
|
SET spoints = ${user.spoints - 1},
|
||||||
cshards = ${user.cshards - 5},
|
cshards = ${user.cshards - 5},
|
||||||
defeats = ${user.defeats + 1}
|
losses = ${user.losses + 1}
|
||||||
WHERE slack_id = ${ctx.context.userId};
|
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\`\`\``
|
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${slackUser.display_name_normalized}_*\n\n\`\`\`NO DAMAGE\`\`\``
|
||||||
} else {
|
} else {
|
||||||
const damage = Math.floor(Math.random() * (user.opponentmax - user.opponentmin + 1)) + user.opponentmin;
|
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\`\`\``
|
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${slackUser.display_name_normalized}_*\n\n\`\`\`${damage.toLocaleString()} DAMAGE\`\`\``
|
||||||
}
|
}
|
||||||
} else if (user.playerdefense == 'Weak') {
|
} else if (user.playerdefense == 'Weak') {
|
||||||
if (Math.random() < 0.25) {
|
if (Math.random() < 0.25) {
|
||||||
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${lackUser.display_name_normalized}_*\n\n\`\`\`NO DAMAGE\`\`\``
|
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${lackUser.display_name_normalized}_*\n\n\`\`\`NO DAMAGE\`\`\``
|
||||||
} else {
|
} else {
|
||||||
const damage = Math.floor(Math.random() * (user.playermax - user.playermin + 1)) + user.playermin;
|
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\`\`\``
|
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${slackUser.display_name_normalized}_*\n\n\`\`\`${damage.toLocaleString()} DAMAGE\`\`\``
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const damage = Math.floor(Math.random() * (user.playermax - user.playermin + 1)) + user.playermin;
|
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\`\`\``
|
response = `*_${AllOpponents.find(x => x.rawId == user.currentopponent).name} attacks ${slackUser.display_name_normalized}_*\n\n\`\`\`${damage.toLocaleString()} DAMAGE\`\`\``
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1020,7 +1093,7 @@ function getTimeDifference(date1, date2) {
|
||||||
|
|
||||||
app.command('/daily', async (ctx) => {
|
app.command('/daily', async (ctx) => {
|
||||||
await ctx.ack();
|
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 user = await initializeUser(ctx.context.userId)
|
||||||
const slackUser = (await ctx.client.users.info({ user: ctx.context.userId })).user.profile;
|
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) => {
|
app.command('/weekly', async (ctx) => {
|
||||||
await ctx.ack();
|
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 user = await initializeUser(ctx.context.userId)
|
||||||
const slackUser = (await ctx.client.users.info({ user: ctx.context.userId })).user.profile;
|
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) => {
|
app.command('/monthly', async (ctx) => {
|
||||||
await ctx.ack();
|
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 user = await initializeUser(ctx.context.userId)
|
||||||
const slackUser = (await ctx.client.users.info({ user: ctx.context.userId })).user.profile;
|
const slackUser = (await ctx.client.users.info({ user: ctx.context.userId })).user.profile;
|
||||||
|
|
||||||
|
@ -1324,8 +1397,179 @@ app.view('upgrade', async (ctx) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
; (async () => {
|
app.command('/downgrade', async (ctx) => {
|
||||||
|
await ctx.ack();
|
||||||
|
|
||||||
|
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);
|
await app.start(process.env.PORT);
|
||||||
|
|
||||||
console.log('⚡️ Bolt app is running!');
|
console.log('⚡️ Bolt app is running!');
|
||||||
})();
|
})();
|
29
opponents/special.js
Normal file
29
opponents/special.js
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
Loading…
Reference in a new issue