pvp cooldowns
This commit is contained in:
parent
b862028524
commit
f44f79a955
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* @param { import("knex").Knex } knex
|
||||
* @returns { Promise<void> }
|
||||
*/
|
||||
exports.up = function(knex) {
|
||||
return knex.schema
|
||||
.createTable('invincibleUsers', table => {
|
||||
table.string('user').notNullable().unique();
|
||||
table.timestamp('since').notNullable();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param { import("knex").Knex } knex
|
||||
* @returns { Promise<void> }
|
||||
*/
|
||||
exports.down = function(knex) {
|
||||
return knex.schema
|
||||
.dropTable('invincibleUsers');
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
import { GuildMember, CommandInteraction, SlashCommandBuilder } from 'discord.js';
|
||||
import { weaponAutocomplete, getItem, getItemQuantity, formatItems } from '../lib/rpg/items';
|
||||
import { weaponAutocomplete, getItem, getItemQuantity, formatItems, formatItem } from '../lib/rpg/items';
|
||||
import { Command } from '../types/index';
|
||||
import { initHealth, dealDamage, BLOOD_ITEM, BLOOD_ID } from '../lib/rpg/pvp';
|
||||
import { initHealth, dealDamage, BLOOD_ITEM, BLOOD_ID, resetInvincible, INVINCIBLE_TIMER, getInvincibleMs } from '../lib/rpg/pvp';
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
|
@ -35,12 +35,15 @@ export default {
|
|||
const weapon = await getItem(weaponID);
|
||||
if (!weapon) return interaction.followUp('No such item exists!');
|
||||
if (weapon.type !== 'weapon') return interaction.followUp('That is not a weapon!');
|
||||
const invinTimer = await getInvincibleMs(user.id);
|
||||
if (invinTimer > 0) return interaction.followUp(`You can only attack this user <t:${Math.floor((Date.now() + invinTimer) / 1000)}:R> (or if they perform an action first)!`);
|
||||
|
||||
const dmg = weapon.maxStack;
|
||||
await dealDamage(user.id, dmg);
|
||||
const newHealth = await getItemQuantity(user.id, BLOOD_ID);
|
||||
|
||||
await interaction.followUp(`You hit ${user} for ${BLOOD_ITEM.emoji} **${dmg}** damage! They are now at ${formatItems(BLOOD_ITEM, newHealth.quantity)}.`);
|
||||
if (user.id !== member.id) await resetInvincible(member.id);
|
||||
await interaction.followUp(`You hit ${user} with ${formatItem(weapon)} for ${BLOOD_ITEM.emoji} **${dmg}** damage! They are now at ${formatItems(BLOOD_ITEM, newHealth.quantity)}.\nYou can attack them again <t:${Math.floor((Date.now() + INVINCIBLE_TIMER) / 1000)}:R> (or if they perform an action first).`);
|
||||
},
|
||||
|
||||
autocomplete: weaponAutocomplete,
|
||||
|
|
|
@ -4,7 +4,7 @@ import { getStation, canUseStation, craftingStations, verb, CraftingStation } fr
|
|||
import { formatItem, getItemQuantity, formatItems, getMaxStack, giveItem, formatItemsArray } from '../lib/rpg/items';
|
||||
import { getRecipe, defaultRecipes, formatRecipe, resolveCustomRecipe } from '../lib/rpg/recipes';
|
||||
import { Command } from '../types/index';
|
||||
import { initHealth } from '../lib/rpg/pvp';
|
||||
import { initHealth, resetInvincible } from '../lib/rpg/pvp';
|
||||
|
||||
export default {
|
||||
data: new SlashCommandBuilder()
|
||||
|
@ -98,6 +98,7 @@ export default {
|
|||
nextUsableAt = Date.now() + station.cooldown * 1000;
|
||||
}
|
||||
|
||||
await resetInvincible(member.id);
|
||||
return interaction.followUp(`${station.emoji} ${verb(station)} ${formatItemsArray(outputs)}!${outputs.length === 1 ? `\n_${outputs[0].item.description}_` : ''}${nextUsableAt ? `\n${station.name} usable again <t:${Math.floor(nextUsableAt / 1000)}:R>` : ''}`);
|
||||
},
|
||||
|
||||
|
|
|
@ -89,4 +89,8 @@ export interface Session {
|
|||
}
|
||||
export interface InitHealth {
|
||||
user: string,
|
||||
}
|
||||
export interface InvincibleUser {
|
||||
user: string,
|
||||
since: number,
|
||||
}
|
|
@ -2,6 +2,7 @@ import { Client, CommandInteraction, GuildMember, EmbedBuilder, TextChannel, Aut
|
|||
import { getSign } from '../util';
|
||||
import { Counter, CounterConfiguration, CounterUserLink, db } from '../db';
|
||||
import { formatItems, getItem, getItemQuantity, getMaxStack, giveItem } from './items';
|
||||
import { resetInvincible } from './pvp';
|
||||
|
||||
export async function getCounter(id: number) {
|
||||
const counter = await db<Counter>('counters')
|
||||
|
@ -359,6 +360,7 @@ function changeCounterInteractionBuilder(linked: boolean) {
|
|||
newInv = await giveItem(member.id, item, amtInv);
|
||||
}
|
||||
|
||||
await resetInvincible(member.id);
|
||||
const newCount = await changeCounter(counter.id, amount);
|
||||
await updateCounter(interaction.client, counter, newCount);
|
||||
await announceCounterUpdate(interaction.client, member, amount, counter, newCount, linked);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { InitHealth, ItemInventory, db } from '../db';
|
||||
import { InitHealth, InvincibleUser, ItemInventory, db } from '../db';
|
||||
import { DefaultItems, getDefaultItem, giveItem, getItemQuantity, formatItems } from './items';
|
||||
import { Client } from 'discord.js';
|
||||
|
||||
|
@ -6,6 +6,7 @@ export const BLOOD_ID = -DefaultItems.BLOOD;
|
|||
export const BLOOD_ITEM = getDefaultItem(BLOOD_ID);
|
||||
export const MAX_HEALTH = BLOOD_ITEM.maxStack;
|
||||
const BLOOD_GAIN_PER_HOUR = 5;
|
||||
export const INVINCIBLE_TIMER = 1_000 * 60 * 60;
|
||||
|
||||
export async function initHealth(user: string) {
|
||||
const isInitialized = await db<InitHealth>('initHealth')
|
||||
|
@ -18,6 +19,35 @@ export async function initHealth(user: string) {
|
|||
}
|
||||
}
|
||||
|
||||
export async function getInvincibleMs(user: string) {
|
||||
const invincible = await db<InvincibleUser>('invincibleUsers')
|
||||
.where('user', user)
|
||||
.first();
|
||||
|
||||
if (!invincible) return 0;
|
||||
return Math.max((invincible.since + INVINCIBLE_TIMER) - Date.now(), 0);
|
||||
}
|
||||
|
||||
export async function resetInvincible(user: string) {
|
||||
await db<InvincibleUser>('invincibleUsers')
|
||||
.where('user', user)
|
||||
.delete();
|
||||
}
|
||||
|
||||
export async function applyInvincible(user: string) {
|
||||
const exists = await db<InvincibleUser>('invincibleUsers')
|
||||
.where('user', user)
|
||||
.first();
|
||||
|
||||
if (exists) {
|
||||
await db<InvincibleUser>('invincibleUsers')
|
||||
.update({ since: Date.now() });
|
||||
} else {
|
||||
await db<InvincibleUser>('invincibleUsers')
|
||||
.insert({ since: Date.now(), user });
|
||||
}
|
||||
}
|
||||
|
||||
export async function getHealth(user: string) {
|
||||
await initHealth(user);
|
||||
return await getItemQuantity(user, BLOOD_ID);
|
||||
|
@ -25,6 +55,7 @@ export async function getHealth(user: string) {
|
|||
|
||||
export async function dealDamage(user: string, dmg: number) {
|
||||
await initHealth(user);
|
||||
await applyInvincible(user);
|
||||
return await giveItem(user, BLOOD_ITEM, -dmg);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue