Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Mission Story Progression #68

Merged
merged 17 commits into from
Jan 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions components/configSwizzleManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -122,7 +121,6 @@ const configs: Record<string, unknown> = {
LeaderboardEntriesTemplate,
GameChangerProperties,
allunlockables,
Destinations,
config: connectionConfigTemplate,
onlineconfig,
privacypolicy,
Expand Down
37 changes: 25 additions & 12 deletions components/eventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -53,6 +58,7 @@ import {
KillC2SEvent,
MurderedBodySeenC2SEvent,
ObjectiveCompletedC2SEvent,
OpportunityEventsC2SEvent,
PacifyC2SEvent,
SecuritySystemRecorderC2SEvent,
SetpiecesC2SEvent,
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
moonysolari marked this conversation as resolved.
Show resolved Hide resolved
}
writeUserData(req.jwt.unique_name, req.gameVersion)
break
}
// We don't care about events below this point.
case "ItemPickedUp":
log(
LogLevel.INFO,
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down
36 changes: 15 additions & 21 deletions components/menuData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"
Expand All @@ -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:
Expand Down Expand Up @@ -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.")
Expand Down
76 changes: 45 additions & 31 deletions components/menus/destinations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -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++
}
}

export function destinationsMenu(req: RequestWithJwt): GameFacingDestination[] {
const destinations = getVersionedConfig<DestinationsMenuDataObject[]>(
"Destinations",
req.gameVersion,
false,
)
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 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"

const template = {
ChallengeCompletion: {
ChallengesCount: 0,
CompletedChallengesCount: 0, // TODO: Hook this up to challenge counts.
"UI_LOCATION_PARENT_" + destination.substring(16) + "_NAME"

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)
}

Expand Down
8 changes: 6 additions & 2 deletions components/menus/planning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
)
Expand All @@ -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,
Expand Down
19 changes: 15 additions & 4 deletions components/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -361,6 +372,9 @@ export interface UserProfile {
__stats?: unknown
PersistentBool: Record<string, unknown>
}
opportunityprogression: {
[opportunityId: RepositoryId]: boolean
}
}
ETag: string | null
Gamertag: string
Expand Down Expand Up @@ -401,6 +415,7 @@ export interface NamespaceEntitlementEpic {
*/
export interface Unlockable {
Id: string
Opportunities?: number
DisplayNameLocKey: string
GameAsset: string | null
Guid: string
Expand Down Expand Up @@ -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.
Expand Down
Loading