返回提交历史
Modified
src/controllers/api/fishmongerController.ts
+5
-23
Modified
src/controllers/api/missionInventoryUpdateController.ts
+9
-4
Modified
src/controllers/api/syndicateStandingBonusController.ts
+3
-35
Modified
src/services/inventoryService.ts
+34
-6
Modified
src/services/missionInventoryUpdateService.ts
+97
-2
Modified
src/types/requestTypes.ts
+1
-0
XFEstudio/SpaceNinjaServer
feat: bounty standing reward (#1556)
Re #388 I think this only missing `Field Bounties` and `Arcana Isolation Vault` Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/1556 Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com> Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
946f3129
代码差异
6 个文件
+149
-70
@@ -1,10 +1,9 @@
1
1
import { getJSONfromString } from "@/src/helpers/stringHelpers";
2
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
3
import { addMiscItems, getInventory, getStandingLimit, updateStandingLimit } from "@/src/services/inventoryService";
2
import { addMiscItems, addStanding, getInventory } from "@/src/services/inventoryService";
4
3
import { getAccountIdForRequest } from "@/src/services/loginService";
5
4
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
6
5
import { RequestHandler } from "express";
7
import { ExportResources, ExportSyndicates } from "warframe-public-export-plus";
6
import { ExportResources } from "warframe-public-export-plus";
8
7
9
8
export const fishmongerController: RequestHandler = async (req, res) => {
10
9
const accountId = await getAccountIdForRequest(req);
@@ -31,32 +30,15 @@ export const fishmongerController: RequestHandler = async (req, res) => {
31
30
miscItemChanges.push({ ItemType: fish.ItemType, ItemCount: fish.ItemCount * -1 });
32
31
}
33
32
addMiscItems(inventory, miscItemChanges);
34
if (gainedStanding && syndicateTag) {
35
let syndicate = inventory.Affiliations.find(x => x.Tag == syndicateTag);
36
if (!syndicate) {
37
syndicate = inventory.Affiliations[inventory.Affiliations.push({ Tag: syndicateTag, Standing: 0 }) - 1];
38
}
39
const syndicateMeta = ExportSyndicates[syndicateTag];
40
41
const max = getMaxStanding(syndicateMeta, syndicate.Title ?? 0);
42
if (syndicate.Standing + gainedStanding > max) {
43
gainedStanding = max - syndicate.Standing;
44
}
45
if (gainedStanding > getStandingLimit(inventory, syndicateMeta.dailyLimitBin)) {
46
gainedStanding = getStandingLimit(inventory, syndicateMeta.dailyLimitBin);
47
}
48
49
syndicate.Standing += gainedStanding;
50
51
updateStandingLimit(inventory, syndicateMeta.dailyLimitBin, gainedStanding);
52
}
33
let affiliationMod;
34
if (gainedStanding && syndicateTag) affiliationMod = addStanding(inventory, syndicateTag, gainedStanding);
53
35
await inventory.save();
54
36
res.json({
55
37
InventoryChanges: {
56
38
MiscItems: miscItemChanges
57
39
},
58
40
SyndicateTag: syndicateTag,
59
StandingChange: gainedStanding
41
StandingChange: affiliationMod?.Standing || 0
60
42
});
61
43
};
62
44
@@ -55,8 +55,10 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
55
55
const inventory = await getInventory(accountId);
56
56
const inventoryUpdates = await addMissionInventoryUpdates(inventory, missionReport);
57
57
58
// 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)
59
if (missionReport.MissionStatus !== "GS_SUCCESS" && !missionReport.RewardInfo?.jobId) {
58
if (
59
missionReport.MissionStatus !== "GS_SUCCESS" &&
60
!(missionReport.RewardInfo?.jobId || missionReport.RewardInfo?.challengeMissionId)
61
) {
60
62
await inventory.save();
61
63
const inventoryResponse = await getInventoryResponse(inventory, true);
62
64
res.json({
@@ -66,7 +68,8 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
66
68
return;
67
69
}
68
70
69
const { MissionRewards, inventoryChanges, credits } = await addMissionRewards(inventory, missionReport);
71
const { MissionRewards, inventoryChanges, credits, AffiliationMods, SyndicateXPItemReward } =
72
await addMissionRewards(inventory, missionReport);
70
73
71
74
await inventory.save();
72
75
const inventoryResponse = await getInventoryResponse(inventory, true);
@@ -78,7 +81,9 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
78
81
MissionRewards,
79
82
...credits,
80
83
...inventoryUpdates,
81
FusionPoints: inventoryChanges?.FusionPoints
84
FusionPoints: inventoryChanges?.FusionPoints,
85
SyndicateXPItemReward,
86
AffiliationMods
82
87
});
83
88
};
84
89
@@ -1,16 +1,9 @@
1
1
import { RequestHandler } from "express";
2
2
import { getAccountIdForRequest } from "@/src/services/loginService";
3
import {
4
addMiscItems,
5
freeUpSlot,
6
getInventory,
7
getStandingLimit,
8
updateStandingLimit
9
} from "@/src/services/inventoryService";
3
import { addMiscItems, addStanding, freeUpSlot, getInventory } from "@/src/services/inventoryService";
10
4
import { IMiscItem, InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
11
5
import { IOid } from "@/src/types/commonTypes";
12
6
import { ExportSyndicates, ExportWeapons } from "warframe-public-export-plus";
13
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
14
7
import { logger } from "@/src/utils/logger";
15
8
import { IInventoryChanges } from "@/src/types/purchaseTypes";
16
9
import { EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
@@ -61,38 +54,13 @@ export const syndicateStandingBonusController: RequestHandler = async (req, res)
61
54
inventoryChanges[slotBin] = { count: -1, platinum: 0, Slots: 1 };
62
55
}
63
56
64
let syndicate = inventory.Affiliations.find(x => x.Tag == request.Operation.AffiliationTag);
65
if (!syndicate) {
66
syndicate =
67
inventory.Affiliations[
68
inventory.Affiliations.push({ Tag: request.Operation.AffiliationTag, Standing: 0 }) - 1
69
];
70
}
71
72
const max = getMaxStanding(syndicateMeta, syndicate.Title ?? 0);
73
if (syndicate.Standing + gainedStanding > max) {
74
gainedStanding = max - syndicate.Standing;
75
}
76
77
if (syndicateMeta.medallionsCappedByDailyLimit) {
78
if (gainedStanding > getStandingLimit(inventory, syndicateMeta.dailyLimitBin)) {
79
gainedStanding = getStandingLimit(inventory, syndicateMeta.dailyLimitBin);
80
}
81
updateStandingLimit(inventory, syndicateMeta.dailyLimitBin, gainedStanding);
82
}
83
84
syndicate.Standing += gainedStanding;
57
const affiliationMod = addStanding(inventory, request.Operation.AffiliationTag, gainedStanding, true);
85
58
86
59
await inventory.save();
87
60
88
61
res.json({
89
62
InventoryChanges: inventoryChanges,
90
AffiliationMods: [
91
{
92
Tag: request.Operation.AffiliationTag,
93
Standing: gainedStanding
94
}
95
]
63
AffiliationMods: [affiliationMod]
96
64
});
97
65
};
98
66
@@ -65,6 +65,7 @@ import { handleBundleAcqusition } from "./purchaseService";
65
65
import libraryDailyTasks from "@/static/fixed_responses/libraryDailyTasks.json";
66
66
import { getRandomElement, getRandomInt, SRng } from "./rngService";
67
67
import { createMessage } from "./inboxService";
68
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
68
69
69
70
export const createInventory = async (
70
71
accountOwnerId: Types.ObjectId,
@@ -930,23 +931,50 @@ const standingLimitBinToInventoryKey: Record<
930
931
931
932
export const allDailyAffiliationKeys: (keyof IDailyAffiliations)[] = Object.values(standingLimitBinToInventoryKey);
932
933
933
export const getStandingLimit = (inventory: IDailyAffiliations, bin: TStandingLimitBin): number => {
934
const getStandingLimit = (inventory: IDailyAffiliations, bin: TStandingLimitBin): number => {
934
935
if (bin == "STANDING_LIMIT_BIN_NONE" || config.noDailyStandingLimits) {
935
936
return Number.MAX_SAFE_INTEGER;
936
937
}
937
938
return inventory[standingLimitBinToInventoryKey[bin]];
938
939
};
939
940
940
export const updateStandingLimit = (
941
inventory: IDailyAffiliations,
942
bin: TStandingLimitBin,
943
subtrahend: number
944
): void => {
941
const updateStandingLimit = (inventory: IDailyAffiliations, bin: TStandingLimitBin, subtrahend: number): void => {
945
942
if (bin != "STANDING_LIMIT_BIN_NONE" && !config.noDailyStandingLimits) {
946
943
inventory[standingLimitBinToInventoryKey[bin]] -= subtrahend;
947
944
}
948
945
};
949
946
947
export const addStanding = (
948
inventory: TInventoryDatabaseDocument,
949
syndicateTag: string,
950
gainedStanding: number,
951
isMedallion: boolean = false
952
): IAffiliationMods => {
953
let syndicate = inventory.Affiliations.find(x => x.Tag == syndicateTag);
954
const syndicateMeta = ExportSyndicates[syndicateTag];
955
956
if (!syndicate) {
957
syndicate =
958
inventory.Affiliations[inventory.Affiliations.push({ Tag: syndicateTag, Standing: 0, Title: 0 }) - 1];
959
}
960
961
const max = getMaxStanding(syndicateMeta, syndicate.Title ?? 0);
962
if (syndicate.Standing + gainedStanding > max) gainedStanding = max - syndicate.Standing;
963
964
if (!isMedallion || (isMedallion && syndicateMeta.medallionsCappedByDailyLimit)) {
965
if (gainedStanding > getStandingLimit(inventory, syndicateMeta.dailyLimitBin)) {
966
gainedStanding = getStandingLimit(inventory, syndicateMeta.dailyLimitBin);
967
}
968
updateStandingLimit(inventory, syndicateMeta.dailyLimitBin, gainedStanding);
969
}
970
971
syndicate.Standing += gainedStanding;
972
return {
973
Tag: syndicateTag,
974
Standing: gainedStanding
975
};
976
};
977
950
978
// TODO: AffiliationMods support (Nightwave).
951
979
export const updateGeneric = async (data: IGenericUpdate, accountId: string): Promise<IUpdateNodeIntrosResponse> => {
952
980
const inventory = await getInventory(accountId, "NodeIntrosCompleted MiscItems");
@@ -28,13 +28,14 @@ import {
28
28
addMods,
29
29
addRecipes,
30
30
addShipDecorations,
31
addStanding,
31
32
combineInventoryChanges,
32
33
updateCurrency,
33
34
updateSyndicate
34
35
} from "@/src/services/inventoryService";
35
36
import { updateQuestKey } from "@/src/services/questService";
36
37
import { Types } from "mongoose";
37
import { IInventoryChanges } from "@/src/types/purchaseTypes";
38
import { IAffiliationMods, IInventoryChanges } from "@/src/types/purchaseTypes";
38
39
import { getLevelKeyRewards, toStoreItem } from "@/src/services/itemDataService";
39
40
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
40
41
import { getEntriesUnsafe } from "@/src/utils/ts-utils";
@@ -529,6 +530,8 @@ interface AddMissionRewardsReturnType {
529
530
MissionRewards: IMissionReward[];
530
531
inventoryChanges?: IInventoryChanges;
531
532
credits?: IMissionCredits;
533
AffiliationMods?: IAffiliationMods[];
534
SyndicateXPItemReward?: number;
532
535
}
533
536
534
537
//TODO: return type of partial missioninventoryupdate response
@@ -555,6 +558,8 @@ export const addMissionRewards = async (
555
558
const MissionRewards: IMissionReward[] = getRandomMissionDrops(rewardInfo, wagerTier);
556
559
logger.debug("random mission drops:", MissionRewards);
557
560
const inventoryChanges: IInventoryChanges = {};
561
const AffiliationMods: IAffiliationMods[] = [];
562
let SyndicateXPItemReward;
558
563
559
564
let missionCompletionCredits = 0;
560
565
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
@@ -718,7 +723,97 @@ export const addMissionRewards = async (
718
723
inventoryChanges.Nemesis.InfNodes = inventory.Nemesis.InfNodes;
719
724
}
720
725
}
721
return { inventoryChanges, MissionRewards, credits };
726
727
if (rewardInfo.JobStage != undefined && rewardInfo.jobId) {
728
// eslint-disable-next-line @typescript-eslint/no-unused-vars
729
const [jobType, tierStr, hubNode, syndicateId, locationTag] = rewardInfo.jobId.split("_");
730
const tier = Number(tierStr);
731
732
const worldState = getWorldState();
733
let syndicateEntry = worldState.SyndicateMissions.find(m => m._id.$oid === syndicateId);
734
if (!syndicateEntry) syndicateEntry = worldState.SyndicateMissions.find(m => m.Tag === syndicateId); // Sometimes syndicateId can be tag
735
if (syndicateEntry && syndicateEntry.Jobs) {
736
let currentJob = syndicateEntry.Jobs[tier];
737
if (syndicateEntry.Tag === "EntratiSyndicate") {
738
const vault = syndicateEntry.Jobs.find(j => j.locationTag === locationTag);
739
if (vault) currentJob = vault;
740
let medallionAmount = currentJob.xpAmounts[rewardInfo.JobStage];
741
742
if (
743
["DeimosEndlessAreaDefenseBounty", "DeimosEndlessExcavateBounty", "DeimosEndlessPurifyBounty"].some(
744
ending => jobType.endsWith(ending)
745
)
746
) {
747
const endlessJob = syndicateEntry.Jobs.find(j => j.endless);
748
if (endlessJob) {
749
const index = rewardInfo.JobStage % endlessJob.xpAmounts.length;
750
const excess = Math.floor(rewardInfo.JobStage / endlessJob.xpAmounts.length);
751
medallionAmount = Math.floor(endlessJob.xpAmounts[index] * (1 + 0.15000001 * excess));
752
}
753
}
754
await addItem(inventory, "/Lotus/Types/Items/Deimos/EntratiFragmentUncommonB", medallionAmount);
755
MissionRewards.push({
756
StoreItem: "/Lotus/StoreItems/Types/Items/Deimos/EntratiFragmentUncommonB",
757
ItemCount: medallionAmount
758
});
759
SyndicateXPItemReward = medallionAmount;
760
} else {
761
if (tier >= 0) {
762
AffiliationMods.push(
763
addStanding(inventory, syndicateEntry.Tag, currentJob.xpAmounts[rewardInfo.JobStage])
764
);
765
} else {
766
if (jobType.endsWith("Heists/HeistProfitTakerBountyOne") && rewardInfo.JobStage === 2) {
767
AffiliationMods.push(addStanding(inventory, syndicateEntry.Tag, 1000));
768
}
769
if (jobType.endsWith("Hunts/AllTeralystsHunt") && rewardInfo.JobStage === 2) {
770
AffiliationMods.push(addStanding(inventory, syndicateEntry.Tag, 5000));
771
}
772
if (
773
[
774
"Hunts/TeralystHunt",
775
"Heists/HeistProfitTakerBountyTwo",
776
"Heists/HeistProfitTakerBountyThree",
777
"Heists/HeistProfitTakerBountyFour",
778
"Heists/HeistExploiterBountyOne"
779
].some(ending => jobType.endsWith(ending))
780
) {
781
AffiliationMods.push(addStanding(inventory, syndicateEntry.Tag, 1000));
782
}
783
}
784
}
785
}
786
}
787
788
if (rewardInfo.challengeMissionId) {
789
const [syndicateTag, tierStr] = rewardInfo.challengeMissionId.split("_"); // TODO: third part in HexSyndicate jobs - Chemistry points
790
const tier = Number(tierStr);
791
const isSteelPath = missions?.Tier;
792
if (syndicateTag === "ZarimanSyndicate") {
793
let medallionAmount = tier + 1;
794
if (isSteelPath) medallionAmount = Math.round(medallionAmount * 1.5);
795
await addItem(inventory, "/Lotus/Types/Gameplay/Zariman/Resources/ZarimanDogTagBounty", medallionAmount);
796
MissionRewards.push({
797
StoreItem: "/Lotus/StoreItems/Types/Gameplay/Zariman/Resources/ZarimanDogTagBounty",
798
ItemCount: medallionAmount
799
});
800
SyndicateXPItemReward = medallionAmount;
801
} else {
802
let standingAmount = (tier + 1) * 1000;
803
if (tier > 5) standingAmount = 7500; // InfestedLichBounty
804
if (isSteelPath) standingAmount *= 1.5;
805
AffiliationMods.push(addStanding(inventory, syndicateTag, standingAmount));
806
}
807
if (isSteelPath) {
808
await addItem(inventory, "/Lotus/Types/Items/MiscItems/SteelEssence", 1);
809
MissionRewards.push({
810
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/SteelEssence",
811
ItemCount: 1
812
});
813
}
814
}
815
816
return { inventoryChanges, MissionRewards, credits, AffiliationMods, SyndicateXPItemReward };
722
817
};
723
818
724
819
interface IMissionCredits {
@@ -150,6 +150,7 @@ export interface IRewardInfo {
150
150
JobStage?: number;
151
151
Q?: boolean; // likely indicates that the bonus objective for this stage was completed
152
152
CheckpointCounter?: number; // starts at 1, is incremented with each job stage upload, and does not reset when starting a new job
153
challengeMissionId?: string;
153
154
}
154
155
155
156
export type IMissionStatus = "GS_SUCCESS" | "GS_FAILURE" | "GS_DUMPED" | "GS_QUIT" | "GS_INTERRUPTED";