forked from OpenWF/SpaceNinjaServer
feat: transmutation (#1112)
Closes #1098 Reviewed-on: OpenWF/SpaceNinjaServer#1112 Co-authored-by: Sainan <sainan@calamity.inc> Co-committed-by: Sainan <sainan@calamity.inc>
This commit is contained in:
parent
d7e3f33ecf
commit
901263ada3
8
package-lock.json
generated
8
package-lock.json
generated
@ -12,7 +12,7 @@
|
|||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
"mongoose": "^8.11.0",
|
"mongoose": "^8.11.0",
|
||||||
"warframe-public-export-plus": "^0.5.40",
|
"warframe-public-export-plus": "^0.5.41",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
@ -4083,9 +4083,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/warframe-public-export-plus": {
|
"node_modules/warframe-public-export-plus": {
|
||||||
"version": "0.5.40",
|
"version": "0.5.41",
|
||||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.40.tgz",
|
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.41.tgz",
|
||||||
"integrity": "sha512-/qr46LE/KqDdEkW4z52EG0vZP0Z8U26FscFJ2G5K5ewbQdlSVxtf5fpOnzRkAO7jWWKfgoqx7l5WUgaLSPDj0g=="
|
"integrity": "sha512-qVOUY4UjF1cyBrBbMwD25xHSdSf9q57/CJgjHsfSE7NUu/6pBDSZzwS0iAetAukws/1V2kDvsuy8AGtOec2L1w=="
|
||||||
},
|
},
|
||||||
"node_modules/warframe-riven-info": {
|
"node_modules/warframe-riven-info": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
"copyfiles": "^2.4.1",
|
"copyfiles": "^2.4.1",
|
||||||
"express": "^5",
|
"express": "^5",
|
||||||
"mongoose": "^8.11.0",
|
"mongoose": "^8.11.0",
|
||||||
"warframe-public-export-plus": "^0.5.40",
|
"warframe-public-export-plus": "^0.5.41",
|
||||||
"warframe-riven-info": "^0.1.2",
|
"warframe-riven-info": "^0.1.2",
|
||||||
"winston": "^3.17.0",
|
"winston": "^3.17.0",
|
||||||
"winston-daily-rotate-file": "^5.0.0"
|
"winston-daily-rotate-file": "^5.0.0"
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
import { toOid } from "@/src/helpers/inventoryHelpers";
|
import { toOid } from "@/src/helpers/inventoryHelpers";
|
||||||
import { IRivenChallenge } from "@/src/helpers/rivenFingerprintHelper";
|
import { createVeiledRivenFingerprint, rivenRawToRealWeighted } from "@/src/helpers/rivenHelper";
|
||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { addMods, getInventory } from "@/src/services/inventoryService";
|
import { addMods, getInventory } from "@/src/services/inventoryService";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { getRandomElement, getRandomInt, getRandomReward } from "@/src/services/rngService";
|
import { getRandomElement } from "@/src/services/rngService";
|
||||||
import { logger } from "@/src/utils/logger";
|
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { ExportUpgrades } from "warframe-public-export-plus";
|
import { ExportUpgrades } from "warframe-public-export-plus";
|
||||||
|
|
||||||
@ -19,40 +18,18 @@ export const activateRandomModController: RequestHandler = async (req, res) => {
|
|||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
const rivenType = getRandomElement(rivenRawToRealWeighted[request.ItemType]);
|
const rivenType = getRandomElement(rivenRawToRealWeighted[request.ItemType]);
|
||||||
const challenge = getRandomElement(ExportUpgrades[rivenType].availableChallenges!);
|
const fingerprint = createVeiledRivenFingerprint(ExportUpgrades[rivenType]);
|
||||||
const fingerprintChallenge: IRivenChallenge = {
|
|
||||||
Type: challenge.fullName,
|
|
||||||
Progress: 0,
|
|
||||||
Required: getRandomInt(challenge.countRange[0], challenge.countRange[1])
|
|
||||||
};
|
|
||||||
if (Math.random() < challenge.complicationChance) {
|
|
||||||
const complications: { type: string; probability: number }[] = [];
|
|
||||||
for (const complication of challenge.complications) {
|
|
||||||
complications.push({
|
|
||||||
type: complication.fullName,
|
|
||||||
probability: complication.weight
|
|
||||||
});
|
|
||||||
}
|
|
||||||
fingerprintChallenge.Complication = getRandomReward(complications)!.type;
|
|
||||||
logger.debug(
|
|
||||||
`riven rolled challenge ${fingerprintChallenge.Type} with complication ${fingerprintChallenge.Complication}`
|
|
||||||
);
|
|
||||||
const complication = challenge.complications.find(x => x.fullName == fingerprintChallenge.Complication)!;
|
|
||||||
fingerprintChallenge.Required *= complication.countMultiplier;
|
|
||||||
} else {
|
|
||||||
logger.debug(`riven rolled challenge ${fingerprintChallenge.Type}`);
|
|
||||||
}
|
|
||||||
const upgradeIndex =
|
const upgradeIndex =
|
||||||
inventory.Upgrades.push({
|
inventory.Upgrades.push({
|
||||||
ItemType: rivenType,
|
ItemType: rivenType,
|
||||||
UpgradeFingerprint: JSON.stringify({ challenge: fingerprintChallenge })
|
UpgradeFingerprint: JSON.stringify(fingerprint)
|
||||||
}) - 1;
|
}) - 1;
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
// For some reason, in this response, the UpgradeFingerprint is simply a nested object and not a string
|
// For some reason, in this response, the UpgradeFingerprint is simply a nested object and not a string
|
||||||
res.json({
|
res.json({
|
||||||
NewMod: {
|
NewMod: {
|
||||||
UpgradeFingerprint: { challenge: fingerprintChallenge },
|
UpgradeFingerprint: fingerprint,
|
||||||
ItemType: inventory.Upgrades[upgradeIndex].ItemType,
|
ItemType: rivenType,
|
||||||
ItemId: toOid(inventory.Upgrades[upgradeIndex]._id)
|
ItemId: toOid(inventory.Upgrades[upgradeIndex]._id)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -61,37 +38,3 @@ export const activateRandomModController: RequestHandler = async (req, res) => {
|
|||||||
interface IActiveRandomModRequest {
|
interface IActiveRandomModRequest {
|
||||||
ItemType: string;
|
ItemType: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const rivenRawToRealWeighted: Record<string, string[]> = {
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/RawArchgunRandomMod": [
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusArchgunRandomModRare"
|
|
||||||
],
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/RawMeleeRandomMod": [
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/PlayerMeleeWeaponRandomModRare"
|
|
||||||
],
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/RawModularMeleeRandomMod": [
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusModularMeleeRandomModRare"
|
|
||||||
],
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/RawModularPistolRandomMod": [
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusModularPistolRandomModRare"
|
|
||||||
],
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/RawPistolRandomMod": ["/Lotus/Upgrades/Mods/Randomized/LotusPistolRandomModRare"],
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/RawRifleRandomMod": ["/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare"],
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/RawShotgunRandomMod": [
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusShotgunRandomModRare"
|
|
||||||
],
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/RawSentinelWeaponRandomMod": [
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusShotgunRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/LotusPistolRandomModRare",
|
|
||||||
"/Lotus/Upgrades/Mods/Randomized/PlayerMeleeWeaponRandomModRare"
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
124
src/controllers/api/artifactTransmutationController.ts
Normal file
124
src/controllers/api/artifactTransmutationController.ts
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
import { toOid } from "@/src/helpers/inventoryHelpers";
|
||||||
|
import { createVeiledRivenFingerprint, rivenRawToRealWeighted } from "@/src/helpers/rivenHelper";
|
||||||
|
import { addMiscItems, addMods, getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { getRandomElement, getRandomWeightedReward, getRandomWeightedRewardUc } from "@/src/services/rngService";
|
||||||
|
import { IOid } from "@/src/types/commonTypes";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
import { ExportBoosterPacks, ExportUpgrades, TRarity } from "warframe-public-export-plus";
|
||||||
|
|
||||||
|
export const artifactTransmutationController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
const payload = JSON.parse(String(req.body)) as IArtifactTransmutationRequest;
|
||||||
|
|
||||||
|
inventory.RegularCredits -= payload.Cost;
|
||||||
|
inventory.FusionPoints -= payload.FusionPointCost;
|
||||||
|
|
||||||
|
if (payload.RivenTransmute) {
|
||||||
|
addMiscItems(inventory, [
|
||||||
|
{
|
||||||
|
ItemType: "/Lotus/Types/Gameplay/Eidolon/Resources/SentientSecretItem",
|
||||||
|
ItemCount: -1
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
payload.Consumed.forEach(upgrade => {
|
||||||
|
inventory.Upgrades.pull({ _id: upgrade.ItemId.$oid });
|
||||||
|
});
|
||||||
|
|
||||||
|
const rawRivenType = getRandomRawRivenType();
|
||||||
|
const rivenType = getRandomElement(rivenRawToRealWeighted[rawRivenType]);
|
||||||
|
const fingerprint = createVeiledRivenFingerprint(ExportUpgrades[rivenType]);
|
||||||
|
|
||||||
|
const upgradeIndex =
|
||||||
|
inventory.Upgrades.push({
|
||||||
|
ItemType: rivenType,
|
||||||
|
UpgradeFingerprint: JSON.stringify(fingerprint)
|
||||||
|
}) - 1;
|
||||||
|
await inventory.save();
|
||||||
|
res.json({
|
||||||
|
NewMods: [
|
||||||
|
{
|
||||||
|
ItemId: toOid(inventory.Upgrades[upgradeIndex]._id),
|
||||||
|
ItemType: rivenType,
|
||||||
|
UpgradeFingerprint: fingerprint
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const counts: Record<TRarity, number> = {
|
||||||
|
COMMON: 0,
|
||||||
|
UNCOMMON: 0,
|
||||||
|
RARE: 0,
|
||||||
|
LEGENDARY: 0
|
||||||
|
};
|
||||||
|
payload.Consumed.forEach(upgrade => {
|
||||||
|
const meta = ExportUpgrades[upgrade.ItemType];
|
||||||
|
counts[meta.rarity] += upgrade.ItemCount;
|
||||||
|
addMods(inventory, [
|
||||||
|
{
|
||||||
|
ItemType: upgrade.ItemType,
|
||||||
|
ItemCount: upgrade.ItemCount * -1
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Based on the table on https://wiki.warframe.com/w/Transmutation
|
||||||
|
const weights: Record<TRarity, number> = {
|
||||||
|
COMMON: counts.COMMON * 95 + counts.UNCOMMON * 15 + counts.RARE * 4,
|
||||||
|
UNCOMMON: counts.COMMON * 4 + counts.UNCOMMON * 80 + counts.RARE * 10,
|
||||||
|
RARE: counts.COMMON * 1 + counts.UNCOMMON * 5 + counts.RARE * 50,
|
||||||
|
LEGENDARY: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
const options: { uniqueName: string; rarity: TRarity }[] = [];
|
||||||
|
Object.entries(ExportUpgrades).forEach(([uniqueName, upgrade]) => {
|
||||||
|
if (upgrade.canBeTransmutation) {
|
||||||
|
options.push({ uniqueName, rarity: upgrade.rarity });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const newModType = getRandomWeightedReward(options, weights)!.uniqueName;
|
||||||
|
addMods(inventory, [
|
||||||
|
{
|
||||||
|
ItemType: newModType,
|
||||||
|
ItemCount: 1
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
await inventory.save();
|
||||||
|
res.json({
|
||||||
|
NewMods: [
|
||||||
|
{
|
||||||
|
ItemType: newModType,
|
||||||
|
ItemCount: 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getRandomRawRivenType = (): string => {
|
||||||
|
const pack = ExportBoosterPacks["/Lotus/Types/BoosterPacks/CalendarRivenPack"];
|
||||||
|
return getRandomWeightedRewardUc(pack.components, pack.rarityWeightsPerRoll[0])!.Item;
|
||||||
|
};
|
||||||
|
|
||||||
|
interface IArtifactTransmutationRequest {
|
||||||
|
Upgrade: IAgnosticUpgradeClient;
|
||||||
|
LevelDiff: number;
|
||||||
|
Consumed: IAgnosticUpgradeClient[];
|
||||||
|
Cost: number;
|
||||||
|
FusionPointCost: number;
|
||||||
|
RivenTransmute?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IAgnosticUpgradeClient {
|
||||||
|
ItemType: string;
|
||||||
|
ItemId: IOid;
|
||||||
|
FromSKU: boolean;
|
||||||
|
UpgradeFingerprint: string;
|
||||||
|
PendingRerollFingerprint: string;
|
||||||
|
ItemCount: number;
|
||||||
|
LastAdded: IOid;
|
||||||
|
}
|
@ -4,7 +4,7 @@ import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inven
|
|||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||||
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { createUnveiledRivenFingerprint } from "@/src/helpers/rivenFingerprintHelper";
|
import { createUnveiledRivenFingerprint } from "@/src/helpers/rivenHelper";
|
||||||
import { ExportUpgrades } from "warframe-public-export-plus";
|
import { ExportUpgrades } from "warframe-public-export-plus";
|
||||||
|
|
||||||
export const completeRandomModChallengeController: RequestHandler = async (req, res) => {
|
export const completeRandomModChallengeController: RequestHandler = async (req, res) => {
|
||||||
|
@ -2,11 +2,7 @@ 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 } from "@/src/services/inventoryService";
|
||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import {
|
import { createUnveiledRivenFingerprint, randomiseRivenStats, RivenFingerprint } from "@/src/helpers/rivenHelper";
|
||||||
createUnveiledRivenFingerprint,
|
|
||||||
randomiseRivenStats,
|
|
||||||
RivenFingerprint
|
|
||||||
} from "@/src/helpers/rivenFingerprintHelper";
|
|
||||||
import { ExportUpgrades } from "warframe-public-export-plus";
|
import { ExportUpgrades } from "warframe-public-export-plus";
|
||||||
import { IOid } from "@/src/types/commonTypes";
|
import { IOid } from "@/src/types/commonTypes";
|
||||||
|
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
import { IUpgrade } from "warframe-public-export-plus";
|
|
||||||
import { getRandomElement, getRandomInt } from "../services/rngService";
|
|
||||||
|
|
||||||
export type RivenFingerprint = IVeiledRivenFingerprint | IUnveiledRivenFingerprint;
|
|
||||||
|
|
||||||
export interface IVeiledRivenFingerprint {
|
|
||||||
challenge: IRivenChallenge;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IRivenChallenge {
|
|
||||||
Type: string;
|
|
||||||
Progress: number;
|
|
||||||
Required: number;
|
|
||||||
Complication?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IUnveiledRivenFingerprint {
|
|
||||||
compat: string;
|
|
||||||
lim: 0;
|
|
||||||
lvl: number;
|
|
||||||
lvlReq: number;
|
|
||||||
rerolls?: number;
|
|
||||||
pol: string;
|
|
||||||
buffs: IRivenStat[];
|
|
||||||
curses: IRivenStat[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IRivenStat {
|
|
||||||
Tag: string;
|
|
||||||
Value: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const createUnveiledRivenFingerprint = (meta: IUpgrade): IUnveiledRivenFingerprint => {
|
|
||||||
const fingerprint: IUnveiledRivenFingerprint = {
|
|
||||||
compat: getRandomElement(meta.compatibleItems!),
|
|
||||||
lim: 0,
|
|
||||||
lvl: 0,
|
|
||||||
lvlReq: getRandomInt(8, 16),
|
|
||||||
pol: getRandomElement(["AP_ATTACK", "AP_DEFENSE", "AP_TACTIC"]),
|
|
||||||
buffs: [],
|
|
||||||
curses: []
|
|
||||||
};
|
|
||||||
randomiseRivenStats(meta, fingerprint);
|
|
||||||
return fingerprint;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const randomiseRivenStats = (meta: IUpgrade, fingerprint: IUnveiledRivenFingerprint): void => {
|
|
||||||
fingerprint.buffs = [];
|
|
||||||
const numBuffs = 2 + Math.trunc(Math.random() * 2); // 2 or 3
|
|
||||||
const buffEntries = meta.upgradeEntries!.filter(x => x.canBeBuff);
|
|
||||||
for (let i = 0; i != numBuffs; ++i) {
|
|
||||||
const buffIndex = Math.trunc(Math.random() * buffEntries.length);
|
|
||||||
const entry = buffEntries[buffIndex];
|
|
||||||
fingerprint.buffs.push({ Tag: entry.tag, Value: Math.trunc(Math.random() * 0x40000000) });
|
|
||||||
buffEntries.splice(buffIndex, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fingerprint.curses = [];
|
|
||||||
if (Math.random() < 0.5) {
|
|
||||||
const entry = getRandomElement(
|
|
||||||
meta.upgradeEntries!.filter(x => x.canBeCurse && !fingerprint.buffs.find(y => y.Tag == x.tag))
|
|
||||||
);
|
|
||||||
fingerprint.curses.push({ Tag: entry.tag, Value: Math.trunc(Math.random() * 0x40000000) });
|
|
||||||
}
|
|
||||||
};
|
|
121
src/helpers/rivenHelper.ts
Normal file
121
src/helpers/rivenHelper.ts
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import { IUpgrade } from "warframe-public-export-plus";
|
||||||
|
import { getRandomElement, getRandomInt, getRandomReward } from "../services/rngService";
|
||||||
|
|
||||||
|
export type RivenFingerprint = IVeiledRivenFingerprint | IUnveiledRivenFingerprint;
|
||||||
|
|
||||||
|
export interface IVeiledRivenFingerprint {
|
||||||
|
challenge: IRivenChallenge;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRivenChallenge {
|
||||||
|
Type: string;
|
||||||
|
Progress: number;
|
||||||
|
Required: number;
|
||||||
|
Complication?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUnveiledRivenFingerprint {
|
||||||
|
compat: string;
|
||||||
|
lim: 0;
|
||||||
|
lvl: number;
|
||||||
|
lvlReq: number;
|
||||||
|
rerolls?: number;
|
||||||
|
pol: string;
|
||||||
|
buffs: IRivenStat[];
|
||||||
|
curses: IRivenStat[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IRivenStat {
|
||||||
|
Tag: string;
|
||||||
|
Value: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createVeiledRivenFingerprint = (meta: IUpgrade): IVeiledRivenFingerprint => {
|
||||||
|
const challenge = getRandomElement(meta.availableChallenges!);
|
||||||
|
const fingerprintChallenge: IRivenChallenge = {
|
||||||
|
Type: challenge.fullName,
|
||||||
|
Progress: 0,
|
||||||
|
Required: getRandomInt(challenge.countRange[0], challenge.countRange[1])
|
||||||
|
};
|
||||||
|
if (Math.random() < challenge.complicationChance) {
|
||||||
|
const complications: { type: string; probability: number }[] = [];
|
||||||
|
for (const complication of challenge.complications) {
|
||||||
|
complications.push({
|
||||||
|
type: complication.fullName,
|
||||||
|
probability: complication.weight
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fingerprintChallenge.Complication = getRandomReward(complications)!.type;
|
||||||
|
const complication = challenge.complications.find(x => x.fullName == fingerprintChallenge.Complication)!;
|
||||||
|
fingerprintChallenge.Required *= complication.countMultiplier;
|
||||||
|
}
|
||||||
|
return { challenge: fingerprintChallenge };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createUnveiledRivenFingerprint = (meta: IUpgrade): IUnveiledRivenFingerprint => {
|
||||||
|
const fingerprint: IUnveiledRivenFingerprint = {
|
||||||
|
compat: getRandomElement(meta.compatibleItems!),
|
||||||
|
lim: 0,
|
||||||
|
lvl: 0,
|
||||||
|
lvlReq: getRandomInt(8, 16),
|
||||||
|
pol: getRandomElement(["AP_ATTACK", "AP_DEFENSE", "AP_TACTIC"]),
|
||||||
|
buffs: [],
|
||||||
|
curses: []
|
||||||
|
};
|
||||||
|
randomiseRivenStats(meta, fingerprint);
|
||||||
|
return fingerprint;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const randomiseRivenStats = (meta: IUpgrade, fingerprint: IUnveiledRivenFingerprint): void => {
|
||||||
|
fingerprint.buffs = [];
|
||||||
|
const numBuffs = 2 + Math.trunc(Math.random() * 2); // 2 or 3
|
||||||
|
const buffEntries = meta.upgradeEntries!.filter(x => x.canBeBuff);
|
||||||
|
for (let i = 0; i != numBuffs; ++i) {
|
||||||
|
const buffIndex = Math.trunc(Math.random() * buffEntries.length);
|
||||||
|
const entry = buffEntries[buffIndex];
|
||||||
|
fingerprint.buffs.push({ Tag: entry.tag, Value: Math.trunc(Math.random() * 0x40000000) });
|
||||||
|
buffEntries.splice(buffIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fingerprint.curses = [];
|
||||||
|
if (Math.random() < 0.5) {
|
||||||
|
const entry = getRandomElement(
|
||||||
|
meta.upgradeEntries!.filter(x => x.canBeCurse && !fingerprint.buffs.find(y => y.Tag == x.tag))
|
||||||
|
);
|
||||||
|
fingerprint.curses.push({ Tag: entry.tag, Value: Math.trunc(Math.random() * 0x40000000) });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const rivenRawToRealWeighted: Record<string, string[]> = {
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawArchgunRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusArchgunRandomModRare"
|
||||||
|
],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawMeleeRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/PlayerMeleeWeaponRandomModRare"
|
||||||
|
],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawModularMeleeRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusModularMeleeRandomModRare"
|
||||||
|
],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawModularPistolRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusModularPistolRandomModRare"
|
||||||
|
],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawPistolRandomMod": ["/Lotus/Upgrades/Mods/Randomized/LotusPistolRandomModRare"],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawRifleRandomMod": ["/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare"],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawShotgunRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusShotgunRandomModRare"
|
||||||
|
],
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/RawSentinelWeaponRandomMod": [
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusRifleRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusShotgunRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/LotusPistolRandomModRare",
|
||||||
|
"/Lotus/Upgrades/Mods/Randomized/PlayerMeleeWeaponRandomModRare"
|
||||||
|
]
|
||||||
|
};
|
@ -7,6 +7,7 @@ import { addFriendImageController } from "@/src/controllers/api/addFriendImageCo
|
|||||||
import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController";
|
import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController";
|
||||||
import { archonFusionController } from "@/src/controllers/api/archonFusionController";
|
import { archonFusionController } from "@/src/controllers/api/archonFusionController";
|
||||||
import { artifactsController } from "@/src/controllers/api/artifactsController";
|
import { artifactsController } from "@/src/controllers/api/artifactsController";
|
||||||
|
import { artifactTransmutationController } from "@/src/controllers/api/artifactTransmutationController";
|
||||||
import { changeDojoRootController } from "@/src/controllers/api/changeDojoRootController";
|
import { changeDojoRootController } from "@/src/controllers/api/changeDojoRootController";
|
||||||
import { checkDailyMissionBonusController } from "@/src/controllers/api/checkDailyMissionBonusController";
|
import { checkDailyMissionBonusController } from "@/src/controllers/api/checkDailyMissionBonusController";
|
||||||
import { claimCompletedRecipeController } from "@/src/controllers/api/claimCompletedRecipeController";
|
import { claimCompletedRecipeController } from "@/src/controllers/api/claimCompletedRecipeController";
|
||||||
@ -150,6 +151,7 @@ apiRouter.post("/addFriendImage.php", addFriendImageController);
|
|||||||
apiRouter.post("/arcaneCommon.php", arcaneCommonController);
|
apiRouter.post("/arcaneCommon.php", arcaneCommonController);
|
||||||
apiRouter.post("/archonFusion.php", archonFusionController);
|
apiRouter.post("/archonFusion.php", archonFusionController);
|
||||||
apiRouter.post("/artifacts.php", artifactsController);
|
apiRouter.post("/artifacts.php", artifactsController);
|
||||||
|
apiRouter.post("/artifactTransmutation.php", artifactTransmutationController);
|
||||||
apiRouter.post("/changeDojoRoot.php", changeDojoRootController);
|
apiRouter.post("/changeDojoRoot.php", changeDojoRootController);
|
||||||
apiRouter.post("/claimCompletedRecipe.php", claimCompletedRecipeController);
|
apiRouter.post("/claimCompletedRecipe.php", claimCompletedRecipeController);
|
||||||
apiRouter.post("/clearDialogueHistory.php", clearDialogueHistoryController);
|
apiRouter.post("/clearDialogueHistory.php", clearDialogueHistoryController);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user