返回提交历史
Modified
src/helpers/nemesisHelpers.ts
+83
-13
Modified
src/services/inventoryService.ts
+13
-26
Modified
src/services/missionInventoryUpdateService.ts
+14
-9
XFEstudio/SpaceNinjaServer
feat: classic lich ephemera reward (#2067)
Reviewed-on: https://onlyg.it/OpenWF/SpaceNinjaServer/pulls/2067 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
8fb676c9
代码差异
3 个文件
+110
-48
@@ -47,6 +47,42 @@ export const showdownNodes: Record<TNemesisFaction, string> = {
47
47
FC_INFESTATION: "CrewBattleNode559"
48
48
};
49
49
50
const ephemeraProbabilities: Record<TNemesisFaction, number> = {
51
FC_GRINEER: 0.05,
52
FC_CORPUS: 0.2,
53
FC_INFESTATION: 0
54
};
55
56
type TInnateDamageTag =
57
| "InnateElectricityDamage"
58
| "InnateHeatDamage"
59
| "InnateFreezeDamage"
60
| "InnateToxinDamage"
61
| "InnateMagDamage"
62
| "InnateRadDamage"
63
| "InnateImpactDamage";
64
65
const ephmeraTypes: Record<"FC_GRINEER" | "FC_CORPUS", Record<TInnateDamageTag, string>> = {
66
FC_GRINEER: {
67
InnateElectricityDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaLightningEphemera",
68
InnateHeatDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaFireEphemera",
69
InnateFreezeDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaIceEphemera",
70
InnateToxinDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaToxinEphemera",
71
InnateMagDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaMagneticEphemera",
72
InnateRadDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaTricksterEphemera",
73
InnateImpactDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaImpactEphemera"
74
},
75
FC_CORPUS: {
76
InnateElectricityDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraA",
77
InnateHeatDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraB",
78
InnateFreezeDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraC",
79
InnateToxinDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraD",
80
InnateMagDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraE",
81
InnateRadDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraF",
82
InnateImpactDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraG"
83
}
84
};
85
50
86
// Get a parazon 'passcode' based on the nemesis fingerprint so it's always the same for the same nemesis.
51
87
export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: TNemesisFaction }): number[] => {
52
88
const rng = new SRng(nemesis.fp);
@@ -271,21 +307,25 @@ export const isNemesisCompatibleWithVersion = (
271
307
return true;
272
308
};
273
309
274
export const getInnateDamageTag = (
275
KillingSuit: string
276
):
277
| "InnateElectricityDamage"
278
| "InnateFreezeDamage"
279
| "InnateHeatDamage"
280
| "InnateImpactDamage"
281
| "InnateMagDamage"
282
| "InnateRadDamage"
283
| "InnateToxinDamage" => {
310
export const getInnateDamageTag = (KillingSuit: string): TInnateDamageTag => {
284
311
return ExportWarframes[KillingSuit].nemesisUpgradeTag!;
285
312
};
286
313
287
// TODO: For -1399275245665749231n, the value should be 75306944, but we're off by 59 with 75307003.
288
export const getInnateDamageValue = (fp: bigint): number => {
314
export interface INemesisProfile {
315
innateDamageTag: TInnateDamageTag;
316
innateDamageValue: number;
317
ephemera?: string;
318
petHead?: string;
319
petBody?: string;
320
petLegs?: string;
321
petTail?: string;
322
}
323
324
export const generateNemesisProfile = (
325
fp: bigint = generateRewardSeed(),
326
Faction: TNemesisFaction = "FC_CORPUS",
327
killingSuit: string = "/Lotus/Powersuits/Ember/Ember"
328
): INemesisProfile => {
289
329
const rng = new SRng(fp);
290
330
rng.randomFloat(); // used for the weapon index
291
331
const WeaponUpgradeValueAttenuationExponent = 2.25;
@@ -293,7 +333,37 @@ export const getInnateDamageValue = (fp: bigint): number => {
293
333
if (value >= 0.941428) {
294
334
value = 1;
295
335
}
296
return Math.trunc(value * 0x40000000);
336
const profile: INemesisProfile = {
337
innateDamageTag: getInnateDamageTag(killingSuit),
338
innateDamageValue: Math.trunc(value * 0x40000000) // TODO: For -1399275245665749231n, the value should be 75306944, but we're off by 59 with 75307003.
339
};
340
if (rng.randomFloat() <= ephemeraProbabilities[Faction] && Faction != "FC_INFESTATION") {
341
profile.ephemera = ephmeraTypes[Faction][profile.innateDamageTag];
342
}
343
rng.randomFloat(); // something related to sentinel agent maybe
344
if (Faction == "FC_CORPUS") {
345
profile.petHead = rng.randomElement([
346
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA",
347
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB",
348
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC"
349
])!;
350
profile.petBody = rng.randomElement([
351
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyA",
352
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyB",
353
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyC"
354
])!;
355
profile.petLegs = rng.randomElement([
356
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsA",
357
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsB",
358
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsC"
359
])!;
360
profile.petTail = rng.randomElement([
361
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailA",
362
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailB",
363
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailC"
364
])!;
365
}
366
return profile;
297
367
};
298
368
299
369
export const getKillTokenRewardCount = (fp: bigint): number => {
@@ -84,7 +84,7 @@ import { getRandomElement, getRandomInt, getRandomWeightedReward, SRng } from ".
84
84
import { createMessage } from "./inboxService";
85
85
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
86
86
import { getWorldState } from "./worldStateService";
87
import { getInnateDamageTag, getInnateDamageValue } from "../helpers/nemesisHelpers";
87
import { generateNemesisProfile, INemesisProfile } from "../helpers/nemesisHelpers";
88
88
89
89
export const createInventory = async (
90
90
accountOwnerId: Types.ObjectId,
@@ -1969,8 +1969,7 @@ export const giveNemesisWeaponRecipe = (
1969
1969
weaponType: string,
1970
1970
nemesisName: string = "AGOR ROK",
1971
1971
weaponLoc?: string,
1972
KillingSuit: string = "/Lotus/Powersuits/Ember/Ember",
1973
fp: bigint = generateRewardSeed()
1972
profile: INemesisProfile = generateNemesisProfile()
1974
1973
): void => {
1975
1974
if (!weaponLoc) {
1976
1975
weaponLoc = ExportWeapons[weaponType].name;
@@ -1991,8 +1990,8 @@ export const giveNemesisWeaponRecipe = (
1991
1990
compat: weaponType,
1992
1991
buffs: [
1993
1992
{
1994
Tag: getInnateDamageTag(KillingSuit),
1995
Value: getInnateDamageValue(fp)
1993
Tag: profile.innateDamageTag,
1994
Value: profile.innateDamageValue
1996
1995
}
1997
1996
]
1998
1997
},
@@ -2001,27 +2000,15 @@ export const giveNemesisWeaponRecipe = (
2001
2000
});
2002
2001
};
2003
2002
2004
export const giveNemesisPetRecipe = (inventory: TInventoryDatabaseDocument, nemesisName: string = "AGOR ROK"): void => {
2005
const head = getRandomElement([
2006
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA",
2007
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB",
2008
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC"
2009
])!;
2010
const body = getRandomElement([
2011
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyA",
2012
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyB",
2013
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyC"
2014
])!;
2015
const legs = getRandomElement([
2016
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsA",
2017
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsB",
2018
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsC"
2019
])!;
2020
const tail = getRandomElement([
2021
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailA",
2022
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailB",
2023
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailC"
2024
])!;
2003
export const giveNemesisPetRecipe = (
2004
inventory: TInventoryDatabaseDocument,
2005
nemesisName: string = "AGOR ROK",
2006
profile: INemesisProfile = generateNemesisProfile()
2007
): void => {
2008
const head = profile.petHead!;
2009
const body = profile.petBody!;
2010
const legs = profile.petLegs!;
2011
const tail = profile.petTail!;
2025
2012
const recipeType = Object.entries(ExportRecipes).find(arr => arr[1].resultType == head)![0];
2026
2013
addRecipes(inventory, [
2027
2014
{
@@ -57,6 +57,7 @@ import kuriaMessage75 from "@/static/fixed_responses/kuriaMessages/seventyFivePe
57
57
import kuriaMessage100 from "@/static/fixed_responses/kuriaMessages/oneHundredPercent.json";
58
58
import conservationAnimals from "@/static/fixed_responses/conservationAnimals.json";
59
59
import {
60
generateNemesisProfile,
60
61
getInfNodes,
61
62
getNemesisPasscode,
62
63
getWeaponsForManifest,
@@ -659,6 +660,12 @@ export const addMissionInventoryUpdates = async (
659
660
k: value.killed
660
661
});
661
662
663
const profile = generateNemesisProfile(
664
inventory.Nemesis.fp,
665
inventory.Nemesis.Faction,
666
inventory.Nemesis.KillingSuit
667
);
668
662
669
if (value.killed) {
663
670
if (
664
671
value.weaponLoc &&
@@ -667,20 +674,18 @@ export const addMissionInventoryUpdates = async (
667
674
const weaponType = getWeaponsForManifest(inventory.Nemesis.manifest)[
668
675
inventory.Nemesis.WeaponIdx
669
676
];
670
giveNemesisWeaponRecipe(
671
inventory,
672
weaponType,
673
value.nemesisName,
674
value.weaponLoc,
675
inventory.Nemesis.KillingSuit,
676
inventory.Nemesis.fp
677
);
677
giveNemesisWeaponRecipe(inventory, weaponType, value.nemesisName, value.weaponLoc, profile);
678
678
}
679
679
if (value.petLoc) {
680
giveNemesisPetRecipe(inventory);
680
giveNemesisPetRecipe(inventory, value.nemesisName, profile);
681
681
}
682
682
}
683
683
684
// "Players will receive a Lich's Ephemera regardless of whether they Vanquish or Convert them."
685
if (profile.ephemera) {
686
addSkin(inventory, profile.ephemera);
687
}
688
684
689
// TOVERIFY: Is the inbox message also sent when converting a lich? If not, how are the rewards given?
685
690
if (inventory.Nemesis.Faction == "FC_INFESTATION") {
686
691
await sendCodaFinishedMessage(inventory, inventory.Nemesis.fp, value.nemesisName, value.killed);