XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFESpaceNinjaServer

feat(webui): KubrowPets support (#1752)

also using `/api/modularWeaponCrafting.php` instead of `/custom/addModularEquipment` for modular equipment Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1752 Reviewed-by: Sainan <sainan@calamity.inc> Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>

98975edc
AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
提交于

代码差异

15 个文件 +538 -176
Modified src/controllers/api/modularWeaponCraftingController.ts +26 -19
@@ -23,6 +23,7 @@ import { Status } from "@/src/types/inventoryTypes/inventoryTypes";
23 23 interface IModularCraftRequest {
24 24 WeaponType: string;
25 25 Parts: string[];
26 isWebUi?: boolean;
26 27 }
27 28
28 29 export const modularWeaponCraftingController: RequestHandler = async (req, res) => {
@@ -139,33 +140,39 @@ export const modularWeaponCraftingController: RequestHandler = async (req, res)
139 140 }
140 141 defaultOverwrites.Configs = applyDefaultUpgrades(inventory, defaultUpgrades);
141 142 addEquipment(inventory, category, data.WeaponType, data.Parts, inventoryChanges, defaultOverwrites);
142 combineInventoryChanges(inventoryChanges, occupySlot(inventory, productCategoryToInventoryBin(category)!, false));
143 combineInventoryChanges(
144 inventoryChanges,
145 occupySlot(inventory, productCategoryToInventoryBin(category)!, !!data.isWebUi)
146 );
143 147 if (defaultUpgrades) {
144 148 inventoryChanges.RawUpgrades = defaultUpgrades.map(x => ({ ItemType: x.ItemType, ItemCount: 1 }));
145 149 }
146 150
147 151 // Remove credits & parts
148 152 const miscItemChanges = [];
149 for (const part of data.Parts) {
150 miscItemChanges.push({
151 ItemType: part,
152 ItemCount: -1
153 });
153 let currencyChanges = {};
154 if (!data.isWebUi) {
155 for (const part of data.Parts) {
156 miscItemChanges.push({
157 ItemType: part,
158 ItemCount: -1
159 });
160 }
161 currencyChanges = updateCurrency(
162 inventory,
163 category == "Hoverboards" ||
164 category == "MoaPets" ||
165 category == "LongGuns" ||
166 category == "Pistols" ||
167 category == "KubrowPets"
168 ? 5000
169 : 4000, // Definitely correct for Melee & OperatorAmps
170 false
171 );
172 addMiscItems(inventory, miscItemChanges);
154 173 }
155 const currencyChanges = updateCurrency(
156 inventory,
157 category == "Hoverboards" ||
158 category == "MoaPets" ||
159 category == "LongGuns" ||
160 category == "Pistols" ||
161 category == "KubrowPets"
162 ? 5000
163 : 4000, // Definitely correct for Melee & OperatorAmps
164 false
165 );
166 addMiscItems(inventory, miscItemChanges);
167 await inventory.save();
168 174
175 await inventory.save();
169 176 // Tell client what we did
170 177 res.json({
171 178 InventoryChanges: {
Modified src/controllers/api/releasePetController.ts +6 -2
@@ -8,7 +8,11 @@ export const releasePetController: RequestHandler = async (req, res) => {
8 8 const inventory = await getInventory(accountId, "RegularCredits KubrowPets");
9 9 const payload = getJSONfromString<IReleasePetRequest>(String(req.body));
10 10
11 const inventoryChanges = updateCurrency(inventory, 25000, false);
11 const inventoryChanges = updateCurrency(
12 inventory,
13 payload.recipeName == "/Lotus/Types/Game/KubrowPet/ReleasePetRecipe" ? 25000 : 0,
14 false
15 );
12 16
13 17 inventoryChanges.RemovedIdItems = [{ ItemId: { $oid: payload.petId } }];
14 18 inventory.KubrowPets.pull({ _id: payload.petId });
@@ -18,6 +22,6 @@ export const releasePetController: RequestHandler = async (req, res) => {
18 22 };
19 23
20 24 interface IReleasePetRequest {
21 recipeName: "/Lotus/Types/Game/KubrowPet/ReleasePetRecipe";
25 recipeName: "/Lotus/Types/Game/KubrowPet/ReleasePetRecipe" | "webui";
22 26 petId: string;
23 27 }
Deleted src/controllers/custom/addModularEquipmentController.ts +0 -98
@@ -1,98 +0,0 @@
1 import { getAccountIdForRequest } from "@/src/services/loginService";
2 import {
3 getInventory,
4 addEquipment,
5 occupySlot,
6 productCategoryToInventoryBin,
7 applyDefaultUpgrades
8 } from "@/src/services/inventoryService";
9 import { modularWeaponTypes } from "@/src/helpers/modularWeaponHelper";
10 import { getDefaultUpgrades } from "@/src/services/itemDataService";
11 import { IEquipmentDatabase } from "@/src/types/inventoryTypes/commonInventoryTypes";
12 import { ExportWeapons } from "warframe-public-export-plus";
13 import { RequestHandler } from "express";
14
15 export const addModularEquipmentController: RequestHandler = async (req, res) => {
16 const requiredFields = new Set();
17 const accountId = await getAccountIdForRequest(req);
18 const request = req.body as IAddModularEquipmentRequest;
19 const category = modularWeaponTypes[request.ItemType];
20 const inventoryBin = productCategoryToInventoryBin(category)!;
21 requiredFields.add(category);
22 requiredFields.add(inventoryBin);
23
24 request.ModularParts.forEach(part => {
25 if (ExportWeapons[part].gunType) {
26 if (category == "LongGuns") {
27 request.ItemType = {
28 GT_RIFLE: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary",
29 GT_SHOTGUN: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryShotgun",
30 GT_BEAM: "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryBeam"
31 }[ExportWeapons[part].gunType];
32 } else {
33 request.ItemType = {
34 GT_RIFLE: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary",
35 GT_SHOTGUN: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun",
36 GT_BEAM: "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam"
37 }[ExportWeapons[part].gunType];
38 }
39 } else if (request.ItemType == "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetPowerSuit") {
40 if (part.includes("ZanukaPetPartHead")) {
41 request.ItemType = {
42 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA":
43 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetAPowerSuit",
44 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB":
45 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetBPowerSuit",
46 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC":
47 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetCPowerSuit"
48 }[part]!;
49 }
50 }
51 });
52 const defaultUpgrades = getDefaultUpgrades(request.ModularParts);
53 if (defaultUpgrades) {
54 requiredFields.add("RawUpgrades");
55 }
56 const defaultWeaponsMap: Record<string, string[]> = {
57 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetAPowerSuit": [
58 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetMeleeWeaponIP"
59 ],
60 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetBPowerSuit": [
61 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetMeleeWeaponIS"
62 ],
63 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetCPowerSuit": [
64 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetMeleeWeaponPS"
65 ]
66 };
67 const defaultWeapons = defaultWeaponsMap[request.ItemType] as string[] | undefined;
68 if (defaultWeapons) {
69 for (const defaultWeapon of defaultWeapons) {
70 const category = ExportWeapons[defaultWeapon].productCategory;
71 requiredFields.add(category);
72 requiredFields.add(productCategoryToInventoryBin(category));
73 }
74 }
75
76 const inventory = await getInventory(accountId, Array.from(requiredFields).join(" "));
77 if (defaultWeapons) {
78 for (const defaultWeapon of defaultWeapons) {
79 const category = ExportWeapons[defaultWeapon].productCategory;
80 addEquipment(inventory, category, defaultWeapon);
81 occupySlot(inventory, productCategoryToInventoryBin(category)!, true);
82 }
83 }
84
85 const defaultOverwrites: Partial<IEquipmentDatabase> = {
86 Configs: applyDefaultUpgrades(inventory, defaultUpgrades)
87 };
88
89 addEquipment(inventory, category, request.ItemType, request.ModularParts, undefined, defaultOverwrites);
90 occupySlot(inventory, inventoryBin, true);
91 await inventory.save();
92 res.end();
93 };
94
95 interface IAddModularEquipmentRequest {
96 ItemType: string;
97 ModularParts: string[];
98 }
Modified src/controllers/custom/getItemListsController.ts +9 -6
@@ -56,6 +56,7 @@ const getItemListsController: RequestHandler = (req, response) => {
56 56 res.Syndicates = [];
57 57 res.OperatorAmps = [];
58 58 res.QuestKeys = [];
59 res.KubrowPets = [];
59 60 for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
60 61 res[item.productCategory].push({
61 62 uniqueName,
@@ -64,7 +65,7 @@ const getItemListsController: RequestHandler = (req, response) => {
64 65 });
65 66 }
66 67 for (const [uniqueName, item] of Object.entries(ExportSentinels)) {
67 if (item.productCategory == "Sentinels") {
68 if (item.productCategory != "SpecialItems") {
68 69 res[item.productCategory].push({
69 70 uniqueName,
70 71 name: getString(item.name, lang)
@@ -73,11 +74,13 @@ const getItemListsController: RequestHandler = (req, response) => {
73 74 }
74 75 for (const [uniqueName, item] of Object.entries(ExportWeapons)) {
75 76 if (item.partType) {
76 res.ModularParts.push({
77 uniqueName,
78 name: getString(item.name, lang),
79 partType: item.partType
80 });
77 if (!uniqueName.startsWith("/Lotus/Types/Items/Deimos/")) {
78 res.ModularParts.push({
79 uniqueName,
80 name: getString(item.name, lang),
81 partType: item.partType
82 });
83 }
81 84 if (uniqueName.split("/")[5] != "SentTrainingAmplifier") {
82 85 res.miscitems.push({
83 86 uniqueName: uniqueName,
Modified src/helpers/inventoryHelpers.ts +142 -0
@@ -1,5 +1,6 @@
1 1 import { IMongoDate, IOid } from "@/src/types/commonTypes";
2 2 import { Types } from "mongoose";
3 import { TRarity } from "warframe-public-export-plus";
3 4
4 5 export const toOid = (objectId: Types.ObjectId): IOid => {
5 6 return { $oid: objectId.toString() } satisfies IOid;
@@ -8,3 +9,144 @@ export const toOid = (objectId: Types.ObjectId): IOid => {
8 9 export const toMongoDate = (date: Date): IMongoDate => {
9 10 return { $date: { $numberLong: date.getTime().toString() } };
10 11 };
12
13 export const kubrowWeights: Record<TRarity, number> = {
14 COMMON: 6,
15 UNCOMMON: 4,
16 RARE: 2,
17 LEGENDARY: 1
18 };
19
20 export const kubrowFurPatternsWeights: Record<TRarity, number> = {
21 COMMON: 6,
22 UNCOMMON: 5,
23 RARE: 2,
24 LEGENDARY: 1
25 };
26
27 export const catbrowDetails = {
28 Colors: [
29 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseA", rarity: "COMMON" as TRarity },
30 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseB", rarity: "COMMON" as TRarity },
31 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseC", rarity: "COMMON" as TRarity },
32 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseD", rarity: "COMMON" as TRarity },
33
34 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryA", rarity: "UNCOMMON" as TRarity },
35 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryB", rarity: "UNCOMMON" as TRarity },
36 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryC", rarity: "UNCOMMON" as TRarity },
37 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryD", rarity: "UNCOMMON" as TRarity },
38
39 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryA", rarity: "RARE" as TRarity },
40 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryB", rarity: "RARE" as TRarity },
41 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryC", rarity: "RARE" as TRarity },
42 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryD", rarity: "RARE" as TRarity },
43
44 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsA", rarity: "LEGENDARY" as TRarity },
45 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsB", rarity: "LEGENDARY" as TRarity },
46 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsC", rarity: "LEGENDARY" as TRarity },
47 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsD", rarity: "LEGENDARY" as TRarity }
48 ],
49
50 EyeColors: [
51 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesA", rarity: "LEGENDARY" as TRarity },
52 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesB", rarity: "LEGENDARY" as TRarity },
53 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesC", rarity: "LEGENDARY" as TRarity },
54 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesD", rarity: "LEGENDARY" as TRarity },
55 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesE", rarity: "LEGENDARY" as TRarity },
56 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesF", rarity: "LEGENDARY" as TRarity },
57 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesG", rarity: "LEGENDARY" as TRarity },
58 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesH", rarity: "LEGENDARY" as TRarity },
59 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesI", rarity: "LEGENDARY" as TRarity },
60 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesJ", rarity: "LEGENDARY" as TRarity },
61 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesK", rarity: "LEGENDARY" as TRarity },
62 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesL", rarity: "LEGENDARY" as TRarity },
63 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesM", rarity: "LEGENDARY" as TRarity },
64 { type: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorEyesN", rarity: "LEGENDARY" as TRarity }
65 ],
66
67 FurPatterns: [{ type: "/Lotus/Types/Game/CatbrowPet/Patterns/CatbrowPetPatternA", rarity: "COMMON" as TRarity }],
68
69 BodyTypes: [
70 { type: "/Lotus/Types/Game/CatbrowPet/BodyTypes/CatbrowPetRegularBodyType", rarity: "UNCOMMON" as TRarity },
71 { type: "/Lotus/Types/Game/CatbrowPet/BodyTypes/CatbrowPetRegularBodyType", rarity: "LEGENDARY" as TRarity }
72 ],
73
74 Heads: [
75 { type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadA", rarity: "LEGENDARY" as TRarity },
76 { type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadB", rarity: "LEGENDARY" as TRarity },
77 { type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadC", rarity: "LEGENDARY" as TRarity },
78 { type: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadD", rarity: "LEGENDARY" as TRarity }
79 ],
80
81 Tails: [
82 { type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailA", rarity: "LEGENDARY" as TRarity },
83 { type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailB", rarity: "LEGENDARY" as TRarity },
84 { type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailC", rarity: "LEGENDARY" as TRarity },
85 { type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailD", rarity: "LEGENDARY" as TRarity },
86 { type: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailE", rarity: "LEGENDARY" as TRarity }
87 ]
88 };
89
90 export const kubrowDetails = {
91 Colors: [
92 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneA", rarity: "UNCOMMON" as TRarity },
93 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneB", rarity: "UNCOMMON" as TRarity },
94 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneC", rarity: "UNCOMMON" as TRarity },
95 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneD", rarity: "UNCOMMON" as TRarity },
96 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneE", rarity: "UNCOMMON" as TRarity },
97 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneF", rarity: "UNCOMMON" as TRarity },
98 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneG", rarity: "UNCOMMON" as TRarity },
99 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMundaneH", rarity: "UNCOMMON" as TRarity },
100
101 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidA", rarity: "RARE" as TRarity },
102 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidB", rarity: "RARE" as TRarity },
103 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidC", rarity: "RARE" as TRarity },
104 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidD", rarity: "RARE" as TRarity },
105 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidE", rarity: "RARE" as TRarity },
106 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidF", rarity: "RARE" as TRarity },
107 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidG", rarity: "RARE" as TRarity },
108 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorMidH", rarity: "RARE" as TRarity },
109
110 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantA", rarity: "LEGENDARY" as TRarity },
111 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantB", rarity: "LEGENDARY" as TRarity },
112 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantC", rarity: "LEGENDARY" as TRarity },
113 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantD", rarity: "LEGENDARY" as TRarity },
114 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantE", rarity: "LEGENDARY" as TRarity },
115 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantF", rarity: "LEGENDARY" as TRarity },
116 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantG", rarity: "LEGENDARY" as TRarity },
117 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorVibrantH", rarity: "LEGENDARY" as TRarity }
118 ],
119
120 EyeColors: [
121 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesA", rarity: "LEGENDARY" as TRarity },
122 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesB", rarity: "LEGENDARY" as TRarity },
123 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesC", rarity: "LEGENDARY" as TRarity },
124 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesD", rarity: "LEGENDARY" as TRarity },
125 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesE", rarity: "LEGENDARY" as TRarity },
126 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesF", rarity: "LEGENDARY" as TRarity },
127 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesG", rarity: "LEGENDARY" as TRarity },
128 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesH", rarity: "LEGENDARY" as TRarity },
129 { type: "/Lotus/Types/Game/KubrowPet/Colors/KubrowPetColorEyesI", rarity: "LEGENDARY" as TRarity }
130 ],
131
132 FurPatterns: [
133 { type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternB", rarity: "UNCOMMON" as TRarity },
134 { type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternA", rarity: "UNCOMMON" as TRarity },
135
136 { type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternC", rarity: "RARE" as TRarity },
137 { type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternD", rarity: "RARE" as TRarity },
138
139 { type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternE", rarity: "LEGENDARY" as TRarity },
140 { type: "/Lotus/Types/Game/KubrowPet/Patterns/KubrowPetPatternF", rarity: "LEGENDARY" as TRarity }
141 ],
142
143 BodyTypes: [
144 { type: "/Lotus/Types/Game/KubrowPet/BodyTypes/KubrowPetRegularBodyType", rarity: "UNCOMMON" as TRarity },
145 { type: "/Lotus/Types/Game/KubrowPet/BodyTypes/KubrowPetHeavyBodyType", rarity: "LEGENDARY" as TRarity },
146 { type: "/Lotus/Types/Game/KubrowPet/BodyTypes/KubrowPetThinBodyType", rarity: "LEGENDARY" as TRarity }
147 ],
148
149 Heads: [],
150
151 Tails: []
152 };
Modified src/routes/custom.ts +0 -2
@@ -15,7 +15,6 @@ import { createAccountController } from "@/src/controllers/custom/createAccountC
15 15 import { createMessageController } from "@/src/controllers/custom/createMessageController";
16 16 import { addCurrencyController } from "@/src/controllers/custom/addCurrencyController";
17 17 import { addItemsController } from "@/src/controllers/custom/addItemsController";
18 import { addModularEquipmentController } from "@/src/controllers/custom/addModularEquipmentController";
19 18 import { addXpController } from "@/src/controllers/custom/addXpController";
20 19 import { importController } from "@/src/controllers/custom/importController";
21 20
@@ -40,7 +39,6 @@ customRouter.post("/createAccount", createAccountController);
40 39 customRouter.post("/createMessage", createMessageController);
41 40 customRouter.post("/addCurrency", addCurrencyController);
42 41 customRouter.post("/addItems", addItemsController);
43 customRouter.post("/addModularEquipment", addModularEquipmentController);
44 42 customRouter.post("/addXp", addXpController);
45 43 customRouter.post("/import", importController);
46 44 customRouter.post("/manageQuests", manageQuestsController);
Modified src/services/inventoryService.ts +101 -3
@@ -23,7 +23,10 @@ import {
23 23 IUpgradeClient,
24 24 TPartialStartingGear,
25 25 ILoreFragmentScan,
26 ICrewMemberClient
26 ICrewMemberClient,
27 Status,
28 IKubrowPetDetailsDatabase,
29 ITraits
27 30 } from "@/src/types/inventoryTypes/inventoryTypes";
28 31 import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
29 32 import { IKeyChainRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes";
@@ -58,14 +61,21 @@ import {
58 61 ExportWeapons,
59 62 IDefaultUpgrade,
60 63 IPowersuit,
64 ISentinel,
61 65 TStandingLimitBin
62 66 } from "warframe-public-export-plus";
63 67 import { createShip } from "./shipService";
64 import { toOid } from "../helpers/inventoryHelpers";
68 import {
69 catbrowDetails,
70 kubrowDetails,
71 kubrowFurPatternsWeights,
72 kubrowWeights,
73 toOid
74 } from "../helpers/inventoryHelpers";
65 75 import { addQuestKey, completeQuest } from "@/src/services/questService";
66 76 import { handleBundleAcqusition } from "./purchaseService";
67 77 import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
68 import { getRandomElement, getRandomInt, SRng } from "./rngService";
78 import { getRandomElement, getRandomInt, getRandomWeightedReward, SRng } from "./rngService";
69 79 import { createMessage } from "./inboxService";
70 80 import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
71 81
@@ -714,6 +724,11 @@ export const addItem = async (
714 724 return {
715 725 MiscItems: miscItemChanges
716 726 };
727 } else if (
728 typeName.substr(1).split("/")[3] == "CatbrowPet" ||
729 typeName.substr(1).split("/")[3] == "KubrowPet"
730 ) {
731 return addKubrowPet(inventory, typeName, undefined, premiumPurchase);
717 732 } else if (typeName.startsWith("/Lotus/Types/Game/CrewShip/CrewMember/")) {
718 733 if (!seed) {
719 734 throw new Error(`Expected crew member to have a seed`);
@@ -932,6 +947,89 @@ export const addSpaceSuit = (
932 947 return inventoryChanges;
933 948 };
934 949
950 export const addKubrowPet = (
951 inventory: TInventoryDatabaseDocument,
952 kubrowPetName: string,
953 details: IKubrowPetDetailsDatabase | undefined,
954 premiumPurchase: boolean,
955 inventoryChanges: IInventoryChanges = {}
956 ): IInventoryChanges => {
957 combineInventoryChanges(inventoryChanges, occupySlot(inventory, InventorySlot.SENTINELS, premiumPurchase));
958
959 const kubrowPet = ExportSentinels[kubrowPetName] as ISentinel | undefined;
960 const exalted = kubrowPet?.exalted ?? [];
961 for (const specialItem of exalted) {
962 addSpecialItem(inventory, specialItem, inventoryChanges);
963 }
964
965 // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
966 const configs: IItemConfig[] = applyDefaultUpgrades(inventory, kubrowPet?.defaultUpgrades);
967
968 if (!details) {
969 let traits: ITraits;
970
971 if (kubrowPetName == "/Lotus/Types/Game/CatbrowPet/VampireCatbrowPetPowerSuit") {
972 traits = {
973 BaseColor: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseVampire",
974 SecondaryColor: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorSecondaryVampire",
975 TertiaryColor: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorTertiaryVampire",
976 AccentColor: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorAccentsVampire",
977 EyeColor: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseA",
978 FurPattern: "/Lotus/Types/Game/CatbrowPet/Patterns/CatbrowPetPatternVampire",
979 Personality: kubrowPetName,
980 BodyType: "/Lotus/Types/Game/CatbrowPet/BodyTypes/CatbrowPetVampireBodyType",
981 Head: "/Lotus/Types/Game/CatbrowPet/Heads/CatbrowHeadVampire",
982 Tail: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailVampire"
983 };
984 } else {
985 const isCatbrow = [
986 "/Lotus/Types/Game/CatbrowPet/MirrorCatbrowPetPowerSuit",
987 "/Lotus/Types/Game/CatbrowPet/CheshireCatbrowPetPowerSuit"
988 ].includes(kubrowPetName);
989 const traitsPool = isCatbrow ? catbrowDetails : kubrowDetails;
990
991 traits = {
992 BaseColor: getRandomWeightedReward(traitsPool.Colors, kubrowWeights)!.type,
993 SecondaryColor: getRandomWeightedReward(traitsPool.Colors, kubrowWeights)!.type,
994 TertiaryColor: getRandomWeightedReward(traitsPool.Colors, kubrowWeights)!.type,
995 AccentColor: getRandomWeightedReward(traitsPool.Colors, kubrowWeights)!.type,
996 EyeColor: getRandomWeightedReward(traitsPool.EyeColors, kubrowWeights)!.type,
997 FurPattern: getRandomWeightedReward(traitsPool.FurPatterns, kubrowFurPatternsWeights)!.type,
998 Personality: kubrowPetName,
999 BodyType: getRandomWeightedReward(traitsPool.BodyTypes, kubrowWeights)!.type,
1000 Head: isCatbrow ? getRandomWeightedReward(traitsPool.Heads, kubrowWeights)!.type : undefined,
1001 Tail: isCatbrow ? getRandomWeightedReward(traitsPool.Tails, kubrowWeights)!.type : undefined
1002 };
1003 }
1004
1005 details = {
1006 Name: "",
1007 IsPuppy: false,
1008 HasCollar: true,
1009 PrintsRemaining: 2,
1010 Status: Status.StatusStasis,
1011 HatchDate: new Date(Math.trunc(Date.now() / 86400000) * 86400000),
1012 IsMale: !!getRandomInt(0, 1),
1013 Size: getRandomInt(70, 100) / 100,
1014 DominantTraits: traits,
1015 RecessiveTraits: traits
1016 };
1017 }
1018
1019 const kubrowPetIndex =
1020 inventory.KubrowPets.push({
1021 ItemType: kubrowPetName,
1022 Configs: configs,
1023 XP: 0,
1024 Details: details,
1025 IsNew: true
1026 }) - 1;
1027 inventoryChanges.KubrowPets ??= [];
1028 inventoryChanges.KubrowPets.push(inventory.KubrowPets[kubrowPetIndex].toJSON<IEquipmentClient>());
1029
1030 return inventoryChanges;
1031 };
1032
935 1033 export const updateSlots = (
936 1034 inventory: TInventoryDatabaseDocument,
937 1035 slotName: SlotNames,
Modified static/webui/index.html +28 -1
@@ -305,7 +305,7 @@
305 305 <input class="form-control" id="acquire-type-MoaPets" list="datalist-MoaPets" />
306 306 <button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
307 307 </form>
308 <form class="input-group mb-3" id="modular-MoaPets" style="display: none;">
308 <form class="input-group mb-3" id="modular-MoaPets-Moa" style="display: none;">
309 309 <input class="form-control" id="acquire-type-MoaPets-MOA_ENGINE" list="datalist-ModularParts-MOA_ENGINE" />
310 310 <input class="form-control" id="acquire-type-MoaPets-MOA_PAYLOAD" list="datalist-ModularParts-MOA_PAYLOAD" />
311 311 <input class="form-control" id="acquire-type-MoaPets-MOA_HEAD" list="datalist-ModularParts-MOA_HEAD" />
@@ -325,6 +325,28 @@
325 325 </div>
326 326 </div>
327 327 <div class="row g-3">
328 <div class="col-lg-6">
329 <div class="card mb-3" style="height: 400px;">
330 <h5 class="card-header" data-loc="inventory_kubrowPets"></h5>
331 <div class="card-body overflow-auto">
332 <form class="input-group mb-3" onsubmit="handleModularSelection('KubrowPets');return false;">
333 <input class="form-control" id="acquire-type-KubrowPets" list="datalist-KubrowPets" />
334 <button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
335 </form>
336 <form class="input-group mb-3" id="modular-KubrowPets-Catbrow" style="display: none;">
337 <input class="form-control" id="acquire-type-KubrowPets-CATBROW_ANTIGEN" list="datalist-ModularParts-CATBROW_ANTIGEN" />
338 <input class="form-control" id="acquire-type-KubrowPets-CATBROW_MUTAGEN" list="datalist-ModularParts-CATBROW_MUTAGEN" />
339 </form>
340 <form class="input-group mb-3" id="modular-KubrowPets-Kubrow" style="display: none;">
341 <input class="form-control" id="acquire-type-KubrowPets-KUBROW_ANTIGEN" list="datalist-ModularParts-KUBROW_ANTIGEN" />
342 <input class="form-control" id="acquire-type-KubrowPets-KUBROW_MUTAGEN" list="datalist-ModularParts-KUBROW_MUTAGEN" />
343 </form>
344 <table class="table table-hover w-100">
345 <tbody id="KubrowPets-list"></tbody>
346 </table>
347 </div>
348 </div>
349 </div>
328 350 <div class="col-lg-6">
329 351 <div class="card mb-3" style="height: 400px;">
330 352 <h5 class="card-header" data-loc="inventory_sentinelWeapons"></h5>
@@ -700,6 +722,7 @@
700 722 <datalist id="datalist-Sentinels"></datalist>
701 723 <datalist id="datalist-MechSuits"></datalist>
702 724 <datalist id="datalist-MoaPets"></datalist>
725 <datalist id="datalist-KubrowPets"></datalist>
703 726 <datalist id="datalist-QuestKeys"></datalist>
704 727 <datalist id="datalist-miscitems"></datalist>
705 728 <datalist id="datalist-mods">
@@ -731,6 +754,10 @@
731 754 <datalist id="datalist-ModularParts-ZANUKA_HEAD"></datalist>
732 755 <datalist id="datalist-ModularParts-ZANUKA_LEG"></datalist>
733 756 <datalist id="datalist-ModularParts-ZANUKA_TAIL"></datalist>
757 <datalist id="datalist-ModularParts-CATBROW_ANTIGEN"></datalist>
758 <datalist id="datalist-ModularParts-CATBROW_MUTAGEN"></datalist>
759 <datalist id="datalist-ModularParts-KUBROW_ANTIGEN"></datalist>
760 <datalist id="datalist-ModularParts-KUBROW_MUTAGEN"></datalist>
734 761 <script src="/webui/libs/jquery-3.6.0.min.js"></script>
735 762 <script src="/webui/libs/whirlpool-js.min.js"></script>
736 763 <script src="/webui/libs/single.js"></script>
Modified static/webui/script.js +208 -45
@@ -163,7 +163,13 @@ const webUiModularWeapons = [
163 163 "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary",
164 164 "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary",
165 165 "/Lotus/Types/Friendly/Pets/MoaPets/MoaPetPowerSuit",
166 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetPowerSuit"
166 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetPowerSuit",
167 "/Lotus/Types/Friendly/Pets/CreaturePets/VulpineInfestedCatbrowPetPowerSuit",
168 "/Lotus/Types/Friendly/Pets/CreaturePets/HornedInfestedCatbrowPetPowerSuit",
169 "/Lotus/Types/Friendly/Pets/CreaturePets/ArmoredInfestedCatbrowPetPowerSuit",
170 "/Lotus/Types/Friendly/Pets/CreaturePets/VizierPredatorKubrowPetPowerSuit",
171 "/Lotus/Types/Friendly/Pets/CreaturePets/PharaohPredatorKubrowPetPowerSuit",
172 "/Lotus/Types/Friendly/Pets/CreaturePets/MedjayPredatorKubrowPetPowerSuit"
167 173 ];
168 174
169 175 let uniqueLevelCaps = {};
@@ -308,7 +314,11 @@ function fetchItemList() {
308 314 "LWPT_ZANUKA_BODY",
309 315 "LWPT_ZANUKA_HEAD",
310 316 "LWPT_ZANUKA_LEG",
311 "LWPT_ZANUKA_TAIL"
317 "LWPT_ZANUKA_TAIL",
318 "LWPT_CATBROW_ANTIGEN",
319 "LWPT_CATBROW_MUTAGEN",
320 "LWPT_KUBROW_ANTIGEN",
321 "LWPT_KUBROW_MUTAGEN"
312 322 ];
313 323 if (supportedModularParts.includes(item.partType)) {
314 324 const option = document.createElement("option");
@@ -361,7 +371,13 @@ function updateInventory() {
361 371 "/Lotus/Types/Friendly/Pets/MoaPets/MoaPetPowerSuit",
362 372 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetAPowerSuit",
363 373 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetBPowerSuit",
364 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetCPowerSuit"
374 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetCPowerSuit",
375 "/Lotus/Types/Friendly/Pets/CreaturePets/VulpineInfestedCatbrowPetPowerSuit",
376 "/Lotus/Types/Friendly/Pets/CreaturePets/HornedInfestedCatbrowPetPowerSuit",
377 "/Lotus/Types/Friendly/Pets/CreaturePets/ArmoredInfestedCatbrowPetPowerSuit",
378 "/Lotus/Types/Friendly/Pets/CreaturePets/VizierPredatorKubrowPetPowerSuit",
379 "/Lotus/Types/Friendly/Pets/CreaturePets/PharaohPredatorKubrowPetPowerSuit",
380 "/Lotus/Types/Friendly/Pets/CreaturePets/MedjayPredatorKubrowPetPowerSuit"
365 381 ];
366 382
367 383 // Populate inventory route
@@ -384,7 +400,8 @@ function updateInventory() {
384 400 "Hoverboards",
385 401 "OperatorAmps",
386 402 "MechSuits",
387 "MoaPets"
403 "MoaPets",
404 "KubrowPets"
388 405 ].forEach(category => {
389 406 document.getElementById(category + "-list").innerHTML = "";
390 407 data[category].forEach(item => {
@@ -462,6 +479,23 @@ function updateInventory() {
462 479 a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M316.9 18C311.6 7 300.4 0 288.1 0s-23.4 7-28.8 18L195 150.3 51.4 171.5c-12 1.8-22 10.2-25.7 21.7s-.7 24.2 7.9 32.7L137.8 329 113.2 474.7c-2 12 3 24.2 12.9 31.3s23 8 33.8 2.3l128.3-68.5 128.3 68.5c10.8 5.7 23.9 4.9 33.8-2.3s14.9-19.3 12.9-31.3L438.5 329 542.7 225.9c8.6-8.5 11.7-21.2 7.9-32.7s-13.7-19.9-25.7-21.7L381.2 150.3 316.9 18z"/></svg>`;
463 480 td.appendChild(a);
464 481 }
482 if (category == "KubrowPets") {
483 const a = document.createElement("a");
484 a.href = "#";
485 a.onclick = function (event) {
486 event.preventDefault();
487 maturePet(item.ItemId.$oid, !item.Details.IsPuppy);
488 };
489 if (item.Details.IsPuppy) {
490 a.title = loc("code_mature");
491 a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M112 48a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zm40 304l0 128c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-223.1L59.4 304.5c-9.1 15.1-28.8 20-43.9 10.9s-20-28.8-10.9-43.9l58.3-97c17.4-28.9 48.6-46.6 82.3-46.6l29.7 0c33.7 0 64.9 17.7 82.3 46.6l58.3 97c9.1 15.1 4.2 34.8-10.9 43.9s-34.8 4.2-43.9-10.9L232 256.9 232 480c0 17.7-14.3 32-32 32s-32-14.3-32-32l0-128-16 0z"/></svg>`;
492 } else {
493 a.title = loc("code_unmature");
494 a.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M256 64A64 64 0 1 0 128 64a64 64 0 1 0 128 0zM152.9 169.3c-23.7-8.4-44.5-24.3-58.8-45.8L74.6 94.2C64.8 79.5 45 75.6 30.2 85.4s-18.7 29.7-8.9 44.4L40.9 159c18.1 27.1 42.8 48.4 71.1 62.4L112 480c0 17.7 14.3 32 32 32s32-14.3 32-32l0-96 32 0 0 96c0 17.7 14.3 32 32 32s32-14.3 32-32l0-258.4c29.1-14.2 54.4-36.2 72.7-64.2l18.2-27.9c9.6-14.8 5.4-34.6-9.4-44.3s-34.6-5.5-44.3 9.4L291 122.4c-21.8 33.4-58.9 53.6-98.8 53.6c-12.6 0-24.9-2-36.6-5.8c-.9-.3-1.8-.7-2.7-.9z"/></svg>`;
495 }
496
497 td.appendChild(a);
498 }
465 499 if (category == "Suits") {
466 500 const a = document.createElement("a");
467 501 a.href = "/webui/powersuit/" + item.ItemId.$oid;
@@ -870,12 +904,12 @@ function doAcquireEquipment(category) {
870 904 });
871 905 }
872 906
873 function doAcquireModularEquipment(category, ItemType) {
907 function doAcquireModularEquipment(category, WeaponType) {
874 908 let requiredParts;
875 let ModularParts = [];
909 let Parts = [];
876 910 switch (category) {
877 911 case "HoverBoards":
878 ItemType = "/Lotus/Types/Vehicles/Hoverboard/HoverboardSuit";
912 WeaponType = "/Lotus/Types/Vehicles/Hoverboard/HoverboardSuit";
879 913 requiredParts = ["HB_DECK", "HB_ENGINE", "HB_FRONT", "HB_JET"];
880 914 break;
881 915 case "OperatorAmps":
@@ -891,20 +925,33 @@ function doAcquireModularEquipment(category, ItemType) {
891 925 requiredParts = ["GUN_BARREL", "GUN_SECONDARY_HANDLE", "GUN_CLIP"];
892 926 break;
893 927 case "MoaPets":
894 if (ItemType == "/Lotus/Types/Friendly/Pets/MoaPets/MoaPetPowerSuit") {
928 if (WeaponType == "/Lotus/Types/Friendly/Pets/MoaPets/MoaPetPowerSuit") {
895 929 requiredParts = ["MOA_ENGINE", "MOA_PAYLOAD", "MOA_HEAD", "MOA_LEG"];
896 930 } else {
897 931 requiredParts = ["ZANUKA_BODY", "ZANUKA_HEAD", "ZANUKA_LEG", "ZANUKA_TAIL"];
898 932 }
899 933 break;
934 case "KubrowPets":
935 if (
936 [
937 "/Lotus/Types/Friendly/Pets/CreaturePets/VulpineInfestedCatbrowPetPowerSuit",
938 "/Lotus/Types/Friendly/Pets/CreaturePets/HornedInfestedCatbrowPetPowerSuit",
939 "/Lotus/Types/Friendly/Pets/CreaturePets/ArmoredInfestedCatbrowPetPowerSuit"
940 ].includes(WeaponType)
941 ) {
942 requiredParts = ["CATBROW_ANTIGEN", "CATBROW_MUTAGEN"];
943 } else {
944 requiredParts = ["KUBROW_ANTIGEN", "KUBROW_MUTAGEN"];
945 }
946 break;
900 947 }
901 948 requiredParts.forEach(part => {
902 949 const partName = getKey(document.getElementById("acquire-type-" + category + "-" + part));
903 950 if (partName) {
904 ModularParts.push(partName);
951 Parts.push(partName);
905 952 }
906 953 });
907 if (ModularParts.length != requiredParts.length) {
954 if (Parts.length != requiredParts.length) {
908 955 let isFirstPart = true;
909 956 requiredParts.forEach(part => {
910 957 const partSelector = document.getElementById("acquire-type-" + category + "-" + part);
@@ -920,20 +967,80 @@ function doAcquireModularEquipment(category, ItemType) {
920 967 }
921 968 });
922 969 } else {
970 const mapping = {
971 LongGuns: {
972 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelAPart":
973 "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryShotgun",
974 "/Lotus/Weapons/Infested/Pistols/InfKitGun/Barrels/InfBarrelEgg/InfModularBarrelEggPart":
975 "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryShotgun",
976 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelBPart":
977 "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary",
978 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelCPart":
979 "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimary",
980 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelDPart":
981 "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryBeam",
982 "/Lotus/Weapons/Infested/Pistols/InfKitGun/Barrels/InfBarrelBeam/InfModularBarrelBeamPart":
983 "/Lotus/Weapons/SolarisUnited/Primary/LotusModularPrimaryBeam"
984 },
985 Pistols: {
986 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelAPart":
987 "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun",
988 "/Lotus/Weapons/Infested/Pistols/InfKitGun/Barrels/InfBarrelEgg/InfModularBarrelEggPart":
989 "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryShotgun",
990 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelBPart":
991 "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary",
992 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelCPart":
993 "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondary",
994 "/Lotus/Weapons/SolarisUnited/Secondary/SUModularSecondarySet1/Barrel/SUModularSecondaryBarrelDPart":
995 "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam",
996 "/Lotus/Weapons/Infested/Pistols/InfKitGun/Barrels/InfBarrelBeam/InfModularBarrelBeamPart":
997 "/Lotus/Weapons/SolarisUnited/Secondary/LotusModularSecondaryBeam"
998 },
999 MoaPets: {
1000 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA":
1001 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetAPowerSuit",
1002 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB":
1003 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetBPowerSuit",
1004 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC":
1005 "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetCPowerSuit"
1006 }
1007 };
1008
1009 Parts.forEach(part => {
1010 const categoryMap = mapping[category];
1011 if (categoryMap && categoryMap[part]) {
1012 WeaponType = categoryMap[part];
1013 }
1014 });
1015 if (category == "KubrowPets") Parts.unshift(WeaponType);
923 1016 revalidateAuthz(() => {
924 1017 const req = $.post({
925 url: "/custom/addModularEquipment?" + window.authz,
926 contentType: "application/json",
1018 url: "/api/modularWeaponCrafting.php?" + window.authz,
1019 contentType: "application/octet-stream",
927 1020 data: JSON.stringify({
928 ItemType,
929 ModularParts
1021 WeaponType,
1022 Parts,
1023 isWebUi: true
930 1024 })
931 1025 });
932 1026 req.done(() => {
933 1027 const mainInput = document.getElementById("acquire-type-" + category);
934 1028 if (mainInput) {
935 1029 mainInput.value = "";
936 document.getElementById("modular-" + category).style.display = "none";
1030 if (category === "MoaPets") {
1031 const modularFieldsMoa = document.getElementById("modular-MoaPets-Moa");
1032 const modularFieldsZanuka = document.getElementById("modular-MoaPets-Zanuka");
1033 modularFieldsZanuka.style.display = "none";
1034 modularFieldsMoa.style.display = "none";
1035 } else if (category === "KubrowPets") {
1036 const modularFieldsCatbrow = document.getElementById("modular-KubrowPets-Catbrow");
1037 const modularFieldsKubrow = document.getElementById("modular-KubrowPets-Kubrow");
1038 modularFieldsCatbrow.style.display = "none";
1039 modularFieldsKubrow.style.display = "none";
1040 } else {
1041 const modularFields = document.getElementById("modular-" + category);
1042 modularFields.style.display = "none";
1043 }
937 1044 }
938 1045 requiredParts.forEach(part => {
939 1046 document.getElementById("acquire-type-" + category + "-" + part).value = "";
@@ -1085,24 +1192,37 @@ function renameGear(category, oid, name) {
1085 1192 }
1086 1193
1087 1194 function disposeOfGear(category, oid) {
1088 const data = {
1089 SellCurrency: "SC_RegularCredits",
1090 SellPrice: 0,
1091 Items: {}
1092 };
1093 data.Items[category] = [
1094 {
1095 String: oid,
1096 Count: 0
1097 }
1098 ];
1099 revalidateAuthz(() => {
1100 $.post({
1101 url: "/api/sell.php?" + window.authz,
1102 contentType: "text/plain",
1103 data: JSON.stringify(data)
1195 if (category == "KubrowPets") {
1196 revalidateAuthz(() => {
1197 $.post({
1198 url: "/api/releasePet.php?" + window.authz,
1199 contentType: "application/octet-stream",
1200 data: JSON.stringify({
1201 Recipe: "webui",
1202 petId: oid
1203 })
1204 });
1104 1205 });
1105 });
1206 } else {
1207 const data = {
1208 SellCurrency: "SC_RegularCredits",
1209 SellPrice: 0,
1210 Items: {}
1211 };
1212 data.Items[category] = [
1213 {
1214 String: oid,
1215 Count: 0
1216 }
1217 ];
1218 revalidateAuthz(() => {
1219 $.post({
1220 url: "/api/sell.php?" + window.authz,
1221 contentType: "text/plain",
1222 data: JSON.stringify(data)
1223 });
1224 });
1225 }
1106 1226 }
1107 1227
1108 1228 function disposeOfItems(category, type, count) {
@@ -1140,6 +1260,21 @@ function gildEquipment(category, oid) {
1140 1260 });
1141 1261 }
1142 1262
1263 function maturePet(oid, revert) {
1264 revalidateAuthz(() => {
1265 $.post({
1266 url: "/api/maturePet.php?" + window.authz,
1267 contentType: "application/octet-stream",
1268 data: JSON.stringify({
1269 petId: oid,
1270 revert
1271 })
1272 }).done(function () {
1273 updateInventory();
1274 });
1275 });
1276 }
1277
1143 1278 function doAcquireMiscItems() {
1144 1279 const uniqueName = getKey(document.getElementById("miscitem-type"));
1145 1280 if (!uniqueName) {
@@ -1589,32 +1724,60 @@ function handleModularSelection(category) {
1589 1724 }
1590 1725 }
1591 1726 {
1592 const supportedModularInventoryCategory = ["OperatorAmps", "Melee", "LongGuns", "Pistols", "MoaPets"];
1727 const supportedModularInventoryCategory = ["OperatorAmps", "Melee", "LongGuns", "Pistols", "MoaPets", "KubrowPets"];
1593 1728 supportedModularInventoryCategory.forEach(inventoryCategory => {
1594 1729 document.getElementById("acquire-type-" + inventoryCategory).addEventListener("input", function () {
1595 1730 const modularFields = document.getElementById("modular-" + inventoryCategory);
1596 const modularFieldsZanuka =
1597 inventoryCategory === "MoaPets"
1598 ? document.getElementById("modular-" + inventoryCategory + "-Zanuka")
1599 : null;
1731 const modularFieldsMoa = document.getElementById("modular-MoaPets-Moa");
1732 const modularFieldsZanuka = document.getElementById("modular-MoaPets-Zanuka");
1733 const modularFieldsCatbrow = document.getElementById("modular-KubrowPets-Catbrow");
1734 const modularFieldsKubrow = document.getElementById("modular-KubrowPets-Kubrow");
1600 1735 const key = getKey(this);
1601 1736
1602 1737 if (webUiModularWeapons.includes(key)) {
1603 if (key === "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetPowerSuit" && modularFieldsZanuka) {
1604 modularFields.style.display = "none";
1605 modularFieldsZanuka.style.display = "";
1606 } else if (key === "/Lotus/Types/Friendly/Pets/MoaPets/MoaPetPowerSuit") {
1607 modularFields.style.display = "";
1608 if (modularFieldsZanuka) {
1738 if (inventoryCategory === "MoaPets") {
1739 if (key === "/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetPowerSuit") {
1740 modularFieldsMoa.style.display = "none";
1741 modularFieldsZanuka.style.display = "";
1742 } else if (key === "/Lotus/Types/Friendly/Pets/MoaPets/MoaPetPowerSuit") {
1743 modularFieldsMoa.style.display = "";
1609 1744 modularFieldsZanuka.style.display = "none";
1610 1745 }
1746 } else if (inventoryCategory === "KubrowPets") {
1747 if (
1748 [
1749 "/Lotus/Types/Friendly/Pets/CreaturePets/VulpineInfestedCatbrowPetPowerSuit",
1750 "/Lotus/Types/Friendly/Pets/CreaturePets/HornedInfestedCatbrowPetPowerSuit",
1751 "/Lotus/Types/Friendly/Pets/CreaturePets/ArmoredInfestedCatbrowPetPowerSuit"
1752 ].includes(key)
1753 ) {
1754 modularFieldsCatbrow.style.display = "";
1755 modularFieldsKubrow.style.display = "none";
1756 } else if (
1757 [
1758 "/Lotus/Types/Friendly/Pets/CreaturePets/VizierPredatorKubrowPetPowerSuit",
1759 "/Lotus/Types/Friendly/Pets/CreaturePets/PharaohPredatorKubrowPetPowerSuit",
1760 "/Lotus/Types/Friendly/Pets/CreaturePets/MedjayPredatorKubrowPetPowerSuit"
1761 ].includes(key)
1762 ) {
1763 modularFieldsCatbrow.style.display = "none";
1764 modularFieldsKubrow.style.display = "";
1765 } else {
1766 modularFieldsCatbrow.style.display = "none";
1767 modularFieldsKubrow.style.display = "none";
1768 }
1611 1769 } else {
1612 1770 modularFields.style.display = "";
1613 1771 }
1614 1772 } else {
1615 modularFields.style.display = "none";
1616 if (modularFieldsZanuka) {
1773 if (inventoryCategory === "MoaPets") {
1617 1774 modularFieldsZanuka.style.display = "none";
1775 modularFieldsMoa.style.display = "none";
1776 } else if (inventoryCategory === "KubrowPets") {
1777 modularFieldsCatbrow.style.display = "none";
1778 modularFieldsKubrow.style.display = "none";
1779 } else {
1780 modularFields.style.display = "none";
1618 1781 }
1619 1782 }
1620 1783 });
Modified static/webui/translations/de.js +3 -0
@@ -54,6 +54,8 @@ dict = {
54 54 code_completed: `Abgeschlossen`,
55 55 code_active: `Aktiv`,
56 56 code_pigment: `Pigment`,
57 code_mature: `[UNTRANSLATED] Mature for combat`,
58 code_unmature: `[UNTRANSLATED] Regress genetic aging`,
57 59 login_description: `Melde dich mit deinem OpenWF-Account an (denselben Angaben wie im Spiel, wenn du dich mit diesem Server verbindest).`,
58 60 login_emailLabel: `E-Mail-Adresse`,
59 61 login_passwordLabel: `Passwort`,
@@ -80,6 +82,7 @@ dict = {
80 82 inventory_operatorAmps: `Verstärker`,
81 83 inventory_hoverboards: `K-Drives`,
82 84 inventory_moaPets: `Moa`,
85 inventory_kubrowPets: `[UNTRANSLATED] Beasts`,
83 86 inventory_bulkAddSuits: `Fehlende Warframes hinzufügen`,
84 87 inventory_bulkAddWeapons: `Fehlende Waffen hinzufügen`,
85 88 inventory_bulkAddSpaceSuits: `Fehlende Archwings hinzufügen`,
Modified static/webui/translations/en.js +3 -0
@@ -53,6 +53,8 @@ dict = {
53 53 code_completed: `Completed`,
54 54 code_active: `Active`,
55 55 code_pigment: `Pigment`,
56 code_mature: `Mature for combat`,
57 code_unmature: `Regress genetic aging`,
56 58 login_description: `Login using your OpenWF account credentials (same as in-game when connecting to this server).`,
57 59 login_emailLabel: `Email address`,
58 60 login_passwordLabel: `Password`,
@@ -79,6 +81,7 @@ dict = {
79 81 inventory_operatorAmps: `Amps`,
80 82 inventory_hoverboards: `K-Drives`,
81 83 inventory_moaPets: `Moa`,
84 inventory_kubrowPets: `Beasts`,
82 85 inventory_bulkAddSuits: `Add Missing Warframes`,
83 86 inventory_bulkAddWeapons: `Add Missing Weapons`,
84 87 inventory_bulkAddSpaceSuits: `Add Missing Archwings`,
Modified static/webui/translations/es.js +3 -0
@@ -54,6 +54,8 @@ dict = {
54 54 code_completed: `Completada`,
55 55 code_active: `Activa`,
56 56 code_pigment: `Pigmento`,
57 code_mature: `[UNTRANSLATED] Mature for combat`,
58 code_unmature: `[UNTRANSLATED] Regress genetic aging`,
57 59 login_description: `Inicia sesión con las credenciales de tu cuenta OpenWF (las mismas que usas en el juego al conectarte a este servidor).`,
58 60 login_emailLabel: `Dirección de correo electrónico`,
59 61 login_passwordLabel: `Contraseña`,
@@ -80,6 +82,7 @@ dict = {
80 82 inventory_operatorAmps: `Amps`,
81 83 inventory_hoverboards: `K-Drives`,
82 84 inventory_moaPets: `Moa`,
85 inventory_kubrowPets: `[UNTRANSLATED] Beasts`,
83 86 inventory_bulkAddSuits: `Agregar Warframes faltantes`,
84 87 inventory_bulkAddWeapons: `Agregar armas faltantes`,
85 88 inventory_bulkAddSpaceSuits: `Agregar Archwings faltantes`,
Modified static/webui/translations/fr.js +3 -0
Modified static/webui/translations/ru.js +3 -0
Modified static/webui/translations/zh.js +3 -0