fix and update quest system

This commit is contained in:
Master 2024-06-25 08:52:35 +08:00
parent 1161988ca4
commit 7bf1708474
9 changed files with 193 additions and 52 deletions

View File

@ -0,0 +1,16 @@
import { RequestHandler } from "express";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { giveKeyChainTriggeredItems } from "@/src/services/questService";
import { IGiveKeyChainTriggeredItemsRequest } from "@/src/types/questTypes";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const giveKeyChainTriggeredItemsController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const payload = getJSONfromString(req.body as string) as IGiveKeyChainTriggeredItemsRequest;
const result = await giveKeyChainTriggeredItems(accountId, payload.KeyChain, payload.ChainStage);
if (result != null) res.json(result);
else res.status(200).end();
};
export { giveKeyChainTriggeredItemsController };

View File

@ -0,0 +1,16 @@
import { RequestHandler } from "express";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { giveKeyChainTriggeredMessage } from "@/src/services/questService";
import { IGiveKeyChainTriggeredMessageRequest } from "@/src/types/questTypes";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const giveKeyChainTriggeredMessageController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const payload = getJSONfromString(req.body as string) as IGiveKeyChainTriggeredMessageRequest;
const result = await giveKeyChainTriggeredMessage(accountId, payload.KeyChain, payload.ChainStage);
if (result != null) res.json(result);
else res.status(200).end();
};
export { giveKeyChainTriggeredMessageController };

View File

@ -1,30 +1,13 @@
import { getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { setActiveQuest } from "@/src/services/questService";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
// eslint-disable-next-line @typescript-eslint/no-misused-promises // eslint-disable-next-line @typescript-eslint/no-misused-promises
const setActiveQuestController: RequestHandler = async (req, res) => { const setActiveQuestController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const quest = req.query.quest as string; const quest = req.query.quest as string;
const result = await setActiveQuest(accountId, quest);
const inventory = await getInventory(accountId); res.json(result);
const questKey = inventory.QuestKeys.find(q => q.ItemType == quest);
if (questKey == null)
inventory.QuestKeys.push({ ItemType: quest });
inventory.ActiveQuest = quest;
await inventory.save();
res.json({
inventoryChanges: {
QuestKey: [{
ItemType: quest
}],
Herses: [],
PremiumCreditsFree: 0,
PremiumCredits: 0,
RegularCredits: 0
}
});
}; };
export { setActiveQuestController }; export { setActiveQuestController };

View File

@ -1,37 +1,13 @@
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { getJSONfromString } from "@/src/helpers/stringHelpers"; import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { IQuestKeyDatabase } from "@/src/types/inventoryTypes/inventoryTypes";
import { logger } from "@/src/utils/logger";
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
export interface IUpdateQuestRequest {
QuestKeys: IQuestKeyDatabase[];
PS: string;
questCompletion: boolean;
PlayerShipEvents: [];
crossPlaySetting: string;
}
export interface IUpdateQuestResponse {
CustomData?: string;
MissionRewards: [];
}
// eslint-disable-next-line @typescript-eslint/no-misused-promises // eslint-disable-next-line @typescript-eslint/no-misused-promises
const updateQuestController: RequestHandler = async (req, res) => { const updateQuestController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const payload = getJSONfromString(req.body as string) as IUpdateQuestRequest; const payload = getJSONfromString(req.body as string) as IUpdateQuestRequest;
logger.debug("quest: " + payload.QuestKeys[0].ItemType); const result = await updateQuest(accountId, payload);
const inventory = await Inventory.findOne({ accountOwnerId: accountId });
if (inventory) {
/* empty */
}
const result: IUpdateQuestResponse = {
MissionRewards: []
};
res.json(result); res.json(result);
}; };

View File

