forked from OpenWF/SpaceNinjaServer
feat: classic lich ephemera reward (#2067)
Reviewed-on: OpenWF/SpaceNinjaServer#2067 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
parent
2ce5cc4562
commit
8fb676c906
@ -47,6 +47,42 @@ export const showdownNodes: Record<TNemesisFaction, string> = {
|
||||
FC_INFESTATION: "CrewBattleNode559"
|
||||
};
|
||||
|
||||
const ephemeraProbabilities: Record<TNemesisFaction, number> = {
|
||||
FC_GRINEER: 0.05,
|
||||
FC_CORPUS: 0.2,
|
||||
FC_INFESTATION: 0
|
||||
};
|
||||
|
||||
type TInnateDamageTag =
|
||||
| "InnateElectricityDamage"
|
||||
| "InnateHeatDamage"
|
||||
| "InnateFreezeDamage"
|
||||
| "InnateToxinDamage"
|
||||
| "InnateMagDamage"
|
||||
| "InnateRadDamage"
|
||||
| "InnateImpactDamage";
|
||||
|
||||
const ephmeraTypes: Record<"FC_GRINEER" | "FC_CORPUS", Record<TInnateDamageTag, string>> = {
|
||||
FC_GRINEER: {
|
||||
InnateElectricityDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaLightningEphemera",
|
||||
InnateHeatDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaFireEphemera",
|
||||
InnateFreezeDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaIceEphemera",
|
||||
InnateToxinDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaToxinEphemera",
|
||||
InnateMagDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaMagneticEphemera",
|
||||
InnateRadDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaTricksterEphemera",
|
||||
InnateImpactDamage: "/Lotus/Upgrades/Skins/Effects/Kuva/KuvaImpactEphemera"
|
||||
},
|
||||
FC_CORPUS: {
|
||||
InnateElectricityDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraA",
|
||||
InnateHeatDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraB",
|
||||
InnateFreezeDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraC",
|
||||
InnateToxinDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraD",
|
||||
InnateMagDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraE",
|
||||
InnateRadDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraF",
|
||||
InnateImpactDamage: "/Lotus/Upgrades/Skins/Effects/CorpusLichEphemeraG"
|
||||
}
|
||||
};
|
||||
|
||||
// Get a parazon 'passcode' based on the nemesis fingerprint so it's always the same for the same nemesis.
|
||||
export const getNemesisPasscode = (nemesis: { fp: bigint; Faction: TNemesisFaction }): number[] => {
|
||||
const rng = new SRng(nemesis.fp);
|
||||
@ -271,21 +307,25 @@ export const isNemesisCompatibleWithVersion = (
|
||||
return true;
|
||||
};
|
||||
|
||||
export const getInnateDamageTag = (
|
||||
KillingSuit: string
|
||||
):
|
||||
| "InnateElectricityDamage"
|
||||
| "InnateFreezeDamage"
|
||||
| "InnateHeatDamage"
|
||||
| "InnateImpactDamage"
|
||||
| "InnateMagDamage"
|
||||
| "InnateRadDamage"
|
||||
| "InnateToxinDamage" => {
|
||||
export const getInnateDamageTag = (KillingSuit: string): TInnateDamageTag => {
|
||||
return ExportWarframes[KillingSuit].nemesisUpgradeTag!;
|
||||
};
|
||||
|
||||
// TODO: For -1399275245665749231n, the value should be 75306944, but we're off by 59 with 75307003.
|
||||
export const getInnateDamageValue = (fp: bigint): number => {
|
||||
export interface INemesisProfile {
|
||||
innateDamageTag: TInnateDamageTag;
|
||||
innateDamageValue: number;
|
||||
ephemera?: string;
|
||||
petHead?: string;
|
||||
petBody?: string;
|
||||
petLegs?: string;
|
||||
petTail?: string;
|
||||
}
|
||||
|
||||
export const generateNemesisProfile = (
|
||||
fp: bigint = generateRewardSeed(),
|
||||
Faction: TNemesisFaction = "FC_CORPUS",
|
||||
killingSuit: string = "/Lotus/Powersuits/Ember/Ember"
|
||||
): INemesisProfile => {
|
||||
const rng = new SRng(fp);
|
||||
rng.randomFloat(); // used for the weapon index
|
||||
const WeaponUpgradeValueAttenuationExponent = 2.25;
|
||||
@ -293,7 +333,37 @@ export const getInnateDamageValue = (fp: bigint): number => {
|
||||
if (value >= 0.941428) {
|
||||
value = 1;
|
||||
}
|
||||
return Math.trunc(value * 0x40000000);
|
||||
const profile: INemesisProfile = {
|
||||
innateDamageTag: getInnateDamageTag(killingSuit),
|
||||
innateDamageValue: Math.trunc(value * 0x40000000) // TODO: For -1399275245665749231n, the value should be 75306944, but we're off by 59 with 75307003.
|
||||
};
|
||||
if (rng.randomFloat() <= ephemeraProbabilities[Faction] && Faction != "FC_INFESTATION") {
|
||||
profile.ephemera = ephmeraTypes[Faction][profile.innateDamageTag];
|
||||
}
|
||||
rng.randomFloat(); // something related to sentinel agent maybe
|
||||
if (Faction == "FC_CORPUS") {
|
||||
profile.petHead = rng.randomElement([
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC"
|
||||
])!;
|
||||
profile.petBody = rng.randomElement([
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyA",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyB",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyC"
|
||||
])!;
|
||||
profile.petLegs = rng.randomElement([
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsA",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsB",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsC"
|
||||
])!;
|
||||
profile.petTail = rng.randomElement([
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailA",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailB",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailC"
|
||||
])!;
|
||||
}
|
||||
return profile;
|
||||
};
|
||||
|
||||
export const getKillTokenRewardCount = (fp: bigint): number => {
|
||||
|
@ -84,7 +84,7 @@ import { getRandomElement, getRandomInt, getRandomWeightedReward, SRng } from ".
|
||||
import { createMessage } from "./inboxService";
|
||||
import { getMaxStanding } from "@/src/helpers/syndicateStandingHelper";
|
||||
import { getWorldState } from "./worldStateService";
|
||||
import { getInnateDamageTag, getInnateDamageValue } from "../helpers/nemesisHelpers";
|
||||
import { generateNemesisProfile, INemesisProfile } from "../helpers/nemesisHelpers";
|
||||
|
||||
export const createInventory = async (
|
||||
accountOwnerId: Types.ObjectId,
|
||||
@ -1969,8 +1969,7 @@ export const giveNemesisWeaponRecipe = (
|
||||
weaponType: string,
|
||||
nemesisName: string = "AGOR ROK",
|
||||
weaponLoc?: string,
|
||||
KillingSuit: string = "/Lotus/Powersuits/Ember/Ember",
|
||||
fp: bigint = generateRewardSeed()
|
||||
profile: INemesisProfile = generateNemesisProfile()
|
||||
): void => {
|
||||
if (!weaponLoc) {
|
||||
weaponLoc = ExportWeapons[weaponType].name;
|
||||
@ -1991,8 +1990,8 @@ export const giveNemesisWeaponRecipe = (
|
||||
compat: weaponType,
|
||||
buffs: [
|
||||
{
|
||||
Tag: getInnateDamageTag(KillingSuit),
|
||||
Value: getInnateDamageValue(fp)
|
||||
Tag: profile.innateDamageTag,
|
||||
Value: profile.innateDamageValue
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -2001,27 +2000,15 @@ export const giveNemesisWeaponRecipe = (
|
||||
});
|
||||
};
|
||||
|
||||
export const giveNemesisPetRecipe = (inventory: TInventoryDatabaseDocument, nemesisName: string = "AGOR ROK"): void => {
|
||||
const head = getRandomElement([
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC"
|
||||
])!;
|
||||
const body = getRandomElement([
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyA",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyB",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyC"
|
||||
])!;
|
||||
const legs = getRandomElement([
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsA",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsB",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartLegsC"
|
||||
])!;
|
||||
const tail = getRandomElement([
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailA",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailB",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartTailC"
|
||||
])!;
|
||||
export const giveNemesisPetRecipe = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
nemesisName: string = "AGOR ROK",
|
||||
profile: INemesisProfile = generateNemesisProfile()
|
||||
): void => {
|
||||
const head = profile.petHead!;
|
||||
const body = profile.petBody!;
|
||||
const legs = profile.petLegs!;
|
||||
const tail = profile.petTail!;
|
||||
const recipeType = Object.entries(ExportRecipes).find(arr => arr[1].resultType == head)![0];
|
||||
addRecipes(inventory, [
|
||||
{
|
||||
|
@ -57,6 +57,7 @@ import kuriaMessage75 from "@/static/fixed_responses/kuriaMessages/seventyFivePe
|
||||
import kuriaMessage100 from "@/static/fixed_responses/kuriaMessages/oneHundredPercent.json";
|
||||
import conservationAnimals from "@/static/fixed_responses/conservationAnimals.json";
|
||||
import {
|
||||
generateNemesisProfile,
|
||||
getInfNodes,
|
||||
getNemesisPasscode,
|
||||
getWeaponsForManifest,
|
||||
@ -659,6 +660,12 @@ export const addMissionInventoryUpdates = async (
|
||||
k: value.killed
|
||||
});
|
||||
|
||||
const profile = generateNemesisProfile(
|
||||
inventory.Nemesis.fp,
|
||||
inventory.Nemesis.Faction,
|
||||
inventory.Nemesis.KillingSuit
|
||||
);
|
||||
|
||||
if (value.killed) {
|
||||
if (
|
||||
value.weaponLoc &&
|
||||
@ -667,20 +674,18 @@ export const addMissionInventoryUpdates = async (
|
||||
const weaponType = getWeaponsForManifest(inventory.Nemesis.manifest)[
|
||||
inventory.Nemesis.WeaponIdx
|
||||
];
|
||||
giveNemesisWeaponRecipe(
|
||||
inventory,
|
||||
weaponType,
|
||||
value.nemesisName,
|
||||
value.weaponLoc,
|
||||
inventory.Nemesis.KillingSuit,
|
||||
inventory.Nemesis.fp
|
||||
);
|
||||
giveNemesisWeaponRecipe(inventory, weaponType, value.nemesisName, value.weaponLoc, profile);
|
||||
}
|
||||
if (value.petLoc) {
|
||||
giveNemesisPetRecipe(inventory);
|
||||
giveNemesisPetRecipe(inventory, value.nemesisName, profile);
|
||||
}
|
||||
}
|
||||
|
||||
// "Players will receive a Lich's Ephemera regardless of whether they Vanquish or Convert them."
|
||||
if (profile.ephemera) {
|
||||
addSkin(inventory, profile.ephemera);
|
||||
}
|
||||
|
||||
// TOVERIFY: Is the inbox message also sent when converting a lich? If not, how are the rewards given?
|
||||
if (inventory.Nemesis.Faction == "FC_INFESTATION") {
|
||||
await sendCodaFinishedMessage(inventory, inventory.Nemesis.fp, value.nemesisName, value.killed);
|
||||
|
Loading…
x
Reference in New Issue
Block a user