forked from OpenWF/SpaceNinjaServer
		
	chore: auto-generate guild advertisment vendor (#1845)
With this, preprocessing is simplified to just refreshing expiry dates. No real change to auto-generation logic. Reviewed-on: OpenWF/SpaceNinjaServer#1845 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
							
								
									3f6734ac1c
								
							
						
					
					
						commit
						90e97d7888
					
				@ -1,13 +1,7 @@
 | 
				
			|||||||
import { unixTimesInMs } from "@/src/constants/timeConstants";
 | 
					import { unixTimesInMs } from "@/src/constants/timeConstants";
 | 
				
			||||||
import { CRng, mixSeeds } from "@/src/services/rngService";
 | 
					import { CRng, mixSeeds } from "@/src/services/rngService";
 | 
				
			||||||
import { IMongoDate } from "@/src/types/commonTypes";
 | 
					import { IMongoDate } from "@/src/types/commonTypes";
 | 
				
			||||||
import {
 | 
					import { IItemManifest, IVendorInfo, IVendorManifest } from "@/src/types/vendorTypes";
 | 
				
			||||||
    IItemManifestPreprocessed,
 | 
					 | 
				
			||||||
    IRawVendorManifest,
 | 
					 | 
				
			||||||
    IVendorInfo,
 | 
					 | 
				
			||||||
    IVendorInfoPreprocessed,
 | 
					 | 
				
			||||||
    IVendorManifestPreprocessed
 | 
					 | 
				
			||||||
} from "@/src/types/vendorTypes";
 | 
					 | 
				
			||||||
import { ExportVendors, IRange } from "warframe-public-export-plus";
 | 
					import { ExportVendors, IRange } from "warframe-public-export-plus";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
 | 
					import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
 | 
				
			||||||
@ -24,7 +18,6 @@ import DeimosProspectorVendorManifest from "@/static/fixed_responses/getVendorIn
 | 
				
			|||||||
import DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo/DuviriAcrithisVendorManifest.json";
 | 
					import DuviriAcrithisVendorManifest from "@/static/fixed_responses/getVendorInfo/DuviriAcrithisVendorManifest.json";
 | 
				
			||||||
import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json";
 | 
					import EntratiLabsEntratiLabsCommisionsManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabsCommisionsManifest.json";
 | 
				
			||||||
import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json";
 | 
					import EntratiLabsEntratiLabVendorManifest from "@/static/fixed_responses/getVendorInfo/EntratiLabsEntratiLabVendorManifest.json";
 | 
				
			||||||
import GuildAdvertisementVendorManifest from "@/static/fixed_responses/getVendorInfo/GuildAdvertisementVendorManifest.json";
 | 
					 | 
				
			||||||
import HubsIronwakeDondaVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsIronwakeDondaVendorManifest.json";
 | 
					import HubsIronwakeDondaVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsIronwakeDondaVendorManifest.json";
 | 
				
			||||||
import HubsRailjackCrewMemberVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsRailjackCrewMemberVendorManifest.json";
 | 
					import HubsRailjackCrewMemberVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsRailjackCrewMemberVendorManifest.json";
 | 
				
			||||||
import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json";
 | 
					import MaskSalesmanManifest from "@/static/fixed_responses/getVendorInfo/MaskSalesmanManifest.json";
 | 
				
			||||||
@ -39,7 +32,7 @@ import SolarisProspectorVendorManifest from "@/static/fixed_responses/getVendorI
 | 
				
			|||||||
import TeshinHardModeVendorManifest from "@/static/fixed_responses/getVendorInfo/TeshinHardModeVendorManifest.json";
 | 
					import TeshinHardModeVendorManifest from "@/static/fixed_responses/getVendorInfo/TeshinHardModeVendorManifest.json";
 | 
				
			||||||
import ZarimanCommisionsManifestArchimedean from "@/static/fixed_responses/getVendorInfo/ZarimanCommisionsManifestArchimedean.json";
 | 
					import ZarimanCommisionsManifestArchimedean from "@/static/fixed_responses/getVendorInfo/ZarimanCommisionsManifestArchimedean.json";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const rawVendorManifests: IRawVendorManifest[] = [
 | 
					const rawVendorManifests: IVendorManifest[] = [
 | 
				
			||||||
    ArchimedeanVendorManifest,
 | 
					    ArchimedeanVendorManifest,
 | 
				
			||||||
    DeimosEntratiFragmentVendorProductsManifest,
 | 
					    DeimosEntratiFragmentVendorProductsManifest,
 | 
				
			||||||
    DeimosFishmongerVendorManifest,
 | 
					    DeimosFishmongerVendorManifest,
 | 
				
			||||||
@ -54,7 +47,6 @@ const rawVendorManifests: IRawVendorManifest[] = [
 | 
				
			|||||||
    DuviriAcrithisVendorManifest,
 | 
					    DuviriAcrithisVendorManifest,
 | 
				
			||||||
    EntratiLabsEntratiLabsCommisionsManifest,
 | 
					    EntratiLabsEntratiLabsCommisionsManifest,
 | 
				
			||||||
    EntratiLabsEntratiLabVendorManifest,
 | 
					    EntratiLabsEntratiLabVendorManifest,
 | 
				
			||||||
    GuildAdvertisementVendorManifest, // uses preprocessing
 | 
					 | 
				
			||||||
    HubsIronwakeDondaVendorManifest, // uses preprocessing
 | 
					    HubsIronwakeDondaVendorManifest, // uses preprocessing
 | 
				
			||||||
    HubsRailjackCrewMemberVendorManifest,
 | 
					    HubsRailjackCrewMemberVendorManifest,
 | 
				
			||||||
    MaskSalesmanManifest,
 | 
					    MaskSalesmanManifest,
 | 
				
			||||||
@ -71,8 +63,8 @@ const rawVendorManifests: IRawVendorManifest[] = [
 | 
				
			|||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IGeneratableVendorInfo extends Omit<IVendorInfo, "ItemManifest" | "Expiry"> {
 | 
					interface IGeneratableVendorInfo extends Omit<IVendorInfo, "ItemManifest" | "Expiry"> {
 | 
				
			||||||
    cycleOffset: number;
 | 
					    cycleOffset?: number;
 | 
				
			||||||
    cycleDuration: number;
 | 
					    cycleDuration?: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const generatableVendors: IGeneratableVendorInfo[] = [
 | 
					const generatableVendors: IGeneratableVendorInfo[] = [
 | 
				
			||||||
@ -99,9 +91,13 @@ const generatableVendors: IGeneratableVendorInfo[] = [
 | 
				
			|||||||
        _id: { $oid: "5be4a159b144f3cdf1c22efa" },
 | 
					        _id: { $oid: "5be4a159b144f3cdf1c22efa" },
 | 
				
			||||||
        TypeName: "/Lotus/Types/Game/VendorManifests/Solaris/DebtTokenVendorManifest",
 | 
					        TypeName: "/Lotus/Types/Game/VendorManifests/Solaris/DebtTokenVendorManifest",
 | 
				
			||||||
        PropertyTextHash: "A39621049CA3CA13761028CD21C239EF",
 | 
					        PropertyTextHash: "A39621049CA3CA13761028CD21C239EF",
 | 
				
			||||||
        RandomSeedType: "VRST_FLAVOUR_TEXT",
 | 
					        RandomSeedType: "VRST_FLAVOUR_TEXT"
 | 
				
			||||||
        cycleOffset: 1734307200_000,
 | 
					    },
 | 
				
			||||||
        cycleDuration: unixTimesInMs.hour
 | 
					    {
 | 
				
			||||||
 | 
					        _id: { $oid: "61ba123467e5d37975aeeb03" },
 | 
				
			||||||
 | 
					        TypeName: "/Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest",
 | 
				
			||||||
 | 
					        PropertyTextHash: "255AFE2169BAE4130B4B20D7C55D14FA",
 | 
				
			||||||
 | 
					        RandomSeedType: "VRST_FLAVOUR_TEXT"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // {
 | 
					    // {
 | 
				
			||||||
    //     _id: { $oid: "5dbb4c41e966f7886c3ce939" },
 | 
					    //     _id: { $oid: "5dbb4c41e966f7886c3ce939" },
 | 
				
			||||||
@ -110,7 +106,7 @@ const generatableVendors: IGeneratableVendorInfo[] = [
 | 
				
			|||||||
    // }
 | 
					    // }
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getVendorManifestByTypeName = (typeName: string): IVendorManifestPreprocessed | undefined => {
 | 
					export const getVendorManifestByTypeName = (typeName: string): IVendorManifest | undefined => {
 | 
				
			||||||
    for (const vendorManifest of rawVendorManifests) {
 | 
					    for (const vendorManifest of rawVendorManifests) {
 | 
				
			||||||
        if (vendorManifest.VendorInfo.TypeName == typeName) {
 | 
					        if (vendorManifest.VendorInfo.TypeName == typeName) {
 | 
				
			||||||
            return preprocessVendorManifest(vendorManifest);
 | 
					            return preprocessVendorManifest(vendorManifest);
 | 
				
			||||||
@ -124,7 +120,7 @@ export const getVendorManifestByTypeName = (typeName: string): IVendorManifestPr
 | 
				
			|||||||
    return undefined;
 | 
					    return undefined;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getVendorManifestByOid = (oid: string): IVendorManifestPreprocessed | undefined => {
 | 
					export const getVendorManifestByOid = (oid: string): IVendorManifest | undefined => {
 | 
				
			||||||
    for (const vendorManifest of rawVendorManifests) {
 | 
					    for (const vendorManifest of rawVendorManifests) {
 | 
				
			||||||
        if (vendorManifest.VendorInfo._id.$oid == oid) {
 | 
					        if (vendorManifest.VendorInfo._id.$oid == oid) {
 | 
				
			||||||
            return preprocessVendorManifest(vendorManifest);
 | 
					            return preprocessVendorManifest(vendorManifest);
 | 
				
			||||||
@ -138,29 +134,20 @@ export const getVendorManifestByOid = (oid: string): IVendorManifestPreprocessed
 | 
				
			|||||||
    return undefined;
 | 
					    return undefined;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const preprocessVendorManifest = (originalManifest: IRawVendorManifest): IVendorManifestPreprocessed => {
 | 
					const preprocessVendorManifest = (originalManifest: IVendorManifest): IVendorManifest => {
 | 
				
			||||||
    if (Date.now() >= parseInt(originalManifest.VendorInfo.Expiry.$date.$numberLong)) {
 | 
					    if (Date.now() >= parseInt(originalManifest.VendorInfo.Expiry.$date.$numberLong)) {
 | 
				
			||||||
        const manifest = structuredClone(originalManifest);
 | 
					        const manifest = structuredClone(originalManifest);
 | 
				
			||||||
        const info = manifest.VendorInfo;
 | 
					        const info = manifest.VendorInfo;
 | 
				
			||||||
        refreshExpiry(info.Expiry);
 | 
					        refreshExpiry(info.Expiry);
 | 
				
			||||||
        for (const offer of info.ItemManifest) {
 | 
					        for (const offer of info.ItemManifest) {
 | 
				
			||||||
            const iteration = refreshExpiry(offer.Expiry);
 | 
					            refreshExpiry(offer.Expiry);
 | 
				
			||||||
            if (offer.ItemPrices) {
 | 
					 | 
				
			||||||
                for (const price of offer.ItemPrices) {
 | 
					 | 
				
			||||||
                    if (typeof price.ItemType != "string") {
 | 
					 | 
				
			||||||
                        const itemSeed = parseInt(offer.Id.$oid.substring(16), 16);
 | 
					 | 
				
			||||||
                        const rng = new CRng(mixSeeds(itemSeed, iteration));
 | 
					 | 
				
			||||||
                        price.ItemType = rng.randomElement(price.ItemType);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return manifest as IVendorManifestPreprocessed;
 | 
					        return manifest;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return originalManifest as IVendorManifestPreprocessed;
 | 
					    return originalManifest;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const refreshExpiry = (expiry: IMongoDate): number => {
 | 
					const refreshExpiry = (expiry: IMongoDate): void => {
 | 
				
			||||||
    const period = parseInt(expiry.$date.$numberLong);
 | 
					    const period = parseInt(expiry.$date.$numberLong);
 | 
				
			||||||
    if (Date.now() >= period) {
 | 
					    if (Date.now() >= period) {
 | 
				
			||||||
        const epoch = 1734307200_000; // Monday (for weekly schedules)
 | 
					        const epoch = 1734307200_000; // Monday (for weekly schedules)
 | 
				
			||||||
@ -168,9 +155,7 @@ const refreshExpiry = (expiry: IMongoDate): number => {
 | 
				
			|||||||
        const start = epoch + iteration * period;
 | 
					        const start = epoch + iteration * period;
 | 
				
			||||||
        const end = start + period;
 | 
					        const end = start + period;
 | 
				
			||||||
        expiry.$date.$numberLong = end.toString();
 | 
					        expiry.$date.$numberLong = end.toString();
 | 
				
			||||||
        return iteration;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const toRange = (value: IRange | number): IRange => {
 | 
					const toRange = (value: IRange | number): IRange => {
 | 
				
			||||||
@ -180,9 +165,9 @@ const toRange = (value: IRange | number): IRange => {
 | 
				
			|||||||
    return value;
 | 
					    return value;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const vendorInfoCache: Record<string, IVendorInfoPreprocessed> = {};
 | 
					const vendorInfoCache: Record<string, IVendorInfo> = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorManifestPreprocessed => {
 | 
					const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorManifest => {
 | 
				
			||||||
    if (!(vendorInfo.TypeName in vendorInfoCache)) {
 | 
					    if (!(vendorInfo.TypeName in vendorInfoCache)) {
 | 
				
			||||||
        // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
					        // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
				
			||||||
        const { cycleOffset, cycleDuration, ...clientVendorInfo } = vendorInfo;
 | 
					        const { cycleOffset, cycleDuration, ...clientVendorInfo } = vendorInfo;
 | 
				
			||||||
@ -205,7 +190,9 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Add new offers
 | 
					        // Add new offers
 | 
				
			||||||
        const vendorSeed = parseInt(vendorInfo._id.$oid.substring(16), 16);
 | 
					        const vendorSeed = parseInt(vendorInfo._id.$oid.substring(16), 16);
 | 
				
			||||||
        const cycleIndex = Math.trunc((Date.now() - vendorInfo.cycleOffset) / vendorInfo.cycleDuration);
 | 
					        const cycleOffset = vendorInfo.cycleOffset ?? 1734307200_000;
 | 
				
			||||||
 | 
					        const cycleDuration = vendorInfo.cycleDuration ?? unixTimesInMs.hour;
 | 
				
			||||||
 | 
					        const cycleIndex = Math.trunc((Date.now() - cycleOffset) / cycleDuration);
 | 
				
			||||||
        const rng = new CRng(mixSeeds(vendorSeed, cycleIndex));
 | 
					        const rng = new CRng(mixSeeds(vendorSeed, cycleIndex));
 | 
				
			||||||
        const manifest = ExportVendors[vendorInfo.TypeName];
 | 
					        const manifest = ExportVendors[vendorInfo.TypeName];
 | 
				
			||||||
        const offersToAdd = [];
 | 
					        const offersToAdd = [];
 | 
				
			||||||
@ -226,14 +213,19 @@ const generateVendorManifest = (vendorInfo: IGeneratableVendorInfo): IVendorMani
 | 
				
			|||||||
                    offersToAdd.push(rawItem);
 | 
					                    offersToAdd.push(rawItem);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // For most vendors, the offers seem to roughly be in reverse order from the manifest. Coda weapons are an odd exception.
 | 
				
			||||||
 | 
					            if (!manifest.isOneBinPerCycle) {
 | 
				
			||||||
 | 
					                offersToAdd.reverse();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const cycleStart = vendorInfo.cycleOffset + cycleIndex * vendorInfo.cycleDuration;
 | 
					        const cycleStart = cycleOffset + cycleIndex * cycleDuration;
 | 
				
			||||||
        for (const rawItem of offersToAdd) {
 | 
					        for (const rawItem of offersToAdd) {
 | 
				
			||||||
            const durationHoursRange = toRange(rawItem.durationHours);
 | 
					            const durationHoursRange = toRange(rawItem.durationHours);
 | 
				
			||||||
            const expiry =
 | 
					            const expiry =
 | 
				
			||||||
                cycleStart +
 | 
					                cycleStart +
 | 
				
			||||||
                rng.randomInt(durationHoursRange.minValue, durationHoursRange.maxValue) * unixTimesInMs.hour;
 | 
					                rng.randomInt(durationHoursRange.minValue, durationHoursRange.maxValue) * unixTimesInMs.hour;
 | 
				
			||||||
            const item: IItemManifestPreprocessed = {
 | 
					            const item: IItemManifest = {
 | 
				
			||||||
                StoreItem: rawItem.storeItem,
 | 
					                StoreItem: rawItem.storeItem,
 | 
				
			||||||
                ItemPrices: rawItem.itemPrices?.map(itemPrice => ({ ...itemPrice, ProductCategory: "MiscItems" })),
 | 
					                ItemPrices: rawItem.itemPrices?.map(itemPrice => ({ ...itemPrice, ProductCategory: "MiscItems" })),
 | 
				
			||||||
                Bin: "BIN_" + rawItem.bin,
 | 
					                Bin: "BIN_" + rawItem.bin,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,15 +1,11 @@
 | 
				
			|||||||
import { IMongoDate, IOid } from "./commonTypes";
 | 
					import { IMongoDate, IOid } from "./commonTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IItemPrice {
 | 
					export interface IItemPrice {
 | 
				
			||||||
    ItemType: string | string[]; // If string[], preprocessing will use RNG to pick one for the current period.
 | 
					    ItemType: string;
 | 
				
			||||||
    ItemCount: number;
 | 
					    ItemCount: number;
 | 
				
			||||||
    ProductCategory: string;
 | 
					    ProductCategory: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IItemPricePreprocessed extends Omit<IItemPrice, "ItemType"> {
 | 
					 | 
				
			||||||
    ItemType: string;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface IItemManifest {
 | 
					export interface IItemManifest {
 | 
				
			||||||
    StoreItem: string;
 | 
					    StoreItem: string;
 | 
				
			||||||
    ItemPrices?: IItemPrice[];
 | 
					    ItemPrices?: IItemPrice[];
 | 
				
			||||||
@ -24,10 +20,6 @@ export interface IItemManifest {
 | 
				
			|||||||
    Id: IOid;
 | 
					    Id: IOid;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IItemManifestPreprocessed extends Omit<IItemManifest, "ItemPrices"> {
 | 
					 | 
				
			||||||
    ItemPrices?: IItemPricePreprocessed[];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface IVendorInfo {
 | 
					export interface IVendorInfo {
 | 
				
			||||||
    _id: IOid;
 | 
					    _id: IOid;
 | 
				
			||||||
    TypeName: string;
 | 
					    TypeName: string;
 | 
				
			||||||
@ -39,14 +31,6 @@ export interface IVendorInfo {
 | 
				
			|||||||
    Expiry: IMongoDate; // Either a date in the distant future or a period in milliseconds for preprocessing.
 | 
					    Expiry: IMongoDate; // Either a date in the distant future or a period in milliseconds for preprocessing.
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IVendorInfoPreprocessed extends Omit<IVendorInfo, "ItemManifest"> {
 | 
					export interface IVendorManifest {
 | 
				
			||||||
    ItemManifest: IItemManifestPreprocessed[];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface IRawVendorManifest {
 | 
					 | 
				
			||||||
    VendorInfo: IVendorInfo;
 | 
					    VendorInfo: IVendorInfo;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface IVendorManifestPreprocessed {
 | 
					 | 
				
			||||||
    VendorInfo: IVendorInfoPreprocessed;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -1,101 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "VendorInfo": {
 | 
					 | 
				
			||||||
    "_id": { "$oid": "61ba123467e5d37975aeeb03" },
 | 
					 | 
				
			||||||
    "TypeName": "/Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest",
 | 
					 | 
				
			||||||
    "ItemManifest": [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementMoon",
 | 
					 | 
				
			||||||
        "ItemPrices": [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            "ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
 | 
					 | 
				
			||||||
            "ItemCount": 12,
 | 
					 | 
				
			||||||
            "ProductCategory": "MiscItems"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "RegularPrice": [1, 1],
 | 
					 | 
				
			||||||
        "Bin": "BIN_4",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					 | 
				
			||||||
        "Expiry": { "$date": { "$numberLong": "604800000" } },
 | 
					 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					 | 
				
			||||||
        "LocTagRandSeed": 79554843,
 | 
					 | 
				
			||||||
        "Id": { "$oid": "67bbb592e1534511d6c1c1e2" }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementMountain",
 | 
					 | 
				
			||||||
        "ItemPrices": [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            "ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
 | 
					 | 
				
			||||||
            "ItemCount": 7,
 | 
					 | 
				
			||||||
            "ProductCategory": "MiscItems"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "RegularPrice": [1, 1],
 | 
					 | 
				
			||||||
        "Bin": "BIN_3",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					 | 
				
			||||||
        "Expiry": { "$date": { "$numberLong": "604800000" } },
 | 
					 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					 | 
				
			||||||
        "LocTagRandSeed": 2413820225,
 | 
					 | 
				
			||||||
        "Id": { "$oid": "67bbb592e1534511d6c1c1e3" }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementStorm",
 | 
					 | 
				
			||||||
        "ItemPrices": [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            "ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
 | 
					 | 
				
			||||||
            "ItemCount": 3,
 | 
					 | 
				
			||||||
            "ProductCategory": "MiscItems"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "RegularPrice": [1, 1],
 | 
					 | 
				
			||||||
        "Bin": "BIN_2",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					 | 
				
			||||||
        "Expiry": { "$date": { "$numberLong": "604800000" } },
 | 
					 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					 | 
				
			||||||
        "LocTagRandSeed": 3262300883,
 | 
					 | 
				
			||||||
        "Id": { "$oid": "67bbb592e1534511d6c1c1e4" }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementShadow",
 | 
					 | 
				
			||||||
        "ItemPrices": [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            "ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
 | 
					 | 
				
			||||||
            "ItemCount": 20,
 | 
					 | 
				
			||||||
            "ProductCategory": "MiscItems"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "RegularPrice": [1, 1],
 | 
					 | 
				
			||||||
        "Bin": "BIN_1",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					 | 
				
			||||||
        "Expiry": { "$date": { "$numberLong": "604800000" } },
 | 
					 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					 | 
				
			||||||
        "LocTagRandSeed": 2797325750,
 | 
					 | 
				
			||||||
        "Id": { "$oid": "67bbb592e1534511d6c1c1e5" }
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementGhost",
 | 
					 | 
				
			||||||
        "ItemPrices": [
 | 
					 | 
				
			||||||
          {
 | 
					 | 
				
			||||||
            "ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
 | 
					 | 
				
			||||||
            "ItemCount": 10,
 | 
					 | 
				
			||||||
            "ProductCategory": "MiscItems"
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "RegularPrice": [1, 1],
 | 
					 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					 | 
				
			||||||
        "Expiry": { "$date": { "$numberLong": "604800000" } },
 | 
					 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					 | 
				
			||||||
        "LocTagRandSeed": 554932310,
 | 
					 | 
				
			||||||
        "Id": { "$oid": "67bbb592e1534511d6c1c1e6" }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    "PropertyTextHash": "255AFE2169BAE4130B4B20D7C55D14FA",
 | 
					 | 
				
			||||||
    "RandomSeedType": "VRST_FLAVOUR_TEXT",
 | 
					 | 
				
			||||||
    "Expiry": { "$date": { "$numberLong": "604800000" } }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user