XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 0 Star 0
UTF-8
import { getJSONfromString } from "../../helpers/stringHelpers.ts";
import { addMiscItems, freeUpSlot, getInventory2, updateCredits } from "../../services/inventoryService.ts";
import { getAccountIdForRequest } from "../../services/loginService.ts";
import type { IOid } from "../../types/commonTypes.ts";
import type { ICrewShipComponentFingerprint } from "../../types/inventoryTypes/inventoryTypes.ts";
import { eInventorySlot } from "../../types/inventoryTypes/inventoryTypes.ts";
import type { IInventoryChanges } from "../../types/purchaseTypes.ts";
import type { RequestHandler } from "express";
import { ExportCustoms, ExportDojoRecipes } from "warframe-public-export-plus";

export const crewShipFusionController: RequestHandler = async (req, res) => {
    const accountId = await getAccountIdForRequest(req);
    const inventory = await getInventory2(
        accountId,
        "CrewShipWeapons",
        "CrewShipWeaponSkins",
        "CrewShipSalvagedWeapons",
        "CrewShipSalvagedWeaponSkins",
        "infiniteCredits",
        "RegularCredits",
        "MiscItems",
        "CrewShipSalvageBin"
    );
    const payload = getJSONfromString<ICrewShipFusionRequest>(String(req.body));

    const isWeapon = inventory.CrewShipWeapons.id(payload.PartA.$oid);
    const itemA = isWeapon ?? inventory.CrewShipWeaponSkins.id(payload.PartA.$oid)!;
    const category = isWeapon ? "CrewShipWeapons" : "CrewShipWeaponSkins";
    const salvageCategory = isWeapon ? "CrewShipSalvagedWeapons" : "CrewShipSalvagedWeaponSkins";
    const itemB = inventory[payload.SourceRecipe ? salvageCategory : category].id(payload.PartB.$oid)!;
    const tierA = itemA.ItemType.charCodeAt(itemA.ItemType.length - 1) - 65;
    const tierB = itemB.ItemType.charCodeAt(itemB.ItemType.length - 1) - 65;

    const inventoryChanges: IInventoryChanges = {};

    // Charge partial repair cost if fusing with an identified but unrepaired part
    if (payload.SourceRecipe) {
        const recipe = ExportDojoRecipes.research[payload.SourceRecipe];
        updateCredits(inventory, Math.round(recipe.price * 0.4), inventoryChanges);
        const miscItemChanges = recipe.ingredients.map(x => ({ ...x, ItemCount: Math.round(x.ItemCount * -0.4) }));
        addMiscItems(inventory, miscItemChanges);
        inventoryChanges.MiscItems = miscItemChanges;
    }

    // Remove inferior item
    if (payload.SourceRecipe) {
        inventory[salvageCategory].pull({ _id: payload.PartB.$oid });
        inventoryChanges.RemovedIdItems = [{ ItemId: payload.PartB }];
    } else {
        const inferiorId = tierA < tierB ? payload.PartA : payload.PartB;
        inventory[category].pull({ _id: inferiorId.$oid });
        inventoryChanges.RemovedIdItems = [{ ItemId: inferiorId }];
        freeUpSlot(inventory, eInventorySlot.RJ_COMPONENT_AND_ARMAMENTS);
        inventoryChanges[eInventorySlot.RJ_COMPONENT_AND_ARMAMENTS] = { count: -1, platinum: 0, Slots: 1 };
    }

    // Upgrade superior item
    const superiorItem = tierA < tierB ? itemB : itemA;
    const inferiorItem = tierA < tierB ? itemA : itemB;
    const fingerprint: ICrewShipComponentFingerprint = JSON.parse(
        superiorItem.UpgradeFingerprint!
    ) as ICrewShipComponentFingerprint;
    const inferiorFingerprint: ICrewShipComponentFingerprint = inferiorItem.UpgradeFingerprint
        ? (JSON.parse(inferiorItem.UpgradeFingerprint) as ICrewShipComponentFingerprint)
        : { compat: "", buffs: [] };
    if (isWeapon) {
        for (let i = 0; i != fingerprint.buffs.length; ++i) {
            const buffA = fingerprint.buffs[i];
            const buffB = i < inferiorFingerprint.buffs.length ? inferiorFingerprint.buffs[i] : undefined;
            const fvalA = buffA.Value / 0x3fffffff;
            const fvalB = (buffB?.Value ?? 0) / 0x3fffffff;
            const percA = 0.3 + fvalA * (0.6 - 0.3);
            const percB = 0.3 + fvalB * (0.6 - 0.3);
            const newPerc = Math.min(0.6, Math.max(percA, percB) * FUSE_MULTIPLIERS[Math.abs(tierA - tierB)]);
            const newFval = (newPerc - 0.3) / (0.6 - 0.3);
            buffA.Value = Math.trunc(newFval * 0x3fffffff);
        }
    } else {
        const superiorMeta = ExportCustoms[superiorItem.ItemType].randomisedUpgrades ?? [];
        const inferiorMeta = ExportCustoms[inferiorItem.ItemType].randomisedUpgrades ?? [];
        for (let i = 0; i != inferiorFingerprint.buffs.length; ++i) {
            const buffA = fingerprint.buffs[i];
            const buffB = inferiorFingerprint.buffs[i];
            const fvalA = buffA.Value / 0x3fffffff;
            const fvalB = buffB.Value / 0x3fffffff;
            const rangeA = superiorMeta[i].range;
            const rangeB = inferiorMeta[i].range;
            const percA = rangeA[0] + fvalA * (rangeA[1] - rangeA[0]);
            const percB = rangeB[0] + fvalB * (rangeB[1] - rangeB[0]);
            const newPerc = Math.min(rangeA[1], Math.max(percA, percB) * FUSE_MULTIPLIERS[Math.abs(tierA - tierB)]);
            const newFval = (newPerc - rangeA[0]) / (rangeA[1] - rangeA[0]);
            buffA.Value = Math.trunc(newFval * 0x3fffffff);
        }
        if (inferiorFingerprint.SubroutineIndex !== undefined) {
            const useSuperiorSubroutine = tierA < tierB ? !payload.UseSubroutineA : payload.UseSubroutineA;
            if (!useSuperiorSubroutine) {
                fingerprint.SubroutineIndex = inferiorFingerprint.SubroutineIndex;
            }
        }
    }
    superiorItem.UpgradeFingerprint = JSON.stringify(fingerprint);
    inventoryChanges[category] = [superiorItem.toJSON() as any];

    await inventory.save();
    res.json({
        InventoryChanges: inventoryChanges
    });
};

interface ICrewShipFusionRequest {
    PartA: IOid;
    PartB: IOid;
    SourceRecipe: string;
    UseSubroutineA: boolean;
}

const FUSE_MULTIPLIERS = [1.1, 1.05, 1.02];