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

XFESpaceNinjaServer

A simple server for a small space ninja game

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFESpaceNinjaServer

feat: invasion death squad inbox messages (#3186)

Closes #3083 Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/3186 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>

ba92dcae
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

5 个文件 +88 -35
Modified src/controllers/api/inventoryController.ts +23 -33
@@ -219,44 +219,34 @@ export const inventoryController: RequestHandler = async (request, response) =>
219 219 if (qi.AttackerScore >= 3) {
220 220 factionSidedWith = invasion.Faction;
221 221 battlePay = invasion.AttackerReward.countedItems;
222 logger.debug(`invasion pay from ${factionSidedWith}`, { battlePay });
223 222 } else if (qi.DefenderScore >= 3) {
224 223 factionSidedWith = invasion.DefenderFaction;
225 224 battlePay = invasion.DefenderReward.countedItems;
226 logger.debug(`invasion pay from ${factionSidedWith}`, { battlePay });
227 225 }
228 if (factionSidedWith) {
229 if (battlePay) {
230 // Decoupling rewards from the inbox message because it may delete itself without being read
231 for (const item of battlePay) {
232 await addItem(inventory, item.ItemType, item.ItemCount);
233 }
234 await createMessage(account._id, [
235 {
236 sndr:
237 factionSidedWith == "FC_GRINEER"
238 ? "/Lotus/Language/Menu/GrineerInvasionLeader"
239 : "/Lotus/Language/Menu/CorpusInvasionLeader",
240 msg: `/Lotus/Language/G1Quests/${factionSidedWith}_InvasionThankyouMessageBody`,
241 sub: `/Lotus/Language/G1Quests/${factionSidedWith}_InvasionThankyouMessageSubject`,
242 countedAtt: battlePay,
243 attVisualOnly: true,
244 icon:
245 factionSidedWith == "FC_GRINEER"
246 ? "/Lotus/Interface/Icons/Npcs/EliteRifleLancerAvatar.png" // Source: https://www.reddit.com/r/Warframe/comments/1aj4usx/battle_pay_worth_10_plat/, https://www.youtube.com/watch?v=XhNZ6ai6BOY
247 : "/Lotus/Interface/Icons/Npcs/CrewmanNormal.png", // My best source for this is https://www.youtube.com/watch?v=rxrCCFm73XE around 1:37
248 // TOVERIFY: highPriority?
249 endDate: new Date(Date.now() + 86400_000) // TOVERIFY: This type of inbox message seems to automatically delete itself. We'll just delete it after 24 hours, but it's not clear if this is correct.
250 }
251 ]);
252 }
253 if (invasion.Faction != "FC_INFESTATION") {
254 // Sided with grineer -> opposed corpus -> send zanuka (harvester)
255 // Sided with corpus -> opposed grineer -> send g3 (death squad)
256 inventory[factionSidedWith != "FC_GRINEER" ? "DeathSquadable" : "Harvestable"] = true;
257 // TOVERIFY: Should this happen earlier?
258 // TOVERIFY: Should this send an (ephemeral) email?
226 if (factionSidedWith && battlePay) {
227 logger.debug(`invasion pay from ${factionSidedWith}`, { battlePay });
228 // Decoupling rewards from the inbox message because it may delete itself without being read
229 for (const item of battlePay) {
230 await addItem(inventory, item.ItemType, item.ItemCount);
259 231 }
232 await createMessage(account._id, [
233 {
234 sndr:
235 factionSidedWith == "FC_GRINEER"
236 ? "/Lotus/Language/Menu/GrineerInvasionLeader"
237 : "/Lotus/Language/Menu/CorpusInvasionLeader",
238 msg: `/Lotus/Language/G1Quests/${factionSidedWith}_InvasionThankyouMessageBody`,
239 sub: `/Lotus/Language/G1Quests/${factionSidedWith}_InvasionThankyouMessageSubject`,
240 countedAtt: battlePay,
241 attVisualOnly: true,
242 icon:
243 factionSidedWith == "FC_GRINEER"
244 ? "/Lotus/Interface/Icons/Npcs/EliteRifleLancerAvatar.png" // Source: https://www.reddit.com/r/Warframe/comments/1aj4usx/battle_pay_worth_10_plat/, https://www.youtube.com/watch?v=XhNZ6ai6BOY
245 : "/Lotus/Interface/Icons/Npcs/CrewmanNormal.png", // My best source for this is https://www.youtube.com/watch?v=rxrCCFm73XE around 1:37
246 // TOVERIFY: highPriority?
247 endDate: new Date(Date.now() + 86400_000) // TOVERIFY: This type of inbox message seems to automatically delete itself. We'll just delete it after 24 hours, but it's not clear if this is correct.
248 }
249 ]);
260 250 }
261 251 logger.debug(`removing QualifyingInvasions entry for completed invasion: ${qi.invasionId.toString()}`);
262 252 inventory.QualifyingInvasions.splice(i, 1);
Modified src/models/inventoryModels/inventoryModel.ts +6 -0
@@ -1909,6 +1909,10 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
1909 1909 //Grustag three
1910 1910 DeathSquadable: Boolean,
1911 1911
1912 // Server-only tracking fields for when to give zanuka or G3 death marks
1913 HarvesterPoints: Number,
1914 DeathSquadPoints: Number,
1915
1912 1916 EndlessXP: { type: [endlessXpProgressSchema], default: undefined },
1913 1917
1914 1918 DescentRewards: { type: [descentCategoryRewardSchema], default: undefined },
@@ -1952,6 +1956,8 @@ inventorySchema.set("toJSON", {
1952 1956 delete returnedObject.__v;
1953 1957 delete returnedObject.accountOwnerId;
1954 1958 delete returnedObject.MissionRelicRewards;
1959 delete returnedObject.HarvesterPoints;
1960 delete returnedObject.DeathSquadPoints;
1955 1961
1956 1962 const inventoryDatabase = returnedObject as Partial<IInventoryDatabase>;
1957 1963 const inventoryResponse = returnedObject as IInventoryClient;
Added src/services/invasionService.ts +29 -0
@@ -0,0 +1,29 @@
1 interface IDeathSquadInfo {
2 booleanKey: "DeathSquadable" | "Harvestable";
3 numberKey: "DeathSquadPoints" | "HarvesterPoints";
4 inboxSender: string;
5 inboxIcon: string;
6 inboxTitle: string;
7 inboxMessage: string;
8 inboxMessageRepeat: string;
9 }
10
11 export const grineerDeathSquadInfo: IDeathSquadInfo = {
12 booleanKey: "DeathSquadable",
13 numberKey: "DeathSquadPoints",
14 inboxSender: "/Lotus/Language/Bosses/BossCouncilorVayHek",
15 inboxIcon: "/Lotus/Interface/Icons/Npcs/VayHekPortrait.png",
16 inboxTitle: "/Lotus/Language/G1Quests/DeathSquadTitle",
17 inboxMessage: "/Lotus/Language/G1Quests/DeathSquadMessage",
18 inboxMessageRepeat: "/Lotus/Language/G1Quests/DeathSquadMessageRepeat"
19 };
20
21 export const corpusDeathSquadInfo: IDeathSquadInfo = {
22 booleanKey: "Harvestable",
23 numberKey: "HarvesterPoints",
24 inboxSender: "/Lotus/Language/Bosses/BossAladV",
25 inboxIcon: "/Lotus/Interface/Icons/Npcs/AladVPortrait_d.png",
26 inboxTitle: "/Lotus/Language/G1Quests/HarvesterTitle",
27 inboxMessage: "/Lotus/Language/G1Quests/HarvesterkMessage",
28 inboxMessageRepeat: "/Lotus/Language/G1Quests/HarvesterkMessageRepeat"
29 };
Modified src/services/missionInventoryUpdateService.ts +26 -0
@@ -73,6 +73,7 @@ import {
73 73 } from "../helpers/nemesisHelpers.ts";
74 74 import { Loadout } from "../models/inventoryModels/loadoutModel.ts";
75 75 import {
76 getInvasionByOid,
76 77 getLiteSortie,
77 78 getSortie,
78 79 getWorldState,
@@ -92,6 +93,7 @@ import { Guild } from "../models/guildModel.ts";
92 93 import { handleGuildGoalProgress } from "./guildService.ts";
93 94 import { importLoadOutConfig } from "./importService.ts";
94 95 import gameToBuildVersion from "../constants/gameToBuildVersion.ts";
96 import { corpusDeathSquadInfo, grineerDeathSquadInfo } from "./invasionService.ts";
95 97
96 98 const getRotations = (rewardInfo: IRewardInfo, tierOverride?: number): number[] => {
97 99 // For Spy missions, e.g. 3 vaults cracked = A, B, C
@@ -826,6 +828,30 @@ export const addMissionInventoryUpdates = async (
826 828 DefenderScore: clientProgress.DefenderScore
827 829 });
828 830 }
831 const invasion = getInvasionByOid(clientProgress._id.$oid)!;
832 const factionSidedWith = clientProgress.AttackerScore ? invasion.Faction : invasion.DefenderFaction;
833 if (invasion.Faction != "FC_INFESTATION") {
834 const info = factionSidedWith != "FC_GRINEER" ? grineerDeathSquadInfo : corpusDeathSquadInfo;
835 if (!inventory[info.booleanKey]) {
836 const numberKey = info.numberKey;
837 inventory[numberKey] ??= 0;
838 inventory[numberKey] += clientProgress.AttackerScore + clientProgress.DefenderScore;
839 if (inventory[numberKey] >= 5) {
840 inventory[numberKey] = 0;
841 const isRepeatMark = inventory[info.booleanKey] !== undefined;
842 inventory[info.booleanKey] = true;
843 await createMessage(inventory.accountOwnerId, [
844 {
845 sndr: info.inboxSender,
846 msg: isRepeatMark ? info.inboxMessageRepeat : info.inboxMessage,
847 sub: info.inboxTitle,
848 icon: info.inboxIcon,
849 highPriority: true
850 }
851 ]);
852 }
853 }
854 }
829 855 }
830 856 break;
831 857 }
Modified src/types/inventoryTypes/inventoryTypes.ts +4 -2
@@ -454,8 +454,10 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
454 454 LibraryActiveDailyTaskInfo?: ILibraryDailyTaskInfo;
455 455 HasResetAccount: boolean;
456 456 PendingCoupon?: IPendingCouponClient;
457 Harvestable: boolean;
458 DeathSquadable: boolean;
457 Harvestable?: boolean;
458 DeathSquadable?: boolean;
459 HarvesterPoints?: number;
460 DeathSquadPoints?: number;
459 461 EndlessXP?: IEndlessXpProgressClient[];
460 462 DescentRewards?: IDescentCategoryRewardClient[];
461 463 DialogueHistory?: IDialogueHistoryClient;