forked from OpenWF/SpaceNinjaServer
		
	feat: track vendor purchases (#1153)
Closes #739 Also adds the `noVendorPurchaseLimits` cheat to disable the logic, which is enabled by default due to lack of vendor rotations. Reviewed-on: OpenWF/SpaceNinjaServer#1153
This commit is contained in:
		
							parent
							
								
									b7800b6d20
								
							
						
					
					
						commit
						6490fadcae
					
				@ -29,6 +29,7 @@
 | 
				
			|||||||
  "unlockExilusEverywhere": false,
 | 
					  "unlockExilusEverywhere": false,
 | 
				
			||||||
  "unlockArcanesEverywhere": false,
 | 
					  "unlockArcanesEverywhere": false,
 | 
				
			||||||
  "noDailyStandingLimits": false,
 | 
					  "noDailyStandingLimits": false,
 | 
				
			||||||
 | 
					  "noVendorPurchaseLimits": true,
 | 
				
			||||||
  "instantResourceExtractorDrones": false,
 | 
					  "instantResourceExtractorDrones": false,
 | 
				
			||||||
  "noDojoRoomBuildStage": false,
 | 
					  "noDojoRoomBuildStage": false,
 | 
				
			||||||
  "fastDojoRoomDestruction": false,
 | 
					  "fastDojoRoomDestruction": false,
 | 
				
			||||||
 | 
				
			|||||||
@ -76,7 +76,10 @@ import {
 | 
				
			|||||||
    IIncentiveState,
 | 
					    IIncentiveState,
 | 
				
			||||||
    ISongChallenge,
 | 
					    ISongChallenge,
 | 
				
			||||||
    ILibraryPersonalProgress,
 | 
					    ILibraryPersonalProgress,
 | 
				
			||||||
    ICrewShipWeaponDatabase
 | 
					    ICrewShipWeaponDatabase,
 | 
				
			||||||
 | 
					    IRecentVendorPurchaseDatabase,
 | 
				
			||||||
 | 
					    IVendorPurchaseHistoryEntryDatabase,
 | 
				
			||||||
 | 
					    IVendorPurchaseHistoryEntryClient
 | 
				
			||||||
} from "../../types/inventoryTypes/inventoryTypes";
 | 
					} from "../../types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
import { IOid } from "../../types/commonTypes";
 | 
					import { IOid } from "../../types/commonTypes";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
