feat: implement awakening quest completion (/api/giveStartingGear) #977
208
src/controllers/api/giveStartingGear.ts
Normal file
208
src/controllers/api/giveStartingGear.ts
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
import { config } from "@/src/services/configService";
|
||||||
|
import { toOid } from "@/src/helpers/inventoryHelpers";
|
||||||
|
import { IOid } from "@/src/types/commonTypes";
|
||||||
|
import { Types } from "mongoose";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||||
|
import {
|
||||||
|
IDailyAffiliations,
|
||||||
|
IInventoryClient,
|
||||||
|
IPlayerSkills,
|
||||||
|
ITypeCount
|
||||||
|
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
|
import { addConsumables, addKeyChainItems, addMods, getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
|
||||||
|
export const giveStartingGearController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
|
||||||
|
const dataJSON = getJSONfromString<IStartingGearClient>(String(req.body));
|
||||||
|
|
||||||
|
for (const key of Object.keys(dataJSON) as Array<keyof IStartingGearClient>) {
|
||||||
|
|||||||
|
switch (key) {
|
||||||
|
// This is the only gear we receive as the rest will come from future quests
|
||||||
|
case "LongGuns":
|
||||||
|
case "Pistols":
|
||||||
|
case "Melee":
|
||||||
|
case "Suits":
|
||||||
|
// Filter out already owned items (shouldnt happen but this was mostly for testing)
|
||||||
|
const existingItems = new Set(inventory[key].map(item => item.ItemType));
|
||||||
|
|
||||||
|
// Adding items to inventory
|
||||||
|
inventory[key].push(
|
||||||
|
...dataJSON[key]
|
||||||
|
.filter(item => !existingItems.has(item.ItemType))
|
||||||
|
.map(x => ({
|
||||||
|
_id: new Types.ObjectId(),
|
||||||
|
ItemType: x.ItemType,
|
||||||
|
XP: x.XP,
|
||||||
|
Configs: [{}, {}, {}]
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Give the Arsenal Segment which is given after the Awakening. (MissionInventoryUpdate doesnt get called so we can't do it there)
|
||||||
|
await addKeyChainItems(inventory, {
|
||||||
|
KeyChain: "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain",
|
||||||
|
ChainStage: 0 // /Lotus/Types/Keys/VorsPrize/MissionOne
|
||||||
|
});
|
||||||
|
|
||||||
|
addConsumables(inventory, [{ ItemCount: 1, ItemType: "/Lotus/Types/Restoratives/LisetAutoHack" }]);
|
||||||
|
if (!config.unlockAllFlavourItems) {
|
||||||
|
inventory.FlavourItems.push([
|
||||||
|
{ ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem1" },
|
||||||
|
{ ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem2" },
|
||||||
|
{ ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem3" },
|
||||||
|
{ ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem4" }
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
addMods(inventory, [
|
||||||
|
{
|
||||||
|
ItemCount: 1,
|
||||||
|
ItemType: "/Lotus/Upgrades/Mods/Warframe/AvatarShieldMaxMod",
|
||||||
|
LastAdded: toOid(new Types.ObjectId())
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
inventory.DrifterMelee.push({
|
||||||
|
ItemType: "/Lotus/Types/Friendly/PlayerControllable/Weapons/DuviriDualSwords",
|
||||||
|
_id: new Types.ObjectId()
|
||||||
|
});
|
||||||
|
inventory.PlayedParkourTutorial = true;
|
||||||
|
inventory.ReceivedStartingGear = true;
|
||||||
|
inventory.TrainingDate = new Date();
|
||||||
|
inventory.QuestKeys.push({
|
||||||
|
Progress: [{ i: true }],
|
||||||
|
unlock: false,
|
||||||
|
ItemType: "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain"
|
||||||
|
});
|
||||||
|
await inventory.save();
|
||||||
|
|
||||||
|
res.json({});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Alot of stuff is not received in the request, instead of being redundant I will just omit an already created type (pain)
|
||||||
|
interface IStartingGearClient
|
||||||
|
extends Omit<
|
||||||
|
IInventoryClient,
|
||||||
|
| keyof IDailyAffiliations
|
||||||
|
| "Missions"
|
||||||
|
| "RandomUpgradesIdentified"
|
||||||
|
| "LastRegionPlayed"
|
||||||
|
| "TradesRemaining"
|
||||||
|
| "DailyFocus"
|
||||||
|
| "GiftsRemaining"
|
||||||
|
| "HasOwnedVoidProjectionsPreviously"
|
||||||
|
| "ChallengesFixVersion"
|
||||||
|
| "ChallengeProgress"
|
||||||
|
| "ReceivedStartingGear"
|
||||||
|
| "PendingRecipes"
|
||||||
|
| "PendingTrades"
|
||||||
|
| "DeathMarks"
|
||||||
|
| "WebFlags"
|
||||||
|
| "CompletedAlerts"
|
||||||
|
| "TauntHistory"
|
||||||
|
| "StoryModeChoice"
|
||||||
|
| "PeriodicMissionCompletions"
|
||||||
|
| "ActiveDojoColorResearch"
|
||||||
|
| "SentientSpawnChanceBoosters"
|
||||||
|
| "SupportedSyndicate"
|
||||||
|
| "Affiliations"
|
||||||
|
| "QualifyingInvasions"
|
||||||
|
| "FactionScores"
|
||||||
|
| "ArchwingEnabled"
|
||||||
|
| "PendingSpectreLoadouts"
|
||||||
|
| "SpectreLoadouts"
|
||||||
|
| "CompletedSyndicates"
|
||||||
|
| "FocusXP"
|
||||||
|
| "Alignment"
|
||||||
|
| "CompletedSorties"
|
||||||
|
| "LastSortieReward"
|
||||||
|
| "ActiveAvatarImageType"
|
||||||
|
| "DiscoveredMarkers"
|
||||||
|
| "CompletedJobs"
|
||||||
|
| "FocusAbility"
|
||||||
|
| "HasContributedToDojo"
|
||||||
|
| "HWIDProtectEnabled"
|
||||||
|
| "AlignmentReplay"
|
||||||
|
| "PersonalGoalProgress"
|
||||||
|
| "ThemeStyle"
|
||||||
|
| "ThemeBackground"
|
||||||
|
| "ThemeSounds"
|
||||||
|
| "BountyScore"
|
||||||
|
| "ChallengeInstanceStates"
|
||||||
|
| "LoginMilestoneRewards"
|
||||||
|
| "NodeIntrosCompleted"
|
||||||
|
| "GuildId"
|
||||||
|
| "CompletedJobChains"
|
||||||
|
| "SeasonChallengeHistory"
|
||||||
|
| "EquippedInstrument"
|
||||||
|
| "InvasionChainProgress"
|
||||||
|
| "NemesisHistory"
|
||||||
|
| "LastNemesisAllySpawnTime"
|
||||||
|
| "Settings"
|
||||||
|
| "PersonalTechProjects"
|
||||||
|
| "PlayerSkills"
|
||||||
|
| "TradeBannedUntil"
|
||||||
|
| "PlayedParkourTutorial"
|
||||||
|
| "SubscribedToEmailsPersonalized"
|
||||||
|
| "BlessingCooldown"
|
||||||
|
| "NemesisAbandonedRewards"
|
||||||
|
| "LastInventorySync"
|
||||||
|
| "NextRefill"
|
||||||
|
| "CustomMarkers"
|
||||||
|
| "ActiveLandscapeTraps"
|
||||||
|
| "EvolutionProgress"
|
||||||
|
| "RepVotes"
|
||||||
|
| "UsedDailyDeals"
|
||||||
|
| "LibraryPersonalTarget"
|
||||||
|
| "LibraryPersonalProgress"
|
||||||
|
| "CollectibleSeries"
|
||||||
|
| "LibraryAvailableDailyTaskInfo"
|
||||||
|
| "HasResetAccount"
|
||||||
|
| "PendingCoupon"
|
||||||
|
| "Harvestable"
|
||||||
|
| "DeathSquadable"
|
||||||
|
| "EndlessXP"
|
||||||
|
| "DialogueHistory"
|
||||||
|
> {
|
||||||
|
LongGuns: IStartingGearItem[];
|
||||||
|
Melee: IStartingGearItem[];
|
||||||
|
Pistols: IStartingGearItem[];
|
||||||
|
Suits: IStartingGearItem[];
|
||||||
|
XPLost?: unknown[];
|
||||||
|
CrewShipFusionPoints?: number;
|
||||||
|
PlayerSkillGains?: IPlayerSkills[];
|
||||||
|
// Lot's of unknown but these never receive data (at least not in this request)
|
||||||
|
StrippedItems?: unknown[];
|
||||||
|
BonusMiscItems?: unknown[];
|
||||||
|
EmailItems: ITypeCount[];
|
||||||
|
OneTimePurchases?: unknown[];
|
||||||
|
Rating?: number;
|
||||||
|
WishlistChanges?: unknown[];
|
||||||
|
RecentVendorPurchases: (string | number)[];
|
||||||
|
RemovedIdItems?: { ItemId: number }[];
|
||||||
|
SongChallenges?: unknown[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStartingGearItem
|
||||||
|
extends Omit<
|
||||||
|
IEquipmentClient,
|
||||||
|
| "_id"
|
||||||
|
| "InfestationDate"
|
||||||
|
| "InfestationDays"
|
||||||
|
| "InfestationType"
|
||||||
|
| "UnlockLevel"
|
||||||
|
| "Weapon"
|
||||||
|
| "Customization"
|
||||||
|
| "RailjackImage"
|
||||||
|
| "CrewMembers"
|
||||||
|
| "Details"
|
||||||
|
> {
|
||||||
|
// Warframe sends an ItemId instead _id, it will be converted to _id before being pushed to the inventory
|
||||||
|
ItemId: IOid;
|
||||||
|
Favorite?: boolean;
|
||||||
|
}
|
@ -35,6 +35,7 @@ import { gildWeaponController } from "@/src/controllers/api/gildWeaponController
|
|||||||
import { giveKeyChainTriggeredItemsController } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
|
import { giveKeyChainTriggeredItemsController } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
|
||||||
import { giveKeyChainTriggeredMessageController } from "@/src/controllers/api/giveKeyChainTriggeredMessageController";
|
import { giveKeyChainTriggeredMessageController } from "@/src/controllers/api/giveKeyChainTriggeredMessageController";
|
||||||
import { giveQuestKeyRewardController } from "@/src/controllers/api/giveQuestKey";
|
import { giveQuestKeyRewardController } from "@/src/controllers/api/giveQuestKey";
|
||||||
|
import { giveStartingGearController } from "../controllers/api/giveStartingGear";
|
||||||
import { guildTechController } from "../controllers/api/guildTechController";
|
import { guildTechController } from "../controllers/api/guildTechController";
|
||||||
import { hostSessionController } from "@/src/controllers/api/hostSessionController";
|
import { hostSessionController } from "@/src/controllers/api/hostSessionController";
|
||||||
import { hubController } from "@/src/controllers/api/hubController";
|
import { hubController } from "@/src/controllers/api/hubController";
|
||||||
@ -146,6 +147,7 @@ apiRouter.post("/gildWeapon.php", gildWeaponController);
|
|||||||
apiRouter.post("/giveKeyChainTriggeredItems.php", giveKeyChainTriggeredItemsController);
|
apiRouter.post("/giveKeyChainTriggeredItems.php", giveKeyChainTriggeredItemsController);
|
||||||
apiRouter.post("/giveKeyChainTriggeredMessage.php", giveKeyChainTriggeredMessageController);
|
apiRouter.post("/giveKeyChainTriggeredMessage.php", giveKeyChainTriggeredMessageController);
|
||||||
apiRouter.post("/giveQuestKeyReward.php", giveQuestKeyRewardController);
|
apiRouter.post("/giveQuestKeyReward.php", giveQuestKeyRewardController);
|
||||||
|
apiRouter.post("/giveStartingGear.php", giveStartingGearController);
|
||||||
apiRouter.post("/guildTech.php", guildTechController);
|
apiRouter.post("/guildTech.php", guildTechController);
|
||||||
apiRouter.post("/hostSession.php", hostSessionController);
|
apiRouter.post("/hostSession.php", hostSessionController);
|
||||||
apiRouter.post("/infestedFoundry.php", infestedFoundryController);
|
apiRouter.post("/infestedFoundry.php", infestedFoundryController);
|
||||||
|
@ -914,10 +914,10 @@ export interface IQuestKeyClient extends Omit<IQuestKeyDatabase, "CompletionDate
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IQuestStage {
|
export interface IQuestStage {
|
||||||
c?: number;
|
c?: number; // Completed?
|
||||||
i?: boolean;
|
i?: boolean; // keyChainItemsGiven?
|
||||||
m?: boolean;
|
m?: boolean; // keyChainMessage[Given](Sent)?
|
||||||
b?: any[];
|
b?: any[]; // unknown/unused
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRawUpgrade {
|
export interface IRawUpgrade {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user
this should not be here, the game handles trigger items itself.
if youre talking about missionInventoryUpdate, then no. the awakening quest doesnt call that. this is why it needs to be done here.
What mission inventory update?
I marked the line addKeychain Items, this is not meant to be done here.
Where else would u do it?
Not at all, because, as I said "the game handles trigger items itself."
try it without but it didnt work for me