@peacockproject/core
Version:
Type definitions for Peacock's core.
1,436 lines (1,435 loc) • 39.4 kB
TypeScript
import type * as core from "express-serve-static-core";
import type { ContractCreationNpcTargetPayload } from "../statemachines/contractCreation";
import { Request } from "express";
import { ChallengeContext, ProfileChallengeData, SavedChallenge } from "./challenges";
import { SessionGhostModeDetails } from "../multiplayer/multiplayerService";
import { IContextListener } from "../statemachines/contextListeners";
import { ManifestScoringModule, ScoringModule } from "./scoring";
import { Timer } from "@peacockproject/statemachine-parser";
import { InventoryItem } from "../inventory";
/**
* A duration or relative point in time expressed in seconds.
*/
export type Seconds = number;
/**
* The game's major version.
*/
export type GameVersion = "h1" | "h2" | "h3" | "scpc";
/**
* The server configuration's target audience.
*
* Notes:
* - pc-prod8 is deprecated, as HITMAN 3 after 3.100.0 no longer uses it.
*/
export type GameAudience = "pc-prod8" | "pc-prod7" | "pc-prod6" | "steam-prod_8" | "epic-prod_8" | "xboxone-prod" | "scpc-prod" | "playtest01-prod_8";
/**
* Data from the JSON Web Token (JWT) authentication scheme.
*/
export interface JwtData {
/**
* Usually bearer.
*/
"auth:method": "bearer" | string;
/**
* Always "user".
*/
roles: "user";
sub: string;
/**
* Profile ID.
*/
unique_name: string;
/**
* User ID.
*/
userid: string;
/**
* Either "steam" or "epic" on PC.
*/
platform: "steam" | "epic";
/**
* Client/account locale.
*/
locale: string;
/**
* Client/account region.
*/
rgn: string;
/**
* External appid.
*/
pis: string;
/**
* Country, specified by the locale property.
*/
cntry: string;
/**
* Expires in.
*/
exp: string;
/**
* Not before.
*/
nbf: string;
/**
* Issuer (from external provider).
*/
iss: string;
/**
* The audience.
*
* @see GameAudience
*/
aud: GameAudience;
}
/**
* A request with a JSON web token (JWT) already parsed. Also contains our custom request properties.
*/
export interface RequestWithJwt<Query = core.Query, RequestBody = any, Params = core.ParamsDictionary> extends Request<Params, any, RequestBody, core.Query & Query> {
/**
* The user's JSON Web Token (JWT) data.
*/
jwt: JwtData;
/**
* The current Hitman server version.
*/
serverVersion?: string;
/**
* The game's version.
*/
gameVersion: GameVersion;
/**
* Used internally to declare if a route should be propagated to its handler or cancelled early.
*/
shouldCease?: boolean;
}
/**
* The status of cameras in a mission.
*/
export declare enum PeacockCameraStatus {
NotSpotted = "NOT_SPOTTED",
Spotted = "SPOTTED",
Erased = "ERASED"
}
/**
* The status of security cameras in a mission (event-end).
*/
export type SecurityCameraStatus = "destroyed" | "spotted" | "erased";
/**
* A repository ID (really just a UUID v4).
*/
export type RepositoryId = string;
/**
* Possible mission `Metadata.Type` values.
*/
export type MissionType = "mission" | "elusive" | "escalation" | "featured" | "sniper" | "usercreated" | "creation" | "tutorial" | "orbis" | "campaign" | "arcade" | "vsrace" | "evergreen" | "flashback";
/**
* The data acquired when using the "contract search" functionality.
*/
export type ContractSearchResult = {
Data: {
Contracts: {
UserCentricContract: UserCentricContract;
}[];
ErrorReason: string;
HasMore: boolean;
HasPrevious: boolean;
Page: number;
TotalCount: number;
};
};
/**
* The last kill in a contract session.
*
* @see ContractSession
*/
export type ContractSessionLastKill = {
timestamp?: Date | number;
repositoryIds?: RepositoryId[];
/**
* If the last kill was unnoticed in H2016.
* See [this video](https://www.youtube.com/watch?v=4fMDqRZg3Ik) for an explanation on how it's supposed to work.
*/
legacyIsUnnoticed?: boolean;
};
/**
* A contract session is created every time you start a level, which contains the data of the play session.
* Primarily used for scoring, saving, and loading.
*/
export interface ContractSession {
Id: string;
gameVersion: GameVersion;
sessionStart: Date | number;
lastUpdate: Date | number;
contractId: string;
userId: string;
timerStart: Date | number;
timerEnd: Date | number;
duration: Date | number;
crowdNpcKills: number;
targetKills: Set<RepositoryId>;
npcKills: Set<RepositoryId>;
bodiesHidden: Set<RepositoryId>;
pacifications: Set<RepositoryId>;
disguisesUsed: Set<RepositoryId>;
disguisesRuined: Set<RepositoryId>;
spottedBy: Set<RepositoryId>;
witnesses: Set<RepositoryId>;
bodiesFoundBy: Set<RepositoryId>;
legacyHasBodyBeenFound: boolean;
killsNoticedBy: Set<RepositoryId>;
completedObjectives: Set<RepositoryId>;
failedObjectives: Set<RepositoryId>;
recording: PeacockCameraStatus;
lastAccident: number;
lastKill: ContractSessionLastKill;
kills: Set<RatingKill>;
markedTargets: Set<RepositoryId>;
compat: boolean;
currentDisguise: string;
difficulty: number;
objectives: Map<string, MissionManifestObjective>;
objectiveStates: Map<string, string>;
objectiveContexts: Map<string, unknown>;
/**
* Session Ghost Mode details.
*
* @since v5.0.0
*/
ghost?: SessionGhostModeDetails;
/**
* The current state of the challenges.
*
* @since v5.6.0-dev.1
*/
challengeContexts?: {
[challengeId: string]: ChallengeContext;
};
/**
* Session Evergreen details.
*
* @since v6.0.0
*/
evergreen?: {
payout: number;
scoringScreenEndState: string | null;
failed: boolean;
};
/**
* Scoring settings, and statemachine settings.
* Currently only used for Sniper Challenge missions.
*
* Settings: Keyed by the type property in modules.
* Context: The current context of the scoring statemachine.
* Definition: The initial definition of the scoring statemachine.
* State: The current state of the scoring statemachine.
* Timers: The current timers of the scoring statemachine.
*
* @since v7.0.0
*/
scoring?: {
Settings: {
[name: string]: ScoringModule;
};
Context: unknown;
Definition: unknown;
State: string;
Timers: Timer[];
};
/**
* Timestamp of first kill.
* Used for calculating Sniper Challenge time bonus.
* @since v7.0.0
*/
firstKillTimestamp?: number;
/**
* If true, it is not possible anymore to get an SA rating.
* @since v8.0.0
*/
silentAssassinLost?: boolean;
}
/**
* The SaveFile object passed by the client in /ProfileService/UpdateUserSaveFileTable
*/
export interface SaveFile {
ContractSessionId: string;
TimeStamp: number;
Value: {
Name: string;
LastEventToken: string;
};
}
/**
* The body sent with the UpdateUserSaveFileTable request from the game after saving.
*
* @see SaveFile
*/
export type UpdateUserSaveFileTableBody = {
clientSaveFileList: SaveFile[];
deletedSaveFileList: SaveFile[];
};
/**
* The Hitman server version in object form.
*/
export type ServerVersion = Readonly<{
_Major: number;
_Minor: number;
_Build: number;
_Revision: number;
}>;
/**
* An event sent from the game client to the server.
*/
export interface ClientToServerEvent<EventValue = unknown> {
Value: EventValue extends object ? Readonly<EventValue> : EventValue;
ContractSessionId: string;
ContractId: string;
Name: string;
Timestamp: number;
}
/**
* A wrapper for {@link ServerToClientEvent} that also has a timestamp value.
*
* @see ServerToClientEvent
*/
export interface S2CEventWithTimestamp<EventValue = unknown> {
time: number | string;
event: ServerToClientEvent<EventValue>;
}
/**
* A server to client push message. The message component is encoded JSON.
*/
export type PushMessage = {
time: number | string | bigint;
message: string;
};
/**
* A server to client event.
*/
export interface ServerToClientEvent<EventValue = unknown> {
message?: string;
CreatedAt?: string;
Token?: string;
IsReplicated?: boolean;
Version: ServerVersion;
CreatedContract?: string | null;
Id?: string;
Name?: string;
UserId?: string;
ContractId?: string;
SessionId?: string | null;
ContractSessionId?: string;
Timestamp?: number;
Value?: EventValue;
Origin?: string | null;
}
export type MissionStory = {
CommonRepositoryId: RepositoryId;
PreviouslyCompleted: boolean;
IsMainOpportunity: boolean;
Title: string;
Summary: string;
Briefing: string;
Location: string;
SubLocation: string;
Image: string;
};
export type PlayerProfileLocation = {
LocationId: string;
Xp: number;
ActionXp: number;
LocationProgression?: {
Level: number;
MaxLevel: number;
};
};
export type PlayerProfileView = {
SubLocationData: {
ParentLocation: Unlockable;
Location: Unlockable;
CompletionData: CompletionData;
ChallengeCategoryCompletion: ChallengeCategoryCompletion[];
ChallengeCompletion: ChallengeCompletion;
OpportunityStatistics: OpportunityStatistics;
LocationCompletionPercent: number;
}[];
PlayerProfileXp: {
Total: number;
Level: number;
Sublocations?: PlayerProfileLocation[];
Seasons: {
Number: number;
Locations: PlayerProfileLocation[];
}[];
};
};
export type ChallengeCompletion = {
ChallengesCount: number;
CompletedChallengesCount: number;
CompletionPercent?: number;
};
export type ChallengeCategoryCompletion = ChallengeCompletion & {
Name: string;
};
export type OpportunityStatistics = {
Count: number;
Completed: number;
};
export type ContractHistory = {
LastPlayedAt?: number;
Completed?: boolean;
IsEscalation?: boolean;
};
export type ProgressionData = {
Xp: number;
Level: number;
PreviouslySeenXp: number;
};
export type UserProfile = {
Id: string;
LinkedAccounts: {
dev?: string;
epic?: string;
steam?: string;
gog?: string;
xbox?: string;
stadia?: string;
};
Extensions: {
/**
* Map of escalation group ID to current level number.
*/
PeacockEscalations: {
[escalationId: string]: number;
};
PeacockFavoriteContracts: string[];
PeacockPlayedContracts: {
[contractId: string]: ContractHistory;
};
PeacockCompletedEscalations: string[];
Saves: {
[slot: string]: {
Timestamp: number;
ContractSessionId: string;
Token: string;
};
};
ChallengeProgression: {
[id: string]: ProfileChallengeData;
};
/**
* Player progression data.
*/
progression: {
/**
* Player XP and level data.
*/
PlayerProfileXP: {
ProfileLevel: number;
/**
* The total amount of XP a user has obtained.
*/
Total: number;
Sublocations: {
[location: string]: {
Xp: number;
ActionXp: number;
};
};
};
/**
* If the mastery location has subpackages and not drops, it will
* be an object.
*/
Locations: {
[location: string]: ProgressionData | {
[subPackageId: string]: ProgressionData;
};
};
};
defaultloadout?: {
[location: string]: GameLoadout & {
[briefcaseId: string]: string;
};
};
entP: string[];
achievements?: unknown;
gamepersistentdata: {
__stats?: unknown;
PersistentBool: Record<string, unknown>;
HitsFilterType: {
MyHistory: string;
MyContracts: string;
MyPlaylist: string;
};
menudata: {
difficulty: {
destinations: {
[locationId: string]: "normal" | "pro1";
};
};
newunlockables: string[];
};
};
opportunityprogression: {
[opportunityId: RepositoryId]: boolean;
};
CPD: CPDStore;
LastOfficialSync: Date | string | null;
};
ETag: string | null;
Gamertag: string;
DevId: string | null;
SteamId: string | null;
EpicId: string | null;
NintendoId: string | null;
XboxLiveId: string | null;
PSNAccountId: string | null;
PSNOnlineId: string | null;
/**
* @since v7.0.0 user profiles are now versioned.
*/
Version: number;
};
export type RatingKill = {
IsHeadshot: boolean;
KillClass: string;
KillItemCategory: string;
KillMethodBroad: string;
KillMethodStrict: string;
KillItemRepositoryId: RepositoryId;
RequiredKillMethodType?: number;
_RepositoryId?: RepositoryId;
RepositoryId?: RepositoryId;
OutfitRepoId: string;
};
export type NamespaceEntitlementEpic = {
namespace: string;
itemId: string;
owned: boolean;
};
/**
* An unlockable item.
*/
export type Unlockable = {
Id: string;
DisplayNameLocKey: string;
GameAsset: string | null;
Guid: string;
Type: string;
Subtype?: string;
SubType?: string;
ImageId?: string | null;
RMTPrice?: number;
GamePrice?: number;
IsPurchasable: boolean;
IsPublished: boolean;
IsDroppable: boolean;
Capabilities: unknown[];
Qualities?: Record<string, unknown> | null;
Properties: {
RewardHidden?: boolean;
HowToUnlock?: string;
AllowUpSync?: boolean;
Background?: string;
Icon?: string;
LockedIcon?: string;
DlcImage?: string;
DlcName?: string;
IsLocked?: boolean;
Order?: number;
ProgressionKey?: string;
Season?: number;
RequiredResources?: string[];
Entitlements?: string[];
ParentLocation?: string;
GameChangers?: unknown[];
CreateContractId?: null | string;
IsFreeDLC?: boolean;
HideProgression?: boolean;
ExcludeParentRewards?: boolean;
Quality?: number | string;
UpcomingContent?: boolean;
UpcomingKey?: "UI_MENU_LIVETILE_CONTENT_UPCOMING_HEADLINE" | string;
LimitedLoadout?: boolean;
NormalLoadoutUnlock?: {
normal: string;
pro1: string;
} | string;
Unlocks?: string[];
Rarity?: string | null;
LoadoutSlot?: "carriedweapon" | "concealedweapon" | "disguise" | "gear" | string;
ItemSize?: string;
IsConsumable?: boolean;
RepositoryId?: RepositoryId;
OrderIndex?: number;
Name?: string;
Description?: string;
UnlockOrder?: number;
UnlockLevel?: string;
Location?: string;
Equip?: string[];
GameAssets?: string[];
RepositoryAssets?: RepositoryId[];
Gameplay?: ItemGameplay;
AlwaysAdd?: boolean;
BlacklistedByDefault?: boolean;
IsContainer?: boolean;
LoadoutSettings?: {
GearSlotsEnabledCount?: number;
GearSlotsAllowContainers?: boolean;
ConcealedWeaponSlotEnabled?: boolean;
};
UnlockedByDefault?: boolean;
DifficultyUnlock?: {
pro1?: string;
};
Difficulty?: string;
/**
* Sniper rifle modifier repository IDs.
*/
Modifiers?: RepositoryId[] | null;
/**
* Inclusion data for an unlockable. The only known use for this is
* sniper rifle unlockables for Sniper Assassin mode.
*/
InclusionData?: InclusionData;
/**
* Item perks - only known use is for Sniper Assassin.
*/
Perks?: string[] | null;
};
Rarity?: string | null;
};
export type ItemGameplay = {
range?: number;
damage?: number;
clipsize?: number;
rateoffire?: number;
};
export type CompletionData = {
Level: number;
MaxLevel: number;
XP: number;
PreviouslySeenXp: number;
Completion: number;
XpLeft: number;
Id: string;
SubLocationId: string;
HideProgression: boolean;
IsLocationProgression: boolean;
Name: string | null;
};
export type UserCentricContract = {
Contract: MissionManifest;
Data: {
IsLocked: boolean;
LockedReason: string;
LocationLevel: number;
LocationMaxLevel: number;
LocationCompletion: number;
LocationXpLeft: number;
LocationHideProgression: boolean;
ElusiveContractState: string;
LastPlayedAt?: string;
IsFeatured?: boolean;
PlaylistData?: {
IsAdded: boolean;
AddedTime: string;
};
Completed?: boolean;
LocationId: string;
ParentLocationId: string;
CompletionData?: CompletionData;
DlcName: string;
DlcImage: string;
EscalationCompleted?: boolean;
EscalationCompletedLevels?: number;
EscalationTotalLevels?: number;
InGroup?: string;
};
};
export type TargetCondition = {
/**
* The target condition type. This can be one of the following:
* - `killmethod` - A way to kill the target.
* - `hitmansuit` - Specifies the outfit must be any suit that you can start a level with which (but not a disguise).
* - `disguise` - Specifies the outfit must be a specific disguise.
*/
Type: "killmethod" | "hitmansuit" | "disguise";
RepositoryId?: RepositoryId;
/**
* If the game should display the objective as optional or not.
*/
HardCondition?: boolean;
/**
* The objective ID that this condition is tied to. When specified, the game can mark the condition with a check mark or X in the F1 menu.
*/
ObjectiveId?: string;
/**
* For outfit requirements, this is just an empty string. For kill methods, this is the kill method.
*/
KillMethod: "" | string;
};
/**
* Data structure for an objective's HUD template.
*/
export interface HUDTemplate {
display: string | {
$loc: {
key: string;
data: string;
};
};
iconType?: number;
}
/**
* Data structure for a mission manifest's `Data.VR` bricks property.
*/
export type VRQualityDefinition = {
Quality: string;
Bricks: string[];
};
export interface MissionManifestObjective {
_comment?: string;
Id: string;
Type?: "kill" | "statemachine" | string;
Scope?: string;
Primary?: boolean;
IsHidden?: boolean;
BriefingText?: string | {
$loc: {
key: string;
data: string | number[];
};
};
LongBriefingText?: string | {
$loc: {
key: string;
data: string | number[];
};
};
Image?: string;
BriefingName?: string;
ShowInHud?: boolean;
CombinedDisplayInHud?: boolean;
DisplayAsKillObjective?: boolean;
Category?: "primary" | "secondary" | "condition" | string;
ForceShowOnLoadingScreen?: boolean;
/**
* Allow Elusive Target Arcade contracts to be restarted if this objective is already successfully completed.
*/
AllowEtRestartOnSuccess?: boolean;
OnInactive?: {
IfCompleted?: {
State?: string;
};
};
Definition?: {
display?: {
iconType?: number;
};
ContextListeners?: null | Record<string, IContextListener<never>>;
Scope?: string;
States?: Record<string, unknown>;
Constants?: Record<string, unknown>;
Context?: Record<string, unknown | string[] | string>;
};
Activation?: {
$eq?: (string | boolean)[];
};
OnActive?: {
IfInProgress?: {
Visible?: boolean;
State?: "Completed" | "InProgress" | "Failed" | string;
};
IfCompleted?: {
Visible?: boolean;
State?: "Completed" | "InProgress" | "Failed" | string;
};
IfFailed?: {
Visible?: boolean;
State?: "Completed" | "InProgress" | "Failed" | string;
};
};
ObjectiveType?: "kill" | "customkill" | "setpiece" | "custom" | string;
TargetConditions?: TargetCondition[];
ExcludeFromScoring?: boolean;
HUDTemplate?: HUDTemplate;
SuccessEvent?: {
EventName: "Kill" | string;
EventValues: {
RepositoryId: RepositoryId;
};
};
FailedEvent?: {
EventName: string;
EventValues?: {
RepositoryId?: RepositoryId;
};
};
ResetEvent?: null;
IgnoreIfInactive?: boolean;
GameChangerName?: string;
IsPrestigeObjective?: boolean;
}
/**
* Data for a group contract.
*/
export type ContractGroupDefinition = {
/**
* The contract group type.
*/
Type: MissionType;
/**
* The contracts in this group, ordered by their position in the group.
*/
Order: string[];
};
export type EscalationInfo = {
Type?: MissionType;
InGroup?: string;
NextContractId?: string;
GroupData?: {
Level: number;
TotalLevels: number;
Completed: boolean;
FirstContractId: string;
};
};
export interface MissionManifestMetadata {
Id: string;
Location: string;
IsPublished?: boolean | null;
CreationTimestamp?: string | null;
CreatorUserId?: string | null;
Title: string;
Description?: string | null;
BriefingVideo?: string | {
Mode: string;
VideoId: string;
}[];
DebriefingVideo?: string | null;
TileImage?: string | {
Mode: string;
Image: string;
}[];
CodeName_Hint?: string | null;
ScenePath: string;
Type: MissionType;
Release?: string | object | null;
RequiredUnlockable?: string | null;
Drops?: string[] | null;
Opportunities?: string[] | null;
OpportunityData?: MissionStory[] | null;
Entitlements: string[] | null;
LastUpdate?: string | null;
PublicId?: string | null;
GroupObjectiveDisplayOrder?: GroupObjectiveDisplayOrderItem[] | null;
GameVersion?: string | null;
ServerVersion?: string | null;
NonTargetKillsAllowed?: boolean | null;
Difficulty?: "pro1" | string | null;
OnlyNeoVR?: boolean | null;
LocationSuitOverride?: string;
CharacterSetup?: {
Mode: "singleplayer" | "multiplayer" | string;
Characters: {
Name: string;
Id: string;
MandatoryLoadout?: string[];
}[];
}[] | null;
CharacterLoadoutData?: {
Id: string;
Loadout: unknown;
CompletionData: CompletionData;
}[] | null;
SpawnSelectionType?: "random" | string | null;
Gamemodes?: ("versus" | string)[] | null;
Enginemodes?: ("singleplayer" | "multiplayer" | string)[] | null;
EndConditions?: {
PointLimit?: number;
} | null;
Subtype?: string | null;
GroupTitle?: string | null;
TargetExpiration?: number | null;
TargetExpirationReduced?: number | null;
TargetLifeTime?: number | null;
NonTargetKillPenaltyEnabled?: boolean | null;
NoticedTargetStreakPenaltyMax?: number | null;
IsFeatured?: boolean | null;
InGroup?: string | null;
NextContractId?: string | null;
GroupDefinition?: ContractGroupDefinition | null;
GroupData?: EscalationInfo["GroupData"] | null;
/**
* Useless property.
*
* @deprecated
*/
readonly UserData?: unknown | null;
IsVersus?: boolean | null;
IsEvergreenSafehouse?: boolean | null;
UseContractProgressionData?: boolean | null;
CpdId?: string | null;
/**
* Custom property used for Elusives (like official's year)
* and Escalations (if it's 0, it is a Peacock escalation,
* and OriginalSeason will exist for filtering).
*/
Season?: number | null;
OriginalSeason?: number | null;
Modules?: ManifestScoringModule[] | null;
}
export type GroupObjectiveDisplayOrderItem = {
Id: string;
IsNew?: boolean;
};
export interface GameChanger {
Id: string;
Name: string;
Description: string;
TileImage?: string | null;
Icon?: string | null;
ObjectivesCategory?: string | null;
IsHidden?: boolean | null;
Resource?: string[] | null;
Objectives?: MissionManifestObjective[] | null;
LongDescription?: string | null;
ShowBasedOnObjectives?: boolean | null;
IsPrestigeObjective?: boolean;
}
/**
* A mission's manifest is what defines how a specific contract plays.
*
* @see MissionManifestMetadata
* @see MissionManifestObjective
*/
export interface MissionManifest {
Data: {
EnableSaving?: boolean;
Objectives?: MissionManifestObjective[];
GameDifficulties?: {
Difficulty: "easy" | "normal" | "hard" | string;
Bricks: string[];
}[];
GameModesBricks?: unknown[];
EngineModesBricks?: unknown[];
/**
* IOI typo.
*
* @deprecated
*/
EngineModessBricks?: null;
MandatoryLoadout?: unknown[];
RecommendedLoadout?: unknown[];
Bricks: string[];
VR?: VRQualityDefinition[];
GameChangers?: string[];
GameChangerReferences?: GameChanger[];
Entrances?: string[];
Stashpoints?: string[];
EnableExits?: {
$eq?: (string | boolean)[];
};
DevOnlyBricks?: string[] | null;
};
Metadata: MissionManifestMetadata;
readonly UserData?: Record<string, never> | never[];
Peacock?: {
noAgencyPickupsActive?: boolean;
noGear?: boolean;
noCarriedWeapon?: boolean;
};
SMF?: {
destinations: {
addToDestinations: boolean;
peacockIntegration?: boolean;
narrativeContext?: "Mission" | "Campaign";
placeBefore?: string;
placeAfter?: string;
};
};
}
/**
* A configuration that tells the game where it should connect to.
* This config is the first thing that the game asks for when logging in.
*/
export type ServerConnectionConfig = {
Versions: {
Name: string;
GAME_VER: string;
ISSUER_ID: string;
SERVER_VER: {
Metrics: {
MetricsServerHost: string;
};
Authentication: {
AuthenticationHost: string;
};
Configuration: {
Url: string;
AgreementUrl: string;
};
Resources: {
ResourcesServicePath: string;
};
GlobalAuthentication: {
AuthenticationHost: string;
RequestedAudience: string;
};
};
}[];
};
/**
* The format we store our locations data in, which is more concise than the
* one used by the game.
*
* @see GameLocationsData
*/
export type PeacockLocationsData = {
/**
* The parent locations.
*/
parents: Record<string, Unlockable>;
/**
* The sub-locations.
*/
children: Record<string, Unlockable>;
};
/**
* A structure representing the game's LocationsData object.
*/
export interface GameLocationsData {
Data: {
HasMore: boolean;
Page: number;
Locations: {
/**
* The contract creation contract.
*/
Contract: MissionManifest;
Location: Unlockable;
SubLocation: Unlockable;
}[];
};
}
/**
* The body sent with the CreateFromParams request from the game during the final phase of contract creation.
*
* @see ContractCreationNpcTargetPayload
*/
export interface CreateFromParamsBody {
creationData: {
Title: string;
Description: string;
ContractId: string;
ContractPublicId: string;
Targets: ContractCreationNpcTargetPayload[];
ContractConditionIds: string[];
};
}
export type SelectEntranceOrPickupData = {
Unlocked: string[];
Contract: MissionManifest;
OrderedUnlocks: Unlockable[];
UserCentric: UserCentricContract;
};
export type CompiledIoiStatemachine = unknown;
/**
* The `ChallengeProgress` data for a `challengetree` context listener.
*/
export type ChallengeProgressCTreeContextListener = {
total: number;
completed: string[] | readonly string[];
missing: number;
all: string[] | readonly string[];
count: number;
};
/**
* The `ChallengeProgress` data for a `challengecount` context listener.
*/
export type ChallengeProgressCCountContextListener = {
total: number;
count: number;
};
export type CompiledChallengeTreeCategory = {
CategoryId: string;
ChallengesCount: number;
CompletedChallengesCount: number;
CompletionData: CompletionData | Record<string, never>;
Icon: string;
Image: string;
ImageLocked?: string;
IsLocked: boolean;
Location: Unlockable | null;
Name: string;
RequiredResources: string[];
OrderIndex: number;
SwitchData: {
Data: {
CategoryData: CompiledChallengeTreeCategoryInfo;
Challenges: CompiledChallengeTreeData[];
CompletionData: CompletionData | Record<string, never>;
HasNext: boolean;
HasPrevious: boolean;
NextCategoryIcon?: string;
PreviousCategoryIcon?: string;
};
IsLeaf: boolean;
};
};
export type CompiledChallengeTreeCategoryInfo = {
Name: string;
Image: string;
Icon: string;
ChallengesCount: number;
CompletedChallengesCount: number;
};
/**
* The data for a challenge's `ChallengeProgression` field. Tells the game how
* many challenges are completed, how many are left, etc.
*/
export type ChallengeTreeWaterfallState = ChallengeProgressCTreeContextListener | ChallengeProgressCCountContextListener | null;
export type CompiledChallengeTreeData = {
CategoryName: string;
ChallengeProgress?: ChallengeTreeWaterfallState;
Completed: boolean;
CompletionData?: CompletionData;
Description: string;
DifficultyLevels?: string[];
Displayed?: boolean;
Drops?: Unlockable[];
HideProgression: boolean;
Icon: string;
Id: string;
ImageName: string;
IsLocked: boolean;
IsPlayable: boolean;
LocationId: string;
Name: string;
ParentLocationId: string;
OrderIndex: number;
Rewards: {
MasteryXP?: number;
};
Type?: string;
UserCentricContract?: UserCentricContract;
TypeHeader?: string;
TypeIcon?: string;
TypeTitle?: string;
};
export interface InclusionData {
ContractIds?: string[];
ContractTypes?: MissionType[];
Locations?: string[];
GameModes?: string[];
}
export type CompiledChallengeIngameData = {
Id: string;
GroupId?: string;
Name: string;
Type: "Hit" | string;
Description?: string;
ImageName?: string;
Definition: CompiledIoiStatemachine;
Tags?: string[];
Drops?: string[];
LastModified?: string;
PlayableSince?: string | null;
PlayableUntil?: string | null;
Xp: number;
XpModifier: unknown;
InclusionData?: InclusionData;
CrowdChoice?: {
Tag: string;
};
};
/**
* Game-facing challenge progression data.
*/
export type ChallengeProgressionData = {
ChallengeId: string;
ProfileId: string;
Completed: boolean;
Ticked?: boolean;
ETag?: string;
State: Record<string, unknown>;
CompletedAt: Date | string | null;
MustBeSaved?: boolean;
};
export interface CompiledChallengeRuntimeData {
Challenge: CompiledChallengeIngameData;
Progression: ChallengeProgressionData;
}
export type LoadoutSavingMechanism = "PROFILES" | "LEGACY";
export type ImageLoadingStrategy = "SAVEASREQUESTED" | "ONLINE" | "OFFLINE";
export type Flag = {
category?: string;
title: string;
desc: string;
possibleValues?: string[];
default: boolean | string | number;
showIngame?: boolean;
requiresGameRestart?: boolean;
requiresPeacockRestart?: boolean;
};
export type FlagSection = {
title: string;
desc: string;
flags: Record<string, Flag>;
};
export type Flags = Record<string, FlagSection>;
/**
* A "hit" object.
*/
export type Hit = {
Id: string;
UserCentricContract: UserCentricContract;
Location: Unlockable;
SubLocation?: Unlockable;
ChallengesCompleted: number;
ChallengesTotal: number;
LocationLevel: number;
LocationMaxLevel: number;
LocationCompletion: number;
LocationXPLeft: number;
LocationHideProgression: boolean;
};
/**
* A video object.
*
* @see CampaignVideo
* @see StoryData
*/
export type Video = {
VideoTitle: string;
VideoHeader: string;
VideoId: string;
Entitlements: string[];
IsLocked: boolean;
LockedReason?: string;
VideoType: string;
VideoImage: string;
RequiredResources: string[];
Data: {
DlcName: string;
DlcImage: string;
};
};
/**
* A campaign mission item.
*
* @see Hit
*/
export type CampaignMission = {
Type: "Mission";
Data: Hit;
};
/**
* A campaign video item.
*
* @see Video
*/
export type CampaignVideo = {
Type: "Video";
Data: Video;
};
export interface RegistryChallenge extends SavedChallenge {
}
/**
* An element for the game's story data.
*/
export type StoryData = CampaignMission | CampaignVideo;
/**
* A campaign object.
*/
export type Campaign = {
Name: string;
Image: string;
Type: MissionType | string;
BackgroundImage?: string | null;
StoryData: StoryData[];
Subgroups?: Campaign[];
Properties?: {
BackgroundImage?: string | null;
};
};
/**
* A loadout.
*/
export type Loadout = {
/**
* Random ID.
*
* @since Peacock v5
*/
id: string;
name: string;
data: {
[locationName: string]: GameLoadout & {
[briefcaseId: string]: string;
};
};
};
/**
* A "final" loadout (that is, close to one the game uses).
* Keep the indices in line with StashpointSlotName
*/
export type GameLoadout = {
0?: string;
1?: string;
2?: string;
3?: string;
4?: string;
5?: string;
6?: string;
};
export type LocationLoadout = {
loadout: GameLoadout;
briefcase?: {
id: string;
unlockableId: string;
};
};
/**
* The object for individual game versions' loadout profiles data.
*
* @see LoadoutFile
*/
export type LoadoutsGameVersion = {
selected: string | null;
loadouts: Loadout[];
};
/**
* The top-level format for the loadout profiles storage file.
*/
export type LoadoutFile = Record<Exclude<GameVersion, "scpc">, LoadoutsGameVersion>;
/**
* A function that generates a campaign mission object for use in the campaigns menu.
* Will throw if contract is not found.
*/
export type GenSingleMissionFunc = (contractId: string, gameVersion: GameVersion) => CampaignMission;
/**
* A function that generates a campaign video object for use in the campaigns menu.
*/
export type GenSingleVideoFunc = (videoId: string, gameVersion: GameVersion) => CampaignVideo;
/**
* A "hits category" is used to display lists of contracts in-game.
*
* @see Hit
*/
export type HitsCategoryCategory = {
Category: string;
Data: {
Type: string;
Hits: Hit[];
Page: number;
HasMore: boolean;
};
CurrentSubType: string;
};
export type PlayNextCampaignDetails = {
CampaignName: string;
ParentCampaignName?: string;
};
export type PlayNextGetCampaignsHookReturn = {
/**
* The UUID of the next contract in the campaign.
*/
nextContractId: string;
/**
* An object containing the campaign's details.
*/
campaignDetails: PlayNextCampaignDetails;
/**
* An array index for plugins to override play next tiles that Peacock
* internally added
*
* @since v6.3.0
*/
overrideIndex?: number;
};
export type SafehouseCategory = {
Category: string;
SubCategories: SafehouseCategory[] | null;
IsLeaf: boolean;
Data: null | {
Type: string;
SubType: string | undefined;
Items: {
Item: InventoryItem;
ItemDetails: {
Capabilities: [];
StatList: {
Name: string;
Ratio: unknown;
PropertyTexts: [];
}[];
};
}[];
Page: number;
HasMore: boolean;
};
};
/**
* Common type for the `Entrances` and `AgencyPickups` configs.
*/
export type SceneConfig = Record<string, string[]>;
/**
* Where a state machine's `Context` data should be stored.
*
* - For `profile`, the challenge's context data should be stored in the user's
* profile. This data will be used across hits, instead of being constrained
* to a single hit, like `Hit` is.
*
* - For `hit`, the challenge's context data should be stored with persistent
* data for the current contract. This appears to function differently when
* this is used in objectives.
*
* - For `session`, the challenge's context data should be stored on the
* contract session. When a mission is restarted, this data is not persisted,
* since that creates a new session.
*/
export type ContextScopedStorageLocation = "profile" | "hit" | "session";
/**
* Evergreen-related types
*/
export type CPDStore = Record<string, Record<string, string | number | boolean>>;
export type ContractProgressionData = Record<string, string | number | boolean>;
/** SMF's lastDeploy.json */
export type SMFLastDeploy = {
runtimePath: string;
retailPath: string;
skipIntro: boolean;
outputToSeparateDirectory: boolean;
loadOrder: string[];
modOptions: {
[modId: string]: string[];
};
outputConfigToAppDataOnDeploy: boolean;
reportErrors: boolean;
developerMode: boolean;
knownMods: string[];
platform: string;
lastServerSideStates?: {
unlockables?: Unlockable[];
contracts?: {
[k: string]: MissionManifest;
};
blobs?: Record<string, string>;
peacockPlugins?: string[];
};
};
export type OfficialSublocation = {
Location: string;
Xp: number;
ActionXp: number;
};
export type MILLocations = {
[location in `LOCATION_${string}`]: string[] | string;
};
export type MissionsInLocation = Record<GameVersion, MILLocations & {
[key: string]: MILLocations | string[];
}>;