feat: implement awakening quest completion (/api/giveStartingGear) #977

Closed
neon wants to merge 3 commits from neon/SpaceNinjaServer:starting-gear into main
2 changed files with 209 additions and 0 deletions
Showing only changes of commit 7efcdfd9a3 - Show all commits

View File

@ -0,0 +1,207 @@
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));
await addKeyChainItems(inventory, {
Review

this should not be here, the game handles trigger items itself.

this should not be here, the game handles trigger items itself.
Review

if youre talking about missionInventoryUpdate, then no. the awakening quest doesnt call that. this is why it needs to be done here.

if youre talking about missionInventoryUpdate, then no. the awakening quest doesnt call that. this is why it needs to be done here.
Review

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.

> 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.
Review

Where else would u do it?

Where else would u do it?
Review

Not at all, because, as I said "the game handles trigger items itself."

Not at all, because, as I said "the game handles trigger items itself."
Review

try it without but it didnt work for me

try it without but it didnt work for me
KeyChain: "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain",
ChainStage: 0
});
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: [{}, {}, {}]
}))
);
}
}
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;
}

View File

@ -35,6 +35,7 @@ import { gildWeaponController } from "@/src/controllers/api/gildWeaponController
import { giveKeyChainTriggeredItemsController } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
import { giveKeyChainTriggeredMessageController } from "@/src/controllers/api/giveKeyChainTriggeredMessageController";
import { giveQuestKeyRewardController } from "@/src/controllers/api/giveQuestKey";
import { giveStartingGearController } from "../controllers/api/giveStartingGear";
import { guildTechController } from "../controllers/api/guildTechController";
import { hostSessionController } from "@/src/controllers/api/hostSessionController";
import { hubController } from "@/src/controllers/api/hubController";
@ -146,6 +147,7 @@ apiRouter.post("/gildWeapon.php", gildWeaponController);
apiRouter.post("/giveKeyChainTriggeredItems.php", giveKeyChainTriggeredItemsController);
apiRouter.post("/giveKeyChainTriggeredMessage.php", giveKeyChainTriggeredMessageController);
apiRouter.post("/giveQuestKeyReward.php", giveQuestKeyRewardController);
apiRouter.post("/giveStartingGear.php", giveStartingGearController);
apiRouter.post("/guildTech.php", guildTechController);
apiRouter.post("/hostSession.php", hostSessionController);
apiRouter.post("/infestedFoundry.php", infestedFoundryController);