Compare commits
9 Commits
08b09e783e
...
9d5d3f17bf
Author | SHA1 | Date | |
---|---|---|---|
9d5d3f17bf | |||
d28437b658 | |||
a6d2c8b18a | |||
0c884576bd | |||
380f0662a4 | |||
bd83738168 | |||
fa68a1357d | |||
43f3917b09 | |||
8ebb749732 |
@ -1,14 +1,12 @@
|
||||
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { generateRewardSeed } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const getNewRewardSeedController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
|
||||
const rewardSeed = generateRewardSeed();
|
||||
logger.debug(`generated new reward seed: ${rewardSeed}`);
|
||||
await Inventory.updateOne(
|
||||
{
|
||||
accountOwnerId: accountId
|
||||
|
20
src/controllers/api/giveShipDecoAndLoreFragmentController.ts
Normal file
20
src/controllers/api/giveShipDecoAndLoreFragmentController.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { addLoreFragmentScans, addShipDecorations, getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { ILoreFragmentScan, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const giveShipDecoAndLoreFragmentController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId, "LoreFragmentScans ShipDecorations");
|
||||
const data = getJSONfromString<IGiveShipDecoAndLoreFragmentRequest>(String(req.body));
|
||||
addLoreFragmentScans(inventory, data.LoreFragmentScans);
|
||||
addShipDecorations(inventory, data.ShipDecorations);
|
||||
await inventory.save();
|
||||
res.end();
|
||||
};
|
||||
|
||||
interface IGiveShipDecoAndLoreFragmentRequest {
|
||||
LoreFragmentScans: ILoreFragmentScan[];
|
||||
ShipDecorations: ITypeCount[];
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { ISetPlacedDecoInfoRequest } from "@/src/types/shipTypes";
|
||||
import { IPictureFrameInfo, ISetPlacedDecoInfoRequest } from "@/src/types/shipTypes";
|
||||
import { RequestHandler } from "express";
|
||||
import { handleSetPlacedDecoInfo } from "@/src/services/shipCustomizationsService";
|
||||
|
||||
@ -7,5 +7,17 @@ export const setPlacedDecoInfoController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const payload = JSON.parse(req.body as string) as ISetPlacedDecoInfoRequest;
|
||||
await handleSetPlacedDecoInfo(accountId, payload);
|
||||
res.end();
|
||||
res.json({
|
||||
DecoId: payload.DecoId,
|
||||
IsPicture: true,
|
||||
PictureFrameInfo: payload.PictureFrameInfo,
|
||||
BootLocation: payload.BootLocation
|
||||
} satisfies ISetPlacedDecoInfoResponse);
|
||||
};
|
||||
|
||||
interface ISetPlacedDecoInfoResponse {
|
||||
DecoId: string;
|
||||
IsPicture: boolean;
|
||||
PictureFrameInfo?: IPictureFrameInfo;
|
||||
BootLocation?: string;
|
||||
}
|
||||
|
@ -25,7 +25,13 @@ export const upgradesController: RequestHandler = async (req, res) => {
|
||||
operation.UpgradeRequirement == "/Lotus/Types/Items/MiscItems/CustomizationSlotUnlocker"
|
||||
) {
|
||||
updateCurrency(inventory, 10, true);
|
||||
} else if (operation.OperationType != "UOT_ABILITY_OVERRIDE") {
|
||||
} else if (
|
||||
operation.OperationType != "UOT_SWAP_POLARITY" &&
|
||||
operation.OperationType != "UOT_ABILITY_OVERRIDE"
|
||||
) {
|
||||
if (!operation.UpgradeRequirement) {
|
||||
throw new Error(`${operation.OperationType} operation should be free?`);
|
||||
}
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: operation.UpgradeRequirement,
|
||||
|
@ -1213,7 +1213,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
||||
accountOwnerId: Schema.Types.ObjectId,
|
||||
SubscribedToEmails: { type: Number, default: 0 },
|
||||
SubscribedToEmailsPersonalized: { type: Number, default: 0 },
|
||||
RewardSeed: Number,
|
||||
RewardSeed: BigInt,
|
||||
|
||||
//Credit
|
||||
RegularCredits: { type: Number, default: 0 },
|
||||
|
@ -62,6 +62,7 @@ import { gildWeaponController } from "@/src/controllers/api/gildWeaponController
|
||||
import { giveKeyChainTriggeredItemsController } from "@/src/controllers/api/giveKeyChainTriggeredItemsController";
|
||||
import { giveKeyChainTriggeredMessageController } from "@/src/controllers/api/giveKeyChainTriggeredMessageController";
|
||||
import { giveQuestKeyRewardController } from "@/src/controllers/api/giveQuestKey";
|
||||
import { giveShipDecoAndLoreFragmentController } from "@/src/controllers/api/giveShipDecoAndLoreFragmentController";
|
||||
import { giveStartingGearController } from "@/src/controllers/api/giveStartingGearController";
|
||||
import { guildTechController } from "@/src/controllers/api/guildTechController";
|
||||
import { hostSessionController } from "@/src/controllers/api/hostSessionController";
|
||||
@ -239,6 +240,7 @@ apiRouter.post("/gildWeapon.php", gildWeaponController);
|
||||
apiRouter.post("/giveKeyChainTriggeredItems.php", giveKeyChainTriggeredItemsController);
|
||||
apiRouter.post("/giveKeyChainTriggeredMessage.php", giveKeyChainTriggeredMessageController);
|
||||
apiRouter.post("/giveQuestKeyReward.php", giveQuestKeyRewardController);
|
||||
apiRouter.post("/giveShipDecoAndLoreFragment.php", giveShipDecoAndLoreFragmentController);
|
||||
apiRouter.post("/giveStartingGear.php", giveStartingGearController);
|
||||
apiRouter.post("/guildTech.php", guildTechController);
|
||||
apiRouter.post("/hostSession.php", hostSessionController);
|
||||
|
@ -21,7 +21,8 @@ import {
|
||||
ICalendarProgress,
|
||||
IDroneClient,
|
||||
IUpgradeClient,
|
||||
TPartialStartingGear
|
||||
TPartialStartingGear,
|
||||
ILoreFragmentScan
|
||||
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
|
||||
import { IKeyChainRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes";
|
||||
@ -1350,6 +1351,17 @@ export const addFocusXpIncreases = (inventory: TInventoryDatabaseDocument, focus
|
||||
inventory.DailyFocus -= focusXpPlus.reduce((a, b) => a + b, 0);
|
||||
};
|
||||
|
||||
export const addLoreFragmentScans = (inventory: TInventoryDatabaseDocument, arr: ILoreFragmentScan[]): void => {
|
||||
arr.forEach(clientFragment => {
|
||||
const fragment = inventory.LoreFragmentScans.find(x => x.ItemType == clientFragment.ItemType);
|
||||
if (fragment) {
|
||||
fragment.Progress += clientFragment.Progress;
|
||||
} else {
|
||||
inventory.LoreFragmentScans.push(clientFragment);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const addChallenges = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
ChallengeProgress: IChallengeProgress[],
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from "warframe-public-export-plus";
|
||||
import { IMissionInventoryUpdateRequest, IRewardInfo } from "../types/requestTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { IRngResult, getRandomElement, getRandomReward } from "@/src/services/rngService";
|
||||
import { IRngResult, SRng, getRandomElement, getRandomReward } from "@/src/services/rngService";
|
||||
import { equipmentKeys, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import {
|
||||
addBooster,
|
||||
@ -23,6 +23,7 @@ import {
|
||||
addGearExpByCategory,
|
||||
addItem,
|
||||
addLevelKeys,
|
||||
addLoreFragmentScans,
|
||||
addMiscItems,
|
||||
addMissionComplete,
|
||||
addMods,
|
||||
@ -30,6 +31,7 @@ import {
|
||||
addShipDecorations,
|
||||
addStanding,
|
||||
combineInventoryChanges,
|
||||
generateRewardSeed,
|
||||
updateCurrency,
|
||||
updateSyndicate
|
||||
} from "@/src/services/inventoryService";
|
||||
@ -69,7 +71,12 @@ const getRotations = (rotationCount: number, tierOverride: number | undefined):
|
||||
return rotatedValues;
|
||||
};
|
||||
|
||||
const getRandomRewardByChance = (pool: IReward[]): IRngResult | undefined => {
|
||||
const getRandomRewardByChance = (pool: IReward[], rng?: SRng): IRngResult | undefined => {
|
||||
if (rng) {
|
||||
const res = rng.randomReward(pool as IRngResult[]);
|
||||
rng.randomFloat(); // something related to rewards multiplier
|
||||
return res;
|
||||
}
|
||||
return getRandomReward(pool as IRngResult[]);
|
||||
};
|
||||
|
||||
@ -291,14 +298,7 @@ export const addMissionInventoryUpdates = async (
|
||||
break;
|
||||
}
|
||||
case "LoreFragmentScans":
|
||||
value.forEach(clientFragment => {
|
||||
const fragment = inventory.LoreFragmentScans.find(x => x.ItemType == clientFragment.ItemType);
|
||||
if (fragment) {
|
||||
fragment.Progress += clientFragment.Progress;
|
||||
} else {
|
||||
inventory.LoreFragmentScans.push(clientFragment);
|
||||
}
|
||||
});
|
||||
addLoreFragmentScans(inventory, value);
|
||||
break;
|
||||
case "LibraryScans":
|
||||
value.forEach(scan => {
|
||||
@ -554,6 +554,11 @@ export const addMissionRewards = async (
|
||||
return { MissionRewards: [] };
|
||||
}
|
||||
|
||||
if (rewardInfo.rewardSeed) {
|
||||
// We're using a reward seed, so give the client a new one in the response.
|
||||
inventory.RewardSeed = generateRewardSeed();
|
||||
}
|
||||
|
||||
//TODO: check double reward merging
|
||||
const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo, wagerTier);
|
||||
logger.debug("random mission drops:", MissionRewards);
|
||||
@ -592,7 +597,14 @@ export const addMissionRewards = async (
|
||||
const node = ExportRegions[missions.Tag];
|
||||
|
||||
//node based credit rewards for mission completion
|
||||
if (node.missionIndex !== 28) {
|
||||
if (
|
||||
node.missionIndex != 23 && // junction
|
||||
node.missionIndex != 28 && // open world
|
||||
missions.Tag != "SolNode761" && // the index
|
||||
missions.Tag != "SolNode762" && // the index
|
||||
missions.Tag != "SolNode763" && // the index
|
||||
missions.Tag != "CrewBattleNode556" // free flight
|
||||
) {
|
||||
const levelCreditReward = getLevelCreditRewards(node);
|
||||
missionCompletionCredits += levelCreditReward;
|
||||
inventory.RegularCredits += levelCreditReward;
|
||||
@ -898,6 +910,12 @@ function getLevelCreditRewards(node: IRegion): number {
|
||||
|
||||
function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | undefined): IMissionReward[] {
|
||||
const drops: IMissionReward[] = [];
|
||||
if (RewardInfo.periodicMissionTag?.startsWith("HardDaily")) {
|
||||
drops.push({
|
||||
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/SteelEssence",
|
||||
ItemCount: 5
|
||||
});
|
||||
}
|
||||
if (RewardInfo.node in ExportRegions) {
|
||||
const region = ExportRegions[RewardInfo.node];
|
||||
let rewardManifests: string[] =
|
||||
@ -922,7 +940,7 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
|
||||
|
||||
if (syndicateEntry.Tag === "EntratiSyndicate") {
|
||||
const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag);
|
||||
if (vault) job = vault;
|
||||
if (vault && locationTag) job = vault;
|
||||
// if (
|
||||
// [
|
||||
// "DeimosRuinsExterminateBounty",
|
||||
@ -997,8 +1015,10 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
|
||||
(RewardInfo.JobStage === job.xpAmounts.length - 1 || job.isVault) &&
|
||||
!isEndlessJob
|
||||
) {
|
||||
rewardManifests.push(job.rewards);
|
||||
rotations.push(ExportRewards[job.rewards].length - 1);
|
||||
if (ExportRewards[job.rewards]) {
|
||||
rewardManifests.push(job.rewards);
|
||||
rotations.push(ExportRewards[job.rewards].length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1053,17 +1073,21 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo, tierOverride: number | u
|
||||
if (rewardManifests.length != 0) {
|
||||
logger.debug(`generating random mission rewards`, { rewardManifests, rotations });
|
||||
}
|
||||
rewardManifests
|
||||
.map(name => ExportRewards[name])
|
||||
.forEach(table => {
|
||||
for (const rotation of rotations) {
|
||||
const rotationRewards = table[rotation];
|
||||
const drop = getRandomRewardByChance(rotationRewards);
|
||||
if (drop) {
|
||||
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
|
||||
}
|
||||
const rng = new SRng(BigInt(RewardInfo.rewardSeed ?? generateRewardSeed()) ^ 0xffffffffffffffffn);
|
||||
rewardManifests.forEach(name => {
|
||||
const table = ExportRewards[name];
|
||||
if (!table) {
|
||||
logger.error(`unknown droptable: ${name}`);
|
||||
return;
|
||||
}
|
||||
for (const rotation of rotations) {
|
||||
const rotationRewards = table[rotation];
|
||||
const drop = getRandomRewardByChance(rotationRewards, rng);
|
||||
if (drop) {
|
||||
drops.push({ StoreItem: drop.type, ItemCount: drop.itemCount });
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (region.cacheRewardManifest && RewardInfo.EnemyCachesFound) {
|
||||
const deck = ExportRewards[region.cacheRewardManifest];
|
||||
|
@ -31,7 +31,7 @@ const getRewardAtPercentage = <T extends { probability: number }>(pool: T[], per
|
||||
return item;
|
||||
}
|
||||
}
|
||||
throw new Error("What the fuck?");
|
||||
return pool[pool.length - 1];
|
||||
};
|
||||
|
||||
export const getRandomReward = <T extends { probability: number }>(pool: T[]): T | undefined => {
|
||||
@ -142,4 +142,8 @@ export class SRng {
|
||||
this.state = (0x5851f42d4c957f2dn * this.state + 0x14057b7ef767814fn) & 0xffffffffffffffffn;
|
||||
return (Number(this.state >> 38n) & 0xffffff) * 0.000000059604645;
|
||||
}
|
||||
|
||||
randomReward<T extends { probability: number }>(pool: T[]): T | undefined {
|
||||
return getRewardAtPercentage(pool, this.randomFloat());
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
||||
Mailbox?: IMailboxClient;
|
||||
SubscribedToEmails: number;
|
||||
Created: IMongoDate;
|
||||
RewardSeed: number;
|
||||
RewardSeed: number | bigint;
|
||||
RegularCredits: number;
|
||||
PremiumCredits: number;
|
||||
PremiumCreditsFree: number;
|
||||
|
@ -141,7 +141,7 @@ export interface IRewardInfo {
|
||||
EOM_AFK?: number;
|
||||
rewardQualifications?: string; // did a Survival for 5 minutes and this was "1"
|
||||
PurgatoryRewardQualifications?: string;
|
||||
rewardSeed?: number;
|
||||
rewardSeed?: number | bigint;
|
||||
periodicMissionTag?: string;
|
||||
|
||||
// for bounties, only EOM_AFK and node are given from above, plus:
|
||||
|
@ -139,7 +139,7 @@ dict = {
|
||||
cheats_noVendorPurchaseLimits: `Keine Kaufbeschränkungen bei Händlern`,
|
||||
cheats_noKimCooldowns: `Keine Wartezeit bei KIM`,
|
||||
cheats_instantResourceExtractorDrones: `Sofortige Ressourcen-Extraktor-Drohnen`,
|
||||
cheats_noResourceExtractorDronesDamage: `[UNTRANSLATED] No Resource Extractor Drones Damage`,
|
||||
cheats_noResourceExtractorDronesDamage: `Kein Schaden für Ressourcen-Extraktor-Drohnen`,
|
||||
cheats_noDojoRoomBuildStage: `Kein Dojo-Raum-Bauvorgang`,
|
||||
cheats_noDojoDecoBuildStage: `Kein Dojo-Deko-Bauvorgang`,
|
||||
cheats_fastDojoRoomDestruction: `Schnelle Dojo-Raum-Zerstörung`,
|
||||
|
@ -139,7 +139,7 @@ dict = {
|
||||
cheats_noVendorPurchaseLimits: `Sin límite de compras de vendedores`,
|
||||
cheats_noKimCooldowns: `Sin tiempo de espera para conversaciones KIM`,
|
||||
cheats_instantResourceExtractorDrones: `Drones de extracción de recursos instantáneos`,
|
||||
cheats_noResourceExtractorDronesDamage: `[UNTRANSLATED] No Resource Extractor Drones Damage`,
|
||||
cheats_noResourceExtractorDronesDamage: `Sin daño a los drones extractores de recursos`,
|
||||
cheats_noDojoRoomBuildStage: `Sin etapa de construcción de sala del dojo`,
|
||||
cheats_noDojoDecoBuildStage: `Sin etapa de construcción de decoraciones del dojo`,
|
||||
cheats_fastDojoRoomDestruction: `Destrucción rápida de salas del dojo`,
|
||||
|
Loading…
x
Reference in New Issue
Block a user