feat: apply & track daily standing limit when trading in medallions (#788)
This commit is contained in:
parent
534f7d8cce
commit
d8845bc478
@ -1,19 +1,19 @@
|
|||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { addMiscItems, getInventory } from "@/src/services/inventoryService";
|
import { addMiscItems, getInventory, getStandingLimit, updateStandingLimit } from "@/src/services/inventoryService";
|
||||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { IOid } from "@/src/types/commonTypes";
|
import { IOid } from "@/src/types/commonTypes";
|
||||||
import { ExportSyndicates } from "warframe-public-export-plus";
|
import { ExportSyndicates, ISyndicate } from "warframe-public-export-plus";
|
||||||
|
|
||||||
export const syndicateStandingBonusController: RequestHandler = async (req, res) => {
|
export const syndicateStandingBonusController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const request = JSON.parse(String(req.body)) as ISyndicateStandingBonusRequest;
|
const request = JSON.parse(String(req.body)) as ISyndicateStandingBonusRequest;
|
||||||
|
|
||||||
|
const syndicateMeta = ExportSyndicates[request.Operation.AffiliationTag];
|
||||||
|
|
||||||
let gainedStanding = 0;
|
let gainedStanding = 0;
|
||||||
request.Operation.Items.forEach(item => {
|
request.Operation.Items.forEach(item => {
|
||||||
const medallion = (ExportSyndicates[request.Operation.AffiliationTag].medallions ?? []).find(
|
const medallion = (syndicateMeta.medallions ?? []).find(medallion => medallion.itemType == item.ItemType);
|
||||||
medallion => medallion.itemType == item.ItemType
|
|
||||||
);
|
|
||||||
if (medallion) {
|
if (medallion) {
|
||||||
gainedStanding += medallion.standing * item.ItemCount;
|
gainedStanding += medallion.standing * item.ItemCount;
|
||||||
}
|
}
|
||||||
@ -27,17 +27,22 @@ export const syndicateStandingBonusController: RequestHandler = async (req, res)
|
|||||||
let syndicate = inventory.Affiliations.find(x => x.Tag == request.Operation.AffiliationTag);
|
let syndicate = inventory.Affiliations.find(x => x.Tag == request.Operation.AffiliationTag);
|
||||||
if (!syndicate) {
|
if (!syndicate) {
|
||||||
syndicate =
|
syndicate =
|
||||||
inventory.Affiliations[inventory.Affiliations.push({ Tag: request.Operation.AffiliationTag, Standing: 0 })];
|
inventory.Affiliations[
|
||||||
|
inventory.Affiliations.push({ Tag: request.Operation.AffiliationTag, Standing: 0 }) - 1
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
const max = getMaxStanding(request.Operation.AffiliationTag, syndicate.Title ?? 0);
|
const max = getMaxStanding(syndicateMeta, syndicate.Title ?? 0);
|
||||||
if (syndicate.Standing + gainedStanding > max) {
|
if (syndicate.Standing + gainedStanding > max) {
|
||||||
gainedStanding = max - syndicate.Standing;
|
gainedStanding = max - syndicate.Standing;
|
||||||
}
|
}
|
||||||
|
if (gainedStanding > getStandingLimit(inventory, syndicateMeta.dailyLimitBin)) {
|
||||||
|
gainedStanding = getStandingLimit(inventory, syndicateMeta.dailyLimitBin);
|
||||||
|
}
|
||||||
|
|
||||||
syndicate.Standing += gainedStanding;
|
syndicate.Standing += gainedStanding;
|
||||||
|
|
||||||
// TODO: Subtract from daily limit bin; maybe also a cheat to skip that.
|
updateStandingLimit(inventory, syndicateMeta.dailyLimitBin, gainedStanding);
|
||||||
|
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
|
|
||||||
@ -63,8 +68,7 @@ interface ISyndicateStandingBonusRequest {
|
|||||||
ModularWeaponId: IOid; // Seems to just be "000000000000000000000000", also note there's a "Category" query field
|
ModularWeaponId: IOid; // Seems to just be "000000000000000000000000", also note there's a "Category" query field
|
||||||
}
|
}
|
||||||
|
|
||||||
const getMaxStanding = (affiliationTag: string, title: number): number => {
|
const getMaxStanding = (syndicate: ISyndicate, title: number): number => {
|
||||||
const syndicate = ExportSyndicates[affiliationTag];
|
|
||||||
if (!syndicate.titles) {
|
if (!syndicate.titles) {
|
||||||
// LibrarySyndicate
|
// LibrarySyndicate
|
||||||
return 125000;
|
return 125000;
|
||||||
|
@ -16,7 +16,8 @@ import {
|
|||||||
IWeaponSkinClient,
|
IWeaponSkinClient,
|
||||||
TEquipmentKey,
|
TEquipmentKey,
|
||||||
equipmentKeys,
|
equipmentKeys,
|
||||||
IFusionTreasure
|
IFusionTreasure,
|
||||||
|
IDailyAffiliations
|
||||||
} from "@/src/types/inventoryTypes/inventoryTypes";
|
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { IGenericUpdate } from "../types/genericUpdate";
|
import { IGenericUpdate } from "../types/genericUpdate";
|
||||||
import {
|
import {
|
||||||
@ -36,7 +37,8 @@ import {
|
|||||||
ExportRecipes,
|
ExportRecipes,
|
||||||
ExportResources,
|
ExportResources,
|
||||||
ExportSentinels,
|
ExportSentinels,
|
||||||
ExportUpgrades
|
ExportUpgrades,
|
||||||
|
TStandingLimitBin
|
||||||
} from "warframe-public-export-plus";
|
} from "warframe-public-export-plus";
|
||||||
import { createShip } from "./shipService";
|
import { createShip } from "./shipService";
|
||||||
|
|
||||||
@ -492,6 +494,43 @@ export const updateCurrencyByAccountId = async (
|
|||||||
return currencyChanges;
|
return currencyChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const standingLimitBinToInventoryKey: Record<
|
||||||
|
Exclude<TStandingLimitBin, "STANDING_LIMIT_BIN_NONE">,
|
||||||
|
keyof IDailyAffiliations
|
||||||
|
> = {
|
||||||
|
STANDING_LIMIT_BIN_NORMAL: "DailyAffiliation",
|
||||||
|
STANDING_LIMIT_BIN_PVP: "DailyAffiliationPvp",
|
||||||
|
STANDING_LIMIT_BIN_LIBRARY: "DailyAffiliationLibrary",
|
||||||
|
STANDING_LIMIT_BIN_CETUS: "DailyAffiliationCetus",
|
||||||
|
STANDING_LIMIT_BIN_QUILLS: "DailyAffiliationQuills",
|
||||||
|
STANDING_LIMIT_BIN_SOLARIS: "DailyAffiliationSolaris",
|
||||||
|
STANDING_LIMIT_BIN_VENTKIDS: "DailyAffiliationVentkids",
|
||||||
|
STANDING_LIMIT_BIN_VOX: "DailyAffiliationVox",
|
||||||
|
STANDING_LIMIT_BIN_ENTRATI: "DailyAffiliationEntrati",
|
||||||
|
STANDING_LIMIT_BIN_NECRALOID: "DailyAffiliationNecraloid",
|
||||||
|
STANDING_LIMIT_BIN_ZARIMAN: "DailyAffiliationZariman",
|
||||||
|
STANDING_LIMIT_BIN_KAHL: "DailyAffiliationKahl",
|
||||||
|
STANDING_LIMIT_BIN_CAVIA: "DailyAffiliationCavia",
|
||||||
|
STANDING_LIMIT_BIN_HEX: "DailyAffiliationHex"
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getStandingLimit = (inventory: IDailyAffiliations, bin: TStandingLimitBin): number => {
|
||||||
|
if (bin == "STANDING_LIMIT_BIN_NONE") {
|
||||||
|
return Number.MAX_SAFE_INTEGER;
|
||||||
|
}
|
||||||
|
return inventory[standingLimitBinToInventoryKey[bin]];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateStandingLimit = (
|
||||||
|
inventory: IDailyAffiliations,
|
||||||
|
bin: TStandingLimitBin,
|
||||||
|
subtrahend: number
|
||||||
|
): void => {
|
||||||
|
if (bin != "STANDING_LIMIT_BIN_NONE") {
|
||||||
|
inventory[standingLimitBinToInventoryKey[bin]] -= subtrahend;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: AffiliationMods support (Nightwave).
|
// TODO: AffiliationMods support (Nightwave).
|
||||||
export const updateGeneric = async (data: IGenericUpdate, accountId: string): Promise<void> => {
|
export const updateGeneric = async (data: IGenericUpdate, accountId: string): Promise<void> => {
|
||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
|
@ -110,7 +110,25 @@ export type TSolarMapRegion =
|
|||||||
export interface IPendingRecipeResponse extends Omit<IPendingRecipe, "CompletionDate"> {
|
export interface IPendingRecipeResponse extends Omit<IPendingRecipe, "CompletionDate"> {
|
||||||
CompletionDate: IMongoDate;
|
CompletionDate: IMongoDate;
|
||||||
}
|
}
|
||||||
export interface IInventoryResponse {
|
|
||||||
|
export interface IDailyAffiliations {
|
||||||
|
DailyAffiliation: number;
|
||||||
|
DailyAffiliationPvp: number;
|
||||||
|
DailyAffiliationLibrary: number;
|
||||||
|
DailyAffiliationCetus: number;
|
||||||
|
DailyAffiliationQuills: number;
|
||||||
|
DailyAffiliationSolaris: number;
|
||||||
|
DailyAffiliationVentkids: number;
|
||||||
|
DailyAffiliationVox: number;
|
||||||
|
DailyAffiliationEntrati: number;
|
||||||
|
DailyAffiliationNecraloid: number;
|
||||||
|
DailyAffiliationZariman: number;
|
||||||
|
DailyAffiliationKahl: number;
|
||||||
|
DailyAffiliationCavia: number;
|
||||||
|
DailyAffiliationHex: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IInventoryResponse extends IDailyAffiliations {
|
||||||
Horses: IEquipmentDatabase[];
|
Horses: IEquipmentDatabase[];
|
||||||
DrifterMelee: IEquipmentDatabase[];
|
DrifterMelee: IEquipmentDatabase[];
|
||||||
DrifterGuns: IEquipmentDatabase[];
|
DrifterGuns: IEquipmentDatabase[];
|
||||||
@ -138,9 +156,6 @@ export interface IInventoryResponse {
|
|||||||
OperatorAmpBin: ISlots;
|
OperatorAmpBin: ISlots;
|
||||||
CrewShipSalvageBin: ISlots;
|
CrewShipSalvageBin: ISlots;
|
||||||
TradesRemaining: number;
|
TradesRemaining: number;
|
||||||
DailyAffiliation: number;
|
|
||||||
DailyAffiliationPvp: number;
|
|
||||||
DailyAffiliationLibrary: number;
|
|
||||||
DailyFocus: number;
|
DailyFocus: number;
|
||||||
GiftsRemaining: number;
|
GiftsRemaining: number;
|
||||||
HandlerPoints: number;
|
HandlerPoints: number;
|
||||||
@ -220,8 +235,6 @@ export interface IInventoryResponse {
|
|||||||
ActiveAvatarImageType: string;
|
ActiveAvatarImageType: string;
|
||||||
KubrowPets: IEquipmentDatabase[];
|
KubrowPets: IEquipmentDatabase[];
|
||||||
ShipDecorations: IConsumable[];
|
ShipDecorations: IConsumable[];
|
||||||
DailyAffiliationCetus: number;
|
|
||||||
DailyAffiliationQuills: number;
|
|
||||||
DiscoveredMarkers: IDiscoveredMarker[];
|
DiscoveredMarkers: IDiscoveredMarker[];
|
||||||
CompletedJobs: ICompletedJob[];
|
CompletedJobs: ICompletedJob[];
|
||||||
FocusAbility: string;
|
FocusAbility: string;
|
||||||
@ -232,7 +245,6 @@ export interface IInventoryResponse {
|
|||||||
KubrowPetPrints: IKubrowPetPrint[];
|
KubrowPetPrints: IKubrowPetPrint[];
|
||||||
AlignmentReplay: IAlignment;
|
AlignmentReplay: IAlignment;
|
||||||
PersonalGoalProgress: IPersonalGoalProgress[];
|
PersonalGoalProgress: IPersonalGoalProgress[];
|
||||||
DailyAffiliationSolaris: number;
|
|
||||||
SpecialItems: IEquipmentDatabase[];
|
SpecialItems: IEquipmentDatabase[];
|
||||||
ThemeStyle: string;
|
ThemeStyle: string;
|
||||||
ThemeBackground: string;
|
ThemeBackground: string;
|
||||||
@ -241,8 +253,6 @@ export interface IInventoryResponse {
|
|||||||
ChallengeInstanceStates: IChallengeInstanceState[];
|
ChallengeInstanceStates: IChallengeInstanceState[];
|
||||||
LoginMilestoneRewards: string[];
|
LoginMilestoneRewards: string[];
|
||||||
OperatorLoadOuts: IOperatorConfigClient[];
|
OperatorLoadOuts: IOperatorConfigClient[];
|
||||||
DailyAffiliationVentkids: number;
|
|
||||||
DailyAffiliationVox: number;
|
|
||||||
RecentVendorPurchases: Array<number | string>;
|
RecentVendorPurchases: Array<number | string>;
|
||||||
Hoverboards: IEquipmentDatabase[];
|
Hoverboards: IEquipmentDatabase[];
|
||||||
NodeIntrosCompleted: string[];
|
NodeIntrosCompleted: string[];
|
||||||
@ -268,8 +278,6 @@ export interface IInventoryResponse {
|
|||||||
TradeBannedUntil?: IMongoDate;
|
TradeBannedUntil?: IMongoDate;
|
||||||
PlayedParkourTutorial: boolean;
|
PlayedParkourTutorial: boolean;
|
||||||
SubscribedToEmailsPersonalized: number;
|
SubscribedToEmailsPersonalized: number;
|
||||||
DailyAffiliationEntrati: number;
|
|
||||||
DailyAffiliationNecraloid: number;
|
|
||||||
MechSuits: IEquipmentDatabase[];
|
MechSuits: IEquipmentDatabase[];
|
||||||
InfestedFoundry?: IInfestedFoundry;
|
InfestedFoundry?: IInfestedFoundry;
|
||||||
BlessingCooldown: IMongoDate;
|
BlessingCooldown: IMongoDate;
|
||||||
@ -279,11 +287,7 @@ export interface IInventoryResponse {
|
|||||||
AdultOperatorLoadOuts: IOperatorConfigClient[];
|
AdultOperatorLoadOuts: IOperatorConfigClient[];
|
||||||
LotusCustomization: ILotusCustomization;
|
LotusCustomization: ILotusCustomization;
|
||||||
UseAdultOperatorLoadout?: boolean;
|
UseAdultOperatorLoadout?: boolean;
|
||||||
DailyAffiliationZariman: number;
|
|
||||||
NemesisAbandonedRewards: string[];
|
NemesisAbandonedRewards: string[];
|
||||||
DailyAffiliationKahl: number;
|
|
||||||
DailyAffiliationCavia: number;
|
|
||||||
DailyAffiliationHex: number;
|
|
||||||
LastInventorySync: IOid;
|
LastInventorySync: IOid;
|
||||||
NextRefill: IMongoDate; // Next time argon crystals will have a decay tick
|
NextRefill: IMongoDate; // Next time argon crystals will have a decay tick
|
||||||
FoundToday?: IMiscItem[]; // for Argon Crystals
|
FoundToday?: IMiscItem[]; // for Argon Crystals
|
||||||
|
Loading…
x
Reference in New Issue
Block a user