@ -974,6 +977,31 @@ const incentiveStateSchema = new Schema<IIncentiveState>(
 | 
				
			|||||||
    { _id: false }
 | 
					    { _id: false }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const vendorPurchaseHistoryEntrySchema = new Schema<IVendorPurchaseHistoryEntryDatabase>(
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Expiry: Date,
 | 
				
			||||||
 | 
					        NumPurchased: Number,
 | 
				
			||||||
 | 
					        ItemId: String
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    { _id: false }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					vendorPurchaseHistoryEntrySchema.set("toJSON", {
 | 
				
			||||||
 | 
					    transform(_doc, obj) {
 | 
				
			||||||
 | 
					        const db = obj as IVendorPurchaseHistoryEntryDatabase;
 | 
				
			||||||
 | 
					        const client = obj as IVendorPurchaseHistoryEntryClient;
 | 
				
			||||||
 | 
					        client.Expiry = toMongoDate(db.Expiry);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const recentVendorPurchaseSchema = new Schema<IRecentVendorPurchaseDatabase>(
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        VendorType: String,
 | 
				
			||||||
 | 
					        PurchaseHistory: [vendorPurchaseHistoryEntrySchema]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    { _id: false }
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const collectibleEntrySchema = new Schema<ICollectibleEntry>(
 | 
					const collectibleEntrySchema = new Schema<ICollectibleEntry>(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        CollectibleType: String,
 | 
					        CollectibleType: String,
 | 
				
			||||||
@ -1361,7 +1389,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
				
			|||||||
        RandomUpgradesIdentified: Number,
 | 
					        RandomUpgradesIdentified: Number,
 | 
				
			||||||
        BountyScore: Number,
 | 
					        BountyScore: Number,
 | 
				
			||||||
        ChallengeInstanceStates: [Schema.Types.Mixed],
 | 
					        ChallengeInstanceStates: [Schema.Types.Mixed],
 | 
				
			||||||
        RecentVendorPurchases: [Schema.Types.Mixed],
 | 
					        RecentVendorPurchases: { type: [recentVendorPurchaseSchema], default: undefined },
 | 
				
			||||||
        Robotics: [Schema.Types.Mixed],
 | 
					        Robotics: [Schema.Types.Mixed],
 | 
				
			||||||
        UsedDailyDeals: [Schema.Types.Mixed],
 | 
					        UsedDailyDeals: [Schema.Types.Mixed],
 | 
				
			||||||
        CollectibleSeries: { type: [collectibleEntrySchema], default: undefined },
 | 
					        CollectibleSeries: { type: [collectibleEntrySchema], default: undefined },
 | 
				
			||||||
 | 
				
			|||||||
@ -55,6 +55,7 @@ interface IConfig {
 | 
				
			|||||||
    unlockExilusEverywhere?: boolean;
 | 
					    unlockExilusEverywhere?: boolean;
 | 
				
			||||||
    unlockArcanesEverywhere?: boolean;
 | 
					    unlockArcanesEverywhere?: boolean;
 | 
				
			||||||
    noDailyStandingLimits?: boolean;
 | 
					    noDailyStandingLimits?: boolean;
 | 
				
			||||||
 | 
					    noVendorPurchaseLimits?: boolean;
 | 
				
			||||||
    instantResourceExtractorDrones?: boolean;
 | 
					    instantResourceExtractorDrones?: boolean;
 | 
				
			||||||
    noDojoRoomBuildStage?: boolean;
 | 
					    noDojoRoomBuildStage?: boolean;
 | 
				
			||||||
    fastDojoRoomDestruction?: boolean;
 | 
					    fastDojoRoomDestruction?: boolean;
 | 
				
			||||||
 | 
				
			|||||||
@ -68,6 +68,45 @@ export const handlePurchase = async (
 | 
				
			|||||||
                    inventoryChanges
 | 
					                    inventoryChanges
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            if (!config.noVendorPurchaseLimits) {
 | 
				
			||||||
 | 
					                inventory.RecentVendorPurchases ??= [];
 | 
				
			||||||
 | 
					                let vendorPurchases = inventory.RecentVendorPurchases.find(
 | 
				
			||||||
 | 
					                    x => x.VendorType == manifest.VendorInfo.TypeName
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					                if (!vendorPurchases) {
 | 
				
			||||||
 | 
					                    vendorPurchases =
 | 
				
			||||||
 | 
					                        inventory.RecentVendorPurchases[
 | 
				
			||||||
 | 
					                            inventory.RecentVendorPurchases.push({
 | 
				
			||||||
 | 
					                                VendorType: manifest.VendorInfo.TypeName,
 | 
				
			||||||
 | 
					                                PurchaseHistory: []
 | 
				
			||||||
 | 
					                            }) - 1
 | 
				
			||||||
 | 
					                        ];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                const historyEntry = vendorPurchases.PurchaseHistory.find(x => x.ItemId == ItemId);
 | 
				
			||||||
 | 
					                let numPurchased = purchaseRequest.PurchaseParams.Quantity;
 | 
				
			||||||
 | 
					                if (historyEntry) {
 | 
				
			||||||
 | 
					                    numPurchased += historyEntry.NumPurchased;
 | 
				
			||||||
 | 
					                    historyEntry.NumPurchased += purchaseRequest.PurchaseParams.Quantity;
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    vendorPurchases.PurchaseHistory.push({
 | 
				
			||||||
 | 
					                        ItemId: ItemId,
 | 
				
			||||||
 | 
					                        NumPurchased: purchaseRequest.PurchaseParams.Quantity,
 | 
				
			||||||
 | 
					                        Expiry: new Date(parseInt(offer.Expiry.$date.$numberLong))
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                inventoryChanges.RecentVendorPurchases = [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        VendorType: manifest.VendorInfo.TypeName,
 | 
				
			||||||
 | 
					                        PurchaseHistory: [
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                ItemId: ItemId,
 | 
				
			||||||
 | 
					                                NumPurchased: numPurchased,
 | 
				
			||||||
 | 
					                                Expiry: offer.Expiry
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        ]
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            purchaseRequest.PurchaseParams.Quantity *= offer.QuantityMultiplier;
 | 
					            purchaseRequest.PurchaseParams.Quantity *= offer.QuantityMultiplier;
 | 
				
			||||||
        } else if (!ExportVendors[purchaseRequest.PurchaseParams.SourceId!]) {
 | 
					        } else if (!ExportVendors[purchaseRequest.PurchaseParams.SourceId!]) {
 | 
				
			||||||
            throw new Error(`unknown vendor: ${purchaseRequest.PurchaseParams.SourceId!}`);
 | 
					            throw new Error(`unknown vendor: ${purchaseRequest.PurchaseParams.SourceId!}`);
 | 
				
			||||||
 | 
				
			|||||||
@ -41,6 +41,7 @@ export interface IInventoryDatabase
 | 
				
			|||||||
            | "KubrowPetEggs"
 | 
					            | "KubrowPetEggs"
 | 
				
			||||||
            | "PendingCoupon"
 | 
					            | "PendingCoupon"
 | 
				
			||||||
            | "Drones"
 | 
					            | "Drones"
 | 
				
			||||||
 | 
					            | "RecentVendorPurchases"
 | 
				
			||||||
            | TEquipmentKey
 | 
					            | TEquipmentKey
 | 
				
			||||||
        >,
 | 
					        >,
 | 
				
			||||||
        InventoryDatabaseEquipment {
 | 
					        InventoryDatabaseEquipment {
 | 
				
			||||||
@ -67,6 +68,7 @@ export interface IInventoryDatabase
 | 
				
			|||||||
    KubrowPetEggs?: IKubrowPetEggDatabase[];
 | 
					    KubrowPetEggs?: IKubrowPetEggDatabase[];
 | 
				
			||||||
    PendingCoupon?: IPendingCouponDatabase;
 | 
					    PendingCoupon?: IPendingCouponDatabase;
 | 
				
			||||||
    Drones: IDroneDatabase[];
 | 
					    Drones: IDroneDatabase[];
 | 
				
			||||||
 | 
					    RecentVendorPurchases?: IRecentVendorPurchaseDatabase[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IQuestKeyDatabase {
 | 
					export interface IQuestKeyDatabase {
 | 
				
			||||||
@ -277,7 +279,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
				
			|||||||
    BountyScore: number;
 | 
					    BountyScore: number;
 | 
				
			||||||
    ChallengeInstanceStates: IChallengeInstanceState[];
 | 
					    ChallengeInstanceStates: IChallengeInstanceState[];
 | 
				
			||||||
    LoginMilestoneRewards: string[];
 | 
					    LoginMilestoneRewards: string[];
 | 
				
			||||||
    RecentVendorPurchases: Array<number | string>;
 | 
					    RecentVendorPurchases?: IRecentVendorPurchaseClient[];
 | 
				
			||||||
    NodeIntrosCompleted: string[];
 | 
					    NodeIntrosCompleted: string[];
 | 
				
			||||||
    GuildId?: IOid;
 | 
					    GuildId?: IOid;
 | 
				
			||||||
    CompletedJobChains: ICompletedJobChain[];
 | 
					    CompletedJobChains: ICompletedJobChain[];
 | 
				
			||||||
@ -361,6 +363,28 @@ export interface IParam {
 | 
				
			|||||||
    v: string;
 | 
					    v: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IRecentVendorPurchaseClient {
 | 
				
			||||||
 | 
					    VendorType: string;
 | 
				
			||||||
 | 
					    PurchaseHistory: IVendorPurchaseHistoryEntryClient[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IVendorPurchaseHistoryEntryClient {
 | 
				
			||||||
 | 
					    Expiry: IMongoDate;
 | 
				
			||||||
 | 
					    NumPurchased: number;
 | 
				
			||||||
 | 
					    ItemId: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IRecentVendorPurchaseDatabase {
 | 
				
			||||||
 | 
					    VendorType: string;
 | 
				
			||||||
 | 
					    PurchaseHistory: IVendorPurchaseHistoryEntryDatabase[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IVendorPurchaseHistoryEntryDatabase {
 | 
				
			||||||
 | 
					    Expiry: Date;
 | 
				
			||||||
 | 
					    NumPurchased: number;
 | 
				
			||||||
 | 
					    ItemId: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface IChallengeProgress {
 | 
					export interface IChallengeProgress {
 | 
				
			||||||
    Progress: number;
 | 
					    Progress: number;
 | 
				
			||||||
    Name: string;
 | 
					    Name: string;
 | 
				
			||||||
 | 
				
			|||||||
@ -517,6 +517,10 @@
 | 
				
			|||||||
                                        <input class="form-check-input" type="checkbox" id="noDailyStandingLimits" />
 | 
					                                        <input class="form-check-input" type="checkbox" id="noDailyStandingLimits" />
 | 
				
			||||||
                                        <label class="form-check-label" for="noDailyStandingLimits" data-loc="cheats_noDailyStandingLimits"></label>
 | 
					                                        <label class="form-check-label" for="noDailyStandingLimits" data-loc="cheats_noDailyStandingLimits"></label>
 | 
				
			||||||
                                    </div>
 | 
					                                    </div>
 | 
				
			||||||
 | 
					                                    <div class="form-check">
 | 
				
			||||||
 | 
					                                        <input class="form-check-input" type="checkbox" id="noVendorPurchaseLimits" />
 | 
				
			||||||
 | 
					                                        <label class="form-check-label" for="noVendorPurchaseLimits" data-loc="cheats_noVendorPurchaseLimits"></label>
 | 
				
			||||||
 | 
					                                    </div>
 | 
				
			||||||
                                    <div class="form-check">
 | 
					                                    <div class="form-check">
 | 
				
			||||||
                                        <input class="form-check-input" type="checkbox" id="instantResourceExtractorDrones" />
 | 
					                                        <input class="form-check-input" type="checkbox" id="instantResourceExtractorDrones" />
 | 
				
			||||||
                                        <label class="form-check-label" for="instantResourceExtractorDrones" data-loc="cheats_instantResourceExtractorDrones"></label>
 | 
					                                        <label class="form-check-label" for="instantResourceExtractorDrones" data-loc="cheats_instantResourceExtractorDrones"></label>
 | 
				
			||||||
 | 
				
			|||||||
@ -110,6 +110,7 @@ dict = {
 | 
				
			|||||||
    cheats_unlockExilusEverywhere: `Exilus-Adapter überall`,
 | 
					    cheats_unlockExilusEverywhere: `Exilus-Adapter überall`,
 | 
				
			||||||
    cheats_unlockArcanesEverywhere: `Arkana-Adapter überall`,
 | 
					    cheats_unlockArcanesEverywhere: `Arkana-Adapter überall`,
 | 
				
			||||||
    cheats_noDailyStandingLimits: `Kein tägliches Ansehenslimit`,
 | 
					    cheats_noDailyStandingLimits: `Kein tägliches Ansehenslimit`,
 | 
				
			||||||
 | 
					    cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`,
 | 
				
			||||||
    cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
 | 
					    cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
 | 
				
			||||||
    cheats_noDojoRoomBuildStage: `Kein Dojo-Raum-Bauvorgang`,
 | 
					    cheats_noDojoRoomBuildStage: `Kein Dojo-Raum-Bauvorgang`,
 | 
				
			||||||
    cheats_fastDojoRoomDestruction: `Schnelle Dojo-Raum-Zerstörung`,
 | 
					    cheats_fastDojoRoomDestruction: `Schnelle Dojo-Raum-Zerstörung`,
 | 
				
			||||||
 | 
				
			|||||||
@ -109,6 +109,7 @@ dict = {
 | 
				
			|||||||
    cheats_unlockExilusEverywhere: `Exilus Adapters Everywhere`,
 | 
					    cheats_unlockExilusEverywhere: `Exilus Adapters Everywhere`,
 | 
				
			||||||
    cheats_unlockArcanesEverywhere: `Arcane Adapters Everywhere`,
 | 
					    cheats_unlockArcanesEverywhere: `Arcane Adapters Everywhere`,
 | 
				
			||||||
    cheats_noDailyStandingLimits: `No Daily Standing Limits`,
 | 
					    cheats_noDailyStandingLimits: `No Daily Standing Limits`,
 | 
				
			||||||
 | 
					    cheats_noVendorPurchaseLimits: `No Vendor Purchase Limits`,
 | 
				
			||||||
    cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`,
 | 
					    cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`,
 | 
				
			||||||
    cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
 | 
					    cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
 | 
				
			||||||
    cheats_fastDojoRoomDestruction: `Fast Dojo Room Destruction`,
 | 
					    cheats_fastDojoRoomDestruction: `Fast Dojo Room Destruction`,
 | 
				
			||||||
 | 
				
			|||||||
@ -110,6 +110,7 @@ dict = {
 | 
				
			|||||||
    cheats_unlockExilusEverywhere: `Adaptateurs Exilus partout`,
 | 
					    cheats_unlockExilusEverywhere: `Adaptateurs Exilus partout`,
 | 
				
			||||||
    cheats_unlockArcanesEverywhere: `Adaptateur d'Arcanes partout`,
 | 
					    cheats_unlockArcanesEverywhere: `Adaptateur d'Arcanes partout`,
 | 
				
			||||||
    cheats_noDailyStandingLimits: `Pas de limite de réputation journalière`,
 | 
					    cheats_noDailyStandingLimits: `Pas de limite de réputation journalière`,
 | 
				
			||||||
 | 
					    cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`,
 | 
				
			||||||
    cheats_instantResourceExtractorDrones: `Ressources de drone d'extraction instantannées`,
 | 
					    cheats_instantResourceExtractorDrones: `Ressources de drone d'extraction instantannées`,
 | 
				
			||||||
    cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
 | 
					    cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
 | 
				
			||||||
    cheats_fastDojoRoomDestruction: `[UNTRANSLATED] Fast Dojo Room Destruction`,
 | 
					    cheats_fastDojoRoomDestruction: `[UNTRANSLATED] Fast Dojo Room Destruction`,
 | 
				
			||||||
 | 
				
			|||||||
@ -110,6 +110,7 @@ dict = {
 | 
				
			|||||||
    cheats_unlockExilusEverywhere: `Адаптеры Эксилус везде`,
 | 
					    cheats_unlockExilusEverywhere: `Адаптеры Эксилус везде`,
 | 
				
			||||||
    cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`,
 | 
					    cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`,
 | 
				
			||||||
    cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`,
 | 
					    cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`,
 | 
				
			||||||
 | 
					    cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`,
 | 
				
			||||||
    cheats_instantResourceExtractorDrones: `Мгновенные Экстракторы Ресурсов`,
 | 
					    cheats_instantResourceExtractorDrones: `Мгновенные Экстракторы Ресурсов`,
 | 
				
			||||||
    cheats_noDojoRoomBuildStage: `Мгновенное Строительтво Комнат Додзё`,
 | 
					    cheats_noDojoRoomBuildStage: `Мгновенное Строительтво Комнат Додзё`,
 | 
				
			||||||
    cheats_fastDojoRoomDestruction: `Мгновенные Уничтожение Комнат Додзё`,
 | 
					    cheats_fastDojoRoomDestruction: `Мгновенные Уничтожение Комнат Додзё`,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user