feat: initial vendor rotations
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Build / build (22) (push) Successful in 1m18s
				
			
		
			
				
	
				Build / build (18) (pull_request) Successful in 43s
				
			
		
			
				
	
				Build / build (20) (push) Successful in 42s
				
			
		
			
				
	
				Build / build (18) (push) Successful in 1m17s
				
			
		
			
				
	
				Build / build (20) (pull_request) Successful in 1m14s
				
			
		
			
				
	
				Build / build (22) (pull_request) Successful in 1m18s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build / build (22) (push) Successful in 1m18s
				
			Build / build (18) (pull_request) Successful in 43s
				
			Build / build (20) (push) Successful in 42s
				
			Build / build (18) (push) Successful in 1m17s
				
			Build / build (20) (pull_request) Successful in 1m14s
				
			Build / build (22) (pull_request) Successful in 1m18s
				
			This commit is contained in:
		
							parent
							
								
									3a904753f2
								
							
						
					
					
						commit
						bd4ab2fcac
					
				@ -1,5 +1,5 @@
 | 
				
			|||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
import { getVendorManifestByTypeName } from "@/src/services/serversideVendorsService";
 | 
					import { getVendorManifestByTypeName, preprocessVendorManifest } from "@/src/services/serversideVendorsService";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getVendorInfoController: RequestHandler = (req, res) => {
 | 
					export const getVendorInfoController: RequestHandler = (req, res) => {
 | 
				
			||||||
    if (typeof req.query.vendor == "string") {
 | 
					    if (typeof req.query.vendor == "string") {
 | 
				
			||||||
@ -7,7 +7,7 @@ export const getVendorInfoController: RequestHandler = (req, res) => {
 | 
				
			|||||||
        if (!manifest) {
 | 
					        if (!manifest) {
 | 
				
			||||||
            throw new Error(`Unknown vendor: ${req.query.vendor}`);
 | 
					            throw new Error(`Unknown vendor: ${req.query.vendor}`);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        res.json(manifest);
 | 
					        res.json(preprocessVendorManifest(manifest));
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        res.status(400).end();
 | 
					        res.status(400).end();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -15,8 +15,7 @@ export const submitLeaderboardScore = async (
 | 
				
			|||||||
        expiry = new Date(Math.trunc(Date.now() / 86400000) * 86400000 + 86400000);
 | 
					        expiry = new Date(Math.trunc(Date.now() / 86400000) * 86400000 + 86400000);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        const EPOCH = 1734307200 * 1000; // Monday
 | 
					        const EPOCH = 1734307200 * 1000; // Monday
 | 
				
			||||||
        const day = Math.trunc((Date.now() - EPOCH) / 86400000);
 | 
					        const week = Math.trunc((Date.now() - EPOCH) / 604800000);
 | 
				
			||||||
        const week = Math.trunc(day / 7);
 | 
					 | 
				
			||||||
        const weekStart = EPOCH + week * 604800000;
 | 
					        const weekStart = EPOCH + week * 604800000;
 | 
				
			||||||
        const weekEnd = weekStart + 604800000;
 | 
					        const weekEnd = weekStart + 604800000;
 | 
				
			||||||
        expiry = new Date(weekEnd);
 | 
					        expiry = new Date(weekEnd);
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ import {
 | 
				
			|||||||
    updateSlots
 | 
					    updateSlots
 | 
				
			||||||
} from "@/src/services/inventoryService";
 | 
					} from "@/src/services/inventoryService";
 | 
				
			||||||
import { getRandomWeightedRewardUc } from "@/src/services/rngService";
 | 
					import { getRandomWeightedRewardUc } from "@/src/services/rngService";
 | 
				
			||||||
import { getVendorManifestByOid } from "@/src/services/serversideVendorsService";
 | 
					import { getVendorManifestByOid, preprocessVendorManifest } from "@/src/services/serversideVendorsService";
 | 
				
			||||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
					import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
import { IPurchaseRequest, IPurchaseResponse, SlotPurchase, IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
					import { IPurchaseRequest, IPurchaseResponse, SlotPurchase, IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { logger } from "@/src/utils/logger";
 | 
					import { logger } from "@/src/utils/logger";
 | 
				
			||||||
@ -52,8 +52,9 @@ export const handlePurchase = async (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const prePurchaseInventoryChanges: IInventoryChanges = {};
 | 
					    const prePurchaseInventoryChanges: IInventoryChanges = {};
 | 
				
			||||||
    if (purchaseRequest.PurchaseParams.Source == 7) {
 | 
					    if (purchaseRequest.PurchaseParams.Source == 7) {
 | 
				
			||||||
        const manifest = getVendorManifestByOid(purchaseRequest.PurchaseParams.SourceId!);
 | 
					        const rawManifest = getVendorManifestByOid(purchaseRequest.PurchaseParams.SourceId!);
 | 
				
			||||||
        if (manifest) {
 | 
					        if (rawManifest) {
 | 
				
			||||||
 | 
					            const manifest = preprocessVendorManifest(rawManifest);
 | 
				
			||||||
            let ItemId: string | undefined;
 | 
					            let ItemId: string | undefined;
 | 
				
			||||||
            if (purchaseRequest.PurchaseParams.ExtraPurchaseInfoJson) {
 | 
					            if (purchaseRequest.PurchaseParams.ExtraPurchaseInfoJson) {
 | 
				
			||||||
                ItemId = (JSON.parse(purchaseRequest.PurchaseParams.ExtraPurchaseInfoJson) as { ItemId: string })
 | 
					                ItemId = (JSON.parse(purchaseRequest.PurchaseParams.ExtraPurchaseInfoJson) as { ItemId: string })
 | 
				
			||||||
@ -87,16 +88,28 @@ export const handlePurchase = async (
 | 
				
			|||||||
                            }) - 1
 | 
					                            }) - 1
 | 
				
			||||||
                        ];
 | 
					                        ];
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					                let expiry = parseInt(offer.Expiry.$date.$numberLong);
 | 
				
			||||||
 | 
					                if (purchaseRequest.PurchaseParams.IsWeekly) {
 | 
				
			||||||
 | 
					                    const EPOCH = 1734307200 * 1000; // Monday
 | 
				
			||||||
 | 
					                    const week = Math.trunc((Date.now() - EPOCH) / 604800000);
 | 
				
			||||||
 | 
					                    const weekStart = EPOCH + week * 604800000;
 | 
				
			||||||
 | 
					                    expiry = weekStart + 604800000;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                const historyEntry = vendorPurchases.PurchaseHistory.find(x => x.ItemId == ItemId);
 | 
					                const historyEntry = vendorPurchases.PurchaseHistory.find(x => x.ItemId == ItemId);
 | 
				
			||||||
                let numPurchased = purchaseRequest.PurchaseParams.Quantity;
 | 
					                let numPurchased = purchaseRequest.PurchaseParams.Quantity;
 | 
				
			||||||
                if (historyEntry) {
 | 
					                if (historyEntry) {
 | 
				
			||||||
 | 
					                    if (Date.now() >= historyEntry.Expiry.getTime()) {
 | 
				
			||||||
 | 
					                        historyEntry.NumPurchased = numPurchased;
 | 
				
			||||||
 | 
					                        historyEntry.Expiry = new Date(expiry);
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
                        numPurchased += historyEntry.NumPurchased;
 | 
					                        numPurchased += historyEntry.NumPurchased;
 | 
				
			||||||
                        historyEntry.NumPurchased += purchaseRequest.PurchaseParams.Quantity;
 | 
					                        historyEntry.NumPurchased += purchaseRequest.PurchaseParams.Quantity;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    vendorPurchases.PurchaseHistory.push({
 | 
					                    vendorPurchases.PurchaseHistory.push({
 | 
				
			||||||
                        ItemId: ItemId,
 | 
					                        ItemId: ItemId,
 | 
				
			||||||
                        NumPurchased: purchaseRequest.PurchaseParams.Quantity,
 | 
					                        NumPurchased: purchaseRequest.PurchaseParams.Quantity,
 | 
				
			||||||
                        Expiry: new Date(parseInt(offer.Expiry.$date.$numberLong))
 | 
					                        Expiry: new Date(expiry)
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                prePurchaseInventoryChanges.NewVendorPurchase = {
 | 
					                prePurchaseInventoryChanges.NewVendorPurchase = {
 | 
				
			||||||
@ -105,7 +118,7 @@ export const handlePurchase = async (
 | 
				
			|||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            ItemId: ItemId,
 | 
					                            ItemId: ItemId,
 | 
				
			||||||
                            NumPurchased: numPurchased,
 | 
					                            NumPurchased: numPurchased,
 | 
				
			||||||
                            Expiry: offer.Expiry
 | 
					                            Expiry: { $date: { $numberLong: expiry.toString() } }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    ]
 | 
					                    ]
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,6 @@
 | 
				
			|||||||
import { IMongoDate, IOid } from "@/src/types/commonTypes";
 | 
					import { CRng, mixSeeds } from "@/src/services/rngService";
 | 
				
			||||||
 | 
					import { IMongoDate } from "@/src/types/commonTypes";
 | 
				
			||||||
 | 
					import { IVendorManifest, IVendorManifestPreprocessed } from "@/src/types/vendorTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
 | 
					import ArchimedeanVendorManifest from "@/static/fixed_responses/getVendorInfo/ArchimedeanVendorManifest.json";
 | 
				
			||||||
import DeimosEntratiFragmentVendorProductsManifest from "@/static/fixed_responses/getVendorInfo/DeimosEntratiFragmentVendorProductsManifest.json";
 | 
					import DeimosEntratiFragmentVendorProductsManifest from "@/static/fixed_responses/getVendorInfo/DeimosEntratiFragmentVendorProductsManifest.json";
 | 
				
			||||||
@ -31,25 +33,6 @@ 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";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface IVendorManifest {
 | 
					 | 
				
			||||||
    VendorInfo: {
 | 
					 | 
				
			||||||
        _id: IOid;
 | 
					 | 
				
			||||||
        TypeName: string;
 | 
					 | 
				
			||||||
        ItemManifest: {
 | 
					 | 
				
			||||||
            StoreItem: string;
 | 
					 | 
				
			||||||
            ItemPrices?: { ItemType: string; ItemCount: number; ProductCategory: string }[];
 | 
					 | 
				
			||||||
            Bin: string;
 | 
					 | 
				
			||||||
            QuantityMultiplier: number;
 | 
					 | 
				
			||||||
            Expiry: IMongoDate;
 | 
					 | 
				
			||||||
            PurchaseQuantityLimit?: number;
 | 
					 | 
				
			||||||
            RotatedWeekly?: boolean;
 | 
					 | 
				
			||||||
            AllowMultipurchase: boolean;
 | 
					 | 
				
			||||||
            Id: IOid;
 | 
					 | 
				
			||||||
        }[];
 | 
					 | 
				
			||||||
        Expiry: IMongoDate;
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const vendorManifests: IVendorManifest[] = [
 | 
					const vendorManifests: IVendorManifest[] = [
 | 
				
			||||||
    ArchimedeanVendorManifest,
 | 
					    ArchimedeanVendorManifest,
 | 
				
			||||||
    DeimosEntratiFragmentVendorProductsManifest,
 | 
					    DeimosEntratiFragmentVendorProductsManifest,
 | 
				
			||||||
@ -65,8 +48,8 @@ const vendorManifests: IVendorManifest[] = [
 | 
				
			|||||||
    DuviriAcrithisVendorManifest,
 | 
					    DuviriAcrithisVendorManifest,
 | 
				
			||||||
    EntratiLabsEntratiLabsCommisionsManifest,
 | 
					    EntratiLabsEntratiLabsCommisionsManifest,
 | 
				
			||||||
    EntratiLabsEntratiLabVendorManifest,
 | 
					    EntratiLabsEntratiLabVendorManifest,
 | 
				
			||||||
    GuildAdvertisementVendorManifest,
 | 
					    GuildAdvertisementVendorManifest, // uses preprocessing
 | 
				
			||||||
    HubsIronwakeDondaVendorManifest,
 | 
					    HubsIronwakeDondaVendorManifest, // uses preprocessing
 | 
				
			||||||
    HubsPerrinSequenceWeaponVendorManifest,
 | 
					    HubsPerrinSequenceWeaponVendorManifest,
 | 
				
			||||||
    HubsRailjackCrewMemberVendorManifest,
 | 
					    HubsRailjackCrewMemberVendorManifest,
 | 
				
			||||||
    MaskSalesmanManifest,
 | 
					    MaskSalesmanManifest,
 | 
				
			||||||
@ -79,7 +62,7 @@ const vendorManifests: IVendorManifest[] = [
 | 
				
			|||||||
    SolarisDebtTokenVendorRepossessionsManifest,
 | 
					    SolarisDebtTokenVendorRepossessionsManifest,
 | 
				
			||||||
    SolarisFishmongerVendorManifest,
 | 
					    SolarisFishmongerVendorManifest,
 | 
				
			||||||
    SolarisProspectorVendorManifest,
 | 
					    SolarisProspectorVendorManifest,
 | 
				
			||||||
    TeshinHardModeVendorManifest,
 | 
					    TeshinHardModeVendorManifest, // uses preprocessing
 | 
				
			||||||
    ZarimanCommisionsManifestArchimedean
 | 
					    ZarimanCommisionsManifestArchimedean
 | 
				
			||||||
];
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -100,3 +83,38 @@ export const getVendorManifestByOid = (oid: string): IVendorManifest | undefined
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return undefined;
 | 
					    return undefined;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const preprocessVendorManifest = (originalManifest: IVendorManifest): IVendorManifestPreprocessed => {
 | 
				
			||||||
 | 
					    if (Date.now() >= parseInt(originalManifest.VendorInfo.Expiry.$date.$numberLong)) {
 | 
				
			||||||
 | 
					        const manifest = structuredClone(originalManifest);
 | 
				
			||||||
 | 
					        const info = manifest.VendorInfo;
 | 
				
			||||||
 | 
					        refreshExpiry(info.Expiry);
 | 
				
			||||||
 | 
					        for (const offer of info.ItemManifest) {
 | 
				
			||||||
 | 
					            const iteration = 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 originalManifest as IVendorManifestPreprocessed;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const refreshExpiry = (expiry: IMongoDate): number => {
 | 
				
			||||||
 | 
					    const period = parseInt(expiry.$date.$numberLong);
 | 
				
			||||||
 | 
					    if (Date.now() >= period) {
 | 
				
			||||||
 | 
					        const epoch = 1734307200 * 1000; // Monday (for weekly schedules)
 | 
				
			||||||
 | 
					        const iteration = Math.trunc((Date.now() - epoch) / period);
 | 
				
			||||||
 | 
					        const start = epoch + iteration * period;
 | 
				
			||||||
 | 
					        const end = start + period;
 | 
				
			||||||
 | 
					        expiry.$date.$numberLong = end.toString();
 | 
				
			||||||
 | 
					        return iteration;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										46
									
								
								src/types/vendorTypes.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/types/vendorTypes.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					import { IMongoDate, IOid } from "./commonTypes";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IItemPrice {
 | 
				
			||||||
 | 
					    ItemType: string | string[]; // If string[], preprocessing will use RNG to pick one for the current period.
 | 
				
			||||||
 | 
					    ItemCount: number;
 | 
				
			||||||
 | 
					    ProductCategory: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IItemPricePreprocessed extends Omit<IItemPrice, "ItemType"> {
 | 
				
			||||||
 | 
					    ItemType: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IItemManifest {
 | 
				
			||||||
 | 
					    StoreItem: string;
 | 
				
			||||||
 | 
					    ItemPrices?: IItemPrice[];
 | 
				
			||||||
 | 
					    Bin: string;
 | 
				
			||||||
 | 
					    QuantityMultiplier: number;
 | 
				
			||||||
 | 
					    Expiry: IMongoDate; // Either a date in the distant future or a period in milliseconds for preprocessing.
 | 
				
			||||||
 | 
					    PurchaseQuantityLimit?: number;
 | 
				
			||||||
 | 
					    RotatedWeekly?: boolean;
 | 
				
			||||||
 | 
					    AllowMultipurchase: boolean;
 | 
				
			||||||
 | 
					    Id: IOid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IItemManifestPreprocessed extends Omit<IItemManifest, "ItemPrices"> {
 | 
				
			||||||
 | 
					    ItemPrices?: IItemPricePreprocessed[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IVendorInfo {
 | 
				
			||||||
 | 
					    _id: IOid;
 | 
				
			||||||
 | 
					    TypeName: string;
 | 
				
			||||||
 | 
					    ItemManifest: IItemManifest[];
 | 
				
			||||||
 | 
					    Expiry: IMongoDate; // Either a date in the distant future or a period in milliseconds for preprocessing.
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IVendorInfoPreprocessed extends Omit<IVendorInfo, "ItemManifest"> {
 | 
				
			||||||
 | 
					    ItemManifest: IItemManifestPreprocessed[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IVendorManifest {
 | 
				
			||||||
 | 
					    VendorInfo: IVendorInfo;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IVendorManifestPreprocessed {
 | 
				
			||||||
 | 
					    VendorInfo: IVendorInfoPreprocessed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -5,11 +5,17 @@
 | 
				
			|||||||
    "ItemManifest": [
 | 
					    "ItemManifest": [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementMoon",
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementMoon",
 | 
				
			||||||
        "ItemPrices": [{ "ItemType": "/Lotus/Types/Items/Research/ChemComponent", "ItemCount": 12, "ProductCategory": "MiscItems" }],
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
 | 
				
			||||||
 | 
					            "ItemCount": 12,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
        "RegularPrice": [1, 1],
 | 
					        "RegularPrice": [1, 1],
 | 
				
			||||||
        "Bin": "BIN_4",
 | 
					        "Bin": "BIN_4",
 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
        "Expiry": { "$date": { "$numberLong": "9999999000000" } },
 | 
					        "Expiry": { "$date": { "$numberLong": "604800000" } },
 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
        "LocTagRandSeed": 79554843,
 | 
					        "LocTagRandSeed": 79554843,
 | 
				
			||||||
@ -17,11 +23,17 @@
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementMountain",
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementMountain",
 | 
				
			||||||
        "ItemPrices": [{ "ItemType": "/Lotus/Types/Items/Research/ChemComponent", "ItemCount": 7, "ProductCategory": "MiscItems" }],
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
 | 
				
			||||||
 | 
					            "ItemCount": 7,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
        "RegularPrice": [1, 1],
 | 
					        "RegularPrice": [1, 1],
 | 
				
			||||||
        "Bin": "BIN_3",
 | 
					        "Bin": "BIN_3",
 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
        "Expiry": { "$date": { "$numberLong": "9999999000000" } },
 | 
					        "Expiry": { "$date": { "$numberLong": "604800000" } },
 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
        "LocTagRandSeed": 2413820225,
 | 
					        "LocTagRandSeed": 2413820225,
 | 
				
			||||||
@ -29,11 +41,17 @@
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementStorm",
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementStorm",
 | 
				
			||||||
        "ItemPrices": [{ "ItemType": "/Lotus/Types/Items/Research/ChemComponent", "ItemCount": 3, "ProductCategory": "MiscItems" }],
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
 | 
				
			||||||
 | 
					            "ItemCount": 3,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
        "RegularPrice": [1, 1],
 | 
					        "RegularPrice": [1, 1],
 | 
				
			||||||
        "Bin": "BIN_2",
 | 
					        "Bin": "BIN_2",
 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
        "Expiry": { "$date": { "$numberLong": "9999999000000" } },
 | 
					        "Expiry": { "$date": { "$numberLong": "604800000" } },
 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
        "LocTagRandSeed": 3262300883,
 | 
					        "LocTagRandSeed": 3262300883,
 | 
				
			||||||
@ -41,11 +59,17 @@
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementShadow",
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementShadow",
 | 
				
			||||||
        "ItemPrices": [{ "ItemType": "/Lotus/Types/Items/Research/EnergyFragment", "ItemCount": 20, "ProductCategory": "MiscItems" }],
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
 | 
				
			||||||
 | 
					            "ItemCount": 20,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
        "RegularPrice": [1, 1],
 | 
					        "RegularPrice": [1, 1],
 | 
				
			||||||
        "Bin": "BIN_1",
 | 
					        "Bin": "BIN_1",
 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
        "Expiry": { "$date": { "$numberLong": "9999999000000" } },
 | 
					        "Expiry": { "$date": { "$numberLong": "604800000" } },
 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
        "LocTagRandSeed": 2797325750,
 | 
					        "LocTagRandSeed": 2797325750,
 | 
				
			||||||
@ -53,11 +77,17 @@
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementGhost",
 | 
					        "StoreItem": "/Lotus/StoreItems/Types/Items/Guild/GuildAdvertisementGhost",
 | 
				
			||||||
        "ItemPrices": [{ "ItemType": "/Lotus/Types/Items/Research/EnergyFragment", "ItemCount": 10, "ProductCategory": "MiscItems" }],
 | 
					        "ItemPrices": [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            "ItemType": ["/Lotus/Types/Items/Research/BioFragment", "/Lotus/Types/Items/Research/ChemComponent", "/Lotus/Types/Items/Research/EnergyFragment"],
 | 
				
			||||||
 | 
					            "ItemCount": 10,
 | 
				
			||||||
 | 
					            "ProductCategory": "MiscItems"
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
        "RegularPrice": [1, 1],
 | 
					        "RegularPrice": [1, 1],
 | 
				
			||||||
        "Bin": "BIN_0",
 | 
					        "Bin": "BIN_0",
 | 
				
			||||||
        "QuantityMultiplier": 1,
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
        "Expiry": { "$date": { "$numberLong": "9999999000000" } },
 | 
					        "Expiry": { "$date": { "$numberLong": "604800000" } },
 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
        "AllowMultipurchase": false,
 | 
					        "AllowMultipurchase": false,
 | 
				
			||||||
        "LocTagRandSeed": 554932310,
 | 
					        "LocTagRandSeed": 554932310,
 | 
				
			||||||
@ -66,6 +96,6 @@
 | 
				
			|||||||
    ],
 | 
					    ],
 | 
				
			||||||
    "PropertyTextHash": "255AFE2169BAE4130B4B20D7C55D14FA",
 | 
					    "PropertyTextHash": "255AFE2169BAE4130B4B20D7C55D14FA",
 | 
				
			||||||
    "RandomSeedType": "VRST_FLAVOUR_TEXT",
 | 
					    "RandomSeedType": "VRST_FLAVOUR_TEXT",
 | 
				
			||||||
    "Expiry": { "$date": { "$numberLong": "9999999000000" } }
 | 
					    "Expiry": { "$date": { "$numberLong": "604800000" } }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@
 | 
				
			|||||||
        "QuantityMultiplier": 1,
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
        "Expiry": {
 | 
					        "Expiry": {
 | 
				
			||||||
          "$date": {
 | 
					          "$date": {
 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					            "$numberLong": "604800000"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "AllowMultipurchase": true,
 | 
					        "AllowMultipurchase": true,
 | 
				
			||||||
@ -39,7 +39,7 @@
 | 
				
			|||||||
        "QuantityMultiplier": 1,
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
        "Expiry": {
 | 
					        "Expiry": {
 | 
				
			||||||
          "$date": {
 | 
					          "$date": {
 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					            "$numberLong": "604800000"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
@ -61,7 +61,7 @@
 | 
				
			|||||||
        "QuantityMultiplier": 1,
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
        "Expiry": {
 | 
					        "Expiry": {
 | 
				
			||||||
          "$date": {
 | 
					          "$date": {
 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					            "$numberLong": "604800000"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
@ -83,7 +83,7 @@
 | 
				
			|||||||
        "QuantityMultiplier": 35000,
 | 
					        "QuantityMultiplier": 35000,
 | 
				
			||||||
        "Expiry": {
 | 
					        "Expiry": {
 | 
				
			||||||
          "$date": {
 | 
					          "$date": {
 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					            "$numberLong": "604800000"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
@ -105,7 +105,7 @@
 | 
				
			|||||||
        "QuantityMultiplier": 1,
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
        "Expiry": {
 | 
					        "Expiry": {
 | 
				
			||||||
          "$date": {
 | 
					          "$date": {
 | 
				
			||||||
            "$numberLong": "9999999000000"
 | 
					            "$numberLong": "604800000"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "PurchaseQuantityLimit": 1,
 | 
					        "PurchaseQuantityLimit": 1,
 | 
				
			||||||
@ -118,7 +118,7 @@
 | 
				
			|||||||
    "PropertyTextHash": "62B64A8065B7C0FA345895D4BC234621",
 | 
					    "PropertyTextHash": "62B64A8065B7C0FA345895D4BC234621",
 | 
				
			||||||
    "Expiry": {
 | 
					    "Expiry": {
 | 
				
			||||||
      "$date": {
 | 
					      "$date": {
 | 
				
			||||||
        "$numberLong": "9999999000000"
 | 
					        "$numberLong": "604800000"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -561,7 +561,7 @@
 | 
				
			|||||||
        "QuantityMultiplier": 1,
 | 
					        "QuantityMultiplier": 1,
 | 
				
			||||||
        "Expiry": {
 | 
					        "Expiry": {
 | 
				
			||||||
          "$date": {
 | 
					          "$date": {
 | 
				
			||||||
            "$numberLong": "2051240400000"
 | 
					            "$numberLong": "604800000"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "PurchaseQuantityLimit": 25,
 | 
					        "PurchaseQuantityLimit": 25,
 | 
				
			||||||
@ -583,7 +583,7 @@
 | 
				
			|||||||
        "QuantityMultiplier": 10000,
 | 
					        "QuantityMultiplier": 10000,
 | 
				
			||||||
        "Expiry": {
 | 
					        "Expiry": {
 | 
				
			||||||
          "$date": {
 | 
					          "$date": {
 | 
				
			||||||
            "$numberLong": "2051240400000"
 | 
					            "$numberLong": "604800000"
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "PurchaseQuantityLimit": 25,
 | 
					        "PurchaseQuantityLimit": 25,
 | 
				
			||||||
@ -596,7 +596,7 @@
 | 
				
			|||||||
    "PropertyTextHash": "0A0F20AFA748FBEE490510DBF5A33A0D",
 | 
					    "PropertyTextHash": "0A0F20AFA748FBEE490510DBF5A33A0D",
 | 
				
			||||||
    "Expiry": {
 | 
					    "Expiry": {
 | 
				
			||||||
      "$date": {
 | 
					      "$date": {
 | 
				
			||||||
        "$numberLong": "2051240400000"
 | 
					        "$numberLong": "604800000"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user