feat: conquest progression & rewards (#1791)
Closes #1570 Co-authored-by: Jānis <janisslsm@noreply.localhost> Reviewed-on: #1791 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
parent
ce5b0fc9e2
commit
15aaa28a4f
8
package-lock.json
generated
8
package-lock.json
generated
@ -18,7 +18,7 @@
|
||||
"morgan": "^1.10.0",
|
||||
"ncp": "^2.0.0",
|
||||
"typescript": "^5.5",
|
||||
"warframe-public-export-plus": "^0.5.56",
|
||||
"warframe-public-export-plus": "^0.5.57",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
@ -3789,9 +3789,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/warframe-public-export-plus": {
|
||||
"version": "0.5.56",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.56.tgz",
|
||||
"integrity": "sha512-px+J7tUm6fkSzwKkvL73ySQReDq9oM1UrHSLM3vbYGBvELM892iBgPYG45okIhScCSdwmmXTiWZTf4x/I4qiNQ=="
|
||||
"version": "0.5.57",
|
||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.57.tgz",
|
||||
"integrity": "sha512-CKbg7/2hSDH7I7yYSWwkrP4N2rEAEK1vNEuehj+RD9vMvl1c4u6klHLMwdh+ULxXiW4djWIlNIhs5bi/fm58Mg=="
|
||||
},
|
||||
"node_modules/warframe-riven-info": {
|
||||
"version": "0.1.2",
|
||||
|
@ -25,7 +25,7 @@
|
||||
"morgan": "^1.10.0",
|
||||
"ncp": "^2.0.0",
|
||||
"typescript": "^5.5",
|
||||
"warframe-public-export-plus": "^0.5.56",
|
||||
"warframe-public-export-plus": "^0.5.57",
|
||||
"warframe-riven-info": "^0.1.2",
|
||||
"winston": "^3.17.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
|
@ -21,10 +21,12 @@ export const entratiLabConquestModeController: RequestHandler = async (req, res)
|
||||
inventory.EntratiVaultCountResetDate = new Date(weekEnd);
|
||||
if (inventory.EntratiLabConquestUnlocked) {
|
||||
inventory.EntratiLabConquestUnlocked = 0;
|
||||
inventory.EntratiLabConquestCacheScoreMission = 0;
|
||||
inventory.EntratiLabConquestActiveFrameVariants = [];
|
||||
}
|
||||
if (inventory.EchoesHexConquestUnlocked) {
|
||||
inventory.EchoesHexConquestUnlocked = 0;
|
||||
inventory.EchoesHexConquestCacheScoreMission = 0;
|
||||
inventory.EchoesHexConquestActiveFrameVariants = [];
|
||||
inventory.EchoesHexConquestActiveStickers = [];
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import { addMissionInventoryUpdates, addMissionRewards } from "@/src/services/mi
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getInventoryResponse } from "./inventoryController";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { IMissionInventoryUpdateResponse } from "@/src/types/missionTypes";
|
||||
|
||||
/*
|
||||
**** INPUT ****
|
||||
@ -71,8 +72,14 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
||||
return;
|
||||
}
|
||||
|
||||
const { MissionRewards, inventoryChanges, credits, AffiliationMods, SyndicateXPItemReward } =
|
||||
await addMissionRewards(inventory, missionReport, firstCompletion);
|
||||
const {
|
||||
MissionRewards,
|
||||
inventoryChanges,
|
||||
credits,
|
||||
AffiliationMods,
|
||||
SyndicateXPItemReward,
|
||||
ConquestCompletedMissionsCount
|
||||
} = await addMissionRewards(inventory, missionReport, firstCompletion);
|
||||
|
||||
await inventory.save();
|
||||
const inventoryResponse = await getInventoryResponse(inventory, true);
|
||||
@ -86,8 +93,9 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
||||
...inventoryUpdates,
|
||||
//FusionPoints: inventoryChanges?.FusionPoints, // This in combination with InventoryJson or InventoryChanges seems to just double the number of endo shown, so unsure when this is needed.
|
||||
SyndicateXPItemReward,
|
||||
AffiliationMods
|
||||
});
|
||||
AffiliationMods,
|
||||
ConquestCompletedMissionsCount
|
||||
} satisfies IMissionInventoryUpdateResponse);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -43,7 +43,7 @@ import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/invento
|
||||
import { getEntriesUnsafe } from "@/src/utils/ts-utils";
|
||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||
import { handleStoreItemAcquisition } from "./purchaseService";
|
||||
import { IMissionReward } from "../types/missionTypes";
|
||||
import { IMissionCredits, IMissionReward } from "../types/missionTypes";
|
||||
import { crackRelic } from "@/src/helpers/relicHelper";
|
||||
import { createMessage } from "./inboxService";
|
||||
import kuriaMessage50 from "@/static/fixed_responses/kuriaMessages/fiftyPercent.json";
|
||||
@ -586,8 +586,140 @@ interface AddMissionRewardsReturnType {
|
||||
credits?: IMissionCredits;
|
||||
AffiliationMods?: IAffiliationMods[];
|
||||
SyndicateXPItemReward?: number;
|
||||
ConquestCompletedMissionsCount?: number;
|
||||
}
|
||||
|
||||
interface IConquestReward {
|
||||
at: number;
|
||||
pool: IRngResult[];
|
||||
}
|
||||
|
||||
const labConquestRewards: IConquestReward[] = [
|
||||
{
|
||||
at: 5,
|
||||
pool: ExportRewards[
|
||||
"/Lotus/Types/Game/MissionDecks/EntratiLabConquestRewards/EntratiLabConquestSilverRewards"
|
||||
][0] as IRngResult[]
|
||||
},
|
||||
{
|
||||
at: 10,
|
||||
pool: ExportRewards[
|
||||
"/Lotus/Types/Game/MissionDecks/EntratiLabConquestRewards/EntratiLabConquestSilverRewards"
|
||||
][0] as IRngResult[]
|
||||
},
|
||||
{
|
||||
at: 15,
|
||||
pool: [
|
||||
{
|
||||
type: "/Lotus/StoreItems/Types/Gameplay/EntratiLab/Resources/EntratiLanthornBundle",
|
||||
itemCount: 3,
|
||||
probability: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
at: 20,
|
||||
pool: ExportRewards[
|
||||
"/Lotus/Types/Game/MissionDecks/EntratiLabConquestRewards/EntratiLabConquestGoldRewards"
|
||||
][0] as IRngResult[]
|
||||
},
|
||||
{
|
||||
at: 28,
|
||||
pool: [
|
||||
{
|
||||
type: "/Lotus/StoreItems/Types/Items/MiscItems/DistillPoints",
|
||||
itemCount: 20,
|
||||
probability: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
at: 31,
|
||||
pool: ExportRewards[
|
||||
"/Lotus/Types/Game/MissionDecks/EntratiLabConquestRewards/EntratiLabConquestGoldRewards"
|
||||
][0] as IRngResult[]
|
||||
},
|
||||
{
|
||||
at: 34,
|
||||
pool: ExportRewards[
|
||||
"/Lotus/Types/Game/MissionDecks/EntratiLabConquestRewards/EntratiLabConquestArcaneRewards"
|
||||
][0] as IRngResult[]
|
||||
},
|
||||
{
|
||||
at: 37,
|
||||
pool: [
|
||||
{
|
||||
type: "/Lotus/StoreItems/Types/Items/MiscItems/DistillPoints",
|
||||
itemCount: 50,
|
||||
probability: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const hexConquestRewards: IConquestReward[] = [
|
||||
{
|
||||
at: 5,
|
||||
pool: ExportRewards[
|
||||
"/Lotus/Types/Game/MissionDecks/1999ConquestRewards/1999ConquestSilverRewards"
|
||||
][0] as IRngResult[]
|
||||
},
|
||||
{
|
||||
at: 10,
|
||||
pool: ExportRewards[
|
||||
"/Lotus/Types/Game/MissionDecks/1999ConquestRewards/1999ConquestSilverRewards"
|
||||
][0] as IRngResult[]
|
||||
},
|
||||
{
|
||||
at: 15,
|
||||
pool: [
|
||||
{
|
||||
type: "/Lotus/StoreItems/Types/BoosterPacks/1999StickersPackEchoesArchimedea",
|
||||
itemCount: 1,
|
||||
probability: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
at: 20,
|
||||
pool: ExportRewards[
|
||||
"/Lotus/Types/Game/MissionDecks/1999ConquestRewards/1999ConquestGoldRewards"
|
||||
][0] as IRngResult[]
|
||||
},
|
||||
{
|
||||
at: 28,
|
||||
pool: [
|
||||
{
|
||||
type: "/Lotus/StoreItems/Types/Items/MiscItems/1999ConquestBucks",
|
||||
itemCount: 6,
|
||||
probability: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
at: 31,
|
||||
pool: ExportRewards[
|
||||
"/Lotus/Types/Game/MissionDecks/1999ConquestRewards/1999ConquestGoldRewards"
|
||||
][0] as IRngResult[]
|
||||
},
|
||||
{
|
||||
at: 34,
|
||||
pool: ExportRewards[
|
||||
"/Lotus/Types/Game/MissionDecks/1999ConquestRewards/1999ConquestArcaneRewards"
|
||||
][0] as IRngResult[]
|
||||
},
|
||||
{
|
||||
at: 37,
|
||||
pool: [
|
||||
{
|
||||
type: "/Lotus/StoreItems/Types/Items/MiscItems/1999ConquestBucks",
|
||||
itemCount: 9,
|
||||
probability: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
//TODO: return type of partial missioninventoryupdate response
|
||||
export const addMissionRewards = async (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
@ -620,6 +752,7 @@ export const addMissionRewards = async (
|
||||
const inventoryChanges: IInventoryChanges = {};
|
||||
const AffiliationMods: IAffiliationMods[] = [];
|
||||
let SyndicateXPItemReward;
|
||||
let ConquestCompletedMissionsCount;
|
||||
|
||||
let missionCompletionCredits = 0;
|
||||
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
|
||||
@ -691,6 +824,62 @@ export const addMissionRewards = async (
|
||||
});
|
||||
}
|
||||
|
||||
if (rewardInfo.ConquestCompleted !== undefined) {
|
||||
let score = 1;
|
||||
if (rewardInfo.ConquestHardModeActive === 1) score += 3;
|
||||
|
||||
if (rewardInfo.ConquestPersonalModifiersActive !== undefined)
|
||||
score += rewardInfo.ConquestPersonalModifiersActive;
|
||||
if (rewardInfo.ConquestEquipmentSuggestionsFulfilled !== undefined)
|
||||
score += rewardInfo.ConquestEquipmentSuggestionsFulfilled;
|
||||
|
||||
score *= rewardInfo.ConquestCompleted + 1;
|
||||
|
||||
if (rewardInfo.ConquestCompleted == 2 && rewardInfo.ConquestHardModeActive === 1) score += 1;
|
||||
|
||||
logger.debug(`completed conquest mission ${rewardInfo.ConquestCompleted + 1} for a score of ${score}`);
|
||||
|
||||
const conquestType = rewardInfo.ConquestType;
|
||||
const conquestNode =
|
||||
conquestType == "HexConquest" ? "EchoesHexConquestHardModeUnlocked" : "EntratiLabConquestHardModeUnlocked";
|
||||
if (score >= 25 && inventory.NodeIntrosCompleted.indexOf(conquestNode) == -1)
|
||||
inventory.NodeIntrosCompleted.push(conquestNode);
|
||||
|
||||
if (conquestType == "HexConquest") {
|
||||
inventory.EchoesHexConquestCacheScoreMission ??= 0;
|
||||
if (score > inventory.EchoesHexConquestCacheScoreMission) {
|
||||
for (const reward of hexConquestRewards) {
|
||||
if (score >= reward.at && inventory.EchoesHexConquestCacheScoreMission < reward.at) {
|
||||
const rolled = getRandomReward(reward.pool)!;
|
||||
logger.debug(`rolled hex conquest reward for reaching ${reward.at} points`, rolled);
|
||||
MissionRewards.push({
|
||||
StoreItem: rolled.type,
|
||||
ItemCount: rolled.itemCount
|
||||
});
|
||||
}
|
||||
}
|
||||
inventory.EchoesHexConquestCacheScoreMission = score;
|
||||
}
|
||||
} else {
|
||||
inventory.EntratiLabConquestCacheScoreMission ??= 0;
|
||||
if (score > inventory.EntratiLabConquestCacheScoreMission) {
|
||||
for (const reward of labConquestRewards) {
|
||||
if (score >= reward.at && inventory.EntratiLabConquestCacheScoreMission < reward.at) {
|
||||
const rolled = getRandomReward(reward.pool)!;
|
||||
logger.debug(`rolled lab conquest reward for reaching ${reward.at} points`, rolled);
|
||||
MissionRewards.push({
|
||||
StoreItem: rolled.type,
|
||||
ItemCount: rolled.itemCount
|
||||
});
|
||||
}
|
||||
}
|
||||
inventory.EntratiLabConquestCacheScoreMission = score;
|
||||
}
|
||||
}
|
||||
|
||||
ConquestCompletedMissionsCount = rewardInfo.ConquestCompleted == 2 ? 0 : rewardInfo.ConquestCompleted + 1;
|
||||
}
|
||||
|
||||
for (const reward of MissionRewards) {
|
||||
const inventoryChange = await handleStoreItemAcquisition(
|
||||
reward.StoreItem,
|
||||
@ -882,16 +1071,16 @@ export const addMissionRewards = async (
|
||||
}
|
||||
}
|
||||
|
||||
return { inventoryChanges, MissionRewards, credits, AffiliationMods, SyndicateXPItemReward };
|
||||
return {
|
||||
inventoryChanges,
|
||||
MissionRewards,
|
||||
credits,
|
||||
AffiliationMods,
|
||||
SyndicateXPItemReward,
|
||||
ConquestCompletedMissionsCount
|
||||
};
|
||||
};
|
||||
|
||||
interface IMissionCredits {
|
||||
MissionCredits: number[];
|
||||
CreditBonus: number[];
|
||||
TotalCredits: number[];
|
||||
DailyMissionBonus?: boolean;
|
||||
}
|
||||
|
||||
//creditBonus is not entirely accurate.
|
||||
//TODO: consider ActiveBoosters
|
||||
export const addCredits = (
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { IAffiliationMods, IInventoryChanges } from "./purchaseTypes";
|
||||
|
||||
export const inventoryFields = ["RawUpgrades", "MiscItems", "Consumables", "Recipes"] as const;
|
||||
export type IInventoryFieldType = (typeof inventoryFields)[number];
|
||||
|
||||
@ -11,3 +13,20 @@ export interface IMissionReward {
|
||||
FromEnemyCache?: boolean;
|
||||
IsStrippedItem?: boolean;
|
||||
}
|
||||
|
||||
export interface IMissionCredits {
|
||||
MissionCredits: number[];
|
||||
CreditBonus: number[];
|
||||
TotalCredits: number[];
|
||||
DailyMissionBonus?: boolean;
|
||||
}
|
||||
|
||||
export interface IMissionInventoryUpdateResponse extends Partial<IMissionCredits> {
|
||||
ConquestCompletedMissionsCount?: number;
|
||||
InventoryJson?: string;
|
||||
MissionRewards?: IMissionReward[];
|
||||
InventoryChanges?: IInventoryChanges;
|
||||
FusionPoints?: number;
|
||||
SyndicateXPItemReward?: number;
|
||||
AffiliationMods?: IAffiliationMods[];
|
||||
}
|
||||
|
@ -125,6 +125,7 @@ export type IMissionInventoryUpdateRequest = {
|
||||
wagerTier?: number; // the index
|
||||
creditsFee?: number; // the index
|
||||
InvasionProgress?: IInvasionProgressClient[];
|
||||
ConquestMissionsCompleted?: number;
|
||||
} & {
|
||||
[K in TEquipmentKey]?: IEquipmentClient[];
|
||||
};
|
||||
@ -150,7 +151,12 @@ export interface IRewardInfo {
|
||||
PurgatoryRewardQualifications?: string;
|
||||
rewardSeed?: number | bigint;
|
||||
periodicMissionTag?: string;
|
||||
|
||||
ConquestType?: string;
|
||||
ConquestCompleted?: number;
|
||||
ConquestEquipmentSuggestionsFulfilled?: number;
|
||||
ConquestPersonalModifiersActive?: number;
|
||||
ConquestStickersActive?: number;
|
||||
ConquestHardModeActive?: number;
|
||||
// for bounties, only EOM_AFK and node are given from above, plus:
|
||||
JobTier?: number;
|
||||
jobId?: string;
|
||||
|
Loading…
x
Reference in New Issue
Block a user