Added profile and trader commands to commando (!309)
Added new spt commands for commando to alter profile levels and skill, as well as trader rep and money spent. Co-authored-by: clodan <clodan@clodan.com> Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/309 Co-authored-by: Alex <clodan@noreply.dev.sp-tarkov.com> Co-committed-by: Alex <clodan@noreply.dev.sp-tarkov.com>
This commit is contained in:
parent
d7a8e1558a
commit
a1e48ca245
@ -90,7 +90,9 @@ import { BotHelper } from "@spt-aki/helpers/BotHelper";
|
||||
import { BotWeaponGeneratorHelper } from "@spt-aki/helpers/BotWeaponGeneratorHelper";
|
||||
import { ContainerHelper } from "@spt-aki/helpers/ContainerHelper";
|
||||
import { SptCommandoCommands } from "@spt-aki/helpers/Dialogue/Commando/SptCommandoCommands";
|
||||
import { GiveSptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/GiveSptCommand";
|
||||
import { GiveSptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/GiveCommand/GiveSptCommand";
|
||||
import { ProfileSptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand";
|
||||
import { TraderSptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand";
|
||||
import { CommandoDialogueChatBot } from "@spt-aki/helpers/Dialogue/CommandoDialogueChatBot";
|
||||
import { SptDialogueChatBot } from "@spt-aki/helpers/Dialogue/SptDialogueChatBot";
|
||||
import { DialogueHelper } from "@spt-aki/helpers/DialogueHelper";
|
||||
@ -375,6 +377,8 @@ export class Container
|
||||
|
||||
// SptCommando Commands
|
||||
depContainer.registerType("SptCommand", "GiveSptCommand");
|
||||
depContainer.registerType("SptCommand", "TraderSptCommand");
|
||||
depContainer.registerType("SptCommand", "ProfileSptCommand");
|
||||
}
|
||||
|
||||
private static registerUtils(depContainer: DependencyContainer): void
|
||||
@ -598,6 +602,12 @@ export class Container
|
||||
});
|
||||
// SptCommands
|
||||
depContainer.register<GiveSptCommand>("GiveSptCommand", GiveSptCommand, { lifecycle: Lifecycle.Singleton });
|
||||
depContainer.register<TraderSptCommand>("TraderSptCommand", TraderSptCommand, {
|
||||
lifecycle: Lifecycle.Singleton,
|
||||
});
|
||||
depContainer.register<ProfileSptCommand>("ProfileSptCommand", ProfileSptCommand, {
|
||||
lifecycle: Lifecycle.Singleton,
|
||||
});
|
||||
}
|
||||
|
||||
private static registerLoaders(depContainer: DependencyContainer): void
|
||||
|
@ -57,12 +57,34 @@ export abstract class AbstractDialogueChatBot implements IDialogueChatBot
|
||||
|
||||
if (splitCommand[0].toLowerCase() === "help")
|
||||
{
|
||||
const helpMessage = this.chatCommands.map((c) =>
|
||||
`Available commands:\n\n${c.getCommandPrefix()}:\n\n${
|
||||
Array.from(c.getCommands()).map((command) => c.getCommandHelp(command)).join("\n")
|
||||
}`
|
||||
).join("\n");
|
||||
this.mailSendService.sendUserMessageToPlayer(sessionId, this.getChatBot(), helpMessage);
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
this.getChatBot(),
|
||||
"The available commands will be listed below:",
|
||||
);
|
||||
// due to BSG being dumb with messages we need a mandatory timeout between messages so they get out on the right order
|
||||
setTimeout(() =>
|
||||
{
|
||||
for (const chatCommand of this.chatCommands)
|
||||
{
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
this.getChatBot(),
|
||||
`Commands available for "${chatCommand.getCommandPrefix()}" prefix:`,
|
||||
);
|
||||
setTimeout(() =>
|
||||
{
|
||||
for (const subCommand of chatCommand.getCommands())
|
||||
{
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
this.getChatBot(),
|
||||
`Subcommand ${subCommand}:\n${chatCommand.getCommandHelp(subCommand)}`,
|
||||
);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
}, 1000);
|
||||
return request.dialogId;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { SavedCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand";
|
||||
import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand";
|
||||
import { SavedCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/SavedCommand";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
|
||||
@ -107,6 +107,15 @@ export class GiveSptCommand implements ISptCommand
|
||||
isItemName = result[5] !== undefined;
|
||||
item = result[5] ? result[5] : result[2];
|
||||
quantity = +result[6];
|
||||
if (quantity <= 0)
|
||||
{
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
commandHandler,
|
||||
`Invalid quantity! Must be 1 or higher. Use \"help\" for more information.`,
|
||||
);
|
||||
return request.dialogId;
|
||||
}
|
||||
|
||||
if (isItemName)
|
||||
{
|
@ -0,0 +1,163 @@
|
||||
import { SavedCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand";
|
||||
import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest";
|
||||
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||
import { SkillTypes } from "@spt-aki/models/enums/SkillTypes";
|
||||
import { IProfileChangeEvent, ProfileChangeEventType } from "@spt-aki/models/spt/dialog/ISendMessageDetails";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocaleService } from "@spt-aki/services/LocaleService";
|
||||
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
@injectable()
|
||||
export class ProfileSptCommand implements ISptCommand
|
||||
{
|
||||
/**
|
||||
* Regex to account for all these cases:
|
||||
* spt profile level 20
|
||||
* spt profile skill metabolism 10
|
||||
*/
|
||||
private static commandRegex =
|
||||
/^spt profile (?<command>level|skill)((?<=.*skill) (?<skill>[\w]+)){0,1} (?<quantity>(?!0+)[0-9]+)$/;
|
||||
|
||||
protected savedCommand: SavedCommand;
|
||||
|
||||
public constructor(
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("HashUtil") protected hashUtil: HashUtil,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
||||
@inject("MailSendService") protected mailSendService: MailSendService,
|
||||
@inject("LocaleService") protected localeService: LocaleService,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public getCommand(): string
|
||||
{
|
||||
return "profile";
|
||||
}
|
||||
|
||||
public getCommandHelp(): string
|
||||
{
|
||||
return "spt profile\n========\nSets the profile level or skill to the desired level through the message system.\n\n\tspt profile level [desired level]\n\t\tEx: spt profile level 20\n\n\tspt profile skill [skill name] [quantity]\n\t\tEx: spt profile skill metabolism 51";
|
||||
}
|
||||
|
||||
public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string
|
||||
{
|
||||
if (!ProfileSptCommand.commandRegex.test(request.text))
|
||||
{
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
commandHandler,
|
||||
"Invalid use of trader command. Use \"help\" for more information.",
|
||||
);
|
||||
return request.dialogId;
|
||||
}
|
||||
|
||||
const result = ProfileSptCommand.commandRegex.exec(request.text);
|
||||
|
||||
const command: string = result.groups.command;
|
||||
const skill: string = result.groups.skill;
|
||||
const quantity: number = +result.groups.quantity;
|
||||
|
||||
let event: IProfileChangeEvent;
|
||||
switch (command)
|
||||
{
|
||||
case "level":
|
||||
if (quantity < 1 || quantity > this.profileHelper.getMaxLevel())
|
||||
{
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
commandHandler,
|
||||
"Invalid use of profile command, the level was outside bounds: 1 to 70. Use \"help\" for more information.",
|
||||
);
|
||||
return request.dialogId;
|
||||
}
|
||||
event = this.handleLevelCommand(quantity);
|
||||
break;
|
||||
case "skill":
|
||||
{
|
||||
const enumSkill = Object.values(SkillTypes).find((t) =>
|
||||
t.toLocaleLowerCase() === skill.toLocaleLowerCase()
|
||||
);
|
||||
|
||||
if (enumSkill === undefined)
|
||||
{
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
commandHandler,
|
||||
"Invalid use of profile command, the skill was not found. Use \"help\" for more information.",
|
||||
);
|
||||
return request.dialogId;
|
||||
}
|
||||
|
||||
if (quantity < 0 || quantity > 51)
|
||||
{
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
commandHandler,
|
||||
"Invalid use of profile command, the skill level was outside bounds: 1 to 51. Use \"help\" for more information.",
|
||||
);
|
||||
return request.dialogId;
|
||||
}
|
||||
event = this.handleSkillCommand(enumSkill, quantity);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
commandHandler,
|
||||
`If you are reading this, this is bad. Please report this to SPT staff with a screenshot. Command ${command}.`,
|
||||
);
|
||||
return request.dialogId;
|
||||
}
|
||||
|
||||
this.mailSendService.sendSystemMessageToPlayer(
|
||||
sessionId,
|
||||
"A single ruble is being attached, required by BSG logic.",
|
||||
[{
|
||||
_id: this.hashUtil.generate(),
|
||||
_tpl: "5449016a4bdc2d6f028b456f",
|
||||
upd: { StackObjectsCount: 1 },
|
||||
parentId: this.hashUtil.generate(),
|
||||
slotId: "main",
|
||||
}],
|
||||
undefined,
|
||||
[event],
|
||||
);
|
||||
return request.dialogId;
|
||||
}
|
||||
|
||||
protected handleSkillCommand(skill: string, level: number): IProfileChangeEvent
|
||||
{
|
||||
const event: IProfileChangeEvent = {
|
||||
_id: this.hashUtil.generate(),
|
||||
Type: ProfileChangeEventType.SKILL_POINTS,
|
||||
value: level * 100,
|
||||
entity: skill,
|
||||
};
|
||||
return event;
|
||||
}
|
||||
|
||||
protected handleLevelCommand(level: number): IProfileChangeEvent
|
||||
{
|
||||
const exp = this.profileHelper.getExperience(level);
|
||||
const event: IProfileChangeEvent = {
|
||||
_id: this.hashUtil.generate(),
|
||||
Type: ProfileChangeEventType.PROFILE_LEVEL,
|
||||
value: exp,
|
||||
entity: null,
|
||||
};
|
||||
return event;
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
import { SavedCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand";
|
||||
import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest";
|
||||
import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||
import { IProfileChangeEvent, ProfileChangeEventType } from "@spt-aki/models/spt/dialog/ISendMessageDetails";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { LocaleService } from "@spt-aki/services/LocaleService";
|
||||
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||
import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
@injectable()
|
||||
export class TraderSptCommand implements ISptCommand
|
||||
{
|
||||
/**
|
||||
* Regex to account for all these cases:
|
||||
* spt trader prapor rep 100
|
||||
* spt trader mechanic spend 1000000
|
||||
*/
|
||||
private static commandRegex = /^spt trader (?<trader>[\w]+) (?<command>rep|spend) (?<quantity>(?!0+)[0-9]+)$/;
|
||||
|
||||
protected savedCommand: SavedCommand;
|
||||
|
||||
public constructor(
|
||||
@inject("WinstonLogger") protected logger: ILogger,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("HashUtil") protected hashUtil: HashUtil,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
@inject("PresetHelper") protected presetHelper: PresetHelper,
|
||||
@inject("MailSendService") protected mailSendService: MailSendService,
|
||||
@inject("LocaleService") protected localeService: LocaleService,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public getCommand(): string
|
||||
{
|
||||
return "trader";
|
||||
}
|
||||
|
||||
public getCommandHelp(): string
|
||||
{
|
||||
return "spt trader\n========\nSets the reputation or money spent to the input quantity through the message system.\n\n\tspt trader [trader] rep [quantity]\n\t\tEx: spt trader prapor rep 2\n\n\tspt trader [trader] spend [quantity]\n\t\tEx: spt trader therapist spend 1000000";
|
||||
}
|
||||
|
||||
public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string
|
||||
{
|
||||
if (!TraderSptCommand.commandRegex.test(request.text))
|
||||
{
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
commandHandler,
|
||||
"Invalid use of trader command. Use \"help\" for more information.",
|
||||
);
|
||||
return request.dialogId;
|
||||
}
|
||||
|
||||
const result = TraderSptCommand.commandRegex.exec(request.text);
|
||||
|
||||
const trader: string = result.groups.trader;
|
||||
const command: string = result.groups.command;
|
||||
const quantity: number = +result.groups.quantity;
|
||||
|
||||
const dbTrader = Object.values(this.databaseServer.getTables().traders).find((t) =>
|
||||
t.base.nickname.toLocaleLowerCase() === trader.toLocaleLowerCase()
|
||||
);
|
||||
if (dbTrader === undefined)
|
||||
{
|
||||
this.mailSendService.sendUserMessageToPlayer(
|
||||
sessionId,
|
||||
commandHandler,
|
||||
"Invalid use of trader command, the trader was not found. Use \"help\" for more information.",
|
||||
);
|
||||
return request.dialogId;
|
||||
}
|
||||
let profileChangeEventType: ProfileChangeEventType;
|
||||
switch (command)
|
||||
{
|
||||
case "rep":
|
||||
profileChangeEventType = ProfileChangeEventType.TRADER_STANDING;
|
||||
break;
|
||||
case "spend":
|
||||
profileChangeEventType = ProfileChangeEventType.TRADER_SALES_SUM;
|
||||
break;
|
||||
}
|
||||
|
||||
const event: IProfileChangeEvent = {
|
||||
_id: this.hashUtil.generate(),
|
||||
Type: profileChangeEventType,
|
||||
value: quantity,
|
||||
entity: dbTrader.base._id,
|
||||
};
|
||||
|
||||
this.mailSendService.sendSystemMessageToPlayer(
|
||||
sessionId,
|
||||
"A single ruble is being attached, required by BSG logic.",
|
||||
[{
|
||||
_id: this.hashUtil.generate(),
|
||||
_tpl: "5449016a4bdc2d6f028b456f",
|
||||
upd: { StackObjectsCount: 1 },
|
||||
parentId: this.hashUtil.generate(),
|
||||
slotId: "main",
|
||||
}],
|
||||
undefined,
|
||||
[event],
|
||||
);
|
||||
return request.dialogId;
|
||||
}
|
||||
}
|
@ -34,7 +34,17 @@ export interface ISendMessageDetails
|
||||
export interface IProfileChangeEvent
|
||||
{
|
||||
_id: string;
|
||||
Type: "TraderSalesSum" | "TraderStanding" | "ProfileLevel" | "SkillPoints" | "ExamineAllItems" | "UnlockTrader";
|
||||
Type: ProfileChangeEventType;
|
||||
value: number;
|
||||
entity?: string;
|
||||
}
|
||||
|
||||
export enum ProfileChangeEventType
|
||||
{
|
||||
TRADER_SALES_SUM = "TraderSalesSum",
|
||||
TRADER_STANDING = "TraderStanding",
|
||||
PROFILE_LEVEL = "ProfileLevel",
|
||||
SKILL_POINTS = "SkillPoints",
|
||||
EXAMINE_ALL_ITEMS = "ExamineAllItems",
|
||||
UNLOCK_TRADER = "UnlockTrader",
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import { Dialogue, IUserDialogInfo, Message, MessageItems } from "@spt-aki/model
|
||||
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
|
||||
import { MessageType } from "@spt-aki/models/enums/MessageType";
|
||||
import { Traders } from "@spt-aki/models/enums/Traders";
|
||||
import { ISendMessageDetails } from "@spt-aki/models/spt/dialog/ISendMessageDetails";
|
||||
import { IProfileChangeEvent, ISendMessageDetails } from "@spt-aki/models/spt/dialog/ISendMessageDetails";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
@ -169,7 +169,8 @@ export class MailSendService
|
||||
sessionId: string,
|
||||
message: string,
|
||||
items: Item[] = [],
|
||||
maxStorageTimeSeconds = null,
|
||||
maxStorageTimeSeconds?: number,
|
||||
profileChangeEvents?: IProfileChangeEvent[],
|
||||
): void
|
||||
{
|
||||
const details: ISendMessageDetails = {
|
||||
@ -185,6 +186,11 @@ export class MailSendService
|
||||
details.itemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800; // 48 hours if no value supplied
|
||||
}
|
||||
|
||||
if ((profileChangeEvents?.length ?? 0) > 0)
|
||||
{
|
||||
details.profileChangeEvents = profileChangeEvents;
|
||||
}
|
||||
|
||||
this.sendMessageToPlayer(details);
|
||||
}
|
||||
|
||||
@ -199,8 +205,8 @@ export class MailSendService
|
||||
sessionId: string,
|
||||
messageLocaleId: string,
|
||||
items: Item[] = [],
|
||||
profileChangeEvents = [],
|
||||
maxStorageTimeSeconds = null,
|
||||
profileChangeEvents?: IProfileChangeEvent[],
|
||||
maxStorageTimeSeconds?: number,
|
||||
): void
|
||||
{
|
||||
const details: ISendMessageDetails = {
|
||||
@ -216,7 +222,7 @@ export class MailSendService
|
||||
details.itemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800; // 48 hours if no value supplied
|
||||
}
|
||||
|
||||
if (profileChangeEvents.length > 0)
|
||||
if ((profileChangeEvents?.length ?? 0) > 0)
|
||||
{
|
||||
details.profileChangeEvents = profileChangeEvents;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user