feat: Allow item effects to specify durations in hours, minutes, or seconds.
This commit is contained in:
@@ -15,8 +15,8 @@ export interface Event<K extends keyof ClientEvents> {
|
|||||||
export type ItemEffect =
|
export type ItemEffect =
|
||||||
| { type: 'ADD_XP'; amount: number }
|
| { type: 'ADD_XP'; amount: number }
|
||||||
| { type: 'ADD_BALANCE'; amount: number }
|
| { type: 'ADD_BALANCE'; amount: number }
|
||||||
| { type: 'XP_BOOST'; multiplier: number; durationSeconds: number }
|
| { type: 'XP_BOOST'; multiplier: number; durationSeconds?: number; durationMinutes?: number; durationHours?: number }
|
||||||
| { type: 'TEMP_ROLE'; roleId: string; durationSeconds: number }
|
| { type: 'TEMP_ROLE'; roleId: string; durationSeconds?: number; durationMinutes?: number; durationHours?: number }
|
||||||
| { type: 'REPLY_MESSAGE'; message: string };
|
| { type: 'REPLY_MESSAGE'; message: string };
|
||||||
|
|
||||||
export interface ItemUsageData {
|
export interface ItemUsageData {
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ import { config } from "@/lib/config";
|
|||||||
import { withTransaction } from "@/lib/db";
|
import { withTransaction } from "@/lib/db";
|
||||||
import type { Transaction, ItemUsageData } from "@/lib/types";
|
import type { Transaction, ItemUsageData } from "@/lib/types";
|
||||||
|
|
||||||
|
// Helper to extract duration in seconds
|
||||||
|
const getDuration = (effect: any): number => {
|
||||||
|
if (effect.durationHours) return effect.durationHours * 3600;
|
||||||
|
if (effect.durationMinutes) return effect.durationMinutes * 60;
|
||||||
|
return effect.durationSeconds || 60; // Default to 60s if nothing provided
|
||||||
|
};
|
||||||
|
|
||||||
export const inventoryService = {
|
export const inventoryService = {
|
||||||
addItem: async (userId: string, itemId: number, quantity: bigint = 1n, tx?: Transaction) => {
|
addItem: async (userId: string, itemId: number, quantity: bigint = 1n, tx?: Transaction) => {
|
||||||
return await withTransaction(async (txFn) => {
|
return await withTransaction(async (txFn) => {
|
||||||
@@ -171,7 +178,8 @@ export const inventoryService = {
|
|||||||
results.push(effect.message);
|
results.push(effect.message);
|
||||||
break;
|
break;
|
||||||
case 'XP_BOOST':
|
case 'XP_BOOST':
|
||||||
const expiresAt = new Date(Date.now() + effect.durationSeconds * 1000);
|
const boostDuration = getDuration(effect);
|
||||||
|
const expiresAt = new Date(Date.now() + boostDuration * 1000);
|
||||||
await txFn.insert(userTimers).values({
|
await txFn.insert(userTimers).values({
|
||||||
userId: BigInt(userId),
|
userId: BigInt(userId),
|
||||||
type: 'EFFECT',
|
type: 'EFFECT',
|
||||||
@@ -182,10 +190,11 @@ export const inventoryService = {
|
|||||||
target: [userTimers.userId, userTimers.type, userTimers.key],
|
target: [userTimers.userId, userTimers.type, userTimers.key],
|
||||||
set: { expiresAt: expiresAt, metadata: { multiplier: effect.multiplier } }
|
set: { expiresAt: expiresAt, metadata: { multiplier: effect.multiplier } }
|
||||||
});
|
});
|
||||||
results.push(`XP Boost (${effect.multiplier}x) active for ${Math.floor(effect.durationSeconds / 60)}m`);
|
results.push(`XP Boost (${effect.multiplier}x) active for ${Math.floor(boostDuration / 60)}m`);
|
||||||
break;
|
break;
|
||||||
case 'TEMP_ROLE':
|
case 'TEMP_ROLE':
|
||||||
const roleExpiresAt = new Date(Date.now() + effect.durationSeconds * 1000);
|
const roleDuration = getDuration(effect);
|
||||||
|
const roleExpiresAt = new Date(Date.now() + roleDuration * 1000);
|
||||||
await txFn.insert(userTimers).values({
|
await txFn.insert(userTimers).values({
|
||||||
userId: BigInt(userId),
|
userId: BigInt(userId),
|
||||||
type: 'ACCESS',
|
type: 'ACCESS',
|
||||||
@@ -196,9 +205,8 @@ export const inventoryService = {
|
|||||||
target: [userTimers.userId, userTimers.type, userTimers.key],
|
target: [userTimers.userId, userTimers.type, userTimers.key],
|
||||||
set: { expiresAt: roleExpiresAt }
|
set: { expiresAt: roleExpiresAt }
|
||||||
});
|
});
|
||||||
// Actual role assignment happens in the Command layer (or here if we had client, but service shouldn't depend on client ideally)
|
// Actual role assignment happens in the Command layer
|
||||||
// We return a flag to let the interaction handler know it needs to assign a role.
|
results.push(`Temporary Role granted for ${Math.floor(roleDuration / 60)}m`);
|
||||||
results.push(`Temporary Role granted for ${Math.floor(effect.durationSeconds / 60)}m`);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user