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,
 | 
			
		||||
  "unlockArcanesEverywhere": false,
 | 
			
		||||
  "noDailyStandingLimits": false,
 | 
			
		||||
  "noVendorPurchaseLimits": true,
 | 
			
		||||
  "instantResourceExtractorDrones": false,
 | 
			
		||||
  "noDojoRoomBuildStage": false,
 | 
			
		||||
  "fastDojoRoomDestruction": false,
 | 
			
		||||
 | 
			
		||||
@ -76,7 +76,10 @@ import {
 | 
			
		||||
    IIncentiveState,
 | 
			
		||||
    ISongChallenge,
 | 
			
		||||
    ILibraryPersonalProgress,
 | 
			
		||||
    ICrewShipWeaponDatabase
 | 
			
		||||
    ICrewShipWeaponDatabase,
 | 
			
		||||
    IRecentVendorPurchaseDatabase,
 | 
			
		||||
    IVendorPurchaseHistoryEntryDatabase,
 | 
			
		||||
    IVendorPurchaseHistoryEntryClient
 | 
			
		||||
} from "../../types/inventoryTypes/inventoryTypes";
 | 
			
		||||
import { IOid } from "../../types/commonTypes";
 | 
			
		||||
import {
 | 
			
		||||
@ -974,6 +977,31 @@ const incentiveStateSchema = new Schema<IIncentiveState>(
 | 
			
		||||
    { _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>(
 | 
			
		||||
    {
 | 
			
		||||
        CollectibleType: String,
 | 
			
		||||
@ -1361,7 +1389,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
 | 
			
		||||
        RandomUpgradesIdentified: Number,
 | 
			
		||||
        BountyScore: Number,
 | 
			
		||||
        ChallengeInstanceStates: [Schema.Types.Mixed],
 | 
			
		||||
        RecentVendorPurchases: [Schema.Types.Mixed],
 | 
			
		||||
        RecentVendorPurchases: { type: [recentVendorPurchaseSchema], default: undefined },
 | 
			
		||||
        Robotics: [Schema.Types.Mixed],
 | 
			
		||||
        UsedDailyDeals: [Schema.Types.Mixed],
 | 
			
		||||
        CollectibleSeries: { type: [collectibleEntrySchema], default: undefined },
 | 
			
		||||
 | 
			
		||||
@ -55,6 +55,7 @@ interface IConfig {
 | 
			
		||||
    unlockExilusEverywhere?: boolean;
 | 
			
		||||
    unlockArcanesEverywhere?: boolean;
 | 
			
		||||
    noDailyStandingLimits?: boolean;
 | 
			
		||||
    noVendorPurchaseLimits?: boolean;
 | 
			
		||||
    instantResourceExtractorDrones?: boolean;
 | 
			
		||||
    noDojoRoomBuildStage?: boolean;
 | 
			
		||||
    fastDojoRoomDestruction?: boolean;
 | 
			
		||||
 | 
			
		||||
@ -68,6 +68,45 @@ export const handlePurchase = async (
 | 
			
		||||
                    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;
 | 
			
		||||
        } else if (!ExportVendors[purchaseRequest.PurchaseParams.SourceId!]) {
 | 
			
		||||
            throw new Error(`unknown vendor: ${purchaseRequest.PurchaseParams.SourceId!}`);
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,7 @@ export interface IInventoryDatabase
 | 
			
		||||
            | "KubrowPetEggs"
 | 
			
		||||
            | "PendingCoupon"
 | 
			
		||||
            | "Drones"
 | 
			
		||||
            | "RecentVendorPurchases"
 | 
			
		||||
            | TEquipmentKey
 | 
			
		||||
        >,
 | 
			
		||||
        InventoryDatabaseEquipment {
 | 
			
		||||
@ -67,6 +68,7 @@ export interface IInventoryDatabase
 | 
			
		||||
    KubrowPetEggs?: IKubrowPetEggDatabase[];
 | 
			
		||||
    PendingCoupon?: IPendingCouponDatabase;
 | 
			
		||||
    Drones: IDroneDatabase[];
 | 
			
		||||
    RecentVendorPurchases?: IRecentVendorPurchaseDatabase[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface IQuestKeyDatabase {
 | 
			
		||||
@ -277,7 +279,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
 | 
			
		||||
    BountyScore: number;
 | 
			
		||||
    ChallengeInstanceStates: IChallengeInstanceState[];
 | 
			
		||||
    LoginMilestoneRewards: string[];
 | 
			
		||||
    RecentVendorPurchases: Array<number | string>;
 | 
			
		||||
    RecentVendorPurchases?: IRecentVendorPurchaseClient[];
 | 
			
		||||
    NodeIntrosCompleted: string[];
 | 
			
		||||
    GuildId?: IOid;
 | 
			
		||||
    CompletedJobChains: ICompletedJobChain[];
 | 
			
		||||
@ -361,6 +363,28 @@ export interface IParam {
 | 
			
		||||
    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 {
 | 
			
		||||
    Progress: number;
 | 
			
		||||
    Name: string;
 | 
			
		||||
 | 
			
		||||
@ -517,6 +517,10 @@
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="noDailyStandingLimits" />
 | 
			
		||||
                                        <label class="form-check-label" for="noDailyStandingLimits" data-loc="cheats_noDailyStandingLimits"></label>
 | 
			
		||||
                                    </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">
 | 
			
		||||
                                        <input class="form-check-input" type="checkbox" id="instantResourceExtractorDrones" />
 | 
			
		||||
                                        <label class="form-check-label" for="instantResourceExtractorDrones" data-loc="cheats_instantResourceExtractorDrones"></label>
 | 
			
		||||
 | 
			
		||||
@ -110,6 +110,7 @@ dict = {
 | 
			
		||||
    cheats_unlockExilusEverywhere: `Exilus-Adapter überall`,
 | 
			
		||||
    cheats_unlockArcanesEverywhere: `Arkana-Adapter überall`,
 | 
			
		||||
    cheats_noDailyStandingLimits: `Kein tägliches Ansehenslimit`,
 | 
			
		||||
    cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`,
 | 
			
		||||
    cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
 | 
			
		||||
    cheats_noDojoRoomBuildStage: `Kein Dojo-Raum-Bauvorgang`,
 | 
			
		||||
    cheats_fastDojoRoomDestruction: `Schnelle Dojo-Raum-Zerstörung`,
 | 
			
		||||
 | 
			
		||||
@ -109,6 +109,7 @@ dict = {
 | 
			
		||||
    cheats_unlockExilusEverywhere: `Exilus Adapters Everywhere`,
 | 
			
		||||
    cheats_unlockArcanesEverywhere: `Arcane Adapters Everywhere`,
 | 
			
		||||
    cheats_noDailyStandingLimits: `No Daily Standing Limits`,
 | 
			
		||||
    cheats_noVendorPurchaseLimits: `No Vendor Purchase Limits`,
 | 
			
		||||
    cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`,
 | 
			
		||||
    cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
 | 
			
		||||
    cheats_fastDojoRoomDestruction: `Fast Dojo Room Destruction`,
 | 
			
		||||
 | 
			
		||||
@ -110,6 +110,7 @@ dict = {
 | 
			
		||||
    cheats_unlockExilusEverywhere: `Adaptateurs Exilus partout`,
 | 
			
		||||
    cheats_unlockArcanesEverywhere: `Adaptateur d'Arcanes partout`,
 | 
			
		||||
    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_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
 | 
			
		||||
    cheats_fastDojoRoomDestruction: `[UNTRANSLATED] Fast Dojo Room Destruction`,
 | 
			
		||||
 | 
			
		||||
@ -110,6 +110,7 @@ dict = {
 | 
			
		||||
    cheats_unlockExilusEverywhere: `Адаптеры Эксилус везде`,
 | 
			
		||||
    cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`,
 | 
			
		||||
    cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`,
 | 
			
		||||
    cheats_noVendorPurchaseLimits: `[UNTRANSLATED] No Vendor Purchase Limits`,
 | 
			
		||||
    cheats_instantResourceExtractorDrones: `Мгновенные Экстракторы Ресурсов`,
 | 
			
		||||
    cheats_noDojoRoomBuildStage: `Мгновенное Строительтво Комнат Додзё`,
 | 
			
		||||
    cheats_fastDojoRoomDestruction: `Мгновенные Уничтожение Комнат Додзё`,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user