feat: bounty standing reward
Re #388 I think this only missing `Field Bounties` and `Arcana Isolation Vault`
This commit is contained in:
parent
355de3fa04
commit
78f681095c
@ -55,8 +55,10 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
const inventoryUpdates = await addMissionInventoryUpdates(inventory, missionReport);
|
const inventoryUpdates = await addMissionInventoryUpdates(inventory, missionReport);
|
||||||
|
|
||||||
// skip mission rewards if not GS_SUCCESS and not a bounty (by presence of jobId, as there's a reward every stage but only the last stage has GS_SUCCESS)
|
if (
|
||||||
if (missionReport.MissionStatus !== "GS_SUCCESS" && !missionReport.RewardInfo?.jobId) {
|
missionReport.MissionStatus !== "GS_SUCCESS" &&
|
||||||
|
!(missionReport.RewardInfo?.jobId || missionReport.RewardInfo?.challengeMissionId)
|
||||||
|
) {
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
const inventoryResponse = await getInventoryResponse(inventory, true);
|
const inventoryResponse = await getInventoryResponse(inventory, true);
|
||||||
res.json({
|
res.json({
|
||||||
@ -66,7 +68,8 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { MissionRewards, inventoryChanges, credits } = await addMissionRewards(inventory, missionReport);
|
const { MissionRewards, inventoryChanges, credits, AffiliationMods, SyndicateXPItemReward } =
|
||||||
|
await addMissionRewards(inventory, missionReport);
|
||||||
|
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
const inventoryResponse = await getInventoryResponse(inventory, true);
|
const inventoryResponse = await getInventoryResponse(inventory, true);
|
||||||
@ -78,7 +81,9 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
MissionRewards,
|
MissionRewards,
|
||||||
...credits,
|
...credits,
|
||||||
...inventoryUpdates,
|
...inventoryUpdates,
|
||||||
FusionPoints: inventoryChanges?.FusionPoints
|
FusionPoints: inventoryChanges?.FusionPoints,
|
||||||
|
SyndicateXPItemReward,
|
||||||
|
AffiliationMods
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,6 +65,7 @@ import { handleBundleAcqusition } from "./purchaseService";
|
|||||||
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
|
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
|
||||||
import { getRandomElement, getRandomInt, SRng } from "./rngService";
|
import { getRandomElement, getRandomInt, SRng } from "./rngService";
|
||||||
import { createMessage } from "./inboxService";
|
import { createMessage } from "./inboxService";
|
||||||
|
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
|
||||||
|
|
||||||
export const createInventory = async (
|
export const createInventory = async (
|
||||||
accountOwnerId: Types.ObjectId,
|
accountOwnerId: Types.ObjectId,
|
||||||
@ -947,6 +948,34 @@ export const updateStandingLimit = (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const addStanding = (
|
||||||
|
inventory: TInventoryDatabaseDocument,
|
||||||
|
syndicateTag: string,
|
||||||
|
gainedStanding: number
|
||||||
|
): IAffiliationMods => {
|
||||||
|
let syndicate = inventory.Affiliations.find(x => x.Tag == syndicateTag);
|
||||||
|
const syndicateMeta = ExportSyndicates[syndicateTag];
|
||||||
|
|
||||||
|
if (!syndicate) {
|
||||||
|
syndicate =
|
||||||
|
inventory.Affiliations[inventory.Affiliations.push({ Tag: syndicateTag, Standing: 0, Title: 0 }) - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const max = getMaxStanding(syndicateMeta, syndicate.Title ?? 0);
|
||||||
|
if (syndicate.Standing + gainedStanding > max) gainedStanding = max - syndicate.Standing;
|
||||||
|
|
||||||
|
if (gainedStanding > getStandingLimit(inventory, syndicateMeta.dailyLimitBin)) {
|
||||||
|
gainedStanding = getStandingLimit(inventory, syndicateMeta.dailyLimitBin);
|
||||||
|
}
|
||||||
|
updateStandingLimit(inventory, syndicateMeta.dailyLimitBin, gainedStanding);
|
||||||
|
|
||||||
|
syndicate.Standing += gainedStanding;
|
||||||
|
return {
|
||||||
|
Tag: syndicateTag,
|
||||||
|
Standing: gainedStanding
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: AffiliationMods support (Nightwave).
|
// TODO: AffiliationMods support (Nightwave).
|
||||||
export const updateGeneric = async (data: IGenericUpdate, accountId: string): Promise<IUpdateNodeIntrosResponse> => {
|
export const updateGeneric = async (data: IGenericUpdate, accountId: string): Promise<IUpdateNodeIntrosResponse> => {
|
||||||
const inventory = await getInventory(accountId, "NodeIntrosCompleted MiscItems");
|
const inventory = await getInventory(accountId, "NodeIntrosCompleted MiscItems");
|
||||||
|
@ -28,13 +28,14 @@ import {
|
|||||||
addMods,
|
addMods,
|
||||||
addRecipes,
|
addRecipes,
|
||||||
addShipDecorations,
|
addShipDecorations,
|
||||||
|
addStanding,
|
||||||
combineInventoryChanges,
|
combineInventoryChanges,
|
||||||
updateCurrency,
|
updateCurrency,
|
||||||
updateSyndicate
|
updateSyndicate
|
||||||
} from "@/src/services/inventoryService";
|
} from "@/src/services/inventoryService";
|
||||||
import { updateQuestKey } from "@/src/services/questService";
|
import { updateQuestKey } from "@/src/services/questService";
|
||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
import { IAffiliationMods, IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||||
import { getLevelKeyRewards, toStoreItem } from "@/src/services/itemDataService";
|
import { getLevelKeyRewards, toStoreItem } from "@/src/services/itemDataService";
|
||||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
import { getEntriesUnsafe } from "@/src/utils/ts-utils";
|
import { getEntriesUnsafe } from "@/src/utils/ts-utils";
|
||||||
@ -529,6 +530,8 @@ interface AddMissionRewardsReturnType {
|
|||||||
MissionRewards: IMissionReward[];
|
MissionRewards: IMissionReward[];
|
||||||
inventoryChanges?: IInventoryChanges;
|
inventoryChanges?: IInventoryChanges;
|
||||||
credits?: IMissionCredits;
|
credits?: IMissionCredits;
|
||||||
|
AffiliationMods?: IAffiliationMods[];
|
||||||
|
SyndicateXPItemReward?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: return type of partial missioninventoryupdate response
|
//TODO: return type of partial missioninventoryupdate response
|
||||||
@ -555,6 +558,8 @@ export const addMissionRewards = async (
|
|||||||
const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo, wagerTier);
|
const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo, wagerTier);
|
||||||
logger.debug("random mission drops:", MissionRewards);
|
logger.debug("random mission drops:", MissionRewards);
|
||||||
const inventoryChanges: IInventoryChanges = {};
|
const inventoryChanges: IInventoryChanges = {};
|
||||||
|
const AffiliationMods: IAffiliationMods[] = [];
|
||||||
|
let SyndicateXPItemReward;
|
||||||
|
|
||||||
let missionCompletionCredits = 0;
|
let missionCompletionCredits = 0;
|
||||||
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
|
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
|
||||||
@ -718,7 +723,98 @@ export const addMissionRewards = async (
|
|||||||
inventoryChanges.Nemesis.InfNodes = inventory.Nemesis.InfNodes;
|
inventoryChanges.Nemesis.InfNodes = inventory.Nemesis.InfNodes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { inventoryChanges, MissionRewards, credits };
|
|
||||||
|
if (rewardInfo.JobStage != undefined && rewardInfo.jobId) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const [jobType, tierStr, hubNode, syndicateId, locationTag] = rewardInfo.jobId.split("_");
|
||||||
|
const tier = Number(tierStr);
|
||||||
|
|
||||||
|
const worldState = getWorldState();
|
||||||
|
let syndicateEntry = worldState.SyndicateMissions.find(m => m._id.$oid === syndicateId);
|
||||||
|
if (!syndicateEntry) syndicateEntry = worldState.SyndicateMissions.find(m => m.Tag === syndicateId); // Sometimes syndicateId can be tag
|
||||||
|
if (syndicateEntry && syndicateEntry.Jobs) {
|
||||||
|
let currentJob = syndicateEntry.Jobs[tier];
|
||||||
|
if (syndicateEntry.Tag === "EntratiSyndicate") {
|
||||||
|
const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag);
|
||||||
|
if (vault) currentJob = vault;
|
||||||
|
let medallionAmount = currentJob.xpAmounts[rewardInfo.JobStage];
|
||||||
|
|
||||||
|
if (
|
||||||
|
["DeimosEndlessAreaDefenseBounty", "DeimosEndlessExcavateBounty", "DeimosEndlessPurifyBounty"].some(
|
||||||
|
ending => jobType.endsWith(ending)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
const endlessJob = syndicateEntry.Jobs.find(j => j.endless);
|
||||||
|
if (endlessJob) {
|
||||||
|
currentJob = endlessJob;
|
||||||
|
const index = rewardInfo.JobStage % currentJob.xpAmounts.length;
|
||||||
|
const excess = Math.floor(rewardInfo.JobStage / currentJob.xpAmounts.length);
|
||||||
|
medallionAmount = Math.floor(currentJob.xpAmounts[index] * (1 + 0.15000001 * excess));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await addItem(inventory, "/Lotus/Types/Items/Deimos/EntratiFragmentUncommonB", medallionAmount);
|
||||||
|
MissionRewards.push({
|
||||||
|
StoreItem: "/Lotus/StoreItems/Types/Items/Deimos/EntratiFragmentUncommonB",
|
||||||
|
ItemCount: medallionAmount
|
||||||
|
});
|
||||||
|
SyndicateXPItemReward = medallionAmount;
|
||||||
|
} else {
|
||||||
|
if (tier >= 0) {
|
||||||
|
AffiliationMods.push(
|
||||||
|
addStanding(inventory, syndicateEntry.Tag, currentJob.xpAmounts[rewardInfo.JobStage])
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
[
|
||||||
|
"Hunts/TeralystHunt",
|
||||||
|
"Heists/HeistProfitTakerBountyOne",
|
||||||
|
"Heists/HeistProfitTakerBountyTwo",
|
||||||
|
"Heists/HeistProfitTakerBountyThree",
|
||||||
|
"Heists/HeistProfitTakerBountyFour",
|
||||||
|
"Heists/HeistExploiterBountyOne"
|
||||||
|
].some(ending => jobType.endsWith(ending))
|
||||||
|
) {
|
||||||
|
AffiliationMods.push(addStanding(inventory, syndicateEntry.Tag, 1000));
|
||||||
|
}
|
||||||
|
if (jobType.endsWith("Hunts/AllTeralystsHunt")) {
|
||||||
|
AffiliationMods.push(addStanding(inventory, syndicateEntry.Tag, 5000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rewardInfo.challengeMissionId) {
|
||||||
|
const [syndicateTag, tierStr] = rewardInfo.challengeMissionId.split("_"); // TODO: third part in HexSyndicate jobs - Chemistry points
|
||||||
|
const tier = Number(tierStr);
|
||||||
|
const isSteelPath = missions?.Tier;
|
||||||
|
if (syndicateTag === "ZarimanSyndicate") {
|
||||||
|
let medallionAmount = tier + 1;
|
||||||
|
if (isSteelPath) medallionAmount = Math.round(medallionAmount * 1.5);
|
||||||
|
await addItem(inventory, "/Lotus/Types/Gameplay/Zariman/Resources/ZarimanDogTagBounty", medallionAmount);
|
||||||
|
MissionRewards.push({
|
||||||
|
StoreItem: "/Lotus/StoreItems/Types/Gameplay/Zariman/Resources/ZarimanDogTagBounty",
|
||||||
|
ItemCount: medallionAmount
|
||||||
|
});
|
||||||
|
SyndicateXPItemReward = medallionAmount;
|
||||||
|
} else {
|
||||||
|
let standingAmount = (tier + 1) * 1000;
|
||||||
|
if (tier > 5) standingAmount = 7500; // InfestedLichBounty
|
||||||
|
if (isSteelPath) standingAmount *= 1.5;
|
||||||
|
const affiliationMod = addStanding(inventory, syndicateTag, standingAmount);
|
||||||
|
|
||||||
|
AffiliationMods.push(affiliationMod);
|
||||||
|
}
|
||||||
|
if (isSteelPath) {
|
||||||
|
await addItem(inventory, "/Lotus/Types/Items/MiscItems/SteelEssence", 1);
|
||||||
|
MissionRewards.push({
|
||||||
|
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/SteelEssence",
|
||||||
|
ItemCount: 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { inventoryChanges, MissionRewards, credits, AffiliationMods, SyndicateXPItemReward };
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IMissionCredits {
|
interface IMissionCredits {
|
||||||
|
@ -150,6 +150,7 @@ export interface IRewardInfo {
|
|||||||
JobStage?: number;
|
JobStage?: number;
|
||||||
Q?: boolean; // likely indicates that the bonus objective for this stage was completed
|
Q?: boolean; // likely indicates that the bonus objective for this stage was completed
|
||||||
CheckpointCounter?: number; // starts at 1, is incremented with each job stage upload, and does not reset when starting a new job
|
CheckpointCounter?: number; // starts at 1, is incremented with each job stage upload, and does not reset when starting a new job
|
||||||
|
challengeMissionId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IMissionStatus = "GS_SUCCESS" | "GS_FAILURE" | "GS_DUMPED" | "GS_QUIT" | "GS_INTERRUPTED";
|
export type IMissionStatus = "GS_SUCCESS" | "GS_FAILURE" | "GS_DUMPED" | "GS_QUIT" | "GS_INTERRUPTED";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user