返回提交历史
Modified
src/services/loginService.ts
+1
-12
Modified
src/services/questService.ts
+357
-3
XFEstudio/XFESpaceNinjaServer
feat: remove quest related items (#2957)
if I haven't missed anything, this should close #1116 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2957 Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com> Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
f2145ed9
代码差异
2 个文件
+358
-15
@@ -41,8 +41,8 @@ export const createAccount = async (accountData: IDatabaseAccountRequiredFields)
41
41
await account.save();
42
42
const loadoutId = await createLoadout(account._id);
43
43
const shipId = await createShip(account._id);
44
await createInventory(account._id, { loadOutPresetId: loadoutId, ship: shipId });
45
44
await createPersonalRooms(account._id, shipId);
45
await createInventory(account._id, { loadOutPresetId: loadoutId, ship: shipId });
46
46
await createStats(account._id.toString());
47
47
return account.toJSON();
48
48
} catch (error) {
@@ -64,17 +64,6 @@ export const createPersonalRooms = async (accountId: Types.ObjectId, shipId: Typ
64
64
personalRoomsOwnerId: accountId,
65
65
activeShipId: shipId
66
66
});
67
if (config.skipTutorial) {
68
// unlocked during Vor's Prize and The Teacher quests
69
const defaultFeatures = [
70
"/Lotus/Types/Items/ShipFeatureItems/MercuryNavigationFeatureItem",
71
"/Lotus/Types/Items/ShipFeatureItems/ArsenalFeatureItem",
72
"/Lotus/Types/Items/ShipFeatureItems/SocialMenuFeatureItem",
73
"/Lotus/Types/Items/ShipFeatureItems/FoundryFeatureItem",
74
"/Lotus/Types/Items/ShipFeatureItems/ModsFeatureItem"
75
];
76
personalRooms.Ship.Features.push(...defaultFeatures);
77
}
78
67
await personalRooms.save();
79
68
};
80
69
@@ -2,16 +2,25 @@ import type { IKeyChainRequest } from "../types/requestTypes.ts";
2
2
import { isEmptyObject } from "../helpers/general.ts";
3
3
import type { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel.ts";
4
4
import { createMessage } from "./inboxService.ts";
5
import { addItem, addItems, addKeyChainItems, setupKahlSyndicate } from "./inventoryService.ts";
5
import {
6
addEquipment,
7
addItem,
8
addItems,
9
addKeyChainItems,
10
addPowerSuit,
11
setupKahlSyndicate
12
} from "./inventoryService.ts";
6
13
import { fromStoreItem, getKeyChainMessage, getLevelKeyRewards } from "./itemDataService.ts";
7
14
import type { IQuestKeyClient, IQuestKeyDatabase, IQuestStage } from "../types/inventoryTypes/inventoryTypes.ts";
8
15
import { logger } from "../utils/logger.ts";
9
import { ExportKeys } from "warframe-public-export-plus";
16
import { ExportKeys, ExportRecipes } from "warframe-public-export-plus";
10
17
import { addFixedLevelRewards } from "./missionInventoryUpdateService.ts";
11
18
import type { IInventoryChanges } from "../types/purchaseTypes.ts";
12
19
import questCompletionItems from "../../static/fixed_responses/questCompletionRewards.json" with { type: "json" };
13
20
import type { ITypeCount } from "../types/commonTypes.ts";
14
21
import { addString } from "../helpers/stringHelpers.ts";
22
import { unlockShipFeature } from "./personalRoomsService.ts";
23
import { EquipmentFeatures } from "../types/equipmentTypes.ts";
15
24
16
25
export interface IUpdateQuestRequest {
17
26
QuestKeys: IQuestKeyClient[];
@@ -193,6 +202,7 @@ export const completeQuest = async (
193
202
stage.c = run;
194
203
await giveKeyChainStageTriggered(inventory, { KeyChain: questKey, ChainStage: i }, sendMessages);
195
204
await giveKeyChainMissionReward(inventory, { KeyChain: questKey, ChainStage: i });
205
await installShipFeatures(inventory, { KeyChain: questKey, ChainStage: i });
196
206
}
197
207
}
198
208
@@ -329,6 +339,9 @@ const handleQuestCompletion = async (
329
339
logger.debug(`quest completion items`, questCompletionItems);
330
340
if (questCompletionItems) {
331
341
await addItems(inventory, questCompletionItems, inventoryChanges);
342
for (const item of questCompletionItems) {
343
await removeRequiredItems(inventory, item.ItemType);
344
}
332
345
}
333
346
};
334
347
@@ -378,7 +391,12 @@ export const giveKeyChainMessage = async (
378
391
await createMessage(inventory.accountOwnerId, [keyChainMessage]);
379
392
} else {
380
393
if (keyChainMessage.countedAtt?.length) await addItems(inventory, keyChainMessage.countedAtt);
381
if (keyChainMessage.att?.length) await addItems(inventory, keyChainMessage.att);
394
if (keyChainMessage.att?.length) {
395
await addItems(inventory, keyChainMessage.att);
396
for (const reward of keyChainMessage.att) {
397
await removeRequiredItems(inventory, reward);
398
}
399
}
382
400
}
383
401
384
402
updateQuestStage(inventory, keyChainInfo, { m: true });
@@ -403,6 +421,7 @@ export const giveKeyChainMissionReward = async (
403
421
404
422
for (const reward of missionRewards) {
405
423
await addItem(inventory, fromStoreItem(reward.StoreItem), reward.ItemCount);
424
await removeRequiredItems(inventory, fromStoreItem(reward.StoreItem));
406
425
}
407
426
408
427
updateQuestStage(inventory, keyChainInfo, { c: run });
@@ -416,6 +435,7 @@ export const giveKeyChainMissionReward = async (
416
435
await addItem(inventory, fromStoreItem(reward.itemType), reward.amount);
417
436
} else {
418
437
await addItem(inventory, fromStoreItem(reward.itemType));
438
await removeRequiredItems(inventory, fromStoreItem(reward.itemType));
419
439
}
420
440
}
421
441
@@ -444,3 +464,337 @@ export const giveKeyChainStageTriggered = async (
444
464
}
445
465
}
446
466
};
467
468
export const installShipFeatures = async (
469
inventory: TInventoryDatabaseDocument,
470
keyChainInfo: IKeyChainRequest
471
): Promise<void> => {
472
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
473
const chainStages = ExportKeys[keyChainInfo.KeyChain]?.chainStages;
474
const questKey = inventory.QuestKeys.find(qk => qk.ItemType === keyChainInfo.KeyChain);
475
if (chainStages && questKey) {
476
if (keyChainInfo.ChainStage - 1 >= 0) {
477
const prevStage = chainStages[keyChainInfo.ChainStage - 1];
478
for (const item of prevStage.itemsToGiveWhenTriggered) {
479
if (item.startsWith("/Lotus/StoreItems/Types/Items/ShipFeatureItems/")) {
480
logger.debug(`installing ship feature ${fromStoreItem(item)}`);
481
await unlockShipFeature(inventory, fromStoreItem(item));
482
}
483
}
484
if (prevStage.key) {
485
const fixedLevelRewards = getLevelKeyRewards(prevStage.key);
486
if (fixedLevelRewards.levelKeyRewards?.items) {
487
for (const item of fixedLevelRewards.levelKeyRewards.items) {
488
if (item.startsWith("/Lotus/StoreItems/Types/Items/ShipFeatureItems/")) {
489
logger.debug(`installing ship feature ${fromStoreItem(item)}`);
490
await unlockShipFeature(inventory, fromStoreItem(item));
491
}
492
}
493
}
494
if (fixedLevelRewards.levelKeyRewards2) {
495
for (const item of fixedLevelRewards.levelKeyRewards2) {
496
if (
497
item.rewardType == "RT_STORE_ITEM" &&
498
item.itemType.startsWith("/Lotus/StoreItems/Types/Items/ShipFeatureItems/")
499
) {
500
logger.debug(`installing ship feature ${fromStoreItem(item.itemType)}`);
501
await unlockShipFeature(inventory, fromStoreItem(item.itemType));
502
}
503
}
504
}
505
}
506
}
507
}
508
};
509
510
export const removeRequiredItems = async (inventory: TInventoryDatabaseDocument, typeName: string): Promise<void> => {
511
switch (typeName) {
512
case "/Lotus/Types/Recipes/WarframeRecipes/MagicianHelmetBlueprint": {
513
const recipeItem = inventory.Recipes.find(
514
i => i.ItemType == "/Lotus/Types/Keys/LimboQuest/LimboHelmetKeyBlueprint"
515
);
516
if (recipeItem && recipeItem.ItemCount > 0) {
517
const recipe = ExportRecipes[recipeItem.ItemType];
518
if (!inventory.MiscItems.find(i => i.ItemType == recipe.resultType)) {
519
await addItem(inventory, recipe.resultType);
520
if (recipe.consumeOnUse) await addItem(inventory, recipeItem.ItemType, -1);
521
}
522
}
523
break;
524
}
525
case "/Lotus/Types/Recipes/WarframeRecipes/MagicianSystemsBlueprint": {
526
const recipeItem = inventory.Recipes.find(
527
i => i.ItemType == "/Lotus/Types/Keys/LimboQuest/LimboSystemsKeyBlueprint"
528
);
529
if (recipeItem && recipeItem.ItemCount > 0) {
530
const recipe = ExportRecipes[recipeItem.ItemType];
531
if (!inventory.MiscItems.find(i => i.ItemType == recipe.resultType)) {
532
await addItem(inventory, recipe.resultType);
533
if (recipe.consumeOnUse) await addItem(inventory, recipeItem.ItemType, -1);
534
}
535
}
536
break;
537
}
538
case "/Lotus/Types/Recipes/WarframeRecipes/MagicianChassisBlueprint": {
539
const recipeItem = inventory.Recipes.find(
540
i => i.ItemType == "/Lotus/Types/Keys/LimboQuest/LimboChassisKeyBlueprint"
541
);
542
if (recipeItem && recipeItem.ItemCount > 0) {
543
const recipe = ExportRecipes[recipeItem.ItemType];
544
if (!inventory.MiscItems.find(i => i.ItemType == recipe.resultType)) {
545
await addItem(inventory, recipe.resultType);
546
if (recipe.consumeOnUse) await addItem(inventory, recipeItem.ItemType, -1);
547
}
548
}
549
break;
550
}
551
552
case "/Lotus/Types/Recipes/WarframeRecipes/BrawlerBlueprint": {
553
const recipeItem = inventory.Recipes.find(
554
i => i.ItemType == "/Lotus/Types/Recipes/Components/InfestedIrradiatedBaitBallBlueprint"
555
);
556
if (recipeItem && recipeItem.ItemCount > 0) {
557
const recipe = ExportRecipes[recipeItem.ItemType];
558
if (!inventory.MiscItems.find(i => i.ItemType == recipe.resultType)) {
559
await addItem(inventory, recipe.resultType);
560
await addItem(inventory, recipe.resultType, -1, false, undefined, undefined, true);
561
if (recipe.consumeOnUse) await addItem(inventory, recipeItem.ItemType, -1);
562
}
563
}
564
break;
565
}
566
567
case "/Lotus/Types/Game/CrewShip/RailJack/DefaultHarness": {
568
const recipeItem = inventory.Recipes.find(
569
i => i.ItemType == "/Lotus/Types/Recipes/ArchwingRecipes/StandardArchwing/StandardArchwingBlueprint"
570
);
571
if (recipeItem && recipeItem.ItemCount > 0) {
572
const recipe = ExportRecipes[recipeItem.ItemType];
573
if (!inventory.MiscItems.find(i => i.ItemType == recipe.resultType)) {
574
await addItem(inventory, recipe.resultType);
575
if (recipe.consumeOnUse) await addItem(inventory, recipeItem.ItemType, recipeItem.ItemCount * -1);
576
await addItems(inventory, [
577
{
578
ItemType:
579
"/Lotus/Types/Recipes/ArchwingRecipes/StandardArchwing/StandardArchwingWingsBlueprint",
580
ItemCount: -1
581
},
582
{
583
ItemType:
584
"/Lotus/Types/Recipes/ArchwingRecipes/StandardArchwing/StandardArchwingChassisBlueprint",
585
ItemCount: -1
586
},
587
{
588
ItemType:
589
"/Lotus/Types/Recipes/ArchwingRecipes/StandardArchwing/StandardArchwingSystemsBlueprint",
590
ItemCount: -1
591
}
592
]);
593
}
594
}
595
break;
596
}
597
598
case "/Lotus/Types/Keys/ModQuest/ModQuestKeyChain": {
599
const recipeItem = inventory.Recipes.find(
600
i => i.ItemType == "/Lotus/Types/Recipes/Components/VorBoltRemoverBlueprint"
601
);
602
if (recipeItem && recipeItem.ItemCount > 0) {
603
const recipe = ExportRecipes[recipeItem.ItemType];
604
if (!inventory.MiscItems.find(i => i.ItemType == recipe.resultType)) {
605
await addItem(inventory, recipe.resultType);
606
if (recipe.consumeOnUse) await addItem(inventory, recipeItem.ItemType, -1);
607
}
608
}
609
break;
610
}
611
612
case "/Lotus/Types/Recipes/WarframeRecipes/ChromaBlueprint": {
613
await addItems(inventory, [
614
{
615
ItemType: "/Lotus/Types/Recipes/WarframeRecipes/ChromaBeaconABlueprint",
616
ItemCount: -1
617
},
618
{
619
ItemType: "/Lotus/Types/Recipes/WarframeRecipes/ChromaBeaconBBlueprint",
620
ItemCount: -1
621
},
622
{
623
ItemType: "/Lotus/Types/Recipes/WarframeRecipes/ChromaBeaconCBlueprint",
624
ItemCount: -1
625
}
626
]);
627
628
break;
629
}
630
631
case "/Lotus/Types/Recipes/WarframeRecipes/OctaviaBlueprint": {
632
const recipeItem = inventory.Recipes.find(
633
i => i.ItemType == "/Lotus/Types/Keys/BardQuest/BardQuestSequencerBlueprint"
634
);
635
if (recipeItem && recipeItem.ItemCount > 0) {
636
const recipe = ExportRecipes[recipeItem.ItemType];
637
if (!inventory.MiscItems.find(i => i.ItemType == recipe.resultType)) {
638
await addItem(inventory, recipe.resultType);
639
if (recipe.consumeOnUse) await addItem(inventory, recipeItem.ItemType, -1);
640
await addItems(inventory, [
641
{
642
ItemType: "/Lotus/Types/Keys/BardQuest/BardQuestSequencerPartA",
643
ItemCount: -1
644
},
645
{
646
ItemType: "/Lotus/Types/Keys/BardQuest/BardQuestSequencerPartB",
647
ItemCount: -1
648
},
649
{
650
ItemType: "/Lotus/Types/Keys/BardQuest/BardQuestSequencerPartC",
651
ItemCount: -1
652
}
653
]);
654
}
655
}
656
break;
657
}
658
659
case "/Lotus/Types/Game/CrewShip/Ships/RailJack": {
660
const recipeItem = inventory.Recipes.find(
661
i => i.ItemType == "/Lotus/Types/Recipes/Railjack/RailjackCephalonBlueprint"
662
);
663
if (recipeItem && recipeItem.ItemCount > 0) {
664
const recipe = ExportRecipes[recipeItem.ItemType];
665
if (!inventory.MiscItems.find(i => i.ItemType == recipe.resultType)) {
666
await addItem(inventory, recipe.resultType);
667
if (recipe.consumeOnUse) await addItem(inventory, recipeItem.ItemType, recipeItem.ItemCount * -1);
668
await unlockShipFeature(inventory, recipe.resultType);
669
}
670
}
671
break;
672
}
673
674
case "/Lotus/Types/Items/ShipDecos/MummyQuestVessel": {
675
const gearItem = inventory.Consumables.find(
676
i => i.ItemType == "/Lotus/Types/Keys/MummyQuest/MummyArtifact01GearItem"
677
);
678
if (gearItem && gearItem.ItemCount > 0) {
679
await addItem(inventory, gearItem.ItemType, gearItem.ItemCount * -1);
680
}
681
break;
682
}
683
684
case "/Lotus/Types/Recipes/WarframeRecipes/ConcreteFrameBlueprint": {
685
const recipeItem = inventory.Recipes.find(
686
i => i.ItemType == "/Lotus/Types/Gameplay/EntratiLab/Quest/GargoyleRecipeItem"
687
);
688
if (recipeItem && recipeItem.ItemCount > 0) {
689
const recipe = ExportRecipes[recipeItem.ItemType];
690
if (!inventory.MiscItems.find(i => i.ItemType == recipe.resultType)) {
691
await addItem(inventory, recipe.resultType);
692
if (recipe.consumeOnUse) await addItem(inventory, recipeItem.ItemType, recipeItem.ItemCount * -1);
693
}
694
}
695
break;
696
}
697
698
case "/Lotus/Upgrades/Skins/Umbra/UmbraAltHelmet": {
699
const recipeItem = inventory.Recipes.find(
700
i => i.ItemType == "/Lotus/Types/Recipes/WarframeRecipes/ExcaliburUmbraBlueprint"
701
);
702
if (recipeItem && recipeItem.ItemCount > 0) {
703
const recipe = ExportRecipes[recipeItem.ItemType];
704
if (!inventory.MiscItems.find(i => i.ItemType == recipe.resultType)) {
705
const umbraModA = (
706
await addItem(
707
inventory,
708
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModA",
709
1,
710
false,
711
undefined,
712
`{"lvl":5}`
713
)
714
).Upgrades![0];
715
const umbraModB = (
716
await addItem(
717
inventory,
718
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModB",
719
1,
720
false,
721
undefined,
722
`{"lvl":5}`
723
)
724
).Upgrades![0];
725
const umbraModC = (
726
await addItem(
727
inventory,
728
"/Lotus/Upgrades/Mods/Sets/Umbra/WarframeUmbraModC",
729
1,
730
false,
731
undefined,
732
`{"lvl":5}`
733
)
734
).Upgrades![0];
735
const sacrificeModA = (
736
await addItem(
737
inventory,
738
"/Lotus/Upgrades/Mods/Sets/Sacrifice/MeleeSacrificeModA",
739
1,
740
false,
741
undefined,
742
`{"lvl":5}`
743
)
744
).Upgrades![0];
745
const sacrificeModB = (
746
await addItem(
747
inventory,
748
"/Lotus/Upgrades/Mods/Sets/Sacrifice/MeleeSacrificeModB",
749
1,
750
false,
751
undefined,
752
`{"lvl":5}`
753
)
754
).Upgrades![0];
755
756
await addPowerSuit(inventory, "/Lotus/Powersuits/Excalibur/ExcaliburUmbra", {
757
Configs: [
758
{
759
Upgrades: [
760
"",
761
"",
762
"",
763
"",
764
"",
765
umbraModA.ItemId.$oid,
766
umbraModB.ItemId.$oid,
767
umbraModC.ItemId.$oid
768
]
769
}
770
],
771
XP: 900_000,
772
Features: EquipmentFeatures.DOUBLE_CAPACITY
773
});
774
inventory.XPInfo.push({
775
ItemType: "/Lotus/Powersuits/Excalibur/ExcaliburUmbra",
776
XP: 900_000
777
});
778
779
addEquipment(inventory, "Melee", "/Lotus/Weapons/Tenno/Melee/Swords/UmbraKatana/UmbraKatana", {
780
Configs: [
781
{
782
Upgrades: ["", "", "", "", "", "", sacrificeModA.ItemId.$oid, sacrificeModB.ItemId.$oid]
783
}
784
],
785
XP: 450_000,
786
Features: EquipmentFeatures.DOUBLE_CAPACITY
787
});
788
inventory.XPInfo.push({
789
ItemType: "/Lotus/Weapons/Tenno/Melee/Swords/UmbraKatana/UmbraKatana",
790
XP: 450_000
791
});
792
if (recipe.consumeOnUse) await addItem(inventory, recipeItem.ItemType, recipeItem.ItemCount * -1);
793
}
794
}
795
break;
796
}
797
default:
798
break;
799
}
800
};