2022-10-19 21:18:35 -04:00
|
|
|
/*
|
|
|
|
* The Peacock Project - a HITMAN server replacement.
|
2023-01-23 13:37:33 -05:00
|
|
|
* Copyright (C) 2021-2023 The Peacock Project Team
|
2022-10-19 21:18:35 -04:00
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU Affero General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
import {
|
|
|
|
ChallengeProgressionData,
|
|
|
|
CompiledChallengeRewardData,
|
|
|
|
CompiledChallengeRuntimeData,
|
|
|
|
RegistryChallenge,
|
|
|
|
} from "../types/types"
|
|
|
|
import assert from "assert"
|
|
|
|
|
|
|
|
export function compileScoringChallenge(
|
|
|
|
challenge: RegistryChallenge,
|
|
|
|
): CompiledChallengeRewardData {
|
|
|
|
return {
|
|
|
|
ChallengeId: challenge.Id,
|
|
|
|
ChallengeName: challenge.Name,
|
|
|
|
ChallengeDescription: challenge.Description,
|
|
|
|
ChallengeImageUrl: challenge.ImageName,
|
|
|
|
XPGain: challenge.Rewards?.MasteryXP || 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function compileRuntimeChallenge(
|
|
|
|
challenge: RegistryChallenge,
|
|
|
|
progression: ChallengeProgressionData,
|
|
|
|
): CompiledChallengeRuntimeData {
|
|
|
|
return {
|
|
|
|
// GetActiveChallengesAndProgression
|
|
|
|
Challenge: {
|
|
|
|
Id: challenge.Id,
|
|
|
|
GroupId: challenge.inGroup,
|
|
|
|
Name: challenge.Name,
|
|
|
|
Type: challenge.RuntimeType || "contract",
|
|
|
|
Description: challenge.Description,
|
|
|
|
ImageName: challenge.ImageName,
|
|
|
|
InclusionData: challenge.InclusionData || undefined,
|
|
|
|
Definition: challenge.Definition,
|
|
|
|
Tags: challenge.Tags,
|
|
|
|
Drops: challenge.Drops,
|
|
|
|
LastModified: "2021-01-06T23:00:32.0117635", // this is a lie 👍
|
|
|
|
PlayableSince: null,
|
|
|
|
PlayableUntil: null,
|
|
|
|
Xp: challenge.Rewards.MasteryXP || 0,
|
|
|
|
XpModifier: challenge.XpModifier || {},
|
|
|
|
},
|
|
|
|
Progression: progression,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export enum ChallengeFilterType {
|
|
|
|
None = "None",
|
|
|
|
Contract = "Contract",
|
2023-01-14 02:12:08 -05:00
|
|
|
Contracts = "Contracts",
|
2022-10-19 21:18:35 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
export type ChallengeFilterOptions =
|
|
|
|
| {
|
|
|
|
type: ChallengeFilterType.None
|
|
|
|
}
|
|
|
|
| {
|
|
|
|
type: ChallengeFilterType.Contract
|
|
|
|
contractId: string
|
|
|
|
locationId: string
|
|
|
|
}
|
2023-01-14 02:12:08 -05:00
|
|
|
| {
|
|
|
|
type: ChallengeFilterType.Contracts
|
|
|
|
contractIds: string[]
|
|
|
|
locationId: string
|
2022-10-19 21:18:35 -04:00
|
|
|
}
|
|
|
|
|
2023-02-24 11:39:55 -05:00
|
|
|
/**
|
|
|
|
* Judges whether a challenge should be included in the challenges list of a contract.
|
|
|
|
* @requires The challenge and the contract share the same parent location.
|
|
|
|
* @param contractId The id of the contract.
|
|
|
|
* @param locationId The sublocation ID of the challenge.
|
|
|
|
* @param challenge The challenge in question.
|
|
|
|
* @returns A boolean value, denoting the result.
|
|
|
|
*/
|
2023-01-14 02:12:08 -05:00
|
|
|
function isChallengeInContract(
|
|
|
|
contractId: string,
|
|
|
|
locationId: string,
|
|
|
|
challenge: RegistryChallenge,
|
2023-02-24 11:39:55 -05:00
|
|
|
): boolean {
|
2023-01-14 02:12:08 -05:00
|
|
|
assert.ok(contractId)
|
|
|
|
assert.ok(locationId)
|
|
|
|
if (!challenge) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2023-01-17 20:40:59 -05:00
|
|
|
if (
|
|
|
|
locationId === "LOCATION_HOKKAIDO_SHIM_MAMUSHI" &&
|
|
|
|
challenge.LocationId === "LOCATION_HOKKAIDO"
|
|
|
|
) {
|
|
|
|
// Special case: winter festival has its own locationId, but for Hokkaido-wide challenges,
|
|
|
|
// the locationId is "LOCATION_HOKKAIDO", not "LOCATION_PARENT_HOKKAIDO".
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2023-02-24 11:39:55 -05:00
|
|
|
// Is this for the current contract?
|
2023-01-14 02:12:08 -05:00
|
|
|
const isForContract = (challenge.InclusionData?.ContractIds || []).includes(
|
|
|
|
contractId,
|
|
|
|
)
|
|
|
|
|
2023-02-24 11:39:55 -05:00
|
|
|
// Is this a location-wide challenge?
|
|
|
|
// "location" is more widely used, but "parentlocation" is used in Ambrose and Berlin, as well as some "Discover XX" challenges.
|
2023-01-17 20:40:59 -05:00
|
|
|
const isForLocation =
|
|
|
|
challenge.Type === "location" || challenge.Type === "parentlocation"
|
2023-01-14 02:12:08 -05:00
|
|
|
|
2023-02-24 11:39:55 -05:00
|
|
|
// Is this for the current location?
|
2023-01-14 02:12:08 -05:00
|
|
|
const isCurrentLocation =
|
2023-02-24 11:39:55 -05:00
|
|
|
// Is this challenge's location one of these things:
|
|
|
|
// 1. The current sub-location, e.g. "LOCATION_COASTALTOWN_NIGHT". This is the most common.
|
|
|
|
// 2. The parent location (yup, that can happen), e.g. "LOCATION_PARENT_HOKKAIDO" in Discover Hokkaido.
|
|
|
|
challenge.LocationId === locationId ||
|
|
|
|
challenge.LocationId === challenge.ParentLocationId
|
2023-01-14 02:12:08 -05:00
|
|
|
|
|
|
|
return isForContract || (isForLocation && isCurrentLocation)
|
|
|
|
}
|
|
|
|
|
2022-10-19 21:18:35 -04:00
|
|
|
export function filterChallenge(
|
|
|
|
options: ChallengeFilterOptions,
|
|
|
|
challenge: RegistryChallenge,
|
|
|
|
): boolean {
|
|
|
|
switch (options.type) {
|
|
|
|
case ChallengeFilterType.None:
|
|
|
|
return true
|
|
|
|
case ChallengeFilterType.Contract: {
|
2023-01-14 02:12:08 -05:00
|
|
|
return isChallengeInContract(
|
|
|
|
options.contractId,
|
|
|
|
options.locationId,
|
|
|
|
challenge,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
case ChallengeFilterType.Contracts: {
|
|
|
|
return options.contractIds.some((contractId) =>
|
|
|
|
isChallengeInContract(
|
|
|
|
contractId,
|
|
|
|
options.locationId,
|
|
|
|
challenge,
|
|
|
|
),
|
|
|
|
)
|
2022-10-19 21:18:35 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|