feat: acquisition of peely pix + free pack for first visit (#1292)

Reviewed-on: OpenWF/SpaceNinjaServer#1292
This commit is contained in:
Sainan 2025-03-23 05:07:15 -07:00
parent e0d31b8988
commit b5a0a2297e
6 changed files with 282 additions and 20 deletions

View File

@ -10,8 +10,7 @@ import { IGenericUpdate } from "@/src/types/genericUpdate";
const genericUpdateController: RequestHandler = async (request, response) => { const genericUpdateController: RequestHandler = async (request, response) => {
const accountId = await getAccountIdForRequest(request); const accountId = await getAccountIdForRequest(request);
const update = getJSONfromString<IGenericUpdate>(String(request.body)); const update = getJSONfromString<IGenericUpdate>(String(request.body));
await updateGeneric(update, accountId); response.json(await updateGeneric(update, accountId));
response.json(update);
}; };
export { genericUpdateController }; export { genericUpdateController };

View File

@ -28,7 +28,7 @@ import {
IUpgradeClient, IUpgradeClient,
ICrewShipWeaponClient ICrewShipWeaponClient
} from "@/src/types/inventoryTypes/inventoryTypes"; } from "@/src/types/inventoryTypes/inventoryTypes";
import { IGenericUpdate } from "../types/genericUpdate"; import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
import { import {
IMissionInventoryUpdateRequest, IMissionInventoryUpdateRequest,
IThemeUpdateRequest, IThemeUpdateRequest,
@ -574,6 +574,39 @@ export const addItem = async (
}; };
} }
break; break;
case "Stickers":
{
const entry = inventory.RawUpgrades.find(x => x.ItemType == typeName);
if (entry && entry.ItemCount >= 10) {
const miscItemChanges = [
{
ItemType: "/Lotus/Types/Items/MiscItems/1999ConquestBucks",
ItemCount: 1
}
];
addMiscItems(inventory, miscItemChanges);
return {
InventoryChanges: {
MiscItems: miscItemChanges
}
};
} else {
const changes = [
{
ItemType: typeName,
ItemCount: quantity
}
];
addMods(inventory, changes);
return {
InventoryChanges: {
RawUpgrades: changes
}
};
}
}
break;
} }
break; break;
} }
@ -876,14 +909,27 @@ export const updateStandingLimit = (
}; };
// 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<IUpdateNodeIntrosResponse> => {
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId, "NodeIntrosCompleted MiscItems");
// Make it an array for easier parsing. // Make it an array for easier parsing.
if (typeof data.NodeIntrosCompleted === "string") { if (typeof data.NodeIntrosCompleted === "string") {
data.NodeIntrosCompleted = [data.NodeIntrosCompleted]; data.NodeIntrosCompleted = [data.NodeIntrosCompleted];
} }
const inventoryChanges: IInventoryChanges = {};
for (const node of data.NodeIntrosCompleted) {
if (node == "KayaFirstVisitPack") {
inventoryChanges.MiscItems = [
{
ItemType: "/Lotus/Types/Items/MiscItems/1999FixedStickersPack",
ItemCount: 1
}
];
addMiscItems(inventory, inventoryChanges.MiscItems);
}
}
// Combine the two arrays into one. // Combine the two arrays into one.
data.NodeIntrosCompleted = inventory.NodeIntrosCompleted.concat(data.NodeIntrosCompleted); data.NodeIntrosCompleted = inventory.NodeIntrosCompleted.concat(data.NodeIntrosCompleted);
@ -892,6 +938,11 @@ export const updateGeneric = async (data: IGenericUpdate, accountId: string): Pr
inventory.NodeIntrosCompleted = nodes; inventory.NodeIntrosCompleted = nodes;
await inventory.save(); await inventory.save();
return {
MissionRewards: [],
InventoryChanges: inventoryChanges
};
}; };
export const updateTheme = async (data: IThemeUpdateRequest, accountId: string): Promise<void> => { export const updateTheme = async (data: IThemeUpdateRequest, accountId: string): Promise<void> => {

View File

@ -54,11 +54,16 @@ export const handlePurchase = async (
if (purchaseRequest.PurchaseParams.Source == 7) { if (purchaseRequest.PurchaseParams.Source == 7) {
const manifest = getVendorManifestByOid(purchaseRequest.PurchaseParams.SourceId!); const manifest = getVendorManifestByOid(purchaseRequest.PurchaseParams.SourceId!);
if (manifest) { if (manifest) {
const ItemId = (JSON.parse(purchaseRequest.PurchaseParams.ExtraPurchaseInfoJson!) as { ItemId: string }) let ItemId: string | undefined;
if (purchaseRequest.PurchaseParams.ExtraPurchaseInfoJson) {
ItemId = (JSON.parse(purchaseRequest.PurchaseParams.ExtraPurchaseInfoJson) as { ItemId: string })
.ItemId; .ItemId;
const offer = manifest.VendorInfo.ItemManifest.find(x => x.Id.$oid == ItemId); }
const offer = ItemId
? manifest.VendorInfo.ItemManifest.find(x => x.Id.$oid == ItemId)
: manifest.VendorInfo.ItemManifest.find(x => x.StoreItem == purchaseRequest.PurchaseParams.StoreItem);
if (!offer) { if (!offer) {
throw new Error(`unknown vendor offer: ${ItemId}`); throw new Error(`unknown vendor offer: ${ItemId ? ItemId : purchaseRequest.PurchaseParams.StoreItem}`);
} }
if (offer.ItemPrices) { if (offer.ItemPrices) {
handleItemPrices( handleItemPrices(
@ -68,7 +73,7 @@ export const handlePurchase = async (
prePurchaseInventoryChanges prePurchaseInventoryChanges
); );
} }
if (!config.noVendorPurchaseLimits) { if (!config.noVendorPurchaseLimits && ItemId) {
inventory.RecentVendorPurchases ??= []; inventory.RecentVendorPurchases ??= [];
let vendorPurchases = inventory.RecentVendorPurchases.find( let vendorPurchases = inventory.RecentVendorPurchases.find(
x => x.VendorType == manifest.VendorInfo.TypeName x => x.VendorType == manifest.VendorInfo.TypeName
@ -410,6 +415,15 @@ const handleBoosterPackPurchase = async (
"attempt to roll over 100 booster packs in a single go. possible but unlikely to be desirable for the user or the server." "attempt to roll over 100 booster packs in a single go. possible but unlikely to be desirable for the user or the server."
); );
} }
if (typeName == "/Lotus/Types/BoosterPacks/1999StickersPackEchoesArchimedeaFixed") {
for (const result of pack.components) {
purchaseResponse.BoosterPackItems += toStoreItem(result.Item) + ',{"lvl":0};';
combineInventoryChanges(
purchaseResponse.InventoryChanges,
(await addItem(inventory, result.Item, 1)).InventoryChanges
);
}
} else {
for (let i = 0; i != quantity; ++i) { for (let i = 0; i != quantity; ++i) {
for (const weights of pack.rarityWeightsPerRoll) { for (const weights of pack.rarityWeightsPerRoll) {
const result = getRandomWeightedRewardUc(pack.components, weights); const result = getRandomWeightedRewardUc(pack.components, weights);
@ -423,6 +437,7 @@ const handleBoosterPackPurchase = async (
} }
} }
} }
}
return purchaseResponse; return purchaseResponse;
}; };

View File

@ -19,6 +19,7 @@ import HubsIronwakeDondaVendorManifest from "@/static/fixed_responses/getVendorI
import HubsPerrinSequenceWeaponVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsPerrinSequenceWeaponVendorManifest.json"; import HubsPerrinSequenceWeaponVendorManifest from "@/static/fixed_responses/getVendorInfo/HubsPerrinSequenceWeaponVendorManifest.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";
import Nova1999ConquestShopManifest from "@/static/fixed_responses/getVendorInfo/Nova1999ConquestShopManifest.json";
import OstronFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronFishmongerVendorManifest.json"; import OstronFishmongerVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronFishmongerVendorManifest.json";
import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json"; import OstronPetVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronPetVendorManifest.json";
import OstronProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronProspectorVendorManifest.json"; import OstronProspectorVendorManifest from "@/static/fixed_responses/getVendorInfo/OstronProspectorVendorManifest.json";
@ -69,6 +70,7 @@ const vendorManifests: IVendorManifest[] = [
HubsPerrinSequenceWeaponVendorManifest, HubsPerrinSequenceWeaponVendorManifest,
HubsRailjackCrewMemberVendorManifest, HubsRailjackCrewMemberVendorManifest,
MaskSalesmanManifest, MaskSalesmanManifest,
Nova1999ConquestShopManifest,
OstronFishmongerVendorManifest, OstronFishmongerVendorManifest,
OstronPetVendorManifest, OstronPetVendorManifest,
OstronProspectorVendorManifest, OstronProspectorVendorManifest,

View File

@ -1,4 +1,11 @@
import { IInventoryChanges } from "./purchaseTypes";
export interface IGenericUpdate { export interface IGenericUpdate {
NodeIntrosCompleted: string | string[]; NodeIntrosCompleted: string | string[];
// AffiliationMods: any[]; // AffiliationMods: any[];
} }
export interface IUpdateNodeIntrosResponse {
MissionRewards: [];
InventoryChanges: IInventoryChanges;
}

View File

@ -0,0 +1,188 @@
{
"VendorInfo": {
"_id": {
"$oid": "67dadc30e4b6e0e5979c8d6a"
},
"TypeName": "/Lotus/Types/Game/VendorManifests/TheHex/Nova1999ConquestShopManifest",
"ItemManifest": [
{
"StoreItem": "/Lotus/StoreItems/Types/BoosterPacks/1999StickersPackEchoesArchimedea",
"ItemPrices": [
{
"ItemCount": 10,
"ItemType": "/Lotus/Types/Items/MiscItems/1999ConquestBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67db32b983b2ad79a9c1c18c"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/BoosterPacks/1999StickersPackEchoesArchimedeaFree",
"ItemPrices": [
{
"ItemCount": 1,
"ItemType": "/Lotus/Types/Items/MiscItems/1999FreeStickersPack",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67db32b983b2ad79a9c1c18d"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/BoosterPacks/1999StickersPackEchoesArchimedeaFixed",
"ItemPrices": [
{
"ItemCount": 1,
"ItemType": "/Lotus/Types/Items/MiscItems/1999FixedStickersPack",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67db32b983b2ad79a9c1c18e"
}
},
{
"StoreItem": "/Lotus/Types/StoreItems/Packages/SyndicateVosforPack",
"ItemPrices": [
{
"ItemCount": 6,
"ItemType": "/Lotus/Types/Items/MiscItems/1999ConquestBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67db32b983b2ad79a9c1c18f"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/StickerPictureFrame",
"ItemPrices": [
{
"ItemCount": 10,
"ItemType": "/Lotus/Types/Items/MiscItems/1999ConquestBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "67db32b983b2ad79a9c1c190"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Utility/AbilityRadiationProcsCreateUniversalOrbsOnKill",
"ItemPrices": [
{
"ItemCount": 5,
"ItemType": "/Lotus/Types/Items/MiscItems/1999ConquestBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"Id": {
"$oid": "67db32b983b2ad79a9c1c191"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Offensive/AbilityHeatProcsGiveCritChance",
"ItemPrices": [
{
"ItemCount": 5,
"ItemType": "/Lotus/Types/Items/MiscItems/1999ConquestBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"Id": {
"$oid": "67db32b983b2ad79a9c1c192"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/CosmeticEnhancers/Defensive/InvulnerabilityOnDeathOnMercyKill",
"ItemPrices": [
{
"ItemCount": 5,
"ItemType": "/Lotus/Types/Items/MiscItems/1999ConquestBucks",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
},
"PurchaseQuantityLimit": 1,
"AllowMultipurchase": false,
"Id": {
"$oid": "67db32b983b2ad79a9c1c193"
}
}
],
"PropertyTextHash": "CB7D0E807FD5E2BCD059195201D963B9",
"RequiredGoalTag": "",
"Expiry": {
"$date": {
"$numberLong": "2051240400000"
}
}
}
}