give all missing skins

This commit is contained in:
AMelonInsideLemon 2025-09-29 17:36:04 +02:00
parent 186d0559ec
commit f2d3837dc0
12 changed files with 85 additions and 82 deletions

View File

@ -15,6 +15,7 @@ import { applyCheatsToInfestedFoundry, handleSubsumeCompletion } from "../../ser
import { import {
addEmailItem, addEmailItem,
addItem, addItem,
addItems,
addMiscItems, addMiscItems,
allDailyAffiliationKeys, allDailyAffiliationKeys,
checkCalendarAutoAdvance, checkCalendarAutoAdvance,
@ -268,6 +269,65 @@ export const inventoryController: RequestHandler = async (request, response) =>
} }
} }
inventory.LastInventorySync = new Types.ObjectId(); inventory.LastInventorySync = new Types.ObjectId();
const weaponMap = new Map<string, string>();
for (const skin of inventory.WeaponSkins) {
weaponMap.set(skin.ItemType, skin._id.toString());
}
const itemsToAdd = new Set<string>();
for (const key of equipmentKeys) {
if (key in inventory) {
for (const equipment of inventory[key]) {
for (const config of equipment.Configs) {
if (config.Skins) collectSkins(config.Skins, weaponMap, itemsToAdd);
}
}
}
}
for (const key of ["AdultOperatorLoadOuts", "OperatorLoadOuts", "KahlLoadOuts"] as const) {
if (key in inventory) {
for (const loadOut of inventory[key]) {
if (loadOut.Skins) collectSkins(loadOut.Skins, weaponMap, itemsToAdd);
}
}
}
if (inventory.LotusCustomization?.Skins) collectSkins(inventory.LotusCustomization.Skins, weaponMap, itemsToAdd);
if (itemsToAdd.size > 0) {
logger.debug(`Adding ${itemsToAdd.size} items due to migration from unlockAllSkins cheat`);
const inventoryChanges = await addItems(inventory, Array.from(itemsToAdd));
if (inventoryChanges.WeaponSkins) {
for (const skin of inventoryChanges.WeaponSkins as IWeaponSkinClient[]) {
weaponMap.set(skin.ItemType, skin.ItemId.toString());
}
}
for (const key of equipmentKeys) {
if (key in inventory) {
for (const equipment of inventory[key]) {
for (const config of equipment.Configs) {
if (config.Skins) replaceSkinIds(config.Skins, weaponMap);
}
}
}
}
for (const key of ["AdultOperatorLoadOuts", "OperatorLoadOuts", "KahlLoadOuts"] as const) {
if (key in inventory) {
for (const loadOut of inventory[key]) {
if (loadOut.Skins) replaceSkinIds(loadOut.Skins, weaponMap);
}
}
}
if (inventory.LotusCustomization?.Skins) replaceSkinIds(inventory.LotusCustomization.Skins, weaponMap);
}
await inventory.save(); await inventory.save();
response.json( response.json(
@ -334,45 +394,6 @@ export const getInventoryResponse = async (
}); });
} }
if (inventory.unlockAllSkins) {
const missingWeaponSkins = new Set(Object.keys(ExportCustoms));
inventoryResponse.WeaponSkins.forEach(x => missingWeaponSkins.delete(x.ItemType));
for (const uniqueName of missingWeaponSkins) {
inventoryResponse.WeaponSkins.push({
ItemId: {
$oid: "ca70ca70ca70ca70" + catBreadHash(uniqueName).toString(16).padStart(8, "0")
},
ItemType: uniqueName
});
}
} else {
for (const key of equipmentKeys) {
if (key in inventoryResponse) {
for (const equipment of inventoryResponse[key]) {
equipment.Configs.forEach(config => {
if (config.Skins) processSkins(config.Skins, inventoryResponse.WeaponSkins, equipment.ItemType);
});
}
}
}
for (const key of ["AdultOperatorLoadOuts", "OperatorLoadOuts", "KahlLoadOuts"] as const) {
if (key in inventoryResponse) {
inventoryResponse[key].forEach(loadOut => {
if (loadOut.Skins) processSkins(loadOut.Skins, inventoryResponse.WeaponSkins, key);
});
}
}
if (inventoryResponse.LotusCustomization?.Skins) {
processSkins(
inventoryResponse.LotusCustomization.Skins,
inventoryResponse.WeaponSkins,
"LotusCustomization"
);
}
}
if (typeof config.spoofMasteryRank === "number" && config.spoofMasteryRank >= 0) { if (typeof config.spoofMasteryRank === "number" && config.spoofMasteryRank >= 0) {
inventoryResponse.PlayerLevel = config.spoofMasteryRank; inventoryResponse.PlayerLevel = config.spoofMasteryRank;
if (!xpBasedLevelCapDisabled) { if (!xpBasedLevelCapDisabled) {
@ -505,20 +526,21 @@ for (const key of Object.keys(ExportCustoms)) {
skinLookupTable[catBreadHash(key)] = key; skinLookupTable[catBreadHash(key)] = key;
} }
const processSkins = (skins: string[], weaponSKins: IWeaponSkinClient[], contextName: string): void => { const collectSkins = (skins: string[], weaponMap: Map<string, string>, itemsToAdd: Set<string>): void => {
skins.forEach((skinId, i) => { for (const skinId of skins) {
if (skinId.startsWith("ca70ca70ca70ca70")) { if (skinId.startsWith("ca70ca70ca70ca70")) {
const skinItemType = skinLookupTable[parseInt(skinId.slice(16), 16)]; const typeName = skinLookupTable[parseInt(skinId.slice(16), 16)];
const inventoryItem = weaponSKins.find(x => x.ItemType === skinItemType); if (!weaponMap.has(typeName)) itemsToAdd.add(typeName);
if (inventoryItem) {
skins[i] = inventoryItem.ItemId.$oid;
} else {
skins[i] = skinItemType;
if (!ExportCustoms[skinItemType].alwaysAvailable) {
logger.warn(`Get ${skinItemType} or you may loose your appearance on ${contextName}`);
}
}
} }
}); }
};
const replaceSkinIds = (skins: string[], weaponMap: Map<string, string>): void => {
for (let i = 0; i < skins.length; i++) {
const skinId = skins[i];
if (skinId.startsWith("ca70ca70ca70ca70")) {
const inventoryId = weaponMap.get(skinLookupTable[parseInt(skinId.slice(16), 16)]);
if (inventoryId) skins[i] = inventoryId;
}
}
}; };

View File

@ -1445,7 +1445,6 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
unlockDoubleCapacityPotatoesEverywhere: Boolean, unlockDoubleCapacityPotatoesEverywhere: Boolean,
unlockExilusEverywhere: Boolean, unlockExilusEverywhere: Boolean,
unlockArcanesEverywhere: Boolean, unlockArcanesEverywhere: Boolean,
unlockAllSkins: Boolean,
syndicateMissionsRepeatable: Boolean, syndicateMissionsRepeatable: Boolean,
instantFinishRivenChallenge: Boolean, instantFinishRivenChallenge: Boolean,
noDailyStandingLimits: Boolean, noDailyStandingLimits: Boolean,

View File

@ -139,22 +139,16 @@ export const handleInventoryItemConfigChange = async (
case "WeaponSkins": { case "WeaponSkins": {
const itemEntries = equipment as IItemEntry; const itemEntries = equipment as IItemEntry;
for (const [itemId, itemConfigEntries] of Object.entries(itemEntries)) { for (const [itemId, itemConfigEntries] of Object.entries(itemEntries)) {
if (itemId.startsWith("ca70ca70ca70ca70")) { const inventoryItem = inventory.WeaponSkins.id(itemId);
logger.warn( if (!inventoryItem) {
`unlockAllSkins does not work with favoriting items because you don't actually own it` logger.warn(`inventory item WeaponSkins not found with id ${itemId}`);
); continue;
} else { }
const inventoryItem = inventory.WeaponSkins.id(itemId); if ("Favorite" in itemConfigEntries) {
if (!inventoryItem) { inventoryItem.Favorite = itemConfigEntries.Favorite;
logger.warn(`inventory item WeaponSkins not found with id ${itemId}`); }
continue; if ("IsNew" in itemConfigEntries) {
} inventoryItem.IsNew = itemConfigEntries.IsNew;
if ("Favorite" in itemConfigEntries) {
inventoryItem.Favorite = itemConfigEntries.Favorite;
}
if ("IsNew" in itemConfigEntries) {
inventoryItem.IsNew = itemConfigEntries.IsNew;
}
} }
} }
break; break;

View File

@ -38,7 +38,6 @@ export interface IAccountCheats {
unlockDoubleCapacityPotatoesEverywhere?: boolean; unlockDoubleCapacityPotatoesEverywhere?: boolean;
unlockExilusEverywhere?: boolean; unlockExilusEverywhere?: boolean;
unlockArcanesEverywhere?: boolean; unlockArcanesEverywhere?: boolean;
unlockAllSkins?: boolean;
syndicateMissionsRepeatable?: boolean; syndicateMissionsRepeatable?: boolean;
instantFinishRivenChallenge?: boolean; instantFinishRivenChallenge?: boolean;
noDailyStandingLimits?: boolean; noDailyStandingLimits?: boolean;

View File

@ -962,10 +962,6 @@
<input class="form-check-input" type="checkbox" id="unlockArcanesEverywhere" /> <input class="form-check-input" type="checkbox" id="unlockArcanesEverywhere" />
<label class="form-check-label" for="unlockArcanesEverywhere" data-loc="cheats_unlockArcanesEverywhere"></label> <label class="form-check-label" for="unlockArcanesEverywhere" data-loc="cheats_unlockArcanesEverywhere"></label>
</div> </div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="unlockAllSkins" />
<label class="form-check-label" for="unlockAllSkins" data-loc="cheats_unlockAllSkins"></label>
</div>
<div class="form-check"> <div class="form-check">
<input class="form-check-input" type="checkbox" id="syndicateMissionsRepeatable" /> <input class="form-check-input" type="checkbox" id="syndicateMissionsRepeatable" />
<label class="form-check-label" for="syndicateMissionsRepeatable" data-loc="cheats_syndicateMissionsRepeatable"></label> <label class="form-check-label" for="syndicateMissionsRepeatable" data-loc="cheats_syndicateMissionsRepeatable"></label>

View File

@ -215,7 +215,6 @@ dict = {
cheats_dontSubtractVoidTraces: `Void-Spuren nicht verbrauchen`, cheats_dontSubtractVoidTraces: `Void-Spuren nicht verbrauchen`,
cheats_dontSubtractConsumables: `Verbrauchsgegenstände (Ausrüstung) nicht verbrauchen`, cheats_dontSubtractConsumables: `Verbrauchsgegenstände (Ausrüstung) nicht verbrauchen`,
cheats_unlockAllShipFeatures: `Alle Schiffs-Funktionen freischalten`, cheats_unlockAllShipFeatures: `Alle Schiffs-Funktionen freischalten`,
cheats_unlockAllSkins: `Alle Skins freischalten`,
cheats_unlockAllCapturaScenes: `Alle Photora-Szenen freischalten`, cheats_unlockAllCapturaScenes: `Alle Photora-Szenen freischalten`,
cheats_universalPolarityEverywhere: `Universelle Polarität überall`, cheats_universalPolarityEverywhere: `Universelle Polarität überall`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Orokin Reaktor & Beschleuniger überall`, cheats_unlockDoubleCapacityPotatoesEverywhere: `Orokin Reaktor & Beschleuniger überall`,

View File

@ -214,7 +214,6 @@ dict = {
cheats_dontSubtractVoidTraces: `Don't Subtract Void Traces`, cheats_dontSubtractVoidTraces: `Don't Subtract Void Traces`,
cheats_dontSubtractConsumables: `Don't Subtract Consumables`, cheats_dontSubtractConsumables: `Don't Subtract Consumables`,
cheats_unlockAllShipFeatures: `Unlock All Ship Features`, cheats_unlockAllShipFeatures: `Unlock All Ship Features`,
cheats_unlockAllSkins: `Unlock All Skins`,
cheats_unlockAllCapturaScenes: `Unlock All Captura Scenes`, cheats_unlockAllCapturaScenes: `Unlock All Captura Scenes`,
cheats_universalPolarityEverywhere: `Universal Polarity Everywhere`, cheats_universalPolarityEverywhere: `Universal Polarity Everywhere`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Potatoes Everywhere`, cheats_unlockDoubleCapacityPotatoesEverywhere: `Potatoes Everywhere`,

View File

@ -215,7 +215,6 @@ dict = {
cheats_dontSubtractVoidTraces: `No descontar vestigios del Vacío`, cheats_dontSubtractVoidTraces: `No descontar vestigios del Vacío`,
cheats_dontSubtractConsumables: `No restar consumibles`, cheats_dontSubtractConsumables: `No restar consumibles`,
cheats_unlockAllShipFeatures: `Desbloquear todas las funciones de nave`, cheats_unlockAllShipFeatures: `Desbloquear todas las funciones de nave`,
cheats_unlockAllSkins: `Desbloquear todas las skins`,
cheats_unlockAllCapturaScenes: `Desbloquear todas las escenas de Captura`, cheats_unlockAllCapturaScenes: `Desbloquear todas las escenas de Captura`,
cheats_universalPolarityEverywhere: `Polaridad universal en todas partes`, cheats_universalPolarityEverywhere: `Polaridad universal en todas partes`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Patatas en todas partes`, cheats_unlockDoubleCapacityPotatoesEverywhere: `Patatas en todas partes`,

View File

@ -215,7 +215,6 @@ dict = {
cheats_dontSubtractVoidTraces: `Ne pas consommer de Void Traces`, cheats_dontSubtractVoidTraces: `Ne pas consommer de Void Traces`,
cheats_dontSubtractConsumables: `Ne pas retirer de consommables`, cheats_dontSubtractConsumables: `Ne pas retirer de consommables`,
cheats_unlockAllShipFeatures: `Débloquer tous les segments du vaisseau`, cheats_unlockAllShipFeatures: `Débloquer tous les segments du vaisseau`,
cheats_unlockAllSkins: `Débloquer tous les skins`,
cheats_unlockAllCapturaScenes: `Débloquer toutes les scènes captura`, cheats_unlockAllCapturaScenes: `Débloquer toutes les scènes captura`,
cheats_universalPolarityEverywhere: `Polarités universelles partout`, cheats_universalPolarityEverywhere: `Polarités universelles partout`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Réacteurs et Catalyseurs partout`, cheats_unlockDoubleCapacityPotatoesEverywhere: `Réacteurs et Catalyseurs partout`,

View File

@ -215,7 +215,6 @@ dict = {
cheats_dontSubtractVoidTraces: `Не вычитать количество Отголосков Бездны`, cheats_dontSubtractVoidTraces: `Не вычитать количество Отголосков Бездны`,
cheats_dontSubtractConsumables: `Не вычитать количество расходников`, cheats_dontSubtractConsumables: `Не вычитать количество расходников`,
cheats_unlockAllShipFeatures: `Разблокировать все функции корабля`, cheats_unlockAllShipFeatures: `Разблокировать все функции корабля`,
cheats_unlockAllSkins: `Разблокировать все скины`,
cheats_unlockAllCapturaScenes: `Разблокировать все сцены Каптуры`, cheats_unlockAllCapturaScenes: `Разблокировать все сцены Каптуры`,
cheats_universalPolarityEverywhere: `Универсальная полярность везде`, cheats_universalPolarityEverywhere: `Универсальная полярность везде`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Реакторы/Катализаторы орокин везде`, cheats_unlockDoubleCapacityPotatoesEverywhere: `Реакторы/Катализаторы орокин везде`,

View File

@ -215,7 +215,6 @@ dict = {
cheats_dontSubtractVoidTraces: `Не вираховувати кількість Відлуння`, cheats_dontSubtractVoidTraces: `Не вираховувати кількість Відлуння`,
cheats_dontSubtractConsumables: `Не вираховувати кількість витратних матеріалів`, cheats_dontSubtractConsumables: `Не вираховувати кількість витратних матеріалів`,
cheats_unlockAllShipFeatures: `Розблокувати всі функції судна`, cheats_unlockAllShipFeatures: `Розблокувати всі функції судна`,
cheats_unlockAllSkins: `Розблокувати всі скіни`,
cheats_unlockAllCapturaScenes: `Розблокувати всі сцени Світлописця`, cheats_unlockAllCapturaScenes: `Розблокувати всі сцени Світлописця`,
cheats_universalPolarityEverywhere: `Будь-яка полярність скрізь`, cheats_universalPolarityEverywhere: `Будь-яка полярність скрізь`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `Орокінські Реактори/Каталізатори скрізь`, cheats_unlockDoubleCapacityPotatoesEverywhere: `Орокінські Реактори/Каталізатори скрізь`,

View File

@ -215,7 +215,6 @@ dict = {
cheats_dontSubtractVoidTraces: `虚空光体无消耗`, cheats_dontSubtractVoidTraces: `虚空光体无消耗`,
cheats_dontSubtractConsumables: `消耗物品使用时无损耗`, cheats_dontSubtractConsumables: `消耗物品使用时无损耗`,
cheats_unlockAllShipFeatures: `解锁所有飞船功能`, cheats_unlockAllShipFeatures: `解锁所有飞船功能`,
cheats_unlockAllSkins: `解锁所有外观`,
cheats_unlockAllCapturaScenes: `解锁所有Captura场景`, cheats_unlockAllCapturaScenes: `解锁所有Captura场景`,
cheats_universalPolarityEverywhere: `全局万用极性`, cheats_universalPolarityEverywhere: `全局万用极性`,
cheats_unlockDoubleCapacityPotatoesEverywhere: `全物品自带Orokin反应堆`, cheats_unlockDoubleCapacityPotatoesEverywhere: `全物品自带Orokin反应堆`,