返回提交历史
Modified
package-lock.json
+3
-3
Modified
src/controllers/api/getNewRewardSeedController.ts
+2
-4
Added
src/controllers/api/giveStartingGearController.ts
+96
-0
Modified
src/controllers/custom/manageQuestsController.ts
+0
-3
Modified
src/models/inventoryModels/inventoryModel.ts
+61
-12
Modified
src/routes/api.ts
+2
-0
Modified
src/services/inboxService.ts
+2
-2
Modified
src/services/inventoryService.ts
+53
-68
Modified
src/services/questService.ts
+2
-1
Modified
src/types/inventoryTypes/inventoryTypes.ts
+24
-2
Added
static/fixed_responses/eventMessages.json
+12
-0
Deleted
static/fixed_responses/messages.json
+0
-49
XFEstudio/XFESpaceNinjaServer
feat: tutorial and natural new player experience (#983)
Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/983 Co-authored-by: Ordis <134585663+OrdisPrime@users.noreply.github.com> Co-committed-by: Ordis <134585663+OrdisPrime@users.noreply.github.com>
bf7fd421
代码差异
12 个文件
+257
-144
@@ -4093,9 +4093,9 @@
4093
4093
}
4094
4094
},
4095
4095
"node_modules/warframe-public-export-plus": {
4096
"version": "0.5.30",
4097
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.30.tgz",
4098
"integrity": "sha512-vzs+naEqp3iFZTbgIky4jiNbjNIovuR4oSimrFiuyIbrnfTlfXFzDfzT0hG2rgS8yEXBAbOcv2Zfm3fmWuZ0Kg=="
4096
"version": "0.5.32",
4097
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.32.tgz",
4098
"integrity": "sha512-jO9i2Gzz9DWibiHlEO17D975ajs6KrTay8cS5I0GkUUe1XWVU8mML4b+IYCHzM4FWq1t6p2YPCGznQfknqvorg=="
4099
4099
},
4100
4100
"node_modules/warframe-riven-info": {
4101
4101
"version": "0.1.2",
@@ -1,13 +1,11 @@
1
1
import { RequestHandler } from "express";
2
2
3
const getNewRewardSeedController: RequestHandler = (_req, res) => {
3
export const getNewRewardSeedController: RequestHandler = (_req, res) => {
4
4
res.json({ rewardSeed: generateRewardSeed() });
5
5
};
6
6
7
function generateRewardSeed(): number {
7
export function generateRewardSeed(): number {
8
8
const min = -Number.MAX_SAFE_INTEGER;
9
9
const max = Number.MAX_SAFE_INTEGER;
10
10
return Math.floor(Math.random() * (max - min + 1)) + min;
11
11
}
12
13
export { getNewRewardSeedController };
@@ -0,0 +1,96 @@
1
import { getJSONfromString } from "@/src/helpers/stringHelpers";
2
import { InventoryDocumentProps } from "@/src/models/inventoryModels/inventoryModel";
3
import {
4
addEquipment,
5
addItem,
6
combineInventoryChanges,
7
getInventory,
8
updateSlots
9
} from "@/src/services/inventoryService";
10
import { getAccountIdForRequest } from "@/src/services/loginService";
11
import { IInventoryClient, IInventoryDatabase, InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
12
import { IInventoryChanges } from "@/src/types/purchaseTypes";
13
import { RequestHandler } from "express";
14
import { HydratedDocument } from "mongoose";
15
16
type TPartialStartingGear = Pick<IInventoryClient, "LongGuns" | "Suits" | "Pistols" | "Melee">;
17
18
export const giveStartingGearController: RequestHandler = async (req, res) => {
19
const accountId = await getAccountIdForRequest(req);
20
const startingGear = getJSONfromString<TPartialStartingGear>(String(req.body));
21
const inventory = await getInventory(accountId);
22
23
const inventoryChanges = await addStartingGear(inventory, startingGear);
24
await inventory.save();
25
26
res.send(inventoryChanges);
27
};
28
29
//TODO: RawUpgrades might need to return a LastAdded
30
const awakeningRewards = [
31
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem1",
32
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem2",
33
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem3",
34
"/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem4",
35
"/Lotus/Types/Restoratives/LisetAutoHack",
36
"/Lotus/Upgrades/Mods/Warframe/AvatarShieldMaxMod"
37
];
38
39
export const addStartingGear = async (
40
inventory: HydratedDocument<IInventoryDatabase, InventoryDocumentProps>,
41
startingGear: TPartialStartingGear | undefined = undefined
42
) => {
43
const { LongGuns, Pistols, Suits, Melee } = startingGear || {
44
LongGuns: [{ ItemType: "/Lotus/Weapons/Tenno/Rifle/Rifle" }],
45
Pistols: [{ ItemType: "/Lotus/Weapons/Tenno/Pistol/Pistol" }],
46
Suits: [{ ItemType: "/Lotus/Powersuits/Excalibur/Excalibur" }],
47
Melee: [{ ItemType: "/Lotus/Weapons/Tenno/Melee/LongSword/LongSword" }]
48
};
49
50
//TODO: properly merge weapon bin changes it is currently static here
51
const inventoryChanges: IInventoryChanges = {};
52
addEquipment(inventory, "LongGuns", LongGuns[0].ItemType, undefined, inventoryChanges);
53
addEquipment(inventory, "Pistols", Pistols[0].ItemType, undefined, inventoryChanges);
54
addEquipment(inventory, "Melee", Melee[0].ItemType, undefined, inventoryChanges);
55
addEquipment(inventory, "Suits", Suits[0].ItemType, undefined, inventoryChanges, { Configs: Suits[0].Configs });
56
addEquipment(
57
inventory,
58
"DataKnives",
59
"/Lotus/Weapons/Tenno/HackingDevices/TnHackingDevice/TnHackingDeviceWeapon",
60
undefined,
61
inventoryChanges,
62
{ XP: 450_000 }
63
);
64
addEquipment(
65
inventory,
66
"Scoops",
67
"/Lotus/Weapons/Tenno/Speedball/SpeedballWeaponTest",
68
undefined,
69
inventoryChanges
70
);
71
72
updateSlots(inventory, InventorySlot.SUITS, 0, 1);
73
updateSlots(inventory, InventorySlot.WEAPONS, 0, 3);
74
inventoryChanges.SuitBin = { count: 1, platinum: 0, Slots: -1 };
75
inventoryChanges.WeaponBin = { count: 3, platinum: 0, Slots: -3 };
76
77
await addItem(inventory, "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain");
78
inventory.ActiveQuest = "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain";
79
80
inventory.PremiumCredits = 50;
81
inventory.PremiumCreditsFree = 50;
82
inventoryChanges.PremiumCredits = 50;
83
inventoryChanges.PremiumCreditsFree = 50;
84
inventory.RegularCredits = 3000;
85
inventoryChanges.RegularCredits = 3000;
86
87
for (const item of awakeningRewards) {
88
const inventoryDelta = await addItem(inventory, item);
89
combineInventoryChanges(inventoryChanges, inventoryDelta.InventoryChanges);
90
}
91
92
inventory.PlayedParkourTutorial = true;
93
inventory.ReceivedStartingGear = true;
94
95
return inventoryChanges;
96
};
@@ -63,8 +63,6 @@ export const manageQuestsController: RequestHandler = async (req, res) => {
63
63
inventory.ArchwingEnabled = true;
64
64
}
65
65
}
66
67
inventory.ActiveQuest = "";
68
66
break;
69
67
}
70
68
case "ResetAll": {
@@ -103,7 +101,6 @@ export const manageQuestsController: RequestHandler = async (req, res) => {
103
101
inventory.ArchwingEnabled = true;
104
102
}
105
103
}
106
inventory.ActiveQuest = "";
107
104
break;
108
105
}
109
106
case "giveAll": {
@@ -64,7 +64,11 @@ import {
64
64
IKubrowPetEggClient,
65
65
ICustomMarkers,
66
66
IMarkerInfo,
67
IMarker
67
IMarker,
68
ICalendarProgress,
69
IPendingCouponDatabase,
70
IPendingCouponClient,
71
ILibraryAvailableDailyTaskInfo
68
72
} from "../../types/inventoryTypes/inventoryTypes";
69
73
import { IOid } from "../../types/commonTypes";
70
74
import {
@@ -323,7 +327,7 @@ MailboxSchema.set("toJSON", {
323
327
const DuviriInfoSchema = new Schema<IDuviriInfo>(
324
328
{
325
329
Seed: Number,
326
NumCompletions: Number
330
NumCompletions: { type: Number, default: 0 }
327
331
},
328
332
{
329
333
_id: false,
@@ -435,6 +439,7 @@ const seasonChallengeHistorySchema = new Schema<ISeasonChallenge>(
435
439
//TODO: check whether this is complete
436
440
const playerSkillsSchema = new Schema<IPlayerSkills>(
437
441
{
442
LPP_NONE: { type: Number, default: 0 },
438
443
LPP_SPACE: { type: Number, default: 0 },
439
444
LPS_PILOTING: { type: Number, default: 0 },
440
445
LPS_GUNNERY: { type: Number, default: 0 },
@@ -891,19 +896,63 @@ const CustomMarkersSchema = new Schema<ICustomMarkers>(
891
896
{ _id: false }
892
897
);
893
898
899
const calenderProgressSchema = new Schema<ICalendarProgress>(
900
{
901
Version: { type: Number, default: 19 },
902
Iteration: { type: Number, default: 2 },
903
YearProgress: {
904
Upgrades: { type: [] }
905
},
906
SeasonProgress: {
907
SeasonType: String,
908
LastCompletedDayIdx: { type: Number, default: -1 },
909
LastCompletedChallengeDayIdx: { type: Number, default: -1 },
910
ActivatedChallenges: []
911
}
912
},
913
{ _id: false }
914
);
915
916
const pendingCouponSchema = new Schema<IPendingCouponDatabase>(
917
{
918
Expiry: { type: Date, default: new Date(0) },
919
Discount: { type: Number, default: 0 }
920
},
921
{ _id: false }
922
);
923
924
pendingCouponSchema.set("toJSON", {
925
transform(_doc, ret, _options) {
926
(ret as IPendingCouponClient).Expiry = toMongoDate((ret as IPendingCouponDatabase).Expiry);
927
}
928
});
929
930
const libraryAvailableDailyTaskInfoSchema = new Schema<ILibraryAvailableDailyTaskInfo>(
931
{
932
EnemyTypes: [String],
933
EnemyLocTag: String,
934
EnemyIcon: String,
935
ScansRequired: Number,
936
RewardStoreItem: String,
937
RewardQuantity: Number,
938
RewardStanding: Number
939
},
940
{ _id: false }
941
);
942
894
943
const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
895
944
{
896
945
accountOwnerId: Schema.Types.ObjectId,
897
SubscribedToEmails: Number,
898
Created: Date,
946
SubscribedToEmails: { type: Number, default: 0 },
947
SubscribedToEmailsPersonalized: { type: Number, default: 0 },
899
948
RewardSeed: Number,
900
949
901
950
//Credit
902
951
RegularCredits: { type: Number, default: 0 },
903
952
//Platinum
904
PremiumCredits: { type: Number, default: 50 },
953
PremiumCredits: { type: Number, default: 0 },
905
954
//Gift Platinum(Non trade)
906
PremiumCreditsFree: { type: Number, default: 50 },
955
PremiumCreditsFree: { type: Number, default: 0 },
907
956
//Endo
908
957
FusionPoints: { type: Number, default: 0 },
909
958
//Regal Aya
@@ -911,7 +960,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
911
960
912
961
//Slots
913
962
SuitBin: { type: slotsBinSchema, default: { Slots: 3 } },
914
WeaponBin: { type: slotsBinSchema, default: { Slots: 10 } },
963
WeaponBin: { type: slotsBinSchema, default: { Slots: 11 } },
915
964
SentinelBin: { type: slotsBinSchema, default: { Slots: 10 } },
916
965
SpaceSuitBin: { type: slotsBinSchema, default: { Slots: 4 } },
917
966
SpaceWeaponBin: { type: slotsBinSchema, default: { Slots: 4 } },
@@ -1022,7 +1071,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1022
1071
//Complete Mission\Quests
1023
1072
Missions: [missionSchema],
1024
1073
QuestKeys: [questKeysSchema],
1025
ActiveQuest: { type: String, default: "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain" }, //TODO: check after mission starting gear
1074
ActiveQuest: { type: String, default: "" },
1026
1075
//item like DojoKey or Boss missions key
1027
1076
LevelKeys: [Schema.Types.Mixed],
1028
1077
//Active quests
@@ -1137,7 +1186,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1137
1186
//Cephalon Simaris Entries Example:"TargetType"+"Scans"(1-10)+"Completed": true|false
1138
1187
LibraryPersonalProgress: [Schema.Types.Mixed],
1139
1188
//Cephalon Simaris Daily Task
1140
LibraryAvailableDailyTaskInfo: Schema.Types.Mixed,
1189
LibraryAvailableDailyTaskInfo: libraryAvailableDailyTaskInfoSchema,
1141
1190
1142
1191
//https://warframe.fandom.com/wiki/Invasion
1143
1192
InvasionChainProgress: [Schema.Types.Mixed],
@@ -1184,7 +1233,6 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1184
1233
HandlerPoints: Number,
1185
1234
ChallengesFixVersion: Number,
1186
1235
PlayedParkourTutorial: Boolean,
1187
SubscribedToEmailsPersonalized: Number,
1188
1236
ActiveLandscapeTraps: [Schema.Types.Mixed],
1189
1237
RepVotes: [Schema.Types.Mixed],
1190
1238
LeagueTickets: [Schema.Types.Mixed],
@@ -1202,7 +1250,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1202
1250
HasResetAccount: { type: Boolean, default: false },
1203
1251
1204
1252
//Discount Coupon
1205
PendingCoupon: Schema.Types.Mixed,
1253
PendingCoupon: pendingCouponSchema,
1206
1254
//Like BossAladV,BossCaptainVor come for you on missions % chance
1207
1255
DeathMarks: [String],
1208
1256
//Zanuka
@@ -1212,7 +1260,8 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1212
1260
1213
1261
EndlessXP: { type: [endlessXpProgressSchema], default: undefined },
1214
1262
1215
DialogueHistory: dialogueHistorySchema
1263
DialogueHistory: dialogueHistorySchema,
1264
CalendarProgress: calenderProgressSchema
1216
1265
},
1217
1266
{ timestamps: { createdAt: "Created", updatedAt: false } }
1218
1267
);
@@ -87,6 +87,7 @@ import { updateSessionGetController, updateSessionPostController } from "@/src/c
87
87
import { updateThemeController } from "../controllers/api/updateThemeController";
88
88
import { upgradesController } from "@/src/controllers/api/upgradesController";
89
89
import { saveSettingsController } from "../controllers/api/saveSettingsController";
90
import { giveStartingGearController } from "@/src/controllers/api/giveStartingGearController";
90
91
91
92
const apiRouter = express.Router();
92
93
@@ -146,6 +147,7 @@ apiRouter.post("/gildWeapon.php", gildWeaponController);
146
147
apiRouter.post("/giveKeyChainTriggeredItems.php", giveKeyChainTriggeredItemsController);
147
148
apiRouter.post("/giveKeyChainTriggeredMessage.php", giveKeyChainTriggeredMessageController);
148
149
apiRouter.post("/giveQuestKeyReward.php", giveQuestKeyRewardController);
150
apiRouter.post("/giveStartingGear.php", giveStartingGearController);
149
151
apiRouter.post("/guildTech.php", guildTechController);
150
152
apiRouter.post("/hostSession.php", hostSessionController);
151
153
apiRouter.post("/infestedFoundry.php", infestedFoundryController);
@@ -2,7 +2,7 @@ import { IMessageDatabase, Inbox } from "@/src/models/inboxModel";
2
2
import { getAccountForRequest } from "@/src/services/loginService";
3
3
import { HydratedDocument } from "mongoose";
4
4
import { Request } from "express";
5
import messages from "@/static/fixed_responses/messages.json";
5
import eventMessages from "@/static/fixed_responses/eventMessages.json";
6
6
import { logger } from "@/src/utils/logger";
7
7
8
8
export const getAllMessagesSorted = async (accountId: string): Promise<HydratedDocument<IMessageDatabase>[]> => {
@@ -32,7 +32,7 @@ export const createNewEventMessages = async (req: Request) => {
32
32
const latestEventMessageDate = account.LatestEventMessageDate;
33
33
34
34
//TODO: is baroo there? create these kind of messages too (periodical messages)
35
const newEventMessages = messages.Messages.filter(m => new Date(m.eventMessageDate) > latestEventMessageDate);
35
const newEventMessages = eventMessages.Messages.filter(m => new Date(m.eventMessageDate) > latestEventMessageDate);
36
36
37
37
if (newEventMessages.length === 0) {
38
38
logger.debug(`No new event messages. Latest event message date: ${latestEventMessageDate.toISOString()}`);
@@ -22,7 +22,9 @@ import {
22
22
IDailyAffiliations,
23
23
IInventoryDatabase,
24
24
IKubrowPetEggDatabase,
25
IKubrowPetEggClient
25
IKubrowPetEggClient,
26
ILibraryAvailableDailyTaskInfo,
27
ICalendarProgress
26
28
} from "@/src/types/inventoryTypes/inventoryTypes";
27
29
import { IGenericUpdate } from "../types/genericUpdate";
28
30
import {
@@ -32,7 +34,7 @@ import {
32
34
} from "../types/requestTypes";
33
35
import { logger } from "@/src/utils/logger";
34
36
import { getExalted, getKeyChainItems } from "@/src/services/itemDataService";
35
import { IEquipmentClient, IItemConfig } from "../types/inventoryTypes/commonInventoryTypes";
37
import { IEquipmentClient, IEquipmentDatabase, IItemConfig } from "../types/inventoryTypes/commonInventoryTypes";
36
38
import {
37
39
ExportArcanes,
38
40
ExportCustoms,
@@ -51,6 +53,9 @@ import { createShip } from "./shipService";
51
53
import { creditBundles, fusionBundles } from "@/src/services/missionInventoryUpdateService";
52
54
import { IKeyChainRequest } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
53
55
import { toOid } from "../helpers/inventoryHelpers";
56
import { generateRewardSeed } from "@/src/controllers/api/getNewRewardSeedController";
57
import { addStartingGear } from "@/src/controllers/api/giveStartingGearController";
58
import { completeQuest } from "@/src/services/questService";
54
59
55
60
export const createInventory = async (
56
61
accountOwnerId: Types.ObjectId,
@@ -65,65 +70,18 @@ export const createInventory = async (
65
70
ReceivedStartingGear: config.skipTutorial
66
71
});
67
72
68
if (config.skipTutorial) {
69
const defaultEquipment = [
70
// Awakening rewards
71
{ ItemCount: 1, ItemType: "/Lotus/Powersuits/Excalibur/Excalibur" },
72
{ ItemCount: 1, ItemType: "/Lotus/Weapons/Tenno/Melee/LongSword/LongSword" },
73
{ ItemCount: 1, ItemType: "/Lotus/Weapons/Tenno/Pistol/Pistol" },
74
{ ItemCount: 1, ItemType: "/Lotus/Weapons/Tenno/Rifle/Rifle" },
75
{ ItemCount: 1, ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem1" },
76
{ ItemCount: 1, ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem2" },
77
{ ItemCount: 1, ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem3" },
78
{ ItemCount: 1, ItemType: "/Lotus/Types/StoreItems/AvatarImages/AvatarImageItem4" },
79
{ ItemCount: 1, ItemType: "/Lotus/Types/Restoratives/LisetAutoHack" }
80
];
81
82
// const vorsPrizeRewards = [
83
// // Vor's Prize rewards
84
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Warframe/AvatarHealthMaxMod" },
85
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Warframe/AvatarShieldMaxMod" },
86
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Warframe/AvatarAbilityRangeMod" },
87
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Warframe/AvatarAbilityStrengthMod" },
88
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Warframe/AvatarAbilityDurationMod" },
89
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Warframe/AvatarPickupBonusMod" },
90
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Warframe/AvatarPowerMaxMod" },
91
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Warframe/AvatarEnemyRadarMod" },
92
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Melee/WeaponFireRateMod" },
93
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Melee/WeaponMeleeDamageMod" },
94
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Rifle/WeaponFactionDamageCorpus" },
95
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Rifle/WeaponFactionDamageGrineer" },
96
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Rifle/WeaponDamageAmountMod" },
97
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Pistol/WeaponFireDamageMod" },
98
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Pistol/WeaponElectricityDamageMod" },
99
// { ItemCount: 1, ItemType: "/Lotus/Upgrades/Mods/Pistol/WeaponDamageAmountMod" },
100
// { ItemCount: 1, ItemType: "/Lotus/Types/Recipes/Weapons/BurstonRifleBlueprint" },
101
// { ItemCount: 1, ItemType: "/Lotus/Types/Items/MiscItems/Morphic" },
102
// { ItemCount: 400, ItemType: "/Lotus/Types/Items/MiscItems/PolymerBundle" },
103
// { ItemCount: 150, ItemType: "/Lotus/Types/Items/MiscItems/AlloyPlate" }
104
// ];
105
for (const equipment of defaultEquipment) {
106
await addItem(inventory, equipment.ItemType, equipment.ItemCount);
107
}
108
109
// Missing in Public Export
110
inventory.Horses.push({
111
ItemType: "/Lotus/Types/NeutralCreatures/ErsatzHorse/ErsatzHorsePowerSuit"
112
});
113
inventory.DataKnives.push({
114
ItemType: "/Lotus/Weapons/Tenno/HackingDevices/TnHackingDevice/TnHackingDeviceWeapon",
115
XP: 450000
116
});
117
inventory.Scoops.push({
118
ItemType: "/Lotus/Weapons/Tenno/Speedball/SpeedballWeaponTest"
119
});
120
inventory.DrifterMelee.push({
121
ItemType: "/Lotus/Types/Friendly/PlayerControllable/Weapons/DuviriDualSwords"
122
});
73
inventory.LibraryAvailableDailyTaskInfo = createLibraryAvailableDailyTaskInfo();
74
inventory.CalendarProgress = createCalendar();
75
inventory.RewardSeed = generateRewardSeed();
76
inventory.DuviriInfo = {
77
Seed: generateRewardSeed(),
78
NumCompletions: 0
79
};
80
await addItem(inventory, "/Lotus/Types/Friendly/PlayerControllable/Weapons/DuviriDualSwords");
123
81
124
inventory.QuestKeys.push({
125
ItemType: "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain"
126
});
82
if (config.skipTutorial) {
83
await addStartingGear(inventory);
84
await completeQuest(inventory, "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain");
127
85
128
86
const completedMissions = ["SolNode27", "SolNode89", "SolNode63", "SolNode85", "SolNode15", "SolNode79"];
129
87
@@ -133,14 +91,11 @@ export const createInventory = async (
133
91
Tag: tag
134
92
}))
135
93
);
136
137
inventory.RegularCredits = 25000;
138
inventory.FusionPoints = 180;
139
94
}
140
95
141
96
await inventory.save();
142
97
} catch (error) {
143
throw new Error(`Error creating inventory: ${error instanceof Error ? error.message : "Unknown error"}`);
98
throw new Error(`Error creating inventory: ${error instanceof Error ? error.message : "Unknown error type"}`);
144
99
}
145
100
};
146
101
@@ -150,6 +105,7 @@ export const createInventory = async (
150
105
* @param InventoryChanges - will hold the combined changes
151
106
* @param delta - inventory changes to be added
152
107
*/
108
//TODO: this fails silently when providing an incorrect object to delta
153
109
export const combineInventoryChanges = (InventoryChanges: IInventoryChanges, delta: IInventoryChanges): void => {
154
110
for (const key in delta) {
155
111
if (!(key in InventoryChanges)) {
@@ -779,15 +735,19 @@ export const addEquipment = (
779
735
category: TEquipmentKey,
780
736
type: string,
781
737
modularParts: string[] | undefined = undefined,
782
inventoryChanges: IInventoryChanges = {}
738
inventoryChanges: IInventoryChanges = {},
739
defaultOverwrites: Partial<IEquipmentDatabase> | undefined = undefined
783
740
): IInventoryChanges => {
784
const index =
785
inventory[category].push({
741
const equipment = Object.assign(
742
{
786
743
ItemType: type,
787
744
Configs: [],
788
745
XP: 0,
789
746
ModularParts: modularParts
790
}) - 1;
747
},
748
defaultOverwrites
749
);
750
const index = inventory[category].push(equipment) - 1;
791
751
792
752
inventoryChanges[category] ??= [];
793
753
inventoryChanges[category].push(inventory[category][index].toJSON<IEquipmentClient>());
@@ -1173,3 +1133,28 @@ export const addKeyChainItems = async (
1173
1133
1174
1134
return inventoryChanges;
1175
1135
};
1136
const createLibraryAvailableDailyTaskInfo = (): ILibraryAvailableDailyTaskInfo => {
1137
return {
1138
EnemyTypes: ["/Lotus/Types/Enemies/Orokin/RifleLancerAvatar"],
1139
EnemyLocTag: "/Lotus/Language/Game/CorruptedLancer",
1140
EnemyIcon: "/Lotus/Interface/Icons/Npcs/OrokinRifleLancerAvatar.png",
1141
ScansRequired: 3,
1142
RewardStoreItem: "/Lotus/StoreItems/Upgrades/Mods/FusionBundles/UncommonFusionBundle",
1143
RewardQuantity: 7,
1144
RewardStanding: 7500
1145
};
1146
};
1147
1148
const createCalendar = (): ICalendarProgress => {
1149
return {
1150
Version: 19,
1151
Iteration: 2,
1152
YearProgress: { Upgrades: [] },
1153
SeasonProgress: {
1154
SeasonType: "CST_SPRING",
1155
LastCompletedDayIdx: -1,
1156
LastCompletedChallengeDayIdx: -1,
1157
ActivatedChallenges: []
1158
}
1159
};
1160
};
@@ -126,7 +126,8 @@ export const completeQuest = async (inventory: TInventoryDatabaseDocument, quest
126
126
});
127
127
}
128
128
}
129
//TODO: handle quest completions
129
inventory.ActiveQuest = "";
130
//TODO: handle quest completion items
130
131
};
131
132
132
133
export const giveKeyChainItem = async (inventory: TInventoryDatabaseDocument, keyChainInfo: IKeyChainRequest) => {
@@ -38,6 +38,7 @@ export interface IInventoryDatabase
38
38
| "InfestedFoundry"
39
39
| "DialogueHistory"
40
40
| "KubrowPetEggs"
41
| "PendingCoupon"
41
42
| TEquipmentKey
42
43
>,
43
44
InventoryDatabaseEquipment {
@@ -61,6 +62,7 @@ export interface IInventoryDatabase
61
62
InfestedFoundry?: IInfestedFoundryDatabase;
62
63
DialogueHistory?: IDialogueHistoryDatabase;
63
64
KubrowPetEggs?: IKubrowPetEggDatabase[];
65
PendingCoupon: IPendingCouponDatabase;
64
66
}
65
67
66
68
export interface IQuestKeyDatabase {
@@ -318,11 +320,12 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
318
320
CollectibleSeries: ICollectibleSery[];
319
321
LibraryAvailableDailyTaskInfo: ILibraryAvailableDailyTaskInfo;
320
322
HasResetAccount: boolean;
321
PendingCoupon: IPendingCoupon;
323
PendingCoupon: IPendingCouponClient;
322
324
Harvestable: boolean;
323
325
DeathSquadable: boolean;
324
326
EndlessXP?: IEndlessXpProgress[];
325
327
DialogueHistory?: IDialogueHistoryClient;
328
CalendarProgress: ICalendarProgress;
326
329
}
327
330
328
331
export interface IAffiliation {
@@ -759,7 +762,12 @@ export enum Manifest {
759
762
LotusTypesGameNemesisKuvaLichKuvaLichManifestVersionTwo = "/Lotus/Types/Game/Nemesis/KuvaLich/KuvaLichManifestVersionTwo"
760
763
}
761
764
762
export interface IPendingCoupon {
765
export interface IPendingCouponDatabase {
766
Expiry: Date;
767
Discount: number;
768
}
769
770
export interface IPendingCouponClient {
763
771
Expiry: IMongoDate;
764
772
Discount: number;
765
773
}
@@ -858,6 +866,7 @@ export interface IPersonalTechProject {
858
866
}
859
867
860
868
export interface IPlayerSkills {
869
LPP_NONE: number;
861
870
LPP_SPACE: number;
862
871
LPS_PILOTING: number;
863
872
LPS_GUNNERY: number;
@@ -1042,3 +1051,16 @@ export interface IMarker {
1042
1051
z: number;
1043
1052
showInHud: boolean;
1044
1053
}
1054
export interface ISeasonProgress {
1055
SeasonType: "CST_UNDEFINED" | "CST_WINTER" | "CST_SPRING" | "CST_SUMMER" | "CST_FALL";
1056
LastCompletedDayIdx: number;
1057
LastCompletedChallengeDayIdx: number;
1058
ActivatedChallenges: unknown[];
1059
}
1060
1061
export interface ICalendarProgress {
1062
Version: number;
1063
Iteration: number;
1064
YearProgress: { Upgrades: unknown[] };
1065
SeasonProgress: ISeasonProgress;
1066
}
@@ -0,0 +1,12 @@
1
{
2
"Messages": [
3
{
4
"sub": "Welcome to Space Ninja Server",
5
"sndr": "/Lotus/Language/Bosses/Ordis",
6
"msg": "Enjoy your Space Ninja Experience",
7
"icon": "/Lotus/Interface/Icons/Npcs/Darvo.png",
8
"eventMessageDate": "2025-01-30T13:00:00.000Z",
9
"r": false
10
}
11
]
12
}
@@ -1,49 +0,0 @@
1
{
2
"Messages": [
3
{
4
"sub": "Welcome to Space Ninja Server",
5
"sndr": "/Lotus/Language/Bosses/Ordis",
6
"msg": "Enjoy your Space Ninja Experience",
7
"icon": "/Lotus/Interface/Icons/Npcs/Darvo.png",
8
"eventMessageDate": "2025-01-30T13:00:00.000Z",
9
"r": false
10
},
11
{
12
"sub": "/Lotus/Language/Inbox/DarvoWeaponCraftingMessageBTitle",
13
"sndr": "/Lotus/Language/Bosses/Darvo",
14
"msg": "/Lotus/Language/Inbox/DarvoWeaponCraftingMessageBDesc",
15
"icon": "/Lotus/Interface/Icons/Npcs/Darvo.png",
16
"countedAtt": [
17
{
18
"ItemCount": 1,
19
"ItemType": "/Lotus/Types/Recipes/Weapons/BurstonRifleBlueprint"
20
},
21
{
22
"ItemCount": 1,
23
"ItemType": "/Lotus/Types/Items/MiscItems/Morphic"
24
},
25
{
26
"ItemCount": 400,
27
"ItemType": "/Lotus/Types/Items/MiscItems/PolymerBundle"
28
},
29
{
30
"ItemCount": 150,
31
"ItemType": "/Lotus/Types/Items/MiscItems/AlloyPlate"
32
}
33
],
34
"highPriority": true,
35
"eventMessageDate": "2023-10-01T17:00:00.000Z",
36
"r": false
37
},
38
{
39
"sub": "/Lotus/Language/G1Quests/Beginner_Growth_Inbox_Title",
40
"sndr": "/Lotus/Language/Menu/Mailbox_WarframeSender",
41
"msg": "/Lotus/Language/G1Quests/Beginner_Growth_Inbox_Desc",
42
"icon": "/Lotus/Interface/Icons/Npcs/Lotus_d.png",
43
"transmission": "/Lotus/Sounds/Dialog/VorsPrize/DLisetPostAssassinate110Lotus",
44
"highPriority": true,
45
"eventMessageDate": "2023-09-01T17:00:00.000Z",
46
"r": false
47
}
48
]
49
}