forked from OpenWF/SpaceNinjaServer
		
	feat: create genetic imprint (#2337)
Re #2212 Reviewed-on: OpenWF/SpaceNinjaServer#2337 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
							
								
									5a7caa5ba9
								
							
						
					
					
						commit
						44a129ab0b
					
				
							
								
								
									
										18
									
								
								.eslintrc
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								.eslintrc
									
									
									
									
									
								
							@ -11,17 +11,17 @@
 | 
			
		||||
        "node": true
 | 
			
		||||
    },
 | 
			
		||||
    "rules": {
 | 
			
		||||
        "@typescript-eslint/explicit-function-return-type": "warn",
 | 
			
		||||
        "@typescript-eslint/restrict-template-expressions": "warn",
 | 
			
		||||
        "@typescript-eslint/restrict-plus-operands": "warn",
 | 
			
		||||
        "@typescript-eslint/no-unsafe-member-access": "warn",
 | 
			
		||||
        "@typescript-eslint/explicit-function-return-type": "error",
 | 
			
		||||
        "@typescript-eslint/restrict-template-expressions": "error",
 | 
			
		||||
        "@typescript-eslint/restrict-plus-operands": "error",
 | 
			
		||||
        "@typescript-eslint/no-unsafe-member-access": "error",
 | 
			
		||||
        "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_", "caughtErrors": "none" }],
 | 
			
		||||
        "@typescript-eslint/no-unsafe-argument": "error",
 | 
			
		||||
        "@typescript-eslint/no-unsafe-call": "warn",
 | 
			
		||||
        "@typescript-eslint/no-unsafe-assignment": "warn",
 | 
			
		||||
        "@typescript-eslint/no-explicit-any": "warn",
 | 
			
		||||
        "no-loss-of-precision": "warn",
 | 
			
		||||
        "@typescript-eslint/no-unnecessary-condition": "warn",
 | 
			
		||||
        "@typescript-eslint/no-unsafe-call": "error",
 | 
			
		||||
        "@typescript-eslint/no-unsafe-assignment": "error",
 | 
			
		||||
        "@typescript-eslint/no-explicit-any": "error",
 | 
			
		||||
        "no-loss-of-precision": "error",
 | 
			
		||||
        "@typescript-eslint/no-unnecessary-condition": "error",
 | 
			
		||||
        "@typescript-eslint/no-base-to-string": "off",
 | 
			
		||||
        "no-case-declarations": "error",
 | 
			
		||||
        "prettier/prettier": "error",
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,8 @@ import {
 | 
			
		||||
    addItem,
 | 
			
		||||
    addRecipes,
 | 
			
		||||
    occupySlot,
 | 
			
		||||
    combineInventoryChanges
 | 
			
		||||
    combineInventoryChanges,
 | 
			
		||||
    addKubrowPetPrint
 | 
			
		||||
} from "@/src/services/inventoryService";
 | 
			
		||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
			
		||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
 | 
			
		||||
