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

SpaceNinjaServer

A simple server for a small space ninja game

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

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
Sainan <63328889+Sainan@users.noreply.github.com>
提交于

代码差异

3 个文件 +110 -48
Modified src/helpers/nemesisHelpers.ts +83 -13
@@ -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 => {
Modified src/services/inventoryService.ts +13 -26
@@ -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 {
Modified src/services/missionInventoryUpdateService.ts +14 -9
@@ -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);