forked from OpenWF/SpaceNinjaServer
		
	feat: identify & repair railjack components (#1664)
Closes #911 Reviewed-on: OpenWF/SpaceNinjaServer#1664 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									51b82df5fd
								
							
						
					
					
						commit
						0ea67ea89a
					
				
							
								
								
									
										41
									
								
								src/controllers/api/crewShipIdentifySalvageController.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/controllers/api/crewShipIdentifySalvageController.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					import { addCrewShipSalvagedWeaponSkin, addCrewShipRawSalvage, getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					import { IInnateDamageFingerprint } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
 | 
					import { ExportCustoms } from "warframe-public-export-plus";
 | 
				
			||||||
 | 
					import { IFingerprintStat } from "@/src/helpers/rivenHelper";
 | 
				
			||||||
 | 
					import { getJSONfromString } from "@/src/helpers/stringHelpers";
 | 
				
			||||||
 | 
					import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const crewShipIdentifySalvageController: RequestHandler = async (req, res) => {
 | 
				
			||||||
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
 | 
					    const inventory = await getInventory(accountId, "CrewShipSalvagedWeaponSkins CrewShipRawSalvage");
 | 
				
			||||||
 | 
					    const payload = getJSONfromString<ICrewShipIdentifySalvageRequest>(String(req.body));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const buffs: IFingerprintStat[] = [];
 | 
				
			||||||
 | 
					    for (const upgrade of ExportCustoms[payload.ItemType].randomisedUpgrades!) {
 | 
				
			||||||
 | 
					        buffs.push({ Tag: upgrade.tag, Value: Math.trunc(Math.random() * 0x40000000) });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const inventoryChanges: IInventoryChanges = addCrewShipSalvagedWeaponSkin(
 | 
				
			||||||
 | 
					        inventory,
 | 
				
			||||||
 | 
					        payload.ItemType,
 | 
				
			||||||
 | 
					        JSON.stringify({ compat: payload.ItemType, buffs } satisfies IInnateDamageFingerprint)
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inventoryChanges.CrewShipRawSalvage = [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ItemType: payload.ItemType,
 | 
				
			||||||
 | 
					            ItemCount: -1
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					    addCrewShipRawSalvage(inventory, inventoryChanges.CrewShipRawSalvage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await inventory.save();
 | 
				
			||||||
 | 
					    res.json({
 | 
				
			||||||
 | 
					        InventoryChanges: inventoryChanges
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface ICrewShipIdentifySalvageRequest {
 | 
				
			||||||
 | 
					    ItemType: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -14,20 +14,23 @@ import {
 | 
				
			|||||||
import { ExportDojoRecipes } from "warframe-public-export-plus";
 | 
					import { ExportDojoRecipes } from "warframe-public-export-plus";
 | 
				
			||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
 | 
					    addCrewShipWeaponSkin,
 | 
				
			||||||
    addItem,
 | 
					    addItem,
 | 
				
			||||||
    addMiscItems,
 | 
					    addMiscItems,
 | 
				
			||||||
    addRecipes,
 | 
					    addRecipes,
 | 
				
			||||||
    combineInventoryChanges,
 | 
					    combineInventoryChanges,
 | 
				
			||||||
    getInventory,
 | 
					    getInventory,
 | 
				
			||||||
 | 
					    occupySlot,
 | 
				
			||||||
    updateCurrency
 | 
					    updateCurrency
 | 
				
			||||||
} from "@/src/services/inventoryService";
 | 
					} from "@/src/services/inventoryService";
 | 
				
			||||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
					import { IMiscItem, InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
					import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { config } from "@/src/services/configService";
 | 
					import { config } from "@/src/services/configService";
 | 
				
			||||||
import { GuildPermission, ITechProjectClient } from "@/src/types/guildTypes";
 | 
					import { GuildPermission, ITechProjectClient } from "@/src/types/guildTypes";
 | 
				
			||||||
import { GuildMember } from "@/src/models/guildModel";
 | 
					import { GuildMember } from "@/src/models/guildModel";
 | 
				
			||||||
import { toMongoDate } from "@/src/helpers/inventoryHelpers";
 | 
					import { toMongoDate } from "@/src/helpers/inventoryHelpers";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
 | 
					import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const guildTechController: RequestHandler = async (req, res) => {
 | 
					export const guildTechController: RequestHandler = async (req, res) => {
 | 
				
			||||||
    const accountId = await getAccountIdForRequest(req);
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
@ -99,6 +102,8 @@ export const guildTechController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
                        State: 0,
 | 
					                        State: 0,
 | 
				
			||||||
                        ReqCredits: recipe.price,
 | 
					                        ReqCredits: recipe.price,
 | 
				
			||||||
                        ItemType: data.RecipeType,
 | 
					                        ItemType: data.RecipeType,
 | 
				
			||||||
 | 
					                        ProductCategory: data.TechProductCategory,
 | 
				
			||||||
 | 
					                        CategoryItemId: data.CategoryItemId,
 | 
				
			||||||
                        ReqItems: recipe.ingredients
 | 
					                        ReqItems: recipe.ingredients
 | 
				
			||||||
                    }) - 1
 | 
					                    }) - 1
 | 
				
			||||||
                ];
 | 
					                ];
 | 
				
			||||||
@ -222,33 +227,44 @@ export const guildTechController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else if (data.Action.split(",")[0] == "Buy") {
 | 
					    } else if (data.Action.split(",")[0] == "Buy") {
 | 
				
			||||||
        const guild = await getGuildForRequestEx(req, inventory);
 | 
					 | 
				
			||||||
        if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
 | 
					 | 
				
			||||||
            res.status(400).send("-1").end();
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        const purchase = data as IGuildTechBuyRequest;
 | 
					        const purchase = data as IGuildTechBuyRequest;
 | 
				
			||||||
        const quantity = parseInt(data.Action.split(",")[1]);
 | 
					        if (purchase.Mode == "Guild") {
 | 
				
			||||||
        const recipeChanges = [
 | 
					            const guild = await getGuildForRequestEx(req, inventory);
 | 
				
			||||||
            {
 | 
					            if (
 | 
				
			||||||
                ItemType: purchase.RecipeType,
 | 
					                !hasAccessToDojo(inventory) ||
 | 
				
			||||||
                ItemCount: quantity
 | 
					                !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                res.status(400).send("-1").end();
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        ];
 | 
					            const quantity = parseInt(data.Action.split(",")[1]);
 | 
				
			||||||
        addRecipes(inventory, recipeChanges);
 | 
					            const recipeChanges = [
 | 
				
			||||||
        const currencyChanges = updateCurrency(
 | 
					                {
 | 
				
			||||||
            inventory,
 | 
					                    ItemType: purchase.RecipeType,
 | 
				
			||||||
            ExportDojoRecipes.research[purchase.RecipeType].replicatePrice,
 | 
					                    ItemCount: quantity
 | 
				
			||||||
            false
 | 
					                }
 | 
				
			||||||
        );
 | 
					            ];
 | 
				
			||||||
        await inventory.save();
 | 
					            addRecipes(inventory, recipeChanges);
 | 
				
			||||||
        // Not a mistake: This response uses `inventoryChanges` instead of `InventoryChanges`.
 | 
					            const currencyChanges = updateCurrency(
 | 
				
			||||||
        res.json({
 | 
					                inventory,
 | 
				
			||||||
            inventoryChanges: {
 | 
					                ExportDojoRecipes.research[purchase.RecipeType].replicatePrice,
 | 
				
			||||||
                ...currencyChanges,
 | 
					                false
 | 
				
			||||||
                Recipes: recipeChanges
 | 
					            );
 | 
				
			||||||
            }
 | 
					            await inventory.save();
 | 
				
			||||||
        });
 | 
					            // Not a mistake: This response uses `inventoryChanges` instead of `InventoryChanges`.
 | 
				
			||||||
 | 
					            res.json({
 | 
				
			||||||
 | 
					                inventoryChanges: {
 | 
				
			||||||
 | 
					                    ...currencyChanges,
 | 
				
			||||||
 | 
					                    Recipes: recipeChanges
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            const inventoryChanges = claimSalvagedComponent(inventory, purchase.CategoryItemId!);
 | 
				
			||||||
 | 
					            await inventory.save();
 | 
				
			||||||
 | 
					            res.json({
 | 
				
			||||||
 | 
					                inventoryChanges: inventoryChanges
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    } else if (data.Action == "Fabricate") {
 | 
					    } else if (data.Action == "Fabricate") {
 | 
				
			||||||
        const guild = await getGuildForRequestEx(req, inventory);
 | 
					        const guild = await getGuildForRequestEx(req, inventory);
 | 
				
			||||||
        if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
 | 
					        if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
 | 
				
			||||||
@ -289,9 +305,18 @@ export const guildTechController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
        guild.ActiveDojoColorResearch = data.RecipeType;
 | 
					        guild.ActiveDojoColorResearch = data.RecipeType;
 | 
				
			||||||
        await guild.save();
 | 
					        await guild.save();
 | 
				
			||||||
        res.end();
 | 
					        res.end();
 | 
				
			||||||
 | 
					    } else if (data.Action == "Rush" && data.CategoryItemId) {
 | 
				
			||||||
 | 
					        const inventoryChanges: IInventoryChanges = {
 | 
				
			||||||
 | 
					            ...updateCurrency(inventory, 20, true),
 | 
				
			||||||
 | 
					            ...claimSalvagedComponent(inventory, data.CategoryItemId)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        await inventory.save();
 | 
				
			||||||
 | 
					        res.json({
 | 
				
			||||||
 | 
					            inventoryChanges: inventoryChanges
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
 | 
					        logger.debug(`data provided to ${req.path}: ${String(req.body)}`);
 | 
				
			||||||
        throw new Error(`unknown guildTech action: ${data.Action}`);
 | 
					        throw new Error(`unhandled guildTech request`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -301,15 +326,15 @@ type TGuildTechRequest =
 | 
				
			|||||||
    | IGuildTechContributeRequest;
 | 
					    | IGuildTechContributeRequest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IGuildTechBasicRequest {
 | 
					interface IGuildTechBasicRequest {
 | 
				
			||||||
    Action: "Start" | "Fabricate" | "Pause" | "Unpause";
 | 
					    Action: "Start" | "Fabricate" | "Pause" | "Unpause" | "Cancel" | "Rush";
 | 
				
			||||||
    Mode: "Guild" | "Personal";
 | 
					    Mode: "Guild" | "Personal";
 | 
				
			||||||
    RecipeType: string;
 | 
					    RecipeType: string;
 | 
				
			||||||
 | 
					    TechProductCategory?: string;
 | 
				
			||||||
 | 
					    CategoryItemId?: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IGuildTechBuyRequest {
 | 
					interface IGuildTechBuyRequest extends Omit<IGuildTechBasicRequest, "Action"> {
 | 
				
			||||||
    Action: string;
 | 
					    Action: string;
 | 
				
			||||||
    Mode: "Guild";
 | 
					 | 
				
			||||||
    RecipeType: string;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IGuildTechContributeRequest {
 | 
					interface IGuildTechContributeRequest {
 | 
				
			||||||
@ -321,3 +346,30 @@ interface IGuildTechContributeRequest {
 | 
				
			|||||||
    VaultCredits: number;
 | 
					    VaultCredits: number;
 | 
				
			||||||
    VaultMiscItems: IMiscItem[];
 | 
					    VaultMiscItems: IMiscItem[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const claimSalvagedComponent = (inventory: TInventoryDatabaseDocument, itemId: string): IInventoryChanges => {
 | 
				
			||||||
 | 
					    // delete personal tech project
 | 
				
			||||||
 | 
					    const personalTechProjectIndex = inventory.PersonalTechProjects.findIndex(x => x.CategoryItemId?.equals(itemId));
 | 
				
			||||||
 | 
					    if (personalTechProjectIndex != -1) {
 | 
				
			||||||
 | 
					        inventory.PersonalTechProjects.splice(personalTechProjectIndex, 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // find salved part & delete it
 | 
				
			||||||
 | 
					    const crewShipSalvagedWeaponSkinsIndex = inventory.CrewShipSalvagedWeaponSkins.findIndex(x => x._id.equals(itemId));
 | 
				
			||||||
 | 
					    const crewShipWeaponSkin = inventory.CrewShipSalvagedWeaponSkins[crewShipSalvagedWeaponSkinsIndex];
 | 
				
			||||||
 | 
					    inventory.CrewShipSalvagedWeaponSkins.splice(crewShipSalvagedWeaponSkinsIndex, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // add final item
 | 
				
			||||||
 | 
					    const inventoryChanges = {
 | 
				
			||||||
 | 
					        ...addCrewShipWeaponSkin(inventory, crewShipWeaponSkin.ItemType, crewShipWeaponSkin.UpgradeFingerprint),
 | 
				
			||||||
 | 
					        ...occupySlot(inventory, InventorySlot.RJ_COMPONENT_AND_ARMAMENTS, false)
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inventoryChanges.RemovedIdItems = [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            ItemId: { $oid: itemId }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return inventoryChanges;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -504,6 +504,8 @@ const personalTechProjectSchema = new Schema<IPersonalTechProjectDatabase>({
 | 
				
			|||||||
    State: Number,
 | 
					    State: Number,
 | 
				
			||||||
    ReqCredits: Number,
 | 
					    ReqCredits: Number,
 | 
				
			||||||
    ItemType: String,
 | 
					    ItemType: String,
 | 
				
			||||||
 | 
					    ProductCategory: String,
 | 
				
			||||||
 | 
					    CategoryItemId: Schema.Types.ObjectId,
 | 
				
			||||||
    ReqItems: { type: [typeCountSchema], default: undefined },
 | 
					    ReqItems: { type: [typeCountSchema], default: undefined },
 | 
				
			||||||
    HasContributions: Boolean,
 | 
					    HasContributions: Boolean,
 | 
				
			||||||
    CompletionDate: Date
 | 
					    CompletionDate: Date
 | 
				
			||||||
@ -522,6 +524,9 @@ personalTechProjectSchema.set("toJSON", {
 | 
				
			|||||||
        const db = ret as IPersonalTechProjectDatabase;
 | 
					        const db = ret as IPersonalTechProjectDatabase;
 | 
				
			||||||
        const client = ret as IPersonalTechProjectClient;
 | 
					        const client = ret as IPersonalTechProjectClient;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (db.CategoryItemId) {
 | 
				
			||||||
 | 
					            client.CategoryItemId = toOid(db.CategoryItemId);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        if (db.CompletionDate) {
 | 
					        if (db.CompletionDate) {
 | 
				
			||||||
            client.CompletionDate = toMongoDate(db.CompletionDate);
 | 
					            client.CompletionDate = toMongoDate(db.CompletionDate);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,7 @@ import { contributeToVaultController } from "@/src/controllers/api/contributeToV
 | 
				
			|||||||
import { createAllianceController } from "@/src/controllers/api/createAllianceController";
 | 
					import { createAllianceController } from "@/src/controllers/api/createAllianceController";
 | 
				
			||||||
import { createGuildController } from "@/src/controllers/api/createGuildController";
 | 
					import { createGuildController } from "@/src/controllers/api/createGuildController";
 | 
				
			||||||
import { creditsController } from "@/src/controllers/api/creditsController";
 | 
					import { creditsController } from "@/src/controllers/api/creditsController";
 | 
				
			||||||
 | 
					import { crewShipIdentifySalvageController } from "@/src/controllers/api/crewShipIdentifySalvageController";
 | 
				
			||||||
import { customizeGuildRanksController } from "@/src/controllers/api/customizeGuildRanksController";
 | 
					import { customizeGuildRanksController } from "@/src/controllers/api/customizeGuildRanksController";
 | 
				
			||||||
import { customObstacleCourseLeaderboardController } from "@/src/controllers/api/customObstacleCourseLeaderboardController";
 | 
					import { customObstacleCourseLeaderboardController } from "@/src/controllers/api/customObstacleCourseLeaderboardController";
 | 
				
			||||||
import { declineAllianceInviteController } from "@/src/controllers/api/declineAllianceInviteController";
 | 
					import { declineAllianceInviteController } from "@/src/controllers/api/declineAllianceInviteController";
 | 
				
			||||||
@ -218,6 +219,7 @@ apiRouter.post("/contributeToDojoComponent.php", contributeToDojoComponentContro
 | 
				
			|||||||
apiRouter.post("/contributeToVault.php", contributeToVaultController);
 | 
					apiRouter.post("/contributeToVault.php", contributeToVaultController);
 | 
				
			||||||
apiRouter.post("/createAlliance.php", createAllianceController);
 | 
					apiRouter.post("/createAlliance.php", createAllianceController);
 | 
				
			||||||
apiRouter.post("/createGuild.php", createGuildController);
 | 
					apiRouter.post("/createGuild.php", createGuildController);
 | 
				
			||||||
 | 
					apiRouter.post("/crewShipIdentifySalvage.php", crewShipIdentifySalvageController);
 | 
				
			||||||
apiRouter.post("/customizeGuildRanks.php", customizeGuildRanksController);
 | 
					apiRouter.post("/customizeGuildRanks.php", customizeGuildRanksController);
 | 
				
			||||||
apiRouter.post("/customObstacleCourseLeaderboard.php", customObstacleCourseLeaderboardController);
 | 
					apiRouter.post("/customObstacleCourseLeaderboard.php", customObstacleCourseLeaderboardController);
 | 
				
			||||||
apiRouter.post("/destroyDojoDeco.php", destroyDojoDecoController);
 | 
					apiRouter.post("/destroyDojoDeco.php", destroyDojoDecoController);
 | 
				
			||||||
 | 
				
			|||||||
@ -426,7 +426,7 @@ export const addItem = async (
 | 
				
			|||||||
                    );
 | 
					                    );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                inventoryChanges = {
 | 
					                inventoryChanges = {
 | 
				
			||||||
                    ...addCrewShipWeaponSkin(inventory, typeName),
 | 
					                    ...addCrewShipWeaponSkin(inventory, typeName, undefined),
 | 
				
			||||||
                    ...occupySlot(inventory, InventorySlot.RJ_COMPONENT_AND_ARMAMENTS, premiumPurchase)
 | 
					                    ...occupySlot(inventory, InventorySlot.RJ_COMPONENT_AND_ARMAMENTS, premiumPurchase)
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -1107,12 +1107,14 @@ export const addSkin = (
 | 
				
			|||||||
    return inventoryChanges;
 | 
					    return inventoryChanges;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const addCrewShipWeaponSkin = (
 | 
					export const addCrewShipWeaponSkin = (
 | 
				
			||||||
    inventory: TInventoryDatabaseDocument,
 | 
					    inventory: TInventoryDatabaseDocument,
 | 
				
			||||||
    typeName: string,
 | 
					    typeName: string,
 | 
				
			||||||
 | 
					    upgradeFingerprint: string | undefined,
 | 
				
			||||||
    inventoryChanges: IInventoryChanges = {}
 | 
					    inventoryChanges: IInventoryChanges = {}
 | 
				
			||||||
): IInventoryChanges => {
 | 
					): IInventoryChanges => {
 | 
				
			||||||
    const index = inventory.CrewShipWeaponSkins.push({ ItemType: typeName }) - 1;
 | 
					    const index =
 | 
				
			||||||
 | 
					        inventory.CrewShipWeaponSkins.push({ ItemType: typeName, UpgradeFingerprint: upgradeFingerprint }) - 1;
 | 
				
			||||||
    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
 | 
					    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
 | 
				
			||||||
    inventoryChanges.CrewShipWeaponSkins ??= [];
 | 
					    inventoryChanges.CrewShipWeaponSkins ??= [];
 | 
				
			||||||
    (inventoryChanges.CrewShipWeaponSkins as IUpgradeClient[]).push(
 | 
					    (inventoryChanges.CrewShipWeaponSkins as IUpgradeClient[]).push(
 | 
				
			||||||
@ -1121,6 +1123,22 @@ const addCrewShipWeaponSkin = (
 | 
				
			|||||||
    return inventoryChanges;
 | 
					    return inventoryChanges;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const addCrewShipSalvagedWeaponSkin = (
 | 
				
			||||||
 | 
					    inventory: TInventoryDatabaseDocument,
 | 
				
			||||||
 | 
					    typeName: string,
 | 
				
			||||||
 | 
					    upgradeFingerprint: string | undefined,
 | 
				
			||||||
 | 
					    inventoryChanges: IInventoryChanges = {}
 | 
				
			||||||
 | 
					): IInventoryChanges => {
 | 
				
			||||||
 | 
					    const index =
 | 
				
			||||||
 | 
					        inventory.CrewShipSalvagedWeaponSkins.push({ ItemType: typeName, UpgradeFingerprint: upgradeFingerprint }) - 1;
 | 
				
			||||||
 | 
					    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
 | 
				
			||||||
 | 
					    inventoryChanges.CrewShipSalvagedWeaponSkins ??= [];
 | 
				
			||||||
 | 
					    (inventoryChanges.CrewShipSalvagedWeaponSkins as IUpgradeClient[]).push(
 | 
				
			||||||
 | 
					        inventory.CrewShipSalvagedWeaponSkins[index].toJSON<IUpgradeClient>()
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					    return inventoryChanges;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const addCrewShip = (
 | 
					const addCrewShip = (
 | 
				
			||||||
    inventory: TInventoryDatabaseDocument,
 | 
					    inventory: TInventoryDatabaseDocument,
 | 
				
			||||||
    typeName: string,
 | 
					    typeName: string,
 | 
				
			||||||
 | 
				
			|||||||
@ -947,15 +947,17 @@ export interface IPersonalTechProjectDatabase {
 | 
				
			|||||||
    State: number;
 | 
					    State: number;
 | 
				
			||||||
    ReqCredits: number;
 | 
					    ReqCredits: number;
 | 
				
			||||||
    ItemType: string;
 | 
					    ItemType: string;
 | 
				
			||||||
 | 
					    ProductCategory?: string;
 | 
				
			||||||
 | 
					    CategoryItemId?: Types.ObjectId;
 | 
				
			||||||
    ReqItems: ITypeCount[];
 | 
					    ReqItems: ITypeCount[];
 | 
				
			||||||
    HasContributions?: boolean;
 | 
					    HasContributions?: boolean;
 | 
				
			||||||
    CompletionDate?: Date;
 | 
					    CompletionDate?: Date;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IPersonalTechProjectClient extends Omit<IPersonalTechProjectDatabase, "CompletionDate"> {
 | 
					export interface IPersonalTechProjectClient
 | 
				
			||||||
    CompletionDate?: IMongoDate;
 | 
					    extends Omit<IPersonalTechProjectDatabase, "CategoryItemId" | "CompletionDate"> {
 | 
				
			||||||
    ProductCategory?: string;
 | 
					 | 
				
			||||||
    CategoryItemId?: IOid;
 | 
					    CategoryItemId?: IOid;
 | 
				
			||||||
 | 
					    CompletionDate?: IMongoDate;
 | 
				
			||||||
    ItemId: IOid;
 | 
					    ItemId: IOid;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -43,6 +43,7 @@ export type IInventoryChanges = {
 | 
				
			|||||||
    Drones?: IDroneClient[];
 | 
					    Drones?: IDroneClient[];
 | 
				
			||||||
    MiscItems?: IMiscItem[];
 | 
					    MiscItems?: IMiscItem[];
 | 
				
			||||||
    EmailItems?: ITypeCount[];
 | 
					    EmailItems?: ITypeCount[];
 | 
				
			||||||
 | 
					    CrewShipRawSalvage?: ITypeCount[];
 | 
				
			||||||
    Nemesis?: Partial<INemesisClient>;
 | 
					    Nemesis?: Partial<INemesisClient>;
 | 
				
			||||||
    NewVendorPurchase?: IRecentVendorPurchaseClient; // >= 38.5.0
 | 
					    NewVendorPurchase?: IRecentVendorPurchaseClient; // >= 38.5.0
 | 
				
			||||||
    RecentVendorPurchases?: IRecentVendorPurchaseClient; // < 38.5.0
 | 
					    RecentVendorPurchases?: IRecentVendorPurchaseClient; // < 38.5.0
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user