jillo-bot/src/lib/rpg/pvp.ts

83 lines
2.4 KiB
TypeScript

import { InitHealth, InvincibleUser, ItemInventory, db } from '../db';
import { DefaultItems, getDefaultItem, giveItem, getItemQuantity, formatItems } from './items';
import { Client } from 'discord.js';
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 = 2;
export const INVINCIBLE_TIMER = 1_000 * 60 * 30;
export async function initHealth(user: string) {
const isInitialized = await db<InitHealth>('initHealth')
.where('user', user)
.first();
if (!isInitialized) {
giveItem(user, BLOOD_ITEM, MAX_HEALTH);
await db<InitHealth>('initHealth').insert({ user });
}
}
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);
}
export async function dealDamage(user: string, dmg: number) {
await initHealth(user);
await applyInvincible(user);
return await giveItem(user, BLOOD_ITEM, -dmg);
}
async function healthCron(bot: Client) {
await db<ItemInventory>('itemInventories')
.where('item', BLOOD_ID)
.update({
quantity: db.raw('MIN(quantity + ?, ?)', [BLOOD_GAIN_PER_HOUR, MAX_HEALTH])
});
const debtedUsers = await db<ItemInventory>('itemInventories')
.select('user', 'quantity')
.where('quantity', '<', '0');
for (const debted of debtedUsers) {
const user = await bot.users.fetch(debted.user);
if (!user) continue;
await user.send(`${formatItems(BLOOD_ITEM, debted.quantity)} You are bleeding out to death`);
}
}
export function init(bot: Client) {
healthCron(bot);
setInterval(() => healthCron(bot), 1_000 * 60 * 60);
}