i think weapons working real ?

This commit is contained in:
Jill 2023-11-21 22:17:15 +03:00
parent 5be9dbfe21
commit 783af8652c
8 changed files with 112 additions and 12 deletions

47
src/commands/attack.ts Normal file
View File

@ -0,0 +1,47 @@
import { GuildMember, CommandInteraction, SlashCommandBuilder } from 'discord.js';
import { weaponAutocomplete, getItem, getItemQuantity, formatItems } from '../lib/rpg/items';
import { Command } from '../types/index';
import { initHealth, dealDamage, BLOOD_ITEM, BLOOD_ID } from '../lib/rpg/pvp';
export default {
data: new SlashCommandBuilder()
.setName('attack')
.setDescription('Attack someone using a weapon you have')
.addStringOption(option =>
option
.setName('weapon')
.setAutocomplete(true)
.setDescription('The weapon to use')
.setRequired(true)
)
.addUserOption(option =>
option
.setName('user')
.setRequired(true)
.setDescription('Who to attack with the weapon')
)
.setDMPermission(false),
execute: async (interaction: CommandInteraction) => {
if (!interaction.isChatInputCommand()) return;
const member = interaction.member! as GuildMember;
await initHealth(member.id);
const weaponID = parseInt(interaction.options.getString('weapon', true));
const user = interaction.options.getUser('user', true);
await interaction.deferReply({ephemeral: true});
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 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)}.`);
},
autocomplete: weaponAutocomplete,
} satisfies Command;

View File

@ -4,6 +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';
export default {
data: new SlashCommandBuilder()
@ -30,6 +31,8 @@ export default {
const member = interaction.member! as GuildMember;
await initHealth(member.id);
const recipeID = parseInt(interaction.options.getString('recipe', true));
await interaction.deferReply({ephemeral: true});

View File

@ -1,4 +1,4 @@
import { GuildMember, EmbedBuilder, SlashCommandBuilder, CommandInteraction } from 'discord.js';
import { EmbedBuilder, SlashCommandBuilder, CommandInteraction } from 'discord.js';
import { writeTmpFile } from '../lib/util';
import { Command } from '../types/index';

View File

@ -1,6 +1,7 @@
import { GuildMember, CommandInteraction, SlashCommandBuilder } from 'discord.js';
import { ItemInventory, db } from '../lib/db';
import { formatItems, getItem } from '../lib/rpg/items';
import { initHealth } from '../lib/rpg/pvp';
import { Command } from '../types/index';
export default {
@ -14,6 +15,8 @@ export default {
const member = interaction.member! as GuildMember;
await initHealth(member.id);
await interaction.deferReply({ephemeral: true});
const itemsList = await db<ItemInventory>('itemInventories')

View File

@ -1,6 +1,7 @@
import { GuildMember, CommandInteraction, SlashCommandBuilder } from 'discord.js';
import { changeLinkedCounterInteraction, linkedCounterAutocomplete } from '../lib/rpg/counter';
import { Command } from '../types/index';
import { initHealth } from '../lib/rpg/pvp';
export default {
data: new SlashCommandBuilder()
@ -27,6 +28,8 @@ export default {
const member = interaction.member! as GuildMember;
await initHealth(member.id);
const amount = Math.trunc(interaction.options.getInteger('amount') || 1);
const type = interaction.options.getString('type')!;

View File

@ -1,5 +1,6 @@
import { GuildMember, CommandInteraction, SlashCommandBuilder } from 'discord.js';
import { changeLinkedCounterInteraction, linkedCounterAutocomplete } from '../lib/rpg/counter';
import { initHealth } from '../lib/rpg/pvp';
import { Command } from '../types/index';
export default {
@ -27,6 +28,8 @@ export default {
const member = interaction.member! as GuildMember;
await initHealth(member.id);
const amount = Math.trunc(interaction.options.getInteger('amount') || 1);
const type = interaction.options.getString('type')!;

View File

@ -1,6 +1,5 @@
import { AutocompleteInteraction } from 'discord.js';
import { CustomItem, ItemInventory, db } from '../db';
import { MAX_HEALTH } from './pvp';
export type DefaultItem = Omit<CustomItem, 'guild'>; // uses negative IDs
export type Item = DefaultItem | CustomItem;
@ -118,7 +117,7 @@ export const defaultItems: DefaultItem[] = [
description: 'ow',
emoji: '🩸',
type: 'plain',
maxStack: MAX_HEALTH,
maxStack: 50,
untradable: false
},
{
@ -374,18 +373,23 @@ export function formatItemsArray(items: Items[], disableBold = false) {
return items.map(i => formatItems(i.item, i.quantity, disableBold)).join(' ');
}
function createItemAutocomplete(onlyCustom: boolean) {
function createItemAutocomplete(onlyCustom: boolean, filterType: 'plain' | 'weapon' | 'consumable' | null) {
return async (interaction: AutocompleteInteraction) => {
const focused = interaction.options.getFocused();
const customItems = await db<CustomItem>('customItems')
const itemQuery = db<CustomItem>('customItems')
.select('emoji', 'name', 'id')
// @ts-expect-error this LITERALLY works
.whereLike(db.raw('UPPER(name)'), `%${focused.toUpperCase()}%`)
.where('guild', interaction.guildId!)
.limit(25);
if (filterType) itemQuery.where('type', filterType);
const customItems = await itemQuery;
const foundDefaultItems = defaultItems.filter(item => item.name.toUpperCase().includes(focused.toUpperCase()));
let foundDefaultItems = defaultItems.filter(item => item.name.toUpperCase().includes(focused.toUpperCase()));
if (filterType) foundDefaultItems = foundDefaultItems.filter(i => i.type === filterType);
let items;
if (onlyCustom) {
@ -400,5 +404,8 @@ function createItemAutocomplete(onlyCustom: boolean) {
};
}
export const itemAutocomplete = createItemAutocomplete(false);
export const customItemAutocomplete = createItemAutocomplete(true);
export const itemAutocomplete = createItemAutocomplete(false, null);
export const customItemAutocomplete = createItemAutocomplete(true, null);
export const plainAutocomplete = createItemAutocomplete(false, 'plain');
export const weaponAutocomplete = createItemAutocomplete(false, 'weapon');
export const consumableAutocomplete = createItemAutocomplete(false, 'consumable');

View File

@ -1,7 +1,11 @@
import { InitHealth, db } from '../db';
import { DefaultItems, getDefaultItem, giveItem } from './items';
import { InitHealth, ItemInventory, db } from '../db';
import { DefaultItems, getDefaultItem, giveItem, getItemQuantity, formatItems } from './items';
import { Client } from 'discord.js';
export const MAX_HEALTH = 100;
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 async function initHealth(user: string) {
const isInitialized = await db<InitHealth>('initHealth')
@ -9,7 +13,37 @@ export async function initHealth(user: string) {
.first();
if (!isInitialized) {
giveItem(user, getDefaultItem(DefaultItems.BLOOD), MAX_HEALTH);
giveItem(user, BLOOD_ITEM, MAX_HEALTH);
await db<InitHealth>('initHealth').insert({ user });
}
}
export async function getHealth(user: string) {
return await getItemQuantity(user, BLOOD_ID);
}
export async function dealDamage(user: string, dmg: number) {
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) {
setInterval(() => healthCron(bot), 1_000 * 60 * 60);
}