forked from OpenWF/SpaceNinjaServer
feat: classic lich vanquish inbox mesage (#2074)
Closes #1897 Reviewed-on: OpenWF/SpaceNinjaServer#2074 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
daf721f7cd
commit
52c8802d57
@ -7,7 +7,7 @@ import {
|
||||
getNemesisPasscodeModTypes,
|
||||
getWeaponsForManifest,
|
||||
IKnifeResponse,
|
||||
showdownNodes
|
||||
nemesisFactionInfos
|
||||
} from "@/src/helpers/nemesisHelpers";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
||||
@ -223,7 +223,7 @@ export const nemesisController: RequestHandler = async (req, res) => {
|
||||
|
||||
inventory.Nemesis!.InfNodes = [
|
||||
{
|
||||
Node: showdownNodes[inventory.Nemesis!.Faction],
|
||||
Node: nemesisFactionInfos[inventory.Nemesis!.Faction].showdownNode,
|
||||
Influence: 1
|
||||
}
|
||||
];
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ExportRegions, ExportWarframes } from "warframe-public-export-plus";
|
||||
import { IInfNode, ITypeCount, TNemesisFaction } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IInfNode, TNemesisFaction } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { getRewardAtPercentage, SRng } from "@/src/services/rngService";
|
||||
import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
|
||||
import { logger } from "../utils/logger";
|
||||
@ -7,13 +7,51 @@ import { IOid } from "../types/commonTypes";
|
||||
import { Types } from "mongoose";
|
||||
import { addMods, generateRewardSeed } from "../services/inventoryService";
|
||||
import { isArchwingMission } from "../services/worldStateService";
|
||||
import { fromStoreItem, toStoreItem } from "../services/itemDataService";
|
||||
import { createMessage } from "../services/inboxService";
|
||||
import { version_compare } from "./inventoryHelpers";
|
||||
|
||||
export interface INemesisFactionInfo {
|
||||
systemIndexes: number[];
|
||||
showdownNode: string;
|
||||
ephemeraChance: number;
|
||||
firstKillReward: string;
|
||||
firstConvertReward: string;
|
||||
messageTitle: string;
|
||||
messageBody: string;
|
||||
}
|
||||
|
||||
export const nemesisFactionInfos: Record<TNemesisFaction, INemesisFactionInfo> = {
|
||||
FC_GRINEER: {
|
||||
systemIndexes: [2, 3, 9, 11, 18],
|
||||
showdownNode: "CrewBattleNode557",
|
||||
ephemeraChance: 0.05,
|
||||
firstKillReward: "/Lotus/StoreItems/Upgrades/Skins/Clan/LichKillerBadgeItem",
|
||||
firstConvertReward: "/Lotus/StoreItems/Upgrades/Skins/Sigils/KuvaLichSigil",
|
||||
messageTitle: "/Lotus/Language/Inbox/VanquishKuvaMsgTitle",
|
||||
messageBody: "/Lotus/Language/Inbox/VanquishLichMsgBody"
|
||||
},
|
||||
FC_CORPUS: {
|
||||
systemIndexes: [1, 15, 4, 7, 8],
|
||||
showdownNode: "CrewBattleNode558",
|
||||
ephemeraChance: 0.2,
|
||||
firstKillReward: "/Lotus/StoreItems/Upgrades/Skins/Clan/CorpusLichBadgeItem",
|
||||
firstConvertReward: "/Lotus/StoreItems/Upgrades/Skins/Sigils/CorpusLichSigil",
|
||||
messageTitle: "/Lotus/Language/Inbox/VanquishLawyerMsgTitle",
|
||||
messageBody: "/Lotus/Language/Inbox/VanquishLichMsgBody"
|
||||
},
|
||||
FC_INFESTATION: {
|
||||
systemIndexes: [23],
|
||||
showdownNode: "CrewBattleNode559",
|
||||
ephemeraChance: 0,
|
||||
firstKillReward: "/Lotus/StoreItems/Upgrades/Skins/Sigils/InfLichVanquishedSigil",
|
||||
firstConvertReward: "/Lotus/StoreItems/Upgrades/Skins/Sigils/InfLichConvertedSigil",
|
||||
messageTitle: "/Lotus/Language/Inbox/VanquishBandMsgTitle",
|
||||
messageBody: "/Lotus/Language/Inbox/VanquishBandMsgBody"
|
||||
}
|
||||
};
|
||||
|
||||
export const getInfNodes = (faction: TNemesisFaction, rank: number): IInfNode[] => {
|
||||
const infNodes = [];
|
||||
const systemIndex = systemIndexes[faction][rank];
|
||||
const systemIndex = nemesisFactionInfos[faction].systemIndexes[rank];
|
||||
for (const [key, value] of Object.entries(ExportRegions)) {
|
||||
if (
|
||||
value.systemIndex === systemIndex &&
|
||||
@ -35,24 +73,6 @@ export const getInfNodes = (faction: TNemesisFaction, rank: number): IInfNode[]
|
||||
return infNodes;
|
||||
};
|
||||
|
||||
const systemIndexes: Record<TNemesisFaction, number[]> = {
|
||||
FC_GRINEER: [2, 3, 9, 11, 18],
|
||||
FC_CORPUS: [1, 15, 4, 7, 8],
|
||||
FC_INFESTATION: [23]
|
||||
};
|
||||
|
||||
export const showdownNodes: Record<TNemesisFaction, string> = {
|
||||
FC_GRINEER: "CrewBattleNode557",
|
||||
FC_CORPUS: "CrewBattleNode558",
|
||||
FC_INFESTATION: "CrewBattleNode559"
|
||||
};
|
||||
|
||||
const ephemeraProbabilities: Record<TNemesisFaction, number> = {
|
||||
FC_GRINEER: 0.05,
|
||||
FC_CORPUS: 0.2,
|
||||
FC_INFESTATION: 0
|
||||
};
|
||||
|
||||
type TInnateDamageTag =
|
||||
| "InnateElectricityDamage"
|
||||
| "InnateHeatDamage"
|
||||
@ -311,11 +331,17 @@ export const getInnateDamageTag = (KillingSuit: string): TInnateDamageTag => {
|
||||
return ExportWarframes[KillingSuit].nemesisUpgradeTag!;
|
||||
};
|
||||
|
||||
const petHeads = [
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC"
|
||||
] as const;
|
||||
|
||||
export interface INemesisProfile {
|
||||
innateDamageTag: TInnateDamageTag;
|
||||
innateDamageValue: number;
|
||||
ephemera?: string;
|
||||
petHead?: string;
|
||||
petHead?: (typeof petHeads)[number];
|
||||
petBody?: string;
|
||||
petLegs?: string;
|
||||
petTail?: string;
|
||||
@ -337,16 +363,12 @@ export const generateNemesisProfile = (
|
||||
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") {
|
||||
if (rng.randomFloat() <= nemesisFactionInfos[Faction].ephemeraChance && 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.petHead = rng.randomElement(petHeads)!;
|
||||
profile.petBody = rng.randomElement([
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyA",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartBodyB",
|
||||
@ -422,52 +444,3 @@ export const getInfestedLichItemRewards = (fp: bigint): string[] => {
|
||||
const rotBReward = getRewardAtPercentage(infestedLichRotB, rng.randomFloat())!.type;
|
||||
return [rotAReward, rotBReward];
|
||||
};
|
||||
|
||||
export const sendCodaFinishedMessage = async (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
fp: bigint = generateRewardSeed(),
|
||||
name: string = "ZEKE_BEATWOMAN_TM.1999",
|
||||
killed: boolean = true
|
||||
): Promise<void> => {
|
||||
const att: string[] = [];
|
||||
|
||||
// First vanquish/convert gives a sigil
|
||||
const sigil = killed
|
||||
? "/Lotus/Upgrades/Skins/Sigils/InfLichVanquishedSigil"
|
||||
: "/Lotus/Upgrades/Skins/Sigils/InfLichConvertedSigil";
|
||||
if (!inventory.WeaponSkins.find(x => x.ItemType == sigil)) {
|
||||
att.push(toStoreItem(sigil));
|
||||
}
|
||||
|
||||
const [rotAReward, rotBReward] = getInfestedLichItemRewards(fp);
|
||||
att.push(fromStoreItem(rotAReward));
|
||||
att.push(fromStoreItem(rotBReward));
|
||||
|
||||
let countedAtt: ITypeCount[] | undefined;
|
||||
if (killed) {
|
||||
countedAtt = [
|
||||
{
|
||||
ItemType: "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
|
||||
ItemCount: getKillTokenRewardCount(fp)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
await createMessage(inventory.accountOwnerId, [
|
||||
{
|
||||
sndr: "/Lotus/Language/Bosses/Ordis",
|
||||
msg: "/Lotus/Language/Inbox/VanquishBandMsgBody",
|
||||
arg: [
|
||||
{
|
||||
Key: "LICH_NAME",
|
||||
Tag: name
|
||||
}
|
||||
],
|
||||
att: att,
|
||||
countedAtt: countedAtt,
|
||||
sub: "/Lotus/Language/Inbox/VanquishBandMsgTitle",
|
||||
icon: "/Lotus/Interface/Icons/Npcs/Ordis.png",
|
||||
highPriority: true
|
||||
}
|
||||
]);
|
||||
};
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
import { IMissionInventoryUpdateRequest, IRewardInfo } from "../types/requestTypes";
|
||||
import { logger } from "@/src/utils/logger";
|
||||
import { IRngResult, SRng, getRandomElement, getRandomReward } from "@/src/services/rngService";
|
||||
import { equipmentKeys, IMission, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { equipmentKeys, IMission, ITypeCount, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import {
|
||||
addBooster,
|
||||
addChallenges,
|
||||
@ -44,7 +44,7 @@ import {
|
||||
import { updateQuestKey } from "@/src/services/questService";
|
||||
import { Types } from "mongoose";
|
||||
import { IAffiliationMods, IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||
import { getLevelKeyRewards, toStoreItem } from "@/src/services/itemDataService";
|
||||
import { fromStoreItem, getLevelKeyRewards, toStoreItem } from "@/src/services/itemDataService";
|
||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { getEntriesUnsafe } from "@/src/utils/ts-utils";
|
||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||
@ -58,10 +58,12 @@ import kuriaMessage100 from "@/static/fixed_responses/kuriaMessages/oneHundredPe
|
||||
import conservationAnimals from "@/static/fixed_responses/conservationAnimals.json";
|
||||
import {
|
||||
generateNemesisProfile,
|
||||
getInfestedLichItemRewards,
|
||||
getInfNodes,
|
||||
getKillTokenRewardCount,
|
||||
getNemesisPasscode,
|
||||
getWeaponsForManifest,
|
||||
sendCodaFinishedMessage
|
||||
nemesisFactionInfos
|
||||
} from "@/src/helpers/nemesisHelpers";
|
||||
import { Loadout } from "../models/inventoryModels/loadoutModel";
|
||||
import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
|
||||
@ -665,6 +667,9 @@ export const addMissionInventoryUpdates = async (
|
||||
inventory.Nemesis.Faction,
|
||||
inventory.Nemesis.KillingSuit
|
||||
);
|
||||
const nemesisFactionInfo = nemesisFactionInfos[inventory.Nemesis.Faction];
|
||||
const att: string[] = [];
|
||||
let countedAtt: ITypeCount[] | undefined;
|
||||
|
||||
if (value.killed) {
|
||||
if (
|
||||
@ -675,45 +680,78 @@ export const addMissionInventoryUpdates = async (
|
||||
inventory.Nemesis.WeaponIdx
|
||||
];
|
||||
giveNemesisWeaponRecipe(inventory, weaponType, value.nemesisName, value.weaponLoc, profile);
|
||||
att.push(weaponType);
|
||||
}
|
||||
if (value.petLoc) {
|
||||
//if (value.petLoc) {
|
||||
if (profile.petHead) {
|
||||
giveNemesisPetRecipe(inventory, value.nemesisName, profile);
|
||||
att.push(
|
||||
{
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA":
|
||||
"/Lotus/Types/Recipes/ZanukaPet/ZanukaPetCompleteHeadABlueprint",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB":
|
||||
"/Lotus/Types/Recipes/ZanukaPet/ZanukaPetCompleteHeadBBlueprint",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC":
|
||||
"/Lotus/Types/Recipes/ZanukaPet/ZanukaPetCompleteHeadCBlueprint"
|
||||
}[profile.petHead]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// "Players will receive a Lich's Ephemera regardless of whether they Vanquish or Convert them."
|
||||
if (profile.ephemera) {
|
||||
addSkin(inventory, profile.ephemera);
|
||||
att.push(profile.ephemera);
|
||||
}
|
||||
|
||||
switch (inventory.Nemesis.Faction) {
|
||||
case "FC_GRINEER":
|
||||
addSkin(
|
||||
inventory,
|
||||
value.killed
|
||||
? "/Lotus/Upgrades/Skins/Clan/LichKillerBadgeItem"
|
||||
: "/Lotus/Upgrades/Skins/Sigils/KuvaLichSigil"
|
||||
);
|
||||
break;
|
||||
const skinRewardStoreItem = value.killed
|
||||
? nemesisFactionInfo.firstKillReward
|
||||
: nemesisFactionInfo.firstConvertReward;
|
||||
if (Object.keys(addSkin(inventory, fromStoreItem(skinRewardStoreItem))).length != 0) {
|
||||
att.push(skinRewardStoreItem);
|
||||
}
|
||||
|
||||
case "FC_CORPUS":
|
||||
addSkin(
|
||||
inventory,
|
||||
value.killed
|
||||
? "/Lotus/Upgrades/Skins/Clan/CorpusLichBadgeItem"
|
||||
: "/Lotus/Upgrades/Skins/Sigils/CorpusLichSigil"
|
||||
);
|
||||
break;
|
||||
if (inventory.Nemesis.Faction == "FC_INFESTATION") {
|
||||
const [rotARewardStoreItem, rotBRewardStoreItem] = getInfestedLichItemRewards(
|
||||
inventory.Nemesis.fp
|
||||
);
|
||||
const rotAReward = fromStoreItem(rotARewardStoreItem);
|
||||
const rotBReward = fromStoreItem(rotBRewardStoreItem);
|
||||
await addItem(inventory, rotAReward);
|
||||
await addItem(inventory, rotBReward);
|
||||
att.push(rotAReward);
|
||||
att.push(rotBReward);
|
||||
|
||||
case "FC_INFESTATION":
|
||||
// TOVERIFY: Is the inbox message also sent when converting a lich? If not, how are the rewards given?
|
||||
await sendCodaFinishedMessage(
|
||||
inventory,
|
||||
inventory.Nemesis.fp,
|
||||
value.nemesisName,
|
||||
value.killed
|
||||
);
|
||||
break;
|
||||
if (value.killed) {
|
||||
countedAtt = [
|
||||
{
|
||||
ItemType: "/Lotus/Types/Items/MiscItems/CodaWeaponBucks",
|
||||
ItemCount: getKillTokenRewardCount(inventory.Nemesis.fp)
|
||||
}
|
||||
];
|
||||
addMiscItems(inventory, countedAtt);
|
||||
}
|
||||
}
|
||||
|
||||
if (value.killed) {
|
||||
await createMessage(inventory.accountOwnerId, [
|
||||
{
|
||||
sndr: "/Lotus/Language/Bosses/Ordis",
|
||||
msg: nemesisFactionInfo.messageBody,
|
||||
arg: [
|
||||
{
|
||||
Key: "LICH_NAME",
|
||||
Tag: value.nemesisName
|
||||
}
|
||||
],
|
||||
att: att,
|
||||
countedAtt: countedAtt,
|
||||
attVisualOnly: true,
|
||||
sub: nemesisFactionInfo.messageTitle,
|
||||
icon: "/Lotus/Interface/Icons/Npcs/Ordis.png",
|
||||
highPriority: true
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
inventory.Nemesis = undefined;
|
||||
|
Loading…
x
Reference in New Issue
Block a user