fix quest system #472
							
								
								
									
										17
									
								
								src/controllers/api/giveKeyChainTriggeredItemsController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/controllers/api/giveKeyChainTriggeredItemsController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
			
		||||
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;
 | 
			
		||||
    if (payload) {
 | 
			
		||||
        const result = await giveKeyChainTriggeredItems(accountId, payload);
 | 
			
		||||
        if (result) res.json(result);
 | 
			
		||||
    } else res.json({});
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { giveKeyChainTriggeredItemsController };
 | 
			
		||||
@ -0,0 +1,28 @@
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
			
		||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { giveKeyChainTriggeredMessage } from "@/src/services/questService";
 | 
			
		||||
 | 
			
		||||
export interface IGiveKeyChainTriggeredMessageGroup {
 | 
			
		||||
    experiment: string;
 | 
			
		||||
    experimentGroup: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IGiveKeyChainTriggeredMessageRequest {
 | 
			
		||||
    KeyChain: string;
 | 
			
		||||
    ChainStage: number;
 | 
			
		||||
    Groups: IGiveKeyChainTriggeredMessageGroup[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 = giveKeyChainTriggeredMessage(accountId, payload.KeyChain, payload.ChainStage);
 | 
			
		||||
 | 
			
		||||
    if (result) res.json(result);
 | 
			
		||||
    else res.status(200).end();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { giveKeyChainTriggeredMessageController };
 | 
			
		||||
@ -1,7 +1,13 @@
 | 
			
		||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { setActiveQuest } from "@/src/services/questService";
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
 | 
			
		||||
const setActiveQuestController: RequestHandler = (_req, res) => {
 | 
			
		||||
    res.sendStatus(200);
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
 | 
			
		||||
const setActiveQuestController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const accountId = await getAccountIdForRequest(req);
 | 
			
		||||
    const quest = req.query.quest as string;
 | 
			
		||||
    const result = await setActiveQuest(accountId, quest);
 | 
			
		||||
    res.json(result);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { setActiveQuestController };
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								src/controllers/api/updateQuestController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/controllers/api/updateQuestController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
import { RequestHandler } from "express";
 | 
			
		||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
			
		||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
			
		||||
import { IUpdateQuestRequest } from "@/src/types/questTypes";
 | 
			
		||||
import { updateQuest } from "@/src/services/questService";
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
 | 
			
		||||
const updateQuestController: RequestHandler = async (req, res) => {
 | 
			
		||||
    const accountId = await getAccountIdForRequest(req);
 | 
			
		||||
    const payload = getJSONfromString(req.body as string) as IUpdateQuestRequest;
 | 
			
		||||
    const result = await updateQuest(accountId, payload);
 | 
			
		||||
    res.json(result);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export { updateQuestController };
 | 
			
		||||
@ -19,18 +19,18 @@ import {
 | 
			
		||||
    equipmentKeys,
 | 
			
		||||
    IFusionTreasure
 | 
			
		||||
} from "@/src/types/inventoryTypes/inventoryTypes";
 | 
			
		||||
import { IGenericUpdate } from "../types/genericUpdate";
 | 
			
		||||
import { IGenericUpdate } from "@/src/types/genericUpdate";
 | 
			
		||||
import {
 | 
			
		||||
    IArtifactsRequest,
 | 
			
		||||
    IMissionInventoryUpdateRequest,
 | 
			
		||||
    IThemeUpdateRequest,
 | 
			
		||||
    IUpdateChallengeProgressRequest
 | 
			
		||||
} from "../types/requestTypes";
 | 
			
		||||
} from "@/src/types/requestTypes";
 | 
			
		||||
import { logger } from "@/src/utils/logger";
 | 
			
		||||
import { getWeaponType, getExalted } from "@/src/services/itemDataService";
 | 
			
		||||
import { getRandomWeightedReward } from "@/src/services/rngService";
 | 
			
		||||
import { ISyndicateSacrifice, ISyndicateSacrificeResponse } from "../types/syndicateTypes";
 | 
			
		||||
import { IEquipmentClient } from "../types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
import { ISyndicateSacrifice, ISyndicateSacrificeResponse } from "@/src/types/syndicateTypes";
 | 
			
		||||
import { IEquipmentClient, IEquipmentDatabase } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
import {
 | 
			
		||||
    ExportBoosterPacks,
 | 
			
		||||
    ExportCustoms,
 | 
			
		||||
@ -870,3 +870,10 @@ export const upgradeMod = async (artifactsData: IArtifactsRequest, accountId: st
 | 
			
		||||
        throw error;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const addHerse = async (ItemType: string, accountId: string): Promise<IEquipmentDatabase> => {
 | 
			
		||||
    const inventory = await getInventory(accountId);
 | 
			
		||||
    const herseIndex = inventory.Horses.push({ ItemType: ItemType, Configs: [], UpgradeVer: 101 });
 | 
			
		||||
    const changedInventory = await inventory.save();
 | 
			
		||||
    return changedInventory.Horses[herseIndex - 1].toJSON();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										193
									
								
								src/services/questService.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								src/services/questService.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,193 @@
 | 
			
		||||
import { ExportKeys, ExportRecipes, ExportResources, IKey } from "warframe-public-export-plus";
 | 
			
		||||
import { addHerse, addItem, getInventory } from "./inventoryService";
 | 
			
		||||
import { logger } from "@/src/utils/logger";
 | 
			
		||||
import {
 | 
			
		||||
    IGiveKeyChainTriggeredItemsRequest,
 | 
			
		||||
    IGiveKeyChainTriggeredItemsResponse,
 | 
			
		||||
    ISetActiveQuestResponse,
 | 
			
		||||
    IUpdateQuestRequest,
 | 
			
		||||
    IUpdateQuestResponse
 | 
			
		||||
} from "@/src/types/questTypes";
 | 
			
		||||
import { IInventoryDatabaseDocument, IQuestKeyDatabase } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
			
		||||
import { toOid } from "@/src/helpers/inventoryHelpers";
 | 
			
		||||
 | 
			
		||||
const getQuest = (quest: string): IKey | undefined => {
 | 
			
		||||
    for (const [k, v] of Object.entries(ExportKeys)) {
 | 
			
		||||
        if (k == quest) {
 | 
			
		||||
            return v;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return undefined;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const setActiveQuest = async (accountId: string, quest: string): Promise<ISetActiveQuestResponse> => {
 | 
			
		||||
    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();
 | 
			
		||||
 | 
			
		||||
    const questData = getQuest(quest);
 | 
			
		||||
    if (questData) {
 | 
			
		||||
        console.log(questData);
 | 
			
		||||
    }
 | 
			
		||||
    const result: ISetActiveQuestResponse = {
 | 
			
		||||
        inventoryChanges: {
 | 
			
		||||
            QuestKey: [],
 | 
			
		||||
            Herses: [],
 | 
			
		||||
            PremiumCreditsFree: 0,
 | 
			
		||||
            PremiumCredits: 0,
 | 
			
		||||
            RegularCredits: 0
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    switch (quest) {
 | 
			
		||||
        case "/Lotus/Types/Keys/DuviriQuest/DuviriQuestKeyChain":
 | 
			
		||||
            // eslint-disable-next-line no-case-declarations
 | 
			
		||||
            const inventory = await getInventory(accountId);
 | 
			
		||||
            // eslint-disable-next-line no-case-declarations
 | 
			
		||||
            const questKey = inventory.QuestKeys.find(q => q.ItemType == quest);
 | 
			
		||||
            if (questKey == null) inventory.QuestKeys.push({ ItemType: quest });
 | 
			
		||||
            inventory.ActiveQuest = quest;
 | 
			
		||||
            await inventory.save();
 | 
			
		||||
            // eslint-disable-next-line no-case-declarations
 | 
			
		||||
            const herse = await addHerse("/Lotus/Types/NeutralCreatures/ErsatzHorse/ErsatzHorsePowerSuit", accountId);
 | 
			
		||||
            result.inventoryChanges.QuestKey.push({ ItemType: quest });
 | 
			
		||||
            // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
 | 
			
		||||
            result.inventoryChanges.Herses.push({ ItemType: herse.ItemType, ItemId: toOid(herse._id) });
 | 
			
		||||
            result.inventoryChanges.PremiumCreditsFree = 50;
 | 
			
		||||
            result.inventoryChanges.PremiumCredits = 50;
 | 
			
		||||
            result.inventoryChanges.RegularCredits = 3000;
 | 
			
		||||
            break;
 | 
			
		||||
        default:
 | 
			
		||||
            result.inventoryChanges.QuestKey.push({ ItemType: quest });
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const updateQuestKeys = async (
 | 
			
		||||
    inventory: IInventoryDatabaseDocument,
 | 
			
		||||
    questKeys: IQuestKeyDatabase[]
 | 
			
		||||
): Promise<void> => {
 | 
			
		||||
    logger.debug("quest: " + questKeys[0].ItemType);
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
): Promise<IUpdateQuestResponse> => {
 | 
			
		||||
    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,
 | 
			
		||||
    payload: IGiveKeyChainTriggeredItemsRequest
 | 
			
		||||
): Promise<IGiveKeyChainTriggeredItemsResponse> => {
 | 
			
		||||
    logger.debug("keyChain: " + payload.KeyChain + " chainStage: " + payload.ChainStage);
 | 
			
		||||
    const inventory = await getInventory(accountId);
 | 
			
		||||
 | 
			
		||||
    const quest = ExportKeys[payload.KeyChain];
 | 
			
		||||
 | 
			
		||||
    const result: IGiveKeyChainTriggeredItemsResponse = {};
 | 
			
		||||
 | 
			
		||||
    if (quest.chainStages) {
 | 
			
		||||
        const stage = quest.chainStages[payload.ChainStage];
 | 
			
		||||
 | 
			
		||||
        if (stage.key && stage.key in ExportKeys) {
 | 
			
		||||
            const stageQuest = ExportKeys[stage.key];
 | 
			
		||||
            if (stageQuest.rewards) {
 | 
			
		||||
                for (const item of stageQuest.rewards) {
 | 
			
		||||
                    switch (item.rewardType) {
 | 
			
		||||
                        case "RT_STORE_ITEM":
 | 
			
		||||
                            await addItem(accountId, item.itemType.replace("/Lotus/StoreItems/", "/Lotus/"), 1);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case "RT_CREDITS":
 | 
			
		||||
                            inventory.RegularCredits += item.amount;
 | 
			
		||||
                            await inventory.save();
 | 
			
		||||
                            break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (stage.itemsToGiveWhenTriggered.length > 0) {
 | 
			
		||||
            let itemType = stage.itemsToGiveWhenTriggered[0];
 | 
			
		||||
            if (itemType.indexOf("") > 0) {
 | 
			
		||||
                itemType = itemType.replace("/Lotus/StoreItems/", "/Lotus/");
 | 
			
		||||
            }
 | 
			
		||||
            await addItem(accountId, itemType, 1);
 | 
			
		||||
 | 
			
		||||
            if (itemType in ExportRecipes) {
 | 
			
		||||
                result.Recipes = [
 | 
			
		||||
                    {
 | 
			
		||||
                        ItemType: itemType,
 | 
			
		||||
                        ItemCount: 1
 | 
			
		||||
                    }
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (itemType in ExportResources) {
 | 
			
		||||
                result.WishlistChanges = [itemType];
 | 
			
		||||
                result.MiscItems = [
 | 
			
		||||
                    {
 | 
			
		||||
                        ItemType: itemType,
 | 
			
		||||
                        ItemCount: 1
 | 
			
		||||
                    }
 | 
			
		||||
                ];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // more
 | 
			
		||||
        } else {
 | 
			
		||||
            result.MissionRewards = [];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const giveKeyChainTriggeredMessage = (accountId: string, keyChain: string, chainStage: number): null => {
 | 
			
		||||
    logger.debug("accountId:" + accountId + "keyChain: " + keyChain + " chainStage: " + chainStage);
 | 
			
		||||
    // TODO:message
 | 
			
		||||
 | 
			
		||||
    return null;
 | 
			
		||||
};
 | 
			
		||||
@ -290,6 +290,7 @@ export interface IInventoryResponse {
 | 
			
		||||
    PendingCoupon: IPendingCoupon;
 | 
			
		||||
    Harvestable: boolean;
 | 
			
		||||
    DeathSquadable: boolean;
 | 
			
		||||
    ActiveQuest: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IAffiliation {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										45
									
								
								src/types/questTypes.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/types/questTypes.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
import { IOid } from "./commonTypes";
 | 
			
		||||
import { IQuestKeyDatabase } from "./inventoryTypes/inventoryTypes";
 | 
			
		||||
 | 
			
		||||
export interface ISetActiveQuestKey {
 | 
			
		||||
    ItemType: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ISetActiveQuestHerse extends ISetActiveQuestKey {
 | 
			
		||||
    ItemId: IOid;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ISetActiveQuestResponse {
 | 
			
		||||
    inventoryChanges: {
 | 
			
		||||
        QuestKey: ISetActiveQuestKey[];
 | 
			
		||||
        Herses: ISetActiveQuestHerse[];
 | 
			
		||||
        PremiumCreditsFree: number;
 | 
			
		||||
        PremiumCredits: number;
 | 
			
		||||
        RegularCredits: number;
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 IGiveKeyChainTriggeredItemsResponse {
 | 
			
		||||
    WishlistChanges?: [string];
 | 
			
		||||
    MiscItems?: [{ ItemType: string; ItemCount: number }];
 | 
			
		||||
    Recipes?: [{ ItemType: string; ItemCount: number }];
 | 
			
		||||
    MissionRewards?: [];
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user