feat: handle NemesisKillConvert at missionInventoryUpdate (#1880)
Closes #1848 Reviewed-on: #1880 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
9e94083875
commit
ee1a49f5f2
@ -133,7 +133,14 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
|
||||
if (recipe.secretIngredientAction != "SIA_UNBRAND") {
|
||||
InventoryChanges = {
|
||||
...InventoryChanges,
|
||||
...(await addItem(inventory, recipe.resultType, recipe.num, false))
|
||||
...(await addItem(
|
||||
inventory,
|
||||
recipe.resultType,
|
||||
recipe.num,
|
||||
false,
|
||||
undefined,
|
||||
pendingRecipe.TargetFingerprint
|
||||
))
|
||||
};
|
||||
}
|
||||
await inventory.save();
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
encodeNemesisGuess,
|
||||
getInfNodes,
|
||||
getNemesisPasscode,
|
||||
getWeaponsForManifest,
|
||||
IKnifeResponse
|
||||
} from "@/src/helpers/nemesisHelpers";
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
@ -170,18 +171,7 @@ export const nemesisController: RequestHandler = async (req, res) => {
|
||||
|
||||
let weaponIdx = -1;
|
||||
if (body.target.Faction != "FC_INFESTATION") {
|
||||
let weapons: readonly string[];
|
||||
if (body.target.manifest == "/Lotus/Types/Game/Nemesis/KuvaLich/KuvaLichManifestVersionSix") {
|
||||
weapons = kuvaLichVersionSixWeapons;
|
||||
} else if (
|
||||
body.target.manifest == "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionFour" ||
|
||||
body.target.manifest == "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionThree"
|
||||
) {
|
||||
weapons = corpusVersionThreeWeapons;
|
||||
} else {
|
||||
throw new Error(`unknown nemesis manifest: ${body.target.manifest}`);
|
||||
}
|
||||
|
||||
const weapons = getWeaponsForManifest(body.target.manifest);
|
||||
const initialWeaponIdx = new SRng(body.target.fp).randomInt(0, weapons.length - 1);
|
||||
weaponIdx = initialWeaponIdx;
|
||||
do {
|
||||
@ -283,39 +273,3 @@ interface INemesisRequiemRequest {
|
||||
HiddenWhenHolstered: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
const kuvaLichVersionSixWeapons = [
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Drakgoon/KuvaDrakgoon",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Karak/KuvaKarak",
|
||||
"/Lotus/Weapons/Grineer/Melee/GrnKuvaLichScythe/GrnKuvaLichScytheWeapon",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Kohm/KuvaKohm",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Ogris/KuvaOgris",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Quartakk/KuvaQuartakk",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Tonkor/KuvaTonkor",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/Secondaries/Brakk/KuvaBrakk",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/Secondaries/Kraken/KuvaKraken",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/Secondaries/Seer/KuvaSeer",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/Secondaries/Stubba/KuvaStubba",
|
||||
"/Lotus/Weapons/Grineer/HeavyWeapons/GrnHeavyGrenadeLauncher",
|
||||
"/Lotus/Weapons/Grineer/LongGuns/GrnKuvaLichRifle/GrnKuvaLichRifleWeapon",
|
||||
"/Lotus/Weapons/Grineer/Bows/GrnBow/GrnBowWeapon",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Hind/KuvaHind",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/Secondaries/Nukor/KuvaNukor",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Hek/KuvaHekWeapon",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Zarr/KuvaZarr",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/HeavyWeapons/Grattler/KuvaGrattler",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Sobek/KuvaSobek"
|
||||
];
|
||||
|
||||
const corpusVersionThreeWeapons = [
|
||||
"/Lotus/Weapons/Corpus/LongGuns/CrpBriefcaseLauncher/CrpBriefcaseLauncher",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Primary/CrpBEArcaPlasmor/CrpBEArcaPlasmor",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Primary/CrpBEFluxRifle/CrpBEFluxRifle",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Primary/CrpBETetra/CrpBETetra",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Secondary/CrpBECycron/CrpBECycron",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Secondary/CrpBEDetron/CrpBEDetron",
|
||||
"/Lotus/Weapons/Corpus/Pistols/CrpIgniterPistol/CrpIgniterPistol",
|
||||
"/Lotus/Weapons/Corpus/Pistols/CrpBriefcaseAkimbo/CrpBriefcaseAkimboPistol",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Secondary/CrpBEPlinx/CrpBEPlinxWeapon",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Primary/CrpBEGlaxion/CrpBEGlaxion"
|
||||
];
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ExportRegions } from "warframe-public-export-plus";
|
||||
import { ExportRegions, ExportWarframes } from "warframe-public-export-plus";
|
||||
import { IInfNode } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { SRng } from "@/src/services/rngService";
|
||||
import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
|
||||
@ -129,3 +129,147 @@ export const consumeModCharge = (
|
||||
response.UpgradeNew.push(true);
|
||||
}
|
||||
};
|
||||
|
||||
const kuvaLichVersionSixWeapons = [
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Drakgoon/KuvaDrakgoon",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Karak/KuvaKarak",
|
||||
"/Lotus/Weapons/Grineer/Melee/GrnKuvaLichScythe/GrnKuvaLichScytheWeapon",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Kohm/KuvaKohm",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Ogris/KuvaOgris",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Quartakk/KuvaQuartakk",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Tonkor/KuvaTonkor",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/Secondaries/Brakk/KuvaBrakk",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/Secondaries/Kraken/KuvaKraken",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/Secondaries/Seer/KuvaSeer",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/Secondaries/Stubba/KuvaStubba",
|
||||
"/Lotus/Weapons/Grineer/HeavyWeapons/GrnHeavyGrenadeLauncher",
|
||||
"/Lotus/Weapons/Grineer/LongGuns/GrnKuvaLichRifle/GrnKuvaLichRifleWeapon",
|
||||
"/Lotus/Weapons/Grineer/Bows/GrnBow/GrnBowWeapon",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Hind/KuvaHind",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/Secondaries/Nukor/KuvaNukor",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Hek/KuvaHekWeapon",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Zarr/KuvaZarr",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/HeavyWeapons/Grattler/KuvaGrattler",
|
||||
"/Lotus/Weapons/Grineer/KuvaLich/LongGuns/Sobek/KuvaSobek"
|
||||
];
|
||||
|
||||
const corpusVersionThreeWeapons = [
|
||||
"/Lotus/Weapons/Corpus/LongGuns/CrpBriefcaseLauncher/CrpBriefcaseLauncher",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Primary/CrpBEArcaPlasmor/CrpBEArcaPlasmor",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Primary/CrpBEFluxRifle/CrpBEFluxRifle",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Primary/CrpBETetra/CrpBETetra",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Secondary/CrpBECycron/CrpBECycron",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Secondary/CrpBEDetron/CrpBEDetron",
|
||||
"/Lotus/Weapons/Corpus/Pistols/CrpIgniterPistol/CrpIgniterPistol",
|
||||
"/Lotus/Weapons/Corpus/Pistols/CrpBriefcaseAkimbo/CrpBriefcaseAkimboPistol",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Secondary/CrpBEPlinx/CrpBEPlinxWeapon",
|
||||
"/Lotus/Weapons/Corpus/BoardExec/Primary/CrpBEGlaxion/CrpBEGlaxion"
|
||||
];
|
||||
|
||||
export const getWeaponsForManifest = (manifest: string): readonly string[] => {
|
||||
switch (manifest) {
|
||||
case "/Lotus/Types/Game/Nemesis/KuvaLich/KuvaLichManifestVersionSix":
|
||||
return kuvaLichVersionSixWeapons;
|
||||
case "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionThree":
|
||||
case "/Lotus/Types/Enemies/Corpus/Lawyers/LawyerManifestVersionFour":
|
||||
return corpusVersionThreeWeapons;
|
||||
}
|
||||
throw new Error(`unknown nemesis manifest: ${manifest}`);
|
||||
};
|
||||
|
||||
// TODO: This sucks.
|
||||
export const getInnateDamageTag = (
|
||||
KillingSuit: string
|
||||
):
|
||||
| "InnateElectricityDamage"
|
||||
| "InnateFreezeDamage"
|
||||
| "InnateHeatDamage"
|
||||
| "InnateImpactDamage"
|
||||
| "InnateMagDamage"
|
||||
| "InnateRadDamage"
|
||||
| "InnateToxinDamage" => {
|
||||
const baseSuitType = ExportWarframes[KillingSuit].parentName;
|
||||
switch (baseSuitType) {
|
||||
case "/Lotus/Powersuits/Volt/VoltBaseSuit":
|
||||
case "/Lotus/Powersuits/Excalibur/ExcaliburBaseSuit":
|
||||
case "/Lotus/Powersuits/AntiMatter/NovaBaseSuit":
|
||||
case "/Lotus/Powersuits/Banshee/BansheeBaseSuit":
|
||||
case "/Lotus/Powersuits/Berserker/BerserkerBaseSuit":
|
||||
case "/Lotus/Powersuits/Magician/MagicianBaseSuit":
|
||||
case "/Lotus/Powersuits/Sentient/SentientBaseSuit":
|
||||
case "/Lotus/Powersuits/Gyre/GyreBaseSuit":
|
||||
return "InnateElectricityDamage";
|
||||
case "/Lotus/Powersuits/Ember/EmberBaseSuit":
|
||||
case "/Lotus/Powersuits/Dragon/DragonBaseSuit":
|
||||
case "/Lotus/Powersuits/Nezha/NezhaBaseSuit":
|
||||
case "/Lotus/Powersuits/Sandman/SandmanBaseSuit":
|
||||
case "/Lotus/Powersuits/Trapper/TrapperBaseSuit":
|
||||
case "/Lotus/Powersuits/Wisp/WispBaseSuit":
|
||||
case "/Lotus/Powersuits/Odalisk/OdaliskBaseSuit":
|
||||
case "/Lotus/Powersuits/PaxDuviricus/PaxDuviricusBaseSuit":
|
||||
case "/Lotus/Powersuits/Choir/ChoirBaseSuit":
|
||||
case "/Lotus/Powersuits/Temple/TempleBaseSuit":
|
||||
return "InnateHeatDamage";
|
||||
case "/Lotus/Powersuits/Frost/FrostBaseSuit":
|
||||
case "/Lotus/Powersuits/Glass/GlassBaseSuit":
|
||||
case "/Lotus/Powersuits/Fairy/FairyBaseSuit":
|
||||
case "/Lotus/Powersuits/IronFrame/IronFrameBaseSuit":
|
||||
case "/Lotus/Powersuits/Revenant/RevenantBaseSuit":
|
||||
case "/Lotus/Powersuits/Trinity/TrinityBaseSuit":
|
||||
case "/Lotus/Powersuits/Hoplite/HopliteBaseSuit":
|
||||
case "/Lotus/Powersuits/Koumei/KoumeiBaseSuit":
|
||||
return "InnateFreezeDamage";
|
||||
case "/Lotus/Powersuits/Saryn/SarynBaseSuit":
|
||||
case "/Lotus/Powersuits/Paladin/PaladinBaseSuit":
|
||||
case "/Lotus/Powersuits/Brawler/BrawlerBaseSuit":
|
||||
case "/Lotus/Powersuits/Infestation/InfestationBaseSuit":
|
||||
case "/Lotus/Powersuits/Necro/NecroBaseSuit":
|
||||
case "/Lotus/Powersuits/Khora/KhoraBaseSuit":
|
||||
case "/Lotus/Powersuits/Ranger/RangerBaseSuit":
|
||||
case "/Lotus/Powersuits/Dagath/DagathBaseSuit":
|
||||
return "InnateToxinDamage";
|
||||
case "/Lotus/Powersuits/Mag/MagBaseSuit":
|
||||
case "/Lotus/Powersuits/Pirate/PirateBaseSuit":
|
||||
case "/Lotus/Powersuits/Cowgirl/CowgirlBaseSuit":
|
||||
case "/Lotus/Powersuits/Priest/PriestBaseSuit":
|
||||
case "/Lotus/Powersuits/BrokenFrame/BrokenFrameBaseSuit":
|
||||
case "/Lotus/Powersuits/Alchemist/AlchemistBaseSuit":
|
||||
case "/Lotus/Powersuits/Yareli/YareliBaseSuit":
|
||||
case "/Lotus/Powersuits/Geode/GeodeBaseSuit":
|
||||
case "/Lotus/Powersuits/Frumentarius/FrumentariusBaseSuit":
|
||||
return "InnateMagDamage";
|
||||
case "/Lotus/Powersuits/Loki/LokiBaseSuit":
|
||||
case "/Lotus/Powersuits/Ninja/NinjaBaseSuit":
|
||||
case "/Lotus/Powersuits/Jade/JadeBaseSuit":
|
||||
case "/Lotus/Powersuits/Bard/BardBaseSuit":
|
||||
case "/Lotus/Powersuits/Harlequin/HarlequinBaseSuit":
|
||||
case "/Lotus/Powersuits/Garuda/GarudaBaseSuit":
|
||||
case "/Lotus/Powersuits/YinYang/YinYangBaseSuit":
|
||||
case "/Lotus/Powersuits/Werewolf/WerewolfBaseSuit":
|
||||
case "/Lotus/Powersuits/ConcreteFrame/ConcreteFrameBaseSuit":
|
||||
return "InnateRadDamage";
|
||||
case "/Lotus/Powersuits/Rhino/RhinoBaseSuit":
|
||||
case "/Lotus/Powersuits/Tengu/TenguBaseSuit":
|
||||
case "/Lotus/Powersuits/MonkeyKing/MonkeyKingBaseSuit":
|
||||
case "/Lotus/Powersuits/Runner/RunnerBaseSuit":
|
||||
case "/Lotus/Powersuits/Pacifist/PacifistBaseSuit":
|
||||
case "/Lotus/Powersuits/Devourer/DevourerBaseSuit":
|
||||
case "/Lotus/Powersuits/Wraith/WraithBaseSuit":
|
||||
case "/Lotus/Powersuits/Pagemaster/PagemasterBaseSuit":
|
||||
return "InnateImpactDamage";
|
||||
}
|
||||
logger.warn(`unknown innate damage type for ${KillingSuit}, using heat as a fallback`);
|
||||
return "InnateHeatDamage";
|
||||
};
|
||||
|
||||
// TODO: For -1399275245665749231n, the value should be 75306944, but we're off by 59 with 75307003.
|
||||
export const getInnateDamageValue = (fp: bigint): number => {
|
||||
const rng = new SRng(fp);
|
||||
rng.randomFloat(); // used for the weapon index
|
||||
const WeaponUpgradeValueAttenuationExponent = 2.25;
|
||||
let value = Math.pow(rng.randomFloat(), WeaponUpgradeValueAttenuationExponent);
|
||||
if (value >= 0.941428) {
|
||||
value = 1;
|
||||
}
|
||||
return Math.trunc(value * 0x40000000);
|
||||
};
|
||||
|
@ -1039,6 +1039,8 @@ const pendingRecipeSchema = new Schema<IPendingRecipeDatabase>(
|
||||
{
|
||||
ItemType: String,
|
||||
CompletionDate: Date,
|
||||
TargetItemId: String,
|
||||
TargetFingerprint: String,
|
||||
LongGuns: { type: [EquipmentSchema], default: undefined },
|
||||
Pistols: { type: [EquipmentSchema], default: undefined },
|
||||
Melee: { type: [EquipmentSchema], default: undefined },
|
||||
@ -1260,11 +1262,11 @@ const nemesisSchema = new Schema<INemesisDatabase>(
|
||||
PrevOwners: Number,
|
||||
SecondInCommand: Boolean,
|
||||
Weakened: Boolean,
|
||||
InfNodes: [infNodeSchema],
|
||||
InfNodes: { type: [infNodeSchema], default: undefined },
|
||||
HenchmenKilled: Number,
|
||||
HintProgress: Number,
|
||||
Hints: [Number],
|
||||
GuessHistory: [Number],
|
||||
Hints: { type: [Number], default: undefined },
|
||||
GuessHistory: { type: [Number], default: undefined },
|
||||
MissionCount: Number,
|
||||
LastEnc: Number
|
||||
},
|
||||
@ -1609,7 +1611,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
||||
//CorpusLich or GrineerLich
|
||||
NemesisAbandonedRewards: { type: [String], default: [] },
|
||||
Nemesis: nemesisSchema,
|
||||
NemesisHistory: [Schema.Types.Mixed],
|
||||
NemesisHistory: { type: [nemesisSchema], default: undefined },
|
||||
LastNemesisAllySpawnTime: Schema.Types.Mixed,
|
||||
|
||||
//TradingRulesConfirmed,ShowFriendInvNotifications(Option->Social)
|
||||
|
@ -26,7 +26,9 @@ import {
|
||||
Status,
|
||||
IKubrowPetDetailsDatabase,
|
||||
ITraits,
|
||||
ICalendarProgress
|
||||
ICalendarProgress,
|
||||
INemesisWeaponTargetFingerprint,
|
||||
INemesisPetTargetFingerprint
|
||||
} from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
import { IGenericUpdate, IUpdateNodeIntrosResponse } from "../types/genericUpdate";
|
||||
import { IKeyChainRequest, IMissionInventoryUpdateRequest } from "../types/requestTypes";
|
||||
@ -79,6 +81,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";
|
||||
|
||||
export const createInventory = async (
|
||||
accountOwnerId: Types.ObjectId,
|
||||
@ -327,7 +330,8 @@ export const addItem = async (
|
||||
typeName: string,
|
||||
quantity: number = 1,
|
||||
premiumPurchase: boolean = false,
|
||||
seed?: bigint
|
||||
seed?: bigint,
|
||||
targetFingerprint?: string
|
||||
): Promise<IInventoryChanges> => {
|
||||
// Bundles are technically StoreItems but a) they don't have a normal counterpart, and b) they are used in non-StoreItem contexts, e.g. email attachments.
|
||||
if (typeName in ExportBundles) {
|
||||
@ -530,6 +534,12 @@ export const addItem = async (
|
||||
]
|
||||
});
|
||||
}
|
||||
if (targetFingerprint) {
|
||||
const targetFingerprintObj = JSON.parse(targetFingerprint) as INemesisWeaponTargetFingerprint;
|
||||
defaultOverwrites.UpgradeType = targetFingerprintObj.ItemType;
|
||||
defaultOverwrites.UpgradeFingerprint = JSON.stringify(targetFingerprintObj.UpgradeFingerprint);
|
||||
defaultOverwrites.ItemName = targetFingerprintObj.Name;
|
||||
}
|
||||
const inventoryChanges = addEquipment(inventory, weapon.productCategory, typeName, defaultOverwrites);
|
||||
if (weapon.additionalItems) {
|
||||
for (const item of weapon.additionalItems) {
|
||||
@ -544,6 +554,27 @@ export const addItem = async (
|
||||
premiumPurchase
|
||||
)
|
||||
};
|
||||
} else if (targetFingerprint) {
|
||||
// Sister's Hound
|
||||
const targetFingerprintObj = JSON.parse(targetFingerprint) as INemesisPetTargetFingerprint;
|
||||
const head = targetFingerprintObj.Parts[0];
|
||||
const defaultOverwrites: Partial<IEquipmentDatabase> = {
|
||||
ModularParts: targetFingerprintObj.Parts,
|
||||
ItemName: targetFingerprintObj.Name,
|
||||
Configs: applyDefaultUpgrades(inventory, ExportWeapons[head].defaultUpgrades)
|
||||
};
|
||||
const itemType = {
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadA":
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetAPowerSuit",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadB":
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetBPowerSuit",
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetParts/ZanukaPetPartHeadC":
|
||||
"/Lotus/Types/Friendly/Pets/ZanukaPets/ZanukaPetCPowerSuit"
|
||||
}[head] as string;
|
||||
return {
|
||||
...addEquipment(inventory, "MoaPets", itemType, defaultOverwrites),
|
||||
...occupySlot(inventory, InventorySlot.SENTINELS, premiumPurchase)
|
||||
};
|
||||
} else {
|
||||
// Modular weapon parts
|
||||
const miscItemChanges = [
|
||||
@ -1851,3 +1882,78 @@ export const getCalendarProgress = (inventory: TInventoryDatabaseDocument): ICal
|
||||
|
||||
return inventory.CalendarProgress;
|
||||
};
|
||||
|
||||
export const giveNemesisWeaponRecipe = (
|
||||
inventory: TInventoryDatabaseDocument,
|
||||
weaponType: string,
|
||||
nemesisName: string = "AGOR ROK",
|
||||
weaponLoc?: string,
|
||||
KillingSuit: string = "/Lotus/Powersuits/Ember/Ember",
|
||||
fp: bigint = generateRewardSeed()
|
||||
): void => {
|
||||
if (!weaponLoc) {
|
||||
weaponLoc = ExportWeapons[weaponType].name;
|
||||
}
|
||||
const recipeType = Object.entries(ExportRecipes).find(arr => arr[1].resultType == weaponType)![0];
|
||||
addRecipes(inventory, [
|
||||
{
|
||||
ItemType: recipeType,
|
||||
ItemCount: 1
|
||||
}
|
||||
]);
|
||||
inventory.PendingRecipes.push({
|
||||
CompletionDate: new Date(),
|
||||
ItemType: recipeType,
|
||||
TargetFingerprint: JSON.stringify({
|
||||
ItemType: "/Lotus/Weapons/Grineer/KuvaLich/Upgrades/InnateDamageRandomMod",
|
||||
UpgradeFingerprint: {
|
||||
compat: weaponType,
|
||||
buffs: [
|
||||
{
|
||||
Tag: getInnateDamageTag(KillingSuit),
|
||||
Value: getInnateDamageValue(fp)
|
||||
}
|
||||
]
|
||||
},
|
||||
Name: weaponLoc + "|" + nemesisName
|
||||
} satisfies INemesisWeaponTargetFingerprint)
|
||||
});
|
||||
};
|
||||
|
||||
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"
|
||||
]);
|
||||
const recipeType = Object.entries(ExportRecipes).find(arr => arr[1].resultType == head)![0];
|
||||
addRecipes(inventory, [
|
||||
{
|
||||
ItemType: recipeType,
|
||||
ItemCount: 1
|
||||
}
|
||||
]);
|
||||
inventory.PendingRecipes.push({
|
||||
CompletionDate: new Date(),
|
||||
ItemType: recipeType,
|
||||
TargetFingerprint: JSON.stringify({
|
||||
Parts: [head, body, legs, tail],
|
||||
Name: "/Lotus/Language/Pets/ZanukaPetName|" + nemesisName
|
||||
} satisfies INemesisPetTargetFingerprint)
|
||||
});
|
||||
};
|
||||
|
@ -35,6 +35,8 @@ import {
|
||||
combineInventoryChanges,
|
||||
generateRewardSeed,
|
||||
getCalendarProgress,
|
||||
giveNemesisPetRecipe,
|
||||
giveNemesisWeaponRecipe,
|
||||
updateCurrency,
|
||||
updateSyndicate
|
||||
} from "@/src/services/inventoryService";
|
||||
@ -53,7 +55,7 @@ import kuriaMessage50 from "@/static/fixed_responses/kuriaMessages/fiftyPercent.
|
||||
import kuriaMessage75 from "@/static/fixed_responses/kuriaMessages/seventyFivePercent.json";
|
||||
import kuriaMessage100 from "@/static/fixed_responses/kuriaMessages/oneHundredPercent.json";
|
||||
import conservationAnimals from "@/static/fixed_responses/conservationAnimals.json";
|
||||
import { getInfNodes } from "@/src/helpers/nemesisHelpers";
|
||||
import { getInfNodes, getWeaponsForManifest } from "@/src/helpers/nemesisHelpers";
|
||||
import { Loadout } from "../models/inventoryModels/loadoutModel";
|
||||
import { ILoadoutConfigDatabase } from "../types/saveLoadoutTypes";
|
||||
import { getLiteSortie, getWorldState, idToWeek } from "./worldStateService";
|
||||
@ -612,6 +614,52 @@ export const addMissionInventoryUpdates = async (
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "NemesisKillConvert":
|
||||
if (inventory.Nemesis) {
|
||||
inventory.NemesisHistory ??= [];
|
||||
inventory.NemesisHistory.push({
|
||||
// Copy over all 'base' values
|
||||
fp: inventory.Nemesis.fp,
|
||||
d: inventory.Nemesis.d,
|
||||
manifest: inventory.Nemesis.manifest,
|
||||
KillingSuit: inventory.Nemesis.KillingSuit,
|
||||
killingDamageType: inventory.Nemesis.killingDamageType,
|
||||
ShoulderHelmet: inventory.Nemesis.ShoulderHelmet,
|
||||
WeaponIdx: inventory.Nemesis.WeaponIdx,
|
||||
AgentIdx: inventory.Nemesis.AgentIdx,
|
||||
BirthNode: inventory.Nemesis.BirthNode,
|
||||
Faction: inventory.Nemesis.Faction,
|
||||
Rank: inventory.Nemesis.Rank,
|
||||
Traded: inventory.Nemesis.Traded,
|
||||
PrevOwners: inventory.Nemesis.PrevOwners,
|
||||
SecondInCommand: inventory.Nemesis.SecondInCommand,
|
||||
Weakened: inventory.Nemesis.Weakened,
|
||||
// And set killed flag
|
||||
k: value.killed
|
||||
});
|
||||
|
||||
if (value.killed) {
|
||||
if (value.weaponLoc) {
|
||||
const weaponType = getWeaponsForManifest(inventory.Nemesis.manifest)[
|
||||
inventory.Nemesis.WeaponIdx
|
||||
];
|
||||
giveNemesisWeaponRecipe(
|
||||
inventory,
|
||||
weaponType,
|
||||
value.nemesisName,
|
||||
value.weaponLoc,
|
||||
inventory.Nemesis.KillingSuit,
|
||||
inventory.Nemesis.fp
|
||||
);
|
||||
}
|
||||
if (value.petLoc) {
|
||||
giveNemesisPetRecipe(inventory);
|
||||
}
|
||||
}
|
||||
|
||||
inventory.Nemesis = undefined;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Equipment XP updates
|
||||
if (equipmentKeys.includes(key as TEquipmentKey)) {
|
||||
|
@ -43,6 +43,7 @@ export interface IInventoryDatabase
|
||||
| "RecentVendorPurchases"
|
||||
| "NextRefill"
|
||||
| "Nemesis"
|
||||
| "NemesisHistory"
|
||||
| "EntratiVaultCountResetDate"
|
||||
| "BrandedSuits"
|
||||
| "LockedWeaponGroup"
|
||||
@ -79,6 +80,7 @@ export interface IInventoryDatabase
|
||||
RecentVendorPurchases?: IRecentVendorPurchaseDatabase[];
|
||||
NextRefill?: Date;
|
||||
Nemesis?: INemesisDatabase;
|
||||
NemesisHistory?: INemesisBaseDatabase[];
|
||||
EntratiVaultCountResetDate?: Date;
|
||||
BrandedSuits?: Types.ObjectId[];
|
||||
LockedWeaponGroup?: ILockedWeaponGroupDatabase;
|
||||
@ -313,7 +315,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
||||
EquippedInstrument?: string;
|
||||
InvasionChainProgress: IInvasionChainProgress[];
|
||||
Nemesis?: INemesisClient;
|
||||
NemesisHistory: INemesisBaseClient[];
|
||||
NemesisHistory?: INemesisBaseClient[];
|
||||
LastNemesisAllySpawnTime?: IMongoDate;
|
||||
Settings?: ISettings;
|
||||
PersonalTechProjects: IPersonalTechProjectClient[];
|
||||
@ -902,8 +904,8 @@ export interface IPendingRecipeDatabase {
|
||||
ItemType: string;
|
||||
CompletionDate: Date;
|
||||
ItemId: IOid;
|
||||
TargetItemId?: string; // likely related to liches
|
||||
TargetFingerprint?: string; // likely related to liches
|
||||
TargetItemId?: string; // unsure what this is for
|
||||
TargetFingerprint?: string;
|
||||
LongGuns?: IEquipmentDatabase[];
|
||||
Pistols?: IEquipmentDatabase[];
|
||||
Melee?: IEquipmentDatabase[];
|
||||
@ -951,6 +953,17 @@ export interface ICrewShipComponentFingerprint extends IInnateDamageFingerprint
|
||||
SubroutineIndex?: number;
|
||||
}
|
||||
|
||||
export interface INemesisWeaponTargetFingerprint {
|
||||
ItemType: string;
|
||||
UpgradeFingerprint: IInnateDamageFingerprint;
|
||||
Name: string;
|
||||
}
|
||||
|
||||
export interface INemesisPetTargetFingerprint {
|
||||
Parts: string[];
|
||||
Name: string;
|
||||
}
|
||||
|
||||
export enum GettingSlotOrderInfo {
|
||||
Empty = "",
|
||||
LotusUpgradesModsRandomizedPlayerMeleeWeaponRandomModRare0 = "/Lotus/Upgrades/Mods/Randomized/PlayerMeleeWeaponRandomModRare:0",
|
||||
|
@ -22,7 +22,8 @@ import {
|
||||
ILoadOutPresets,
|
||||
IInvasionProgressClient,
|
||||
IWeaponSkinClient,
|
||||
IKubrowPetEggClient
|
||||
IKubrowPetEggClient,
|
||||
INemesisClient
|
||||
} from "./inventoryTypes/inventoryTypes";
|
||||
import { IGroup } from "./loginTypes";
|
||||
|
||||
@ -74,6 +75,14 @@ export type IMissionInventoryUpdateRequest = {
|
||||
PS: string;
|
||||
ActiveDojoColorResearch: string;
|
||||
RewardInfo?: IRewardInfo;
|
||||
NemesisKillConvert?: {
|
||||
nemesisName: string;
|
||||
weaponLoc: string;
|
||||
petLoc: "" | "/Lotus/Language/Pets/ZanukaPetName";
|
||||
fingerprint: bigint | number;
|
||||
killed: boolean;
|
||||
};
|
||||
target?: INemesisClient;
|
||||
ReceivedCeremonyMsg: boolean;
|
||||
LastCeremonyResetDate: number;
|
||||
MissionPTS: number;
|
||||
|
Loading…
x
Reference in New Issue
Block a user