@ -28,6 +28,7 @@ import { WeaponTypeInternal, getWeaponType, getExalted } from "@/src/services/it
import { ISyndicateSacrifice, ISyndicateSacrificeResponse } from "../types/syndicateTypes"; import { ISyndicateSacrifice, ISyndicateSacrificeResponse } from "../types/syndicateTypes";
import { IEquipmentClient } from "../types/inventoryTypes/commonInventoryTypes"; import { IEquipmentClient } from "../types/inventoryTypes/commonInventoryTypes";
import { ExportCustoms, ExportFlavour, ExportRecipes, ExportResources } from "warframe-public-export-plus"; import { ExportCustoms, ExportFlavour, ExportRecipes, ExportResources } from "warframe-public-export-plus";
import { updateQuestKeys } from "./questService";
export const createInventory = async ( export const createInventory = async (
accountOwnerId: Types.ObjectId, accountOwnerId: Types.ObjectId,
@ -121,9 +122,9 @@ export const addItem = async (
} }
// Path-based duck typing // Path-based duck typing
switch (typeName.substr(1).split("/")[1]) { switch (typeName.substring(1).split("/")[1]) {
case "Powersuits": case "Powersuits":
switch (typeName.substr(1).split("/")[2]) { switch (typeName.substring(1).split("/")[2]) {
default: { default: {
const suit = await addPowerSuit(typeName, accountId); const suit = await addPowerSuit(typeName, accountId);
await updateSlots(accountId, InventorySlot.SUITS, 0, 1); await updateSlots(accountId, InventorySlot.SUITS, 0, 1);
@ -196,7 +197,7 @@ export const addItem = async (
}; };
} }
case "Types": case "Types":
switch (typeName.substr(1).split("/")[2]) { switch (typeName.substring(1).split("/")[2]) {
case "Sentinels": case "Sentinels":
// TOOD: Sentinels should also grant their DefaultUpgrades & SentinelWeapon. // TOOD: Sentinels should also grant their DefaultUpgrades & SentinelWeapon.
const sentinel = await addSentinel(typeName, accountId); const sentinel = await addSentinel(typeName, accountId);
@ -208,7 +209,7 @@ export const addItem = async (
} }
}; };
case "Items": { case "Items": {
switch (typeName.substr(1).split("/")[3]) { switch (typeName.substring(1).split("/")[3]) {
case "ShipDecos": { case "ShipDecos": {
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);
const changes = [ const changes = [
@ -622,7 +623,7 @@ const addMissionComplete = (inventory: IInventoryDatabaseDocument, { Tag, Comple
const gearKeys = ["Suits", "Pistols", "LongGuns", "Melee"] as const; const gearKeys = ["Suits", "Pistols", "LongGuns", "Melee"] as const;
export const missionInventoryUpdate = async (data: IMissionInventoryUpdateRequest, accountId: string) => { export const missionInventoryUpdate = async (data: IMissionInventoryUpdateRequest, accountId: string) => {
const { RawUpgrades, MiscItems, RegularCredits, ChallengeProgress, FusionPoints, Consumables, Recipes, Missions } = const { RawUpgrades, MiscItems, RegularCredits, ChallengeProgress, FusionPoints, Consumables, Recipes, Missions, QuestKeys } =
data; data;
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);
@ -678,6 +679,9 @@ export const missionInventoryUpdate = async (data: IMissionInventoryUpdateReques
if (Missions) { if (Missions) {
addMissionComplete(inventory, Missions); addMissionComplete(inventory, Missions);
} }
if(QuestKeys) {
await updateQuestKeys(inventory, QuestKeys);
}
const changedInventory = await inventory.save(); const changedInventory = await inventory.save();
return changedInventory.toJSON(); return changedInventory.toJSON();

View File

@ -7,7 +7,9 @@ import {
ExportGear, ExportGear,
ExportRecipes, ExportRecipes,
ExportRelics, ExportRelics,
IReward IReward,
ExportKeys,
ExportResources
} from "warframe-public-export-plus"; } from "warframe-public-export-plus";
import { IMissionInventoryUpdateRequest } from "../types/requestTypes"; import { IMissionInventoryUpdateRequest } from "../types/requestTypes";
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
@ -64,6 +66,14 @@ const getRewards = ({
} }
} }
if (RewardInfo.node in ExportKeys) {
const quest = ExportKeys[RewardInfo.node];
const rewards = quest.rewards ?? [];
if (rewards.length == 0) {
return { InventoryChanges: {}, MissionRewards: [] };
}
}
logger.debug("Mission rewards:", drops); logger.debug("Mission rewards:", drops);
return formatRewardsToInventoryType(drops); return formatRewardsToInventoryType(drops);
}; };
@ -181,6 +191,8 @@ const formatRewardsToInventoryType = (
addRewardResponse(InventoryChanges, MissionRewards, type, reward.itemCount, "Recipes"); addRewardResponse(InventoryChanges, MissionRewards, type, reward.itemCount, "Recipes");
} else if (type in ExportRelics) { } else if (type in ExportRelics) {
addRewardResponse(InventoryChanges, MissionRewards, type, reward.itemCount, "MiscItems"); addRewardResponse(InventoryChanges, MissionRewards, type, reward.itemCount, "MiscItems");
} else if (type in ExportResources) {
addRewardResponse(InventoryChanges, MissionRewards, type, reward.itemCount, "MiscItems");
} else { } else {
logger.error(`rolled reward ${reward.itemCount}X ${reward.type} but unsure how to give it`); logger.error(`rolled reward ${reward.itemCount}X ${reward.type} but unsure how to give it`);
} }

View File

@ -0,0 +1,102 @@
import { IInventoryDatabaseDocument, IQuestKeyDatabase } from "@/src/types/inventoryTypes/inventoryTypes";
import { IUpdateQuestRequest, IUpdateQuestResponse } from "@/src/types/questTypes";
import { addItem, getInventory } from "./inventoryService";
import { logger } from "../utils/logger";
import { ExportKeys } from "warframe-public-export-plus";
export const setActiveQuest = async (accountId: string, quest: string) => {
const inventory = await getInventory(accountId);
const questKey = inventory.QuestKeys.find(q => q.ItemType == quest);
if (questKey == null) inventory.QuestKeys.push({ ItemType: quest });
inventory.ActiveQuest = quest;
await inventory.save();
return {
inventoryChanges: {
QuestKey: [
{
ItemType: quest
}
],
Herses: [],
PremiumCreditsFree: 0,
PremiumCredits: 0,
RegularCredits: 0
}
};
};
export const updateQuestKeys = async (inventory: IInventoryDatabaseDocument, questKeys: IQuestKeyDatabase[]) => {
const questKeyIndex = inventory.QuestKeys.findIndex(questKey => questKey.ItemType === questKeys[0].ItemType);
inventory.QuestKeys[questKeyIndex] = questKeys[0];
if (questKeys[0].Completed) {
inventory.QuestKeys[questKeyIndex].CompletionDate = new Date();
}
await inventory.save();
};
export const updateQuest = async (accountId: string, updateQuest: IUpdateQuestRequest) => {
const inventory = await getInventory(accountId);
await updateQuestKeys(inventory, updateQuest.QuestKeys);
const result: IUpdateQuestResponse = {
MissionRewards: []
};
if (updateQuest.QuestKeys[0].Completed) {
const quest = ExportKeys[updateQuest.QuestKeys[0].ItemType];
if (quest.rewards != null) {
for (const reward of quest.rewards) {
switch (reward.rewardType) {
case "RT_STORE_ITEM":
await addItem(accountId, reward.itemType.replace("/Lotus/StoreItems/", "/Lotus/"), 1);
break;
case "RT_RECIPE":
await addItem(accountId, reward.itemType, 1);
break;
case "RT_CREDITS":
inventory.RegularCredits += reward.amount;
await inventory.save();
break;
}
// push MissionRewards
// result.MissionRewards.push({});
}
}
}
return result;
};
export const giveKeyChainTriggeredItems = async (accountId: string, keyChain: string, chainStage: number) => {
logger.debug("keyChain: " + keyChain + " chainStage: " + chainStage);
// TODO:rewards
const quest = ExportKeys[keyChain];
if (quest.chainStages) {
for (const chainStage of quest.chainStages) {
if (chainStage.itemsToGiveWhenTriggered.length > 0) {
let itemType = chainStage.itemsToGiveWhenTriggered[0];
if (itemType.indexOf("") > 0) {
itemType = itemType.replace("/Lotus/StoreItems/", "/Lotus/");
}
await addItem(accountId, itemType, 1);
}
}
}
return null;
};
export const giveKeyChainTriggeredMessage = async (accountId: string, keyChain: string, chainStage: number) => {
logger.debug("keyChain: " + keyChain + " chainStage: " + chainStage);
// TODO:message
return null;
};

30
src/types/questTypes.ts Normal file
View File

@ -0,0 +1,30 @@
import { IQuestKeyDatabase } from "./inventoryTypes/inventoryTypes";
export interface IUpdateQuestRequest {
QuestKeys: IQuestKeyDatabase[];
PS: string;
questCompletion: boolean;
PlayerShipEvents: [];
crossPlaySetting: string;
}
export interface IUpdateQuestResponse {
CustomData?: string;
MissionRewards: [];
}
export interface IGiveKeyChainTriggeredItemsRequest {
KeyChain: string;
ChainStage: number;
}
export interface IGiveKeyChainTriggeredMessageGroup {
experiment: string;
experimentGroup: string;
}
export interface IGiveKeyChainTriggeredMessageRequest {
KeyChain: string;
ChainStage: number;
Groups: IGiveKeyChainTriggeredMessageGroup[];
}

View File

@ -11,7 +11,8 @@ import {
IMission, IMission,
IRawUpgrade, IRawUpgrade,
ISeasonChallenge, ISeasonChallenge,
TEquipmentKey TEquipmentKey,
IQuestKeyDatabase
} from "./inventoryTypes/inventoryTypes"; } from "./inventoryTypes/inventoryTypes";
export interface IArtifactsRequest { export interface IArtifactsRequest {
@ -57,6 +58,7 @@ export interface IMissionInventoryUpdateRequest {
RewardInfo?: IMissionInventoryUpdateRequestRewardInfo; RewardInfo?: IMissionInventoryUpdateRequestRewardInfo;
Missions?: IMission; Missions?: IMission;
EvolutionProgress?: IEvolutionProgress[]; EvolutionProgress?: IEvolutionProgress[];
QuestKeys?: IQuestKeyDatabase[];
FusionPoints?: number; // Not a part of the request, but we put it in this struct as an intermediate storage. FusionPoints?: number; // Not a part of the request, but we put it in this struct as an intermediate storage.
} }