@ -119,6 +120,9 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            pet.Details!.Status = canSetActive ? Status.StatusAvailable : Status.StatusStasis;
 | 
			
		||||
        } else if (recipe.secretIngredientAction == "SIA_DISTILL_PRINT") {
 | 
			
		||||
            const pet = inventory.KubrowPets.id(pendingRecipe.KubrowPet!)!;
 | 
			
		||||
            addKubrowPetPrint(inventory, pet, InventoryChanges);
 | 
			
		||||
        } else if (recipe.secretIngredientAction != "SIA_UNBRAND") {
 | 
			
		||||
            InventoryChanges = {
 | 
			
		||||
                ...InventoryChanges,
 | 
			
		||||
 | 
			
		||||
@ -45,9 +45,9 @@ export const startRecipeController: RequestHandler = async (req, res) => {
 | 
			
		||||
    for (let i = 0; i != recipe.ingredients.length; ++i) {
 | 
			
		||||
        if (startRecipeRequest.Ids[i] && startRecipeRequest.Ids[i][0] != "/") {
 | 
			
		||||
            if (recipe.ingredients[i].ItemType == "/Lotus/Types/Game/KubrowPet/Eggs/KubrowPetEggItem") {
 | 
			
		||||
                const index = inventory.KubrowPetEggs!.findIndex(x => x._id.equals(startRecipeRequest.Ids[i]));
 | 
			
		||||
                const index = inventory.KubrowPetEggs.findIndex(x => x._id.equals(startRecipeRequest.Ids[i]));
 | 
			
		||||
                if (index != -1) {
 | 
			
		||||
                    inventory.KubrowPetEggs!.splice(index, 1);
 | 
			
		||||
                    inventory.KubrowPetEggs.splice(index, 1);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                const category = ExportWeapons[recipe.ingredients[i].ItemType].productCategory;
 | 
			
		||||
@ -72,6 +72,10 @@ export const startRecipeController: RequestHandler = async (req, res) => {
 | 
			
		||||
    if (recipe.secretIngredientAction == "SIA_CREATE_KUBROW") {
 | 
			
		||||
        inventoryChanges = addKubrowPet(inventory, getRandomElement(recipe.secretIngredients!)!.ItemType);
 | 
			
		||||
        pr.KubrowPet = new Types.ObjectId(fromOid(inventoryChanges.KubrowPets![0].ItemId));
 | 
			
		||||
    } else if (recipe.secretIngredientAction == "SIA_DISTILL_PRINT") {
 | 
			
		||||
        pr.KubrowPet = new Types.ObjectId(startRecipeRequest.Ids[recipe.ingredients.length]);
 | 
			
		||||
        const pet = inventory.KubrowPets.id(pr.KubrowPet)!;
 | 
			
		||||
        pet.Details!.PrintsRemaining -= 1;
 | 
			
		||||
    } else if (recipe.secretIngredientAction == "SIA_SPECTRE_LOADOUT_COPY") {
 | 
			
		||||
        const spectreLoadout: ISpectreLoadout = {
 | 
			
		||||
            ItemType: recipe.resultType,
 | 
			
		||||
 | 
			
		||||
@ -99,7 +99,9 @@ import {
 | 
			
		||||
    ILotusCustomization,
 | 
			
		||||
    IEndlessXpReward,
 | 
			
		||||
    IPersonalGoalProgressDatabase,
 | 
			
		||||
    IPersonalGoalProgressClient
 | 
			
		||||
    IPersonalGoalProgressClient,
 | 
			
		||||
    IKubrowPetPrintClient,
 | 
			
		||||
    IKubrowPetPrintDatabase
 | 
			
		||||
} from "../../types/inventoryTypes/inventoryTypes";
 | 
			
		||||
import { IOid } from "../../types/commonTypes";
 | 
			
		||||
import {
 | 
			
		||||
@ -1008,6 +1010,27 @@ const traitsSchema = new Schema<ITraits>(
 | 
			
		||||
    { _id: false }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
const kubrowPetPrintSchema = new Schema<IKubrowPetPrintDatabase>({
 | 
			
		||||
    ItemType: String,
 | 
			
		||||
    Name: String,
 | 
			
		||||
    IsMale: Boolean,
 | 
			
		||||
    Size: Number,
 | 
			
		||||
    DominantTraits: traitsSchema,
 | 
			
		||||
    RecessiveTraits: traitsSchema
 | 
			
		||||
});
 | 
			
		||||
kubrowPetPrintSchema.set("toJSON", {
 | 
			
		||||
    virtuals: true,
 | 
			
		||||
    transform(_doc, obj) {
 | 
			
		||||
        const db = obj as IKubrowPetPrintDatabase;
 | 
			
		||||
        const client = obj as IKubrowPetPrintClient;
 | 
			
		||||
 | 
			
		||||
        client.ItemId = toOid(db._id);
 | 
			
		||||
 | 
			
		||||
        delete obj._id;
 | 
			
		||||
        delete obj.__v;
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const detailsSchema = new Schema<IKubrowPetDetailsDatabase>(
 | 
			
		||||
    {
 | 
			
		||||
        Name: String,
 | 
			
		||||
@ -1511,7 +1534,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
			
		||||
 | 
			
		||||
        KubrowPetEggs: [kubrowPetEggSchema],
 | 
			
		||||
        //Prints   Cat(3 Prints)\Kubrow(2 Prints) Pets
 | 
			
		||||
        //KubrowPetPrints: [Schema.Types.Mixed],
 | 
			
		||||
        KubrowPetPrints: [kubrowPetPrintSchema],
 | 
			
		||||
 | 
			
		||||
        //Item for EquippedGear example:Scaner,LoadoutTechSummon etc
 | 
			
		||||
        Consumables: [typeCountSchema],
 | 
			
		||||
@ -1852,6 +1875,7 @@ export type InventoryDocumentProps = {
 | 
			
		||||
    CrewShipSalvagedWeaponSkins: Types.DocumentArray<IUpgradeDatabase>;
 | 
			
		||||
    PersonalTechProjects: Types.DocumentArray<IPersonalTechProjectDatabase>;
 | 
			
		||||
    CrewMembers: Types.DocumentArray<ICrewMemberDatabase>;
 | 
			
		||||
    KubrowPetPrints: Types.DocumentArray<IKubrowPetPrintDatabase>;
 | 
			
		||||
} & { [K in TEquipmentKey]: Types.DocumentArray<IEquipmentDatabase> };
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,8 @@ import {
 | 
			
		||||
    ICalendarProgress,
 | 
			
		||||
    INemesisWeaponTargetFingerprint,
 | 
			
		||||
    INemesisPetTargetFingerprint,
 | 
			
		||||
    IDialogueDatabase
 | 
			
		||||
    IDialogueDatabase,
 | 
			
		||||
    IKubrowPetPrintClient
 | 
			
		||||
} from "@/src/types/inventoryTypes/inventoryTypes";
 | 
			
		||||
import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
 | 
			
		||||
import { IKeyChainRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes";
 | 
			
		||||
@ -424,7 +425,6 @@ export const addItem = async (
 | 
			
		||||
                    ItemType: "/Lotus/Types/Game/KubrowPet/Eggs/KubrowEgg",
 | 
			
		||||
                    _id: new Types.ObjectId()
 | 
			
		||||
                };
 | 
			
		||||
                inventory.KubrowPetEggs ??= [];
 | 
			
		||||
                inventory.KubrowPetEggs.push(egg);
 | 
			
		||||
                changes.push({
 | 
			
		||||
                    ItemType: egg.ItemType,
 | 
			
		||||
@ -784,7 +784,11 @@ export const addItem = async (
 | 
			
		||||
                        typeName.substr(1).split("/")[3] == "CatbrowPet" ||
 | 
			
		||||
                        typeName.substr(1).split("/")[3] == "KubrowPet"
 | 
			
		||||
                    ) {
 | 
			
		||||
                        if (typeName != "/Lotus/Types/Game/KubrowPet/Eggs/KubrowPetEggItem") {
 | 
			
		||||
                        if (
 | 
			
		||||
                            typeName != "/Lotus/Types/Game/KubrowPet/Eggs/KubrowPetEggItem" &&
 | 
			
		||||
                            typeName != "/Lotus/Types/Game/KubrowPet/BlankTraitPrint" &&
 | 
			
		||||
                            typeName != "/Lotus/Types/Game/KubrowPet/ImprintedTraitPrint"
 | 
			
		||||
                        ) {
 | 
			
		||||
                            return addKubrowPet(inventory, typeName, undefined, premiumPurchase);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else if (typeName.startsWith("/Lotus/Types/Game/CrewShip/CrewMember/")) {
 | 
			
		||||
@ -1048,8 +1052,13 @@ export const addKubrowPet = (
 | 
			
		||||
    const configs: IItemConfig[] = applyDefaultUpgrades(inventory, kubrowPet?.defaultUpgrades);
 | 
			
		||||
 | 
			
		||||
    if (!details) {
 | 
			
		||||
        let traits: ITraits;
 | 
			
		||||
        const isCatbrow = [
 | 
			
		||||
            "/Lotus/Types/Game/CatbrowPet/CheshireCatbrowPetPowerSuit",
 | 
			
		||||
            "/Lotus/Types/Game/CatbrowPet/MirrorCatbrowPetPowerSuit",
 | 
			
		||||
            "/Lotus/Types/Game/CatbrowPet/VampireCatbrowPetPowerSuit"
 | 
			
		||||
        ].includes(kubrowPetName);
 | 
			
		||||
 | 
			
		||||
        let traits: ITraits;
 | 
			
		||||
        if (kubrowPetName == "/Lotus/Types/Game/CatbrowPet/VampireCatbrowPetPowerSuit") {
 | 
			
		||||
            traits = {
 | 
			
		||||
                BaseColor: "/Lotus/Types/Game/CatbrowPet/Colors/CatbrowPetColorBaseVampire",
 | 
			
		||||
@ -1064,12 +1073,7 @@ export const addKubrowPet = (
 | 
			
		||||
                Tail: "/Lotus/Types/Game/CatbrowPet/Tails/CatbrowTailVampire"
 | 
			
		||||
            };
 | 
			
		||||
        } else {
 | 
			
		||||
            const isCatbrow = [
 | 
			
		||||
                "/Lotus/Types/Game/CatbrowPet/MirrorCatbrowPetPowerSuit",
 | 
			
		||||
                "/Lotus/Types/Game/CatbrowPet/CheshireCatbrowPetPowerSuit"
 | 
			
		||||
            ].includes(kubrowPetName);
 | 
			
		||||
            const traitsPool = isCatbrow ? catbrowDetails : kubrowDetails;
 | 
			
		||||
 | 
			
		||||
            traits = {
 | 
			
		||||
                BaseColor: getRandomWeightedReward(traitsPool.Colors, kubrowWeights)!.type,
 | 
			
		||||
                SecondaryColor: getRandomWeightedReward(traitsPool.Colors, kubrowWeights)!.type,
 | 
			
		||||
@ -1088,7 +1092,7 @@ export const addKubrowPet = (
 | 
			
		||||
            Name: "",
 | 
			
		||||
            IsPuppy: !premiumPurchase,
 | 
			
		||||
            HasCollar: true,
 | 
			
		||||
            PrintsRemaining: 3,
 | 
			
		||||
            PrintsRemaining: isCatbrow ? 3 : 2,
 | 
			
		||||
            Status: premiumPurchase ? Status.StatusStasis : Status.StatusIncubating,
 | 
			
		||||
            HatchDate: premiumPurchase ? new Date() : new Date(Date.now() + 10 * unixTimesInMs.hour), // On live, this seems to be somewhat randomised so that the pet hatches 9~11 hours after start.
 | 
			
		||||
            IsMale: !!getRandomInt(0, 1),
 | 
			
		||||
@ -1112,6 +1116,26 @@ export const addKubrowPet = (
 | 
			
		||||
    return inventoryChanges;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const addKubrowPetPrint = (
 | 
			
		||||
    inventory: TInventoryDatabaseDocument,
 | 
			
		||||
    pet: IEquipmentDatabase,
 | 
			
		||||
    inventoryChanges: IInventoryChanges
 | 
			
		||||
): void => {
 | 
			
		||||
    inventoryChanges.KubrowPetPrints ??= [];
 | 
			
		||||
    inventoryChanges.KubrowPetPrints.push(
 | 
			
		||||
        inventory.KubrowPetPrints[
 | 
			
		||||
            inventory.KubrowPetPrints.push({
 | 
			
		||||
                ItemType: "/Lotus/Types/Game/KubrowPet/ImprintedTraitPrint",
 | 
			
		||||
                Name: pet.Details!.Name,
 | 
			
		||||
                IsMale: pet.Details!.IsMale,
 | 
			
		||||
                Size: pet.Details!.Size,
 | 
			
		||||
                DominantTraits: pet.Details!.DominantTraits,
 | 
			
		||||
                RecessiveTraits: pet.Details!.RecessiveTraits
 | 
			
		||||
            }) - 1
 | 
			
		||||
        ].toJSON<IKubrowPetPrintClient>()
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const updateSlots = (
 | 
			
		||||
    inventory: TInventoryDatabaseDocument,
 | 
			
		||||
    slotName: SlotNames,
 | 
			
		||||
 | 
			
		||||
@ -525,7 +525,6 @@ export const addMissionInventoryUpdates = async (
 | 
			
		||||
            }
 | 
			
		||||
            case "KubrowPetEggs": {
 | 
			
		||||
                for (const egg of value) {
 | 
			
		||||
                    inventory.KubrowPetEggs ??= [];
 | 
			
		||||
                    inventory.KubrowPetEggs.push({
 | 
			
		||||
                        ItemType: egg.ItemType,
 | 
			
		||||
                        _id: new Types.ObjectId()
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,7 @@ export interface IInventoryDatabase
 | 
			
		||||
            | "InfestedFoundry"
 | 
			
		||||
            | "DialogueHistory"
 | 
			
		||||
            | "KubrowPetEggs"
 | 
			
		||||
            | "KubrowPetPrints"
 | 
			
		||||
            | "PendingCoupon"
 | 
			
		||||
            | "Drones"
 | 
			
		||||
            | "RecentVendorPurchases"
 | 
			
		||||
@ -79,7 +80,8 @@ export interface IInventoryDatabase
 | 
			
		||||
    KahlLoadOuts: IOperatorConfigDatabase[];
 | 
			
		||||
    InfestedFoundry?: IInfestedFoundryDatabase;
 | 
			
		||||
    DialogueHistory?: IDialogueHistoryDatabase;
 | 
			
		||||
    KubrowPetEggs?: IKubrowPetEggDatabase[];
 | 
			
		||||
    KubrowPetEggs: IKubrowPetEggDatabase[];
 | 
			
		||||
    KubrowPetPrints: IKubrowPetPrintDatabase[];
 | 
			
		||||
    PendingCoupon?: IPendingCouponDatabase;
 | 
			
		||||
    Drones: IDroneDatabase[];
 | 
			
		||||
    RecentVendorPurchases?: IRecentVendorPurchaseDatabase[];
 | 
			
		||||
@ -307,7 +309,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
			
		||||
    FocusUpgrades: IFocusUpgrade[];
 | 
			
		||||
    HasContributedToDojo?: boolean;
 | 
			
		||||
    HWIDProtectEnabled?: boolean;
 | 
			
		||||
    //KubrowPetPrints: IKubrowPetPrint[];
 | 
			
		||||
    KubrowPetPrints: IKubrowPetPrintClient[];
 | 
			
		||||
    AlignmentReplay?: IAlignment;
 | 
			
		||||
    PersonalGoalProgress?: IPersonalGoalProgressClient[];
 | 
			
		||||
    ThemeStyle: string;
 | 
			
		||||
@ -722,8 +724,8 @@ export interface IKubrowPetEggDatabase {
 | 
			
		||||
    _id: Types.ObjectId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IKubrowPetPrint {
 | 
			
		||||
    ItemType: KubrowPetPrintItemType;
 | 
			
		||||
export interface IKubrowPetPrintClient {
 | 
			
		||||
    ItemType: "/Lotus/Types/Game/KubrowPet/ImprintedTraitPrint";
 | 
			
		||||
    Name: string;
 | 
			
		||||
    IsMale: boolean;
 | 
			
		||||
    Size: number; // seems to be 0.7 to 1.0
 | 
			
		||||
@ -733,6 +735,10 @@ export interface IKubrowPetPrint {
 | 
			
		||||
    InheritedModularParts?: any[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IKubrowPetPrintDatabase extends Omit<IKubrowPetPrintClient, "ItemId" | "InheritedModularParts"> {
 | 
			
		||||
    _id: Types.ObjectId;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ITraits {
 | 
			
		||||
    BaseColor: string;
 | 
			
		||||
    SecondaryColor: string;
 | 
			
		||||
@ -746,15 +752,11 @@ export interface ITraits {
 | 
			
		||||
    Tail?: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export enum KubrowPetPrintItemType {
 | 
			
		||||
    LotusTypesGameKubrowPetImprintedTraitPrint = "/Lotus/Types/Game/KubrowPet/ImprintedTraitPrint"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IKubrowPetDetailsDatabase {
 | 
			
		||||
    Name?: string;
 | 
			
		||||
    IsPuppy?: boolean;
 | 
			
		||||
    HasCollar: boolean;
 | 
			
		||||
    PrintsRemaining?: number;
 | 
			
		||||
    PrintsRemaining: number;
 | 
			
		||||
    Status: Status;
 | 
			
		||||
    HatchDate?: Date;
 | 
			
		||||
    DominantTraits: ITraits;
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,8 @@ import {
 | 
			
		||||
    ITypeCount,
 | 
			
		||||
    IRecentVendorPurchaseClient,
 | 
			
		||||
    TEquipmentKey,
 | 
			
		||||
    ICrewMemberClient
 | 
			
		||||
    ICrewMemberClient,
 | 
			
		||||
    IKubrowPetPrintClient
 | 
			
		||||
} from "./inventoryTypes/inventoryTypes";
 | 
			
		||||
 | 
			
		||||
export enum PurchaseSource {
 | 
			
		||||
@ -78,6 +79,7 @@ export type IInventoryChanges = {
 | 
			
		||||
    NewVendorPurchase?: IRecentVendorPurchaseClient; // >= 38.5.0
 | 
			
		||||
    RecentVendorPurchases?: IRecentVendorPurchaseClient; // < 38.5.0
 | 
			
		||||
    CrewMembers?: ICrewMemberClient[];
 | 
			
		||||
    KubrowPetPrints?: IKubrowPetPrintClient[];
 | 
			
		||||
} & Record<
 | 
			
		||||
        Exclude<
 | 
			
		||||
            string,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user