update quest objects and implement get achievemetns

This commit is contained in:
Dev 2023-12-27 17:15:38 +00:00
parent 87b177586e
commit 9e55a52965
10 changed files with 85 additions and 71 deletions

View File

@ -1,3 +1,4 @@
import { AchievementController } from "@spt-aki/controllers/AchievementController";
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData"; import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil"; import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
import { inject, injectable } from "tsyringe"; import { inject, injectable } from "tsyringe";
@ -6,7 +7,7 @@ import { inject, injectable } from "tsyringe";
export class AchievementCallbacks export class AchievementCallbacks
{ {
constructor( constructor(
// @inject("AchievementController") protected botController: AchievementController, @inject("AchievementController") protected achievementController: AchievementController,
@inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil,
) )
{} {}
@ -19,7 +20,7 @@ export class AchievementCallbacks
public getAchievements(url: string, info: IEmptyRequestData, sessionID: string): any public getAchievements(url: string, info: IEmptyRequestData, sessionID: string): any
{ {
throw new Error("Not implemented"); return this.httpResponse.getBody(this.achievementController.getAchievements(sessionID));
} }
/** /**

View File

@ -6,7 +6,6 @@ import { inject, injectable } from "tsyringe";
export class BuildsCallbacks export class BuildsCallbacks
{ {
constructor( constructor(
// @inject("AchievementController") protected botController: AchievementController,
@inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil, @inject("HttpResponseUtil") protected httpResponse: HttpResponseUtil,
) )
{} {}

View File

@ -135,7 +135,7 @@ export class QuestController
for (const conditionToFulfil of questRequirements) for (const conditionToFulfil of questRequirements)
{ {
// If the previous quest isn't in the user profile, it hasn't been completed or started // If the previous quest isn't in the user profile, it hasn't been completed or started
const prerequisiteQuest = profile.Quests.find((pq) => pq.qid === conditionToFulfil._props.target); const prerequisiteQuest = profile.Quests.find((pq) => pq.qid === conditionToFulfil.target);
if (!prerequisiteQuest) if (!prerequisiteQuest)
{ {
haveCompletedPreviousQuest = false; haveCompletedPreviousQuest = false;
@ -143,18 +143,18 @@ export class QuestController
} }
// Prereq does not have its status requirement fulfilled // Prereq does not have its status requirement fulfilled
if (!conditionToFulfil._props.status.includes(prerequisiteQuest.status)) if (!conditionToFulfil.status.includes(prerequisiteQuest.status))
{ {
haveCompletedPreviousQuest = false; haveCompletedPreviousQuest = false;
break; break;
} }
// Has a wait timer // Has a wait timer
if (conditionToFulfil._props.availableAfter > 0) if (conditionToFulfil.availableAfter > 0)
{ {
// Compare current time to unlock time for previous quest // Compare current time to unlock time for previous quest
const previousQuestCompleteTime = prerequisiteQuest.statusTimers[prerequisiteQuest.status]; const previousQuestCompleteTime = prerequisiteQuest.statusTimers[prerequisiteQuest.status];
const unlockTime = previousQuestCompleteTime + conditionToFulfil._props.availableAfter; const unlockTime = previousQuestCompleteTime + conditionToFulfil.availableAfter;
if (unlockTime > this.timeUtil.getTimestamp()) if (unlockTime > this.timeUtil.getTimestamp())
{ {
this.logger.debug( this.logger.debug(
@ -175,7 +175,7 @@ export class QuestController
let passesLoyaltyRequirements = true; let passesLoyaltyRequirements = true;
for (const condition of loyaltyRequirements) for (const condition of loyaltyRequirements)
{ {
if (!this.questHelper.traderLoyaltyLevelRequirementCheck(condition._props, profile)) if (!this.questHelper.traderLoyaltyLevelRequirementCheck(condition, profile))
{ {
passesLoyaltyRequirements = false; passesLoyaltyRequirements = false;
break; break;
@ -185,7 +185,7 @@ export class QuestController
let passesStandingRequirements = true; let passesStandingRequirements = true;
for (const condition of standingRequirements) for (const condition of standingRequirements)
{ {
if (!this.questHelper.traderStandingRequirementCheck(condition._props, profile)) if (!this.questHelper.traderStandingRequirementCheck(condition, profile))
{ {
passesStandingRequirements = false; passesStandingRequirements = false;
break; break;
@ -637,13 +637,13 @@ export class QuestController
{ {
// If quest has prereq of completed quest + availableAfter value > 0 (quest has wait time) // If quest has prereq of completed quest + availableAfter value > 0 (quest has wait time)
const nextQuestWaitCondition = quest.conditions.AvailableForStart.find((x) => const nextQuestWaitCondition = quest.conditions.AvailableForStart.find((x) =>
x._props.target === completedQuestId && x._props.availableAfter > 0 x.target === completedQuestId && x.availableAfter > 0
); );
if (nextQuestWaitCondition) if (nextQuestWaitCondition)
{ {
// Now + wait time // Now + wait time
const availableAfterTimestamp = this.timeUtil.getTimestamp() const availableAfterTimestamp = this.timeUtil.getTimestamp()
+ nextQuestWaitCondition._props.availableAfter; + nextQuestWaitCondition.availableAfter;
// Update quest in profile with status of AvailableAfter // Update quest in profile with status of AvailableAfter
const existingQuestInProfile = pmcData.Quests.find((x) => x.qid === quest._id); const existingQuestInProfile = pmcData.Quests.find((x) => x.qid === quest._id);
@ -687,7 +687,7 @@ export class QuestController
return false; return false;
} }
return x.conditions.Fail.some((y) => y._props.target === completedQuestId); return x.conditions.Fail.some((y) => y.target === completedQuestId);
}); });
} }
@ -709,7 +709,7 @@ export class QuestController
for (const questToFail of questsToFail) for (const questToFail of questsToFail)
{ {
// Skip failing a quest that has a fail status of something other than success // Skip failing a quest that has a fail status of something other than success
if (questToFail.conditions.Fail?.some((x) => x._props.status?.some((y) => y !== QuestStatus.Success))) if (questToFail.conditions.Fail?.some((x) => x.status?.some((y) => y !== QuestStatus.Success)))
{ {
continue; continue;
} }
@ -764,12 +764,12 @@ export class QuestController
for (const condition of quest.conditions.AvailableForFinish) for (const condition of quest.conditions.AvailableForFinish)
{ {
if ( if (
condition._props.id === handoverQuestRequest.conditionId condition.id === handoverQuestRequest.conditionId
&& handoverQuestTypes.includes(condition._parent) && handoverQuestTypes.includes(condition.conditionType)
) )
{ {
handedInCount = Number.parseInt(<string>condition._props.value); handedInCount = Number.parseInt(<string>condition.value);
isItemHandoverQuest = condition._parent === handoverQuestTypes[0]; isItemHandoverQuest = condition.conditionType === handoverQuestTypes[0];
handoverRequirements = condition; handoverRequirements = condition;
const profileCounter = (handoverQuestRequest.conditionId in pmcData.BackendCounters) const profileCounter = (handoverQuestRequest.conditionId in pmcData.BackendCounters)
@ -807,7 +807,7 @@ export class QuestController
for (const itemHandover of handoverQuestRequest.items) for (const itemHandover of handoverQuestRequest.items)
{ {
const matchingItemInProfile = pmcData.Inventory.items.find((item) => item._id === itemHandover.id); const matchingItemInProfile = pmcData.Inventory.items.find((item) => item._id === itemHandover.id);
if (!matchingItemInProfile || !handoverRequirements._props.target.includes(matchingItemInProfile._tpl)) if (!matchingItemInProfile || !handoverRequirements.target.includes(matchingItemInProfile._tpl))
{ {
// Item handed in by player doesnt match what was requested // Item handed in by player doesnt match what was requested
return this.showQuestItemHandoverMatchError( return this.showQuestItemHandoverMatchError(
@ -904,7 +904,7 @@ export class QuestController
const errorMessage = this.localisationService.getText("quest-handover_wrong_item", { const errorMessage = this.localisationService.getText("quest-handover_wrong_item", {
questId: handoverQuestRequest.qid, questId: handoverQuestRequest.qid,
handedInTpl: itemHandedOver._tpl, handedInTpl: itemHandedOver._tpl,
requiredTpl: handoverRequirements._props.target[0], requiredTpl: handoverRequirements.target[0],
}); });
this.logger.error(errorMessage); this.logger.error(errorMessage);

View File

@ -1,6 +1,8 @@
import { DependencyContainer, Lifecycle } from "tsyringe"; import { DependencyContainer, Lifecycle } from "tsyringe";
import { AchievementCallbacks } from "@spt-aki/callbacks/AchievementCallbacks";
import { BotCallbacks } from "@spt-aki/callbacks/BotCallbacks"; import { BotCallbacks } from "@spt-aki/callbacks/BotCallbacks";
import { BuildsCallbacks } from "@spt-aki/callbacks/BuildsCallbacks";
import { BundleCallbacks } from "@spt-aki/callbacks/BundleCallbacks"; import { BundleCallbacks } from "@spt-aki/callbacks/BundleCallbacks";
import { ClientLogCallbacks } from "@spt-aki/callbacks/ClientLogCallbacks"; import { ClientLogCallbacks } from "@spt-aki/callbacks/ClientLogCallbacks";
import { CustomizationCallbacks } from "@spt-aki/callbacks/CustomizationCallbacks"; import { CustomizationCallbacks } from "@spt-aki/callbacks/CustomizationCallbacks";
@ -33,6 +35,7 @@ import { TraderCallbacks } from "@spt-aki/callbacks/TraderCallbacks";
import { WeatherCallbacks } from "@spt-aki/callbacks/WeatherCallbacks"; import { WeatherCallbacks } from "@spt-aki/callbacks/WeatherCallbacks";
import { WishlistCallbacks } from "@spt-aki/callbacks/WishlistCallbacks"; import { WishlistCallbacks } from "@spt-aki/callbacks/WishlistCallbacks";
import { ApplicationContext } from "@spt-aki/context/ApplicationContext"; import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
import { AchievementController } from "@spt-aki/controllers/AchievementController";
import { BotController } from "@spt-aki/controllers/BotController"; import { BotController } from "@spt-aki/controllers/BotController";
import { ClientLogController } from "@spt-aki/controllers/ClientLogController"; import { ClientLogController } from "@spt-aki/controllers/ClientLogController";
import { CustomizationController } from "@spt-aki/controllers/CustomizationController"; import { CustomizationController } from "@spt-aki/controllers/CustomizationController";
@ -643,6 +646,8 @@ export class Container
depContainer.register<TraderCallbacks>("TraderCallbacks", { useClass: TraderCallbacks }); depContainer.register<TraderCallbacks>("TraderCallbacks", { useClass: TraderCallbacks });
depContainer.register<WeatherCallbacks>("WeatherCallbacks", { useClass: WeatherCallbacks }); depContainer.register<WeatherCallbacks>("WeatherCallbacks", { useClass: WeatherCallbacks });
depContainer.register<WishlistCallbacks>("WishlistCallbacks", { useClass: WishlistCallbacks }); depContainer.register<WishlistCallbacks>("WishlistCallbacks", { useClass: WishlistCallbacks });
depContainer.register<AchievementCallbacks>("AchievementCallbacks", { useClass: AchievementCallbacks });
depContainer.register<BuildsCallbacks>("BuildsCallbacks", { useClass: BuildsCallbacks });
} }
private static registerServices(depContainer: DependencyContainer): void private static registerServices(depContainer: DependencyContainer): void
@ -787,5 +792,6 @@ export class Container
depContainer.register<TraderController>("TraderController", { useClass: TraderController }); depContainer.register<TraderController>("TraderController", { useClass: TraderController });
depContainer.register<WeatherController>("WeatherController", { useClass: WeatherController }); depContainer.register<WeatherController>("WeatherController", { useClass: WeatherController });
depContainer.register<WishlistController>("WishlistController", WishlistController); depContainer.register<WishlistController>("WishlistController", WishlistController);
depContainer.register<AchievementController>("AchievementController", AchievementController);
} }
} }

View File

@ -327,14 +327,14 @@ export class InRaidHelper
// Does failed quest have requirement to collect items from raid // Does failed quest have requirement to collect items from raid
const questDbData = this.questHelper.getQuestFromDb(postRaidQuest.qid, pmcData); const questDbData = this.questHelper.getQuestFromDb(postRaidQuest.qid, pmcData);
// AvailableForFinish // AvailableForFinish
const matchingAffFindConditions = questDbData.conditions.AvailableForFinish.filter(x => x._parent === "FindItem"); const matchingAffFindConditions = questDbData.conditions.AvailableForFinish.filter(x => x.conditionType === "FindItem");
const itemsToCollect: string[] = []; const itemsToCollect: string[] = [];
if (matchingAffFindConditions) if (matchingAffFindConditions)
{ {
// Find all items the failed quest wanted // Find all items the failed quest wanted
for (const condition of matchingAffFindConditions) for (const condition of matchingAffFindConditions)
{ {
itemsToCollect.push(...condition._props.target); itemsToCollect.push(...condition.target);
} }
} }
@ -381,12 +381,12 @@ export class InRaidHelper
} }
// Find the time requirement in AvailableForStart array (assuming there is one as quest in locked state === its time-gated) // Find the time requirement in AvailableForStart array (assuming there is one as quest in locked state === its time-gated)
const afsRequirement = dbQuest.conditions.AvailableForStart.find(x => x._parent === "Quest"); const afsRequirement = dbQuest.conditions.AvailableForStart.find(x => x.conditionType === "Quest");
if (afsRequirement && afsRequirement._props.availableAfter > 0) if (afsRequirement && afsRequirement.availableAfter > 0)
{ {
// Prereq quest has a wait // Prereq quest has a wait
// Set quest as AvailableAfter and set timer // Set quest as AvailableAfter and set timer
const timestamp = this.timeUtil.getTimestamp() + afsRequirement._props.availableAfter; const timestamp = this.timeUtil.getTimestamp() + afsRequirement.availableAfter;
lockedQuest.availableAfter = timestamp; lockedQuest.availableAfter = timestamp;
lockedQuest.statusTimers.AvailableAfter = timestamp; lockedQuest.statusTimers.AvailableAfter = timestamp;
lockedQuest.status = 9; lockedQuest.status = 9;

View File

@ -45,7 +45,7 @@ export class QuestConditionHelper
{ {
const filteredQuests = q.filter((c) => const filteredQuests = q.filter((c) =>
{ {
if (c._parent === questType) if (c.conditionType === questType)
{ {
if (furtherFilter) if (furtherFilter)
{ {

View File

@ -10,7 +10,7 @@ import { TraderHelper } from "@spt-aki/helpers/TraderHelper";
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData"; import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
import { Common, IQuestStatus } from "@spt-aki/models/eft/common/tables/IBotBase"; import { Common, IQuestStatus } from "@spt-aki/models/eft/common/tables/IBotBase";
import { Item } from "@spt-aki/models/eft/common/tables/IItem"; import { Item } from "@spt-aki/models/eft/common/tables/IItem";
import { AvailableForConditions, AvailableForProps, IQuest, Reward } from "@spt-aki/models/eft/common/tables/IQuest"; import { AvailableForConditions, IQuest, Reward } from "@spt-aki/models/eft/common/tables/IQuest";
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse"; import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
import { IAcceptQuestRequestData } from "@spt-aki/models/eft/quests/IAcceptQuestRequestData"; import { IAcceptQuestRequestData } from "@spt-aki/models/eft/quests/IAcceptQuestRequestData";
import { IFailQuestRequestData } from "@spt-aki/models/eft/quests/IFailQuestRequestData"; import { IFailQuestRequestData } from "@spt-aki/models/eft/quests/IFailQuestRequestData";
@ -80,25 +80,25 @@ export class QuestHelper
*/ */
public doesPlayerLevelFulfilCondition(playerLevel: number, condition: AvailableForConditions): boolean public doesPlayerLevelFulfilCondition(playerLevel: number, condition: AvailableForConditions): boolean
{ {
if (condition._parent === "Level") if (condition.conditionType === "Level")
{ {
switch (condition._props.compareMethod) switch (condition.compareMethod)
{ {
case ">=": case ">=":
return playerLevel >= <number>condition._props.value; return playerLevel >= <number>condition.value;
case ">": case ">":
return playerLevel > <number>condition._props.value; return playerLevel > <number>condition.value;
case "<": case "<":
return playerLevel < <number>condition._props.value; return playerLevel < <number>condition.value;
case "<=": case "<=":
return playerLevel <= <number>condition._props.value; return playerLevel <= <number>condition.value;
case "=": case "=":
return playerLevel === <number>condition._props.value; return playerLevel === <number>condition.value;
default: default:
this.logger.error( this.logger.error(
this.localisationService.getText( this.localisationService.getText(
"quest-unable_to_find_compare_condition", "quest-unable_to_find_compare_condition",
condition._props.compareMethod, condition.compareMethod,
), ),
); );
return false; return false;
@ -198,7 +198,7 @@ export class QuestHelper
* @param profile Player profile * @param profile Player profile
* @returns true if loyalty is high enough to fulfill quest requirement * @returns true if loyalty is high enough to fulfill quest requirement
*/ */
public traderLoyaltyLevelRequirementCheck(questProperties: AvailableForProps, profile: IPmcData): boolean public traderLoyaltyLevelRequirementCheck(questProperties: AvailableForConditions, profile: IPmcData): boolean
{ {
const requiredLoyaltyLevel = Number(questProperties.value); const requiredLoyaltyLevel = Number(questProperties.value);
const trader = profile.TradersInfo[<string>questProperties.target]; const trader = profile.TradersInfo[<string>questProperties.target];
@ -216,7 +216,7 @@ export class QuestHelper
* @param profile Player profile * @param profile Player profile
* @returns true if standing is high enough to fulfill quest requirement * @returns true if standing is high enough to fulfill quest requirement
*/ */
public traderStandingRequirementCheck(questProperties: AvailableForProps, profile: IPmcData): boolean public traderStandingRequirementCheck(questProperties: AvailableForConditions, profile: IPmcData): boolean
{ {
const requiredStanding = Number(questProperties.value); const requiredStanding = Number(questProperties.value);
const trader = profile.TradersInfo[<string>questProperties.target]; const trader = profile.TradersInfo[<string>questProperties.target];
@ -373,13 +373,13 @@ export class QuestHelper
// Check if quest has a prereq to be placed in a 'pending' state // Check if quest has a prereq to be placed in a 'pending' state
const questDbData = this.getQuestFromDb(acceptedQuest.qid, pmcData); const questDbData = this.getQuestFromDb(acceptedQuest.qid, pmcData);
const waitTime = questDbData.conditions.AvailableForStart.find((x) => x._props.availableAfter > 0); const waitTime = questDbData.conditions.AvailableForStart.find((x) => x.availableAfter > 0);
if (waitTime && acceptedQuest.type !== "repeatable") if (waitTime && acceptedQuest.type !== "repeatable")
{ {
// Quest should be put into 'pending' state // Quest should be put into 'pending' state
newQuest.startTime = 0; newQuest.startTime = 0;
newQuest.status = QuestStatus.AvailableAfter; // 9 newQuest.status = QuestStatus.AvailableAfter; // 9
newQuest.availableAfter = currentTimestamp + waitTime._props.availableAfter; newQuest.availableAfter = currentTimestamp + waitTime.availableAfter;
} }
else else
{ {
@ -409,9 +409,9 @@ export class QuestHelper
// e.g. Quest A passed in, quest B is looped over and has requirement of A to be started, include it // e.g. Quest A passed in, quest B is looped over and has requirement of A to be started, include it
const acceptedQuestCondition = quest.conditions.AvailableForStart.find((x) => const acceptedQuestCondition = quest.conditions.AvailableForStart.find((x) =>
{ {
return x._parent === "Quest" return x.conditionType === "Quest"
&& x._props.target === startedQuestId && x.target === startedQuestId
&& x._props.status[0] === QuestStatus.Started; && x.status[0] === QuestStatus.Started;
}); });
// Not found, skip quest // Not found, skip quest
@ -425,7 +425,7 @@ export class QuestHelper
); );
for (const condition of standingRequirements) for (const condition of standingRequirements)
{ {
if (!this.traderStandingRequirementCheck(condition._props, profile)) if (!this.traderStandingRequirementCheck(condition, profile))
{ {
return false; return false;
} }
@ -436,7 +436,7 @@ export class QuestHelper
); );
for (const condition of loyaltyRequirements) for (const condition of loyaltyRequirements)
{ {
if (!this.traderLoyaltyLevelRequirementCheck(condition._props, profile)) if (!this.traderLoyaltyLevelRequirementCheck(condition, profile))
{ {
return false; return false;
} }
@ -465,9 +465,9 @@ export class QuestHelper
{ {
const acceptedQuestCondition = q.conditions.AvailableForStart.find((c) => const acceptedQuestCondition = q.conditions.AvailableForStart.find((c) =>
{ {
return c._parent === "Quest" return c.conditionType === "Quest"
&& c._props.target === failedQuestId && c.target === failedQuestId
&& c._props.status[0] === QuestStatus.Fail; && c.status[0] === QuestStatus.Fail;
}); });
if (!acceptedQuestCondition) if (!acceptedQuestCondition)
@ -602,7 +602,7 @@ export class QuestHelper
public getQuestWithOnlyLevelRequirementStartCondition(quest: IQuest): IQuest public getQuestWithOnlyLevelRequirementStartCondition(quest: IQuest): IQuest
{ {
quest = this.jsonUtil.clone(quest); quest = this.jsonUtil.clone(quest);
quest.conditions.AvailableForStart = quest.conditions.AvailableForStart.filter((q) => q._parent === "Level"); quest.conditions.AvailableForStart = quest.conditions.AvailableForStart.filter((q) => q.conditionType === "Level");
return quest; return quest;
} }
@ -958,11 +958,11 @@ export class QuestHelper
} }
const condition = questInDb.conditions.AvailableForFinish.find((c) => const condition = questInDb.conditions.AvailableForFinish.find((c) =>
c._parent === "FindItem" && c._props?.target?.includes(itemTpl) c.conditionType === "FindItem" && c?.target?.includes(itemTpl)
); );
if (condition) if (condition)
{ {
result[questId] = condition._props.id; result[questId] = condition.id;
break; break;
} }

View File

@ -9,7 +9,7 @@ export interface IQuest
QuestName?: string; QuestName?: string;
_id: string; _id: string;
canShowNotificationsInGame: boolean; canShowNotificationsInGame: boolean;
conditions: Conditions; conditions: IQuestConditions;
description: string; description: string;
failMessageText: string; failMessageText: string;
name: string; name: string;
@ -27,7 +27,7 @@ export interface IQuest
startedMessageText: string; startedMessageText: string;
successMessageText: string; successMessageText: string;
templateId: string; templateId: string;
rewards: Rewards; rewards: IRewards;
/** Becomes 'AppearStatus' inside client */ /** Becomes 'AppearStatus' inside client */
status: string | number; status: string | number;
KeyQuest: boolean; KeyQuest: boolean;
@ -38,7 +38,7 @@ export interface IQuest
sptStatus?: QuestStatus; sptStatus?: QuestStatus;
} }
export interface Conditions export interface IQuestConditions
{ {
Started: AvailableForConditions[]; Started: AvailableForConditions[];
AvailableForFinish: AvailableForConditions[]; AvailableForFinish: AvailableForConditions[];
@ -48,13 +48,6 @@ export interface Conditions
} }
export interface AvailableForConditions export interface AvailableForConditions
{
_parent: string;
_props: AvailableForProps;
dynamicLocale?: boolean;
}
export interface AvailableForProps
{ {
id: string; id: string;
index: number; index: number;
@ -79,7 +72,9 @@ export interface AvailableForProps
zoneId?: string; zoneId?: string;
type?: boolean; type?: boolean;
countInRaid?: boolean; countInRaid?: boolean;
globalQuestCounterId?: any; globalQuestCounterId?: string;
completeInSeconds?: number
conditionType?: string
} }
export interface AvailableForCounter export interface AvailableForCounter
@ -89,26 +84,36 @@ export interface AvailableForCounter
} }
export interface CounterCondition export interface CounterCondition
{
_parent: string;
_props: CounterProps;
}
export interface CounterProps
{ {
id: string; id: string;
dynamicLocale: boolean
target: string[] | string; // TODO: some objects have an array and some are just strings, thanks bsg very cool target: string[] | string; // TODO: some objects have an array and some are just strings, thanks bsg very cool
compareMethod?: string; compareMethod?: string;
value?: string; value?: string;
weapon?: string[]; weapon?: string[];
distance: ICounterConditionDistance
equipmentInclusive?: string[][]; equipmentInclusive?: string[][];
weaponModsInclusive?: string[][]; weaponModsInclusive?: string[][];
weaponModsExclusive?: string[][];
enemyEquipmentInclusive?: string[][];
enemyEquipmentExclusive?: string[][];
weaponCaliber: string[]
savageRole: any[]
status?: string[]; status?: string[];
bodyPart?: string[]; bodyPart?: string[];
daytime?: DaytimeCounter; daytime?: IDaytimeCounter;
conditionType?: string
enemyHealthEffects: any[]
resetOnSessionEnd: boolean
} }
export interface DaytimeCounter export interface ICounterConditionDistance
{
value: number
compareMethod: string
}
export interface IDaytimeCounter
{ {
from: number; from: number;
to: number; to: number;
@ -122,7 +127,7 @@ export interface VisibilityCondition
oneSessionOnly: boolean; oneSessionOnly: boolean;
} }
export interface Rewards export interface IRewards
{ {
AvailableForStart: Reward[]; AvailableForStart: Reward[];
AvailableForFinish: Reward[]; AvailableForFinish: Reward[];

View File

@ -52,6 +52,9 @@ export interface IDatabaseTables
/** Default equipment loadouts that show on main inventory screen */ /** Default equipment loadouts that show on main inventory screen */
defaultEquipmentPresets: IEquipmentBuild[]; defaultEquipmentPresets: IEquipmentBuild[];
/** Achievements */
achievements: IAchievement[]
}; };
traders?: Record<string, ITrader>; traders?: Record<string, ITrader>;

View File

@ -6,7 +6,7 @@ import { RouteAction, StaticRouter } from "@spt-aki/di/Router";
@injectable() @injectable()
export class AchievementStaticRouter extends StaticRouter export class AchievementStaticRouter extends StaticRouter
{ {
constructor(@inject("AchievementStaticRouter") protected achievementCallbacks: AchievementCallbacks) constructor(@inject("AchievementCallbacks") protected achievementCallbacks: AchievementCallbacks)
{ {
super([ super([
new RouteAction( new RouteAction(