1
mirror of https://github.com/thepeacockproject/Peacock synced 2025-02-23 03:35:25 +01:00

Added Mission Story Progression ()

This commit is contained in:
moonysolari 2023-01-06 21:15:14 -05:00 committed by GitHub
parent 2ed110a703
commit f3803be4ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 466 additions and 317 deletions

@ -29,7 +29,6 @@ import FilterData from "../static/FilterData.json"
import LocationsData from "../static/LocationsData.json"
import GameChangerProperties from "../static/GameChangerProperties.json"
import allunlockables from "../static/allunlockables.json"
import Destinations from "../static/Destinations.json"
import connectionConfigTemplate from "../static/config.json"
import onlineconfig from "../static/onlineconfig.json"
import privacypolicy from "../static/privacypolicy.json"
@ -122,7 +121,6 @@ const configs: Record<string, unknown> = {
LeaderboardEntriesTemplate,
GameChangerProperties,
allunlockables,
Destinations,
config: connectionConfigTemplate,
onlineconfig,
privacypolicy,

@ -33,7 +33,12 @@ import {
import { extractToken, ServerVer } from "./utils"
import { json as jsonMiddleware } from "body-parser"
import { log, LogLevel } from "./loggingInterop"
import { getContractSession, writeContractSession } from "./databaseHandler"
import {
getContractSession,
getUserData,
writeContractSession,
writeUserData,
} from "./databaseHandler"
import { controller } from "./controller"
import { swapToLocationStatus } from "./discordRp"
import { randomUUID } from "crypto"
@ -53,6 +58,7 @@ import {
KillC2SEvent,
MurderedBodySeenC2SEvent,
ObjectiveCompletedC2SEvent,
OpportunityEventsC2SEvent,
PacifyC2SEvent,
SecuritySystemRecorderC2SEvent,
SetpiecesC2SEvent,
@ -458,7 +464,7 @@ function saveEvents(
): string[] {
const response: string[] = []
const processed: string[] = []
const userData = getUserData(req.jwt.unique_name, req.gameVersion)
events.forEach((event) => {
const session = contractSessions.get(event.ContractSessionId)
@ -719,6 +725,23 @@ function saveEvents(
}
break
}
case "StartingSuit":
session.currentDisguise = event.Value as string
break
case "ContractFailed":
session.timerEnd = event.Timestamp
contractFailed(event, session)
break
case "OpportunityEvents": {
const val = (<OpportunityEventsC2SEvent>event).Value
const opportunities = userData.Extensions.opportunityprogression
if (val.Event === "Completed") {
opportunities[val.RepositoryId] = true
}
writeUserData(req.jwt.unique_name, req.gameVersion)
break
}
// We don't care about events below this point.
case "ItemPickedUp":
log(
LogLevel.INFO,
@ -727,13 +750,6 @@ function saveEvents(
}`,
)
break
case "StartingSuit":
session.currentDisguise = event.Value as string
break
case "ContractFailed":
session.timerEnd = event.Timestamp
contractFailed(event, session)
break
case "setpieces":
log(
LogLevel.DEBUG,
@ -762,10 +778,7 @@ function saveEvents(
case "NPC_Distracted":
case "ShotsHit":
case "FirstNonHeadshot":
case "OpportunityEvents":
case "FirstMissedShot":
// we don't care about these
break
default:
// no-op on our part
break

@ -33,7 +33,11 @@ import {
peacockRecentEscalations,
} from "./controller"
import { makeCampaigns } from "./menus/campaigns"
import { createLocationsData, destinationsMenu } from "./menus/destinations"
import {
createLocationsData,
destinationsMenu,
getDestinationCompletion,
} from "./menus/destinations"
import type {
CommonSelectScreenConfig,
HitsCategoryCategory,
@ -800,6 +804,14 @@ menuDataRouter.get(
(req: RequestWithJwt<{ locationId: string; difficulty?: string }>, res) => {
const LOCATION = req.query.locationId
const locData = getVersionedConfig<PeacockLocationsData>(
"LocationsData",
req.gameVersion,
false,
)
const locationData = locData.parents[LOCATION]
const response = {
template:
req.gameVersion === "h1"
@ -808,17 +820,8 @@ menuDataRouter.get(
data: {
Location: {},
MissionData: {
Location: {},
SubLocationMissionsData: [],
ChallengeCompletion: {
ChallengesCount: 0,
CompletedChallengesCount: 0,
},
OpportunityStatistics: {
Count: 0,
Completed: 0,
},
LocationCompletionPercent: 0,
...getDestinationCompletion(locationData, req),
...{ SubLocationMissionsData: [] },
},
ChallengeData: {
Children:
@ -854,20 +857,11 @@ menuDataRouter.get(
log(LogLevel.DEBUG, `Looking up locations details for ${LOCATION}.`)
}
const locData = getVersionedConfig<PeacockLocationsData>(
"LocationsData",
req.gameVersion,
false,
)
const locationData = locData.parents[LOCATION]
const sublocationsData = Object.values(locData.children).filter(
(subLocation) => subLocation.Properties.ParentLocation === LOCATION,
)
response.data.Location = locationData
response.data.MissionData.Location = locationData
if (req.query.difficulty === "pro1") {
log(LogLevel.DEBUG, "Adjusting for legacy-pro1.")

@ -16,18 +16,19 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { getVersionedConfig } from "../configSwizzleManager"
import { getConfig, getVersionedConfig } from "../configSwizzleManager"
import type {
CompletionData,
DestinationsMenuDataObject,
GameLocationsData,
GameVersion,
MissionStory,
PeacockLocationsData,
RequestWithJwt,
Unlockable,
} from "../types/types"
import { controller } from "../controller"
import { generateCompletionData } from "../contracts/dataGen"
import { getUserData } from "components/databaseHandler"
type GameFacingDestination = {
ChallengeCompletion: {
@ -42,47 +43,60 @@ type GameFacingDestination = {
LocationCompletionPercent: number
Location: Unlockable
}
const missionStories = getConfig<Record<string, MissionStory>>(
"MissionStories",
false,
)
export function getDestinationCompletion(
parent: Unlockable,
req: RequestWithJwt,
) {
const userData = getUserData(req.jwt.unique_name, req.gameVersion)
let opportunityCompletedCount = 0
for (const ms in userData.Extensions.opportunityprogression) {
if (missionStories[ms].Location === parent.Id) {
opportunityCompletedCount++
}
}
return {
ChallengeCompletion: {
ChallengesCount: 0,
CompletedChallengesCount: 0, // TODO: Hook this up to challenge counts.
},
OpportunityStatistics: {
Count: parent.Opportunities,
Completed: opportunityCompletedCount,
},
LocationCompletionPercent: 0,
Location: parent,
}
}
export function destinationsMenu(req: RequestWithJwt): GameFacingDestination[] {
const destinations = getVersionedConfig<DestinationsMenuDataObject[]>(
"Destinations",
req.gameVersion,
false,
)
const result: GameFacingDestination[] = []
const locations = getVersionedConfig<PeacockLocationsData>(
"LocationsData",
req.gameVersion,
true,
)
for (const destination of destinations) {
const parent = locations.parents[destination.ParentId]
for (const [destination, parent] of Object.entries(locations.parents)) {
parent.GameAsset = null
parent.DisplayNameLocKey =
"UI_LOCATION_PARENT_" + destination.ParentId.substring(16) + "_NAME"
"UI_LOCATION_PARENT_" + destination.substring(16) + "_NAME"
const template = {
ChallengeCompletion: {
ChallengesCount: 0,
CompletedChallengesCount: 0, // TODO: Hook this up to challenge counts.
const template: GameFacingDestination = {
...getDestinationCompletion(parent, req),
...{
CompletionData: generateCompletionData(
destination,
req.jwt.unique_name,
req.gameVersion,
),
},
CompletionData: generateCompletionData(
destination.ParentId,
req.jwt.unique_name,
req.gameVersion,
),
OpportunityStatistics: {
Count: 0,
Completed: 0,
},
LocationCompletionPercent: 0,
Location: parent,
}
result.push(template)
}

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import type { RequestWithJwt, SceneConfig } from "../types/types"
import type { MissionStory, RequestWithJwt, SceneConfig } from "../types/types"
import { log, LogLevel } from "../loggingInterop"
import { _legacyBull, _theLastYardbirdScpc, controller } from "../controller"
import {
@ -52,7 +52,7 @@ export async function planningView(
}
const entranceData = getConfig<SceneConfig>("Entrances", false)
const missionStories = getConfig<Record<string, unknown>>(
const missionStories = getConfig<Record<string, MissionStory>>(
"MissionStories",
false,
)
@ -61,6 +61,10 @@ export async function planningView(
const isForReset = req.query.resetescalation === "true"
for (const ms in userData.Extensions.opportunityprogression) {
missionStories[ms].PreviouslyCompleted = true
}
if (isForReset) {
const escalationGroupId = contractIdToEscalationGroupId(
req.query.contractid,

@ -310,6 +310,17 @@ export interface ServerToClientEvent<EventValue = unknown> {
Origin?: string | null
}
export interface MissionStory {
CommonRepositoryId: RepositoryId
PreviouslyCompleted: boolean
IsMainOpportunity: boolean
Title: string
Summary: string
Briefing: string
Location: string
Image: string
}
export interface UserProfile {
Id: string
LinkedAccounts: {
@ -361,6 +372,9 @@ export interface UserProfile {
__stats?: unknown
PersistentBool: Record<string, unknown>
}
opportunityprogression: {
[opportunityId: RepositoryId]: boolean
}
}
ETag: string | null
Gamertag: string
@ -401,6 +415,7 @@ export interface NamespaceEntitlementEpic {
*/
export interface Unlockable {
Id: string
Opportunities?: number
DisplayNameLocKey: string
GameAsset: string | null
Guid: string
@ -805,10 +820,6 @@ export interface MissionManifest {
}
}
export type DestinationsMenuDataObject = {
ParentId: 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.

@ -84,44 +84,44 @@ export async function packContractsAndChallenges() {
continue
}
// dev scope
if (json.Metadata.PublicId?.startsWith("0")) {
delete json.Metadata.PublicId
}
if (json.Metadata.LastUpdate) {
delete json.Metadata.LastUpdate
}
if (json.Metadata.Release) {
delete json.Metadata.Release
}
if (json.Metadata.ServerVersion) {
delete json.Metadata.ServerVersion
}
if (json.Metadata.GameVersion) {
delete json.Metadata.GameVersion
}
if (json.Metadata.CreationTimestamp) {
delete json.Metadata.CreationTimestamp
}
if (json.Metadata.CodeName_Hint) {
delete json.Metadata.CodeName_Hint
}
switch (json?.Metadata?.Type) {
case "elusive":
el.push(json)
break
default:
b.push(json)
}
// dev scope
if (json.Metadata.PublicId?.startsWith("0")) {
delete json.Metadata.PublicId
}
if (json.Metadata.LastUpdate) {
delete json.Metadata.LastUpdate
}
if (json.Metadata.Release) {
delete json.Metadata.Release
}
if (json.Metadata.ServerVersion) {
delete json.Metadata.ServerVersion
}
if (json.Metadata.GameVersion) {
delete json.Metadata.GameVersion
}
if (json.Metadata.CreationTimestamp) {
delete json.Metadata.CreationTimestamp
}
if (json.Metadata.CodeName_Hint) {
delete json.Metadata.CodeName_Hint
}
switch (json?.Metadata?.Type) {
case "elusive":
el.push(json)
break
default:
b.push(json)
}
}
const d = JSON.stringify({ b, el })
const compressed = await promisify(brotliCompress)(d)
await writeFile("resources/contracts.br", compressed)

@ -1,98 +0,0 @@
[
{
"ParentId": "LOCATION_PARENT_ICA_FACILITY",
"Opportunities": 4
},
{
"ParentId": "LOCATION_PARENT_PARIS",
"Opportunities": 8
},
{
"ParentId": "LOCATION_PARENT_COASTALTOWN",
"Opportunities": 19
},
{
"ParentId": "LOCATION_PARENT_MARRAKECH",
"Opportunities": 12
},
{
"ParentId": "LOCATION_PARENT_BANGKOK",
"Opportunities": 8
},
{
"ParentId": "LOCATION_PARENT_COLORADO",
"Opportunities": 6
},
{
"ParentId": "LOCATION_PARENT_HOKKAIDO",
"Opportunities": 7
},
{
"ParentId": "LOCATION_PARENT_NEWZEALAND"
},
{
"ParentId": "LOCATION_PARENT_MIAMI",
"Opportunities": 7
},
{
"ParentId": "LOCATION_PARENT_COLOMBIA",
"Opportunities": 7
},
{
"ParentId": "LOCATION_PARENT_MUMBAI",
"Opportunities": 7
},
{
"ParentId": "LOCATION_PARENT_NORTHAMERICA",
"Opportunities": 7
},
{
"ParentId": "LOCATION_PARENT_NORTHSEA",
"Opportunities": 6
},
{
"ParentId": "LOCATION_PARENT_GREEDY",
"Opportunities": 5
},
{
"ParentId": "LOCATION_PARENT_OPULENT",
"Opportunities": 5
},
{
"ParentId": "LOCATION_PARENT_AUSTRIA",
"SubLocationId": "LOCATION_AUSTRIA"
},
{
"ParentId": "LOCATION_PARENT_SALTY",
"SubLocationId": "LOCATION_SALTY_SEAGULL"
},
{
"ParentId": "LOCATION_PARENT_CAGED",
"SubLocationId": "LOCATION_CAGED_FALCON"
},
{
"ParentId": "LOCATION_PARENT_GOLDEN",
"Opportunities": 3
},
{
"ParentId": "LOCATION_PARENT_ANCESTRAL",
"Opportunities": 3
},
{
"ParentId": "LOCATION_PARENT_EDGY"
},
{
"ParentId": "LOCATION_PARENT_WET",
"Opportunities": 3
},
{
"ParentId": "LOCATION_PARENT_ELEGANT",
"Opportunities": 3
},
{
"ParentId": "LOCATION_PARENT_TRAPPED"
},
{
"ParentId": "LOCATION_PARENT_ROCKY"
}
]

@ -2,6 +2,7 @@
"parents": {
"LOCATION_PARENT_ICA_FACILITY": {
"Id": "LOCATION_PARENT_ICA_FACILITY",
"Opportunities": 4,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -34,6 +35,7 @@
},
"LOCATION_PARENT_PARIS": {
"Id": "LOCATION_PARENT_PARIS",
"Opportunities": 8,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -67,6 +69,7 @@
},
"LOCATION_PARENT_COASTALTOWN": {
"Id": "LOCATION_PARENT_COASTALTOWN",
"Opportunities": 19,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -99,6 +102,7 @@
},
"LOCATION_PARENT_MARRAKECH": {
"Id": "LOCATION_PARENT_MARRAKECH",
"Opportunities": 12,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -131,6 +135,7 @@
},
"LOCATION_PARENT_BANGKOK": {
"Id": "LOCATION_PARENT_BANGKOK",
"Opportunities": 8,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -165,6 +170,7 @@
},
"LOCATION_PARENT_COLORADO": {
"Id": "LOCATION_PARENT_COLORADO",
"Opportunities": 6,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -199,6 +205,7 @@
},
"LOCATION_PARENT_HOKKAIDO": {
"Id": "LOCATION_PARENT_HOKKAIDO",
"Opportunities": 7,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -269,6 +276,7 @@
},
"LOCATION_PARENT_MIAMI": {
"Id": "LOCATION_PARENT_MIAMI",
"Opportunities": 7,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -306,6 +314,7 @@
},
"LOCATION_PARENT_COLOMBIA": {
"Id": "LOCATION_PARENT_COLOMBIA",
"Opportunities": 7,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -342,6 +351,7 @@
},
"LOCATION_PARENT_MUMBAI": {
"Id": "LOCATION_PARENT_MUMBAI",
"Opportunities": 7,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -378,6 +388,7 @@
},
"LOCATION_PARENT_NORTHAMERICA": {
"Id": "LOCATION_PARENT_NORTHAMERICA",
"Opportunities": 7,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -411,6 +422,7 @@
},
"LOCATION_PARENT_NORTHSEA": {
"Id": "LOCATION_PARENT_NORTHSEA",
"Opportunities": 6,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -444,6 +456,7 @@
},
"LOCATION_PARENT_GREEDY": {
"Id": "LOCATION_PARENT_GREEDY",
"Opportunities": 5,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -480,6 +493,7 @@
},
"LOCATION_PARENT_OPULENT": {
"Id": "LOCATION_PARENT_OPULENT",
"Opportunities": 5,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -516,6 +530,7 @@
},
"LOCATION_PARENT_GOLDEN": {
"Id": "LOCATION_PARENT_GOLDEN",
"Opportunities": 3,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -572,6 +587,7 @@
"Rarity": null,
"DisplayNameLocKey": "UI_LOCATION_PARENT_ANCESTRAL_NAME",
"Id": "LOCATION_PARENT_ANCESTRAL",
"Opportunities": 3,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -623,6 +639,7 @@
},
"LOCATION_PARENT_WET": {
"Id": "LOCATION_PARENT_WET",
"Opportunities": 3,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -659,6 +676,7 @@
},
"LOCATION_PARENT_ELEGANT": {
"Id": "LOCATION_PARENT_ELEGANT",
"Opportunities": 3,
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -767,6 +785,7 @@
},
"LOCATION_PARENT_AUSTRIA": {
"Id": "LOCATION_PARENT_AUSTRIA",
"SubLocationId": "LOCATION_AUSTRIA",
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -800,6 +819,7 @@
},
"LOCATION_PARENT_SALTY": {
"Id": "LOCATION_PARENT_SALTY",
"SubLocationId": "LOCATION_SALTY_SEAGULL",
"Type": "location",
"Subtype": "location",
"GameAsset": null,
@ -833,6 +853,7 @@
},
"LOCATION_PARENT_CAGED": {
"Id": "LOCATION_PARENT_CAGED",
"SubLocationId": "LOCATION_CAGED_FALCON",
"Type": "location",
"Subtype": "location",
"GameAsset": null,

File diff suppressed because it is too large Load Diff