Compare commits
8 Commits
eb3acad598
...
a03c987f69
Author | SHA1 | Date | |
---|---|---|---|
a03c987f69 | |||
7863833850 | |||
4398d37566 | |||
7c59d4fe3f | |||
4504b95977 | |||
90b6d13923 | |||
3d62fc4259 | |||
d4c5e367b4 |
17
src/controllers/custom/addCurrencyController.ts
Normal file
17
src/controllers/custom/addCurrencyController.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { RequestHandler } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
|
||||
export const addCurrencyController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const request = req.body as IAddCurrencyRequest;
|
||||
inventory[request.currency] += request.delta;
|
||||
await inventory.save();
|
||||
res.end();
|
||||
};
|
||||
|
||||
interface IAddCurrencyRequest {
|
||||
currency: "RegularCredits" | "PremiumCredits" | "FusionPoints" | "PrimeTokens";
|
||||
delta: number;
|
||||
}
|
@ -8,6 +8,7 @@ import {
|
||||
ExportRecipes,
|
||||
ExportResources,
|
||||
ExportSentinels,
|
||||
ExportSyndicates,
|
||||
ExportUpgrades,
|
||||
ExportWarframes,
|
||||
ExportWeapons
|
||||
@ -36,6 +37,7 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
res.SpaceSuits = [];
|
||||
res.MechSuits = [];
|
||||
res.miscitems = [];
|
||||
res.Syndicates = [];
|
||||
for (const [uniqueName, item] of Object.entries(ExportWarframes)) {
|
||||
if (
|
||||
item.productCategory == "Suits" ||
|
||||
@ -160,6 +162,12 @@ const getItemListsController: RequestHandler = (req, response) => {
|
||||
badItems[uniqueName] = true;
|
||||
}
|
||||
}
|
||||
for (const [uniqueName, syndicate] of Object.entries(ExportSyndicates)) {
|
||||
res.Syndicates.push({
|
||||
uniqueName,
|
||||
name: getString(syndicate.name, lang)
|
||||
});
|
||||
}
|
||||
|
||||
response.json({
|
||||
badItems,
|
||||
|
@ -125,6 +125,7 @@ favouriteLoadoutSchema.set("toJSON", {
|
||||
const tailorShopSchema = new Schema<ITailorShopDatabase>(
|
||||
{
|
||||
FavouriteLoadouts: [favouriteLoadoutSchema],
|
||||
Colors: { type: colorSchema, required: false },
|
||||
CustomJson: String,
|
||||
LevelDecosVisible: Boolean,
|
||||
Rooms: [roomSchema]
|
||||
|
@ -12,7 +12,7 @@ cacheRouter.get(/^\/origin\/[a-zA-Z0-9]+\/[0-9]+\/H\.Cache\.bin.*$/, (req, res)
|
||||
}
|
||||
});
|
||||
|
||||
cacheRouter.get(/^\/0\/Lotus\/.+!.+$/, async (req, res) => {
|
||||
cacheRouter.get(/^\/0\/.+!.+$/, async (req, res) => {
|
||||
try {
|
||||
const dir = req.path.substr(0, req.path.lastIndexOf("/"));
|
||||
const file = req.path.substr(dir.length + 1);
|
||||
|
@ -8,13 +8,14 @@ import { deleteAccountController } from "@/src/controllers/custom/deleteAccountC
|
||||
import { renameAccountController } from "@/src/controllers/custom/renameAccountController";
|
||||
|
||||
import { createAccountController } from "@/src/controllers/custom/createAccountController";
|
||||
import { createMessageController } from "@/src/controllers/custom/createMessageController";
|
||||
import { addCurrencyController } from "../controllers/custom/addCurrencyController";
|
||||
import { addItemsController } from "@/src/controllers/custom/addItemsController";
|
||||
import { addXpController } from "@/src/controllers/custom/addXpController";
|
||||
import { importController } from "@/src/controllers/custom/importController";
|
||||
|
||||
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
||||
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
||||
import { createMessageController } from "@/src/controllers/custom/createMessageController";
|
||||
|
||||
const customRouter = express.Router();
|
||||
|
||||
@ -27,6 +28,7 @@ customRouter.get("/renameAccount", renameAccountController);
|
||||
|
||||
customRouter.post("/createAccount", createAccountController);
|
||||
customRouter.post("/createMessage", createMessageController);
|
||||
customRouter.post("/addCurrency", addCurrencyController);
|
||||
customRouter.post("/addItems", addItemsController);
|
||||
customRouter.post("/addXp", addXpController);
|
||||
customRouter.post("/import", importController);
|
||||
|
@ -229,6 +229,9 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<
|
||||
if (client.FocusUpgrades !== undefined) {
|
||||
db.FocusUpgrades = client.FocusUpgrades;
|
||||
}
|
||||
if (client.EvolutionProgress !== undefined) {
|
||||
db.EvolutionProgress = client.EvolutionProgress;
|
||||
}
|
||||
if (client.InfestedFoundry !== undefined) {
|
||||
db.InfestedFoundry = convertInfestedFoundry(client.InfestedFoundry);
|
||||
}
|
||||
|
@ -83,6 +83,19 @@ export const addMissionInventoryUpdates = (
|
||||
if (inventoryUpdates.MissionFailed === true) {
|
||||
return;
|
||||
}
|
||||
if (inventoryUpdates.RewardInfo && inventoryUpdates.RewardInfo.periodicMissionTag) {
|
||||
const tag = inventoryUpdates.RewardInfo.periodicMissionTag;
|
||||
const existingCompletion = inventory.PeriodicMissionCompletions.find(completion => completion.tag === tag);
|
||||
|
||||
if (existingCompletion) {
|
||||
existingCompletion.date = new Date();
|
||||
} else {
|
||||
inventory.PeriodicMissionCompletions.push({
|
||||
tag: tag,
|
||||
date: new Date()
|
||||
});
|
||||
}
|
||||
}
|
||||
for (const [key, value] of getEntriesUnsafe(inventoryUpdates)) {
|
||||
if (value === undefined) {
|
||||
logger.error(`Inventory update key ${key} has no value `);
|
||||
@ -178,6 +191,22 @@ export const addMissionInventoryUpdates = (
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "SyndicateId": {
|
||||
inventory.CompletedSyndicates.push(value);
|
||||
break;
|
||||
}
|
||||
case "SortieId": {
|
||||
inventory.CompletedSorties.push(value);
|
||||
break;
|
||||
}
|
||||
case "SeasonChallengeCompletions":
|
||||
const processedCompletions = value.map(({ challenge, id }) => ({
|
||||
challenge: challenge.substring(challenge.lastIndexOf("/") + 1),
|
||||
id
|
||||
}));
|
||||
|
||||
inventory.SeasonChallengeHistory.push(...processedCompletions);
|
||||
break;
|
||||
default:
|
||||
// Equipment XP updates
|
||||
if (equipmentKeys.includes(key as TEquipmentKey)) {
|
||||
@ -347,6 +376,24 @@ function getRandomMissionDrops(RewardInfo: IRewardInfo): IRngResult[] {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (RewardInfo.nightmareMode) {
|
||||
const deck = ExportRewards["/Lotus/Types/Game/MissionDecks/NightmareModeRewards"];
|
||||
let rotation = 0;
|
||||
|
||||
if (region.missionIndex === 3 && RewardInfo.rewardTier) {
|
||||
rotation = RewardInfo.rewardTier;
|
||||
} else if ([6, 7, 8, 10, 11].includes(region.systemIndex)) {
|
||||
rotation = 2;
|
||||
} else if ([4, 9, 12, 14, 15, 16, 17, 18].includes(region.systemIndex)) {
|
||||
rotation = 1;
|
||||
}
|
||||
|
||||
const drop = getRandomRewardByChance(deck[rotation]);
|
||||
if (drop) {
|
||||
drops.push(drop);
|
||||
}
|
||||
}
|
||||
}
|
||||
return drops;
|
||||
}
|
||||
|
@ -28,7 +28,13 @@ export const setShipCustomizations = async (
|
||||
}
|
||||
} else {
|
||||
const personalRooms = await getPersonalRooms(accountId);
|
||||
personalRooms.ShipInteriorColors = shipCustomization.Customization.Colors;
|
||||
if (shipCustomization.IsShop) {
|
||||
personalRooms.TailorShop.Colors = shipCustomization.Customization.Colors;
|
||||
personalRooms.TailorShop.LevelDecosVisible = shipCustomization.Customization.LevelDecosVisible;
|
||||
personalRooms.TailorShop.CustomJson = shipCustomization.Customization.CustomJson;
|
||||
} else {
|
||||
personalRooms.ShipInteriorColors = shipCustomization.Customization.Colors;
|
||||
}
|
||||
await personalRooms.save();
|
||||
}
|
||||
};
|
||||
|
@ -44,6 +44,9 @@ export type IMissionInventoryUpdateRequest = {
|
||||
CrewShipAmmo?: ITypeCount[];
|
||||
BonusMiscItems?: ITypeCount[];
|
||||
|
||||
SyndicateId?: string;
|
||||
SortieId?: string;
|
||||
SeasonChallengeCompletions?: ISeasonChallenge[];
|
||||
AffiliationChanges?: IAffiliationChange[];
|
||||
crossPlaySetting?: string;
|
||||
rewardsMultiplier?: number;
|
||||
@ -100,6 +103,7 @@ export interface IRewardInfo {
|
||||
rewardQualifications?: string; // did a Survival for 5 minutes and this was "1"
|
||||
PurgatoryRewardQualifications?: string;
|
||||
rewardSeed?: number;
|
||||
periodicMissionTag?: string;
|
||||
}
|
||||
|
||||
export type IMissionStatus = "GS_SUCCESS" | "GS_FAILURE" | "GS_DUMPED" | "GS_QUIT" | "GS_INTERRUPTED";
|
||||
|
@ -84,12 +84,15 @@ export interface ISetShipCustomizationsRequest {
|
||||
Customization: Customization;
|
||||
IsExterior: boolean;
|
||||
AirSupportPower?: string;
|
||||
IsShop?: boolean;
|
||||
}
|
||||
|
||||
export interface Customization {
|
||||
SkinFlavourItem: string;
|
||||
Colors: IColor;
|
||||
ShipAttachments: ShipAttachments;
|
||||
LevelDecosVisible: boolean;
|
||||
CustomJson: string;
|
||||
}
|
||||
|
||||
//TODO: check for more attachments
|
||||
@ -155,12 +158,12 @@ export interface IFavouriteLoadoutDatabase {
|
||||
|
||||
export interface ITailorShopDatabase {
|
||||
FavouriteLoadouts: IFavouriteLoadoutDatabase[];
|
||||
CustomJson: "{}"; // ???
|
||||
Colors?: IColor;
|
||||
CustomJson: string;
|
||||
LevelDecosVisible: boolean;
|
||||
Rooms: IRoom[];
|
||||
}
|
||||
|
||||
export interface ITailorShop extends Omit<ITailorShopDatabase, "FavouriteLoadouts"> {
|
||||
FavouriteLoadouts: IFavouriteLoadout[];
|
||||
Colors?: []; // ???
|
||||
}
|
||||
|
@ -94,6 +94,56 @@
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-3">
|
||||
<div class="card mb-3">
|
||||
<h5 class="card-header" data-loc="currency_RegularCredits"></h5>
|
||||
<div class="card-body">
|
||||
<p class="card-text" id="RegularCredits-owned"></p>
|
||||
<form class="input-group" onsubmit="doAddCurrency('RegularCredits');return false;">
|
||||
<input class="form-control" id="RegularCredits-delta" type="number" value="1000000" step="1000000" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card mb-3">
|
||||
<h5 class="card-header" data-loc="currency_PremiumCredits"></h5>
|
||||
<div class="card-body">
|
||||
<p class="card-text" id="PremiumCredits-owned"></p>
|
||||
<form class="input-group" onsubmit="doAddCurrency('PremiumCredits');return false;">
|
||||
<input class="form-control" id="PremiumCredits-delta" type="number" value="100" step="100" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card mb-3">
|
||||
<h5 class="card-header" data-loc="currency_FusionPoints"></h5>
|
||||
<div class="card-body">
|
||||
<p class="card-text" id="FusionPoints-owned"></p>
|
||||
<form class="input-group" onsubmit="doAddCurrency('FusionPoints');return false;">
|
||||
<input class="form-control" id="FusionPoints-delta" type="number" value="1000" step="1000" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card mb-3">
|
||||
<h5 class="card-header" data-loc="currency_PrimeTokens"></h5>
|
||||
<div class="card-body">
|
||||
<p class="card-text" id="PrimeTokens-owned"></p>
|
||||
<form class="input-group" onsubmit="doAddCurrency('PrimeTokens');return false;">
|
||||
<input class="form-control" id="PrimeTokens-delta" type="number" value="1" step="1" />
|
||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
<div class="col-lg-6">
|
||||
<div class="card mb-3" style="height: 400px;">
|
||||
@ -364,7 +414,7 @@
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<div class="card mb-3">
|
||||
<h5 class="card-header">Server</h5>
|
||||
<h5 class="card-header" data-loc="cheats_server"></h5>
|
||||
<div class="card-body">
|
||||
<div id="server-settings-no-perms" class="d-none">
|
||||
<p class="card-text" data-loc="cheats_administratorRequirement"></p>
|
||||
@ -465,6 +515,15 @@
|
||||
<div class="card-body">
|
||||
<p><button class="btn btn-primary" onclick="doUnlockAllFocusSchools();" data-loc="cheats_unlockAllFocusSchools"></button></p>
|
||||
<button class="btn btn-primary" onclick="doHelminthUnlockAll();" data-loc="cheats_helminthUnlockAll"></button>
|
||||
<form class="mt-2" onsubmit="doChangeSupportedSyndicate(); return false;">
|
||||
<label class="form-label" for="changeSyndicate" data-loc="cheats_changeSupportedSyndicate"></label>
|
||||
<div class="input-group">
|
||||
<select class="form-control" id="changeSyndicate">
|
||||
<option value="" data-loc="cheats_none"></option>
|
||||
</select>
|
||||
<button class="btn btn-primary" type="submit" data-loc="cheats_changeButton"></button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -191,6 +191,15 @@ function fetchItemList() {
|
||||
});
|
||||
} else if (type == "uniqueLevelCaps") {
|
||||
uniqueLevelCaps = items;
|
||||
} else if (type == "Syndicates") {
|
||||
items.forEach(item => {
|
||||
if (item.uniqueName.startsWith("RadioLegion")) item.name += " (" + item.uniqueName + ")";
|
||||
const option = document.createElement("option");
|
||||
option.value = item.uniqueName;
|
||||
option.innerHTML = item.name;
|
||||
document.getElementById("changeSyndicate").appendChild(option);
|
||||
itemMap[item.uniqueName] = { ...item, type };
|
||||
});
|
||||
} else if (type != "badItems") {
|
||||
items.forEach(item => {
|
||||
if (item.uniqueName in data.badItems) {
|
||||
@ -218,6 +227,15 @@ function updateInventory() {
|
||||
window.didInitialInventoryUpdate = true;
|
||||
|
||||
// Populate inventory route
|
||||
[
|
||||
"RegularCredits",
|
||||
"PremiumCredits",
|
||||
"FusionPoints",
|
||||
"PrimeTokens"
|
||||
].forEach(currency => {
|
||||
document.getElementById(currency + "-owned").textContent = loc("currency_owned").split("|COUNT|").join(data[currency].toLocaleString());
|
||||
});
|
||||
|
||||
[
|
||||
"Suits",
|
||||
"SpaceSuits",
|
||||
@ -524,6 +542,8 @@ function updateInventory() {
|
||||
single.loadRoute("/webui/inventory");
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("changeSyndicate").value = data.SupportedSyndicate ?? "";
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -1096,3 +1116,25 @@ function doImport() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function doChangeSupportedSyndicate() {
|
||||
const uniqueName = document.getElementById("changeSyndicate").value;
|
||||
revalidateAuthz(() => {
|
||||
$.get("/api/setSupportedSyndicate.php?" + window.authz + "&syndicate=" + uniqueName).done(function () {
|
||||
updateInventory();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function doAddCurrency(currency) {
|
||||
$.post({
|
||||
url: "/custom/addCurrency?" + window.authz,
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
currency,
|
||||
delta: document.getElementById(currency + "-delta").valueAsNumber
|
||||
})
|
||||
}).then(function () {
|
||||
updateInventory();
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
dict = {
|
||||
general_inventoryUpdateNote: `Note: Changes made here will only be reflected in-game when the game re-downloads your inventory. Visiting the navigation should be the easiest way to trigger that.`,
|
||||
general_inventoryUpdateNote: `Note: Changes made here will only be applied in-game when the game syncs the inventory. Visiting the navigation should be the easiest way to trigger that.`,
|
||||
general_addButton: `Add`,
|
||||
general_bulkActions: `Bulk Actions`,
|
||||
code_nonValidAuthz: `Your credentials are no longer valid.`,
|
||||
@ -72,6 +72,11 @@ dict = {
|
||||
inventory_bulkRankUpSpaceWeapons: `Max Rank All Archwing Weapons`,
|
||||
inventory_bulkRankUpSentinels: `Max Rank All Sentinels`,
|
||||
inventory_bulkRankUpSentinelWeapons: `Max Rank All Sentinel Weapons`,
|
||||
currency_RegularCredits: `Credits`,
|
||||
currency_PremiumCredits: `Platinum`,
|
||||
currency_FusionPoints: `Endo`,
|
||||
currency_PrimeTokens: `Regal Aya`,
|
||||
currency_owned: `You have |COUNT|.`,
|
||||
powersuit_archonShardsLabel: `Archon Shard Slots`,
|
||||
powersuit_archonShardsDescription: `You can use these unlimited slots to apply a wide range of upgrades`,
|
||||
mods_addRiven: `Add Riven`,
|
||||
@ -81,6 +86,7 @@ dict = {
|
||||
mods_mods: `Mods`,
|
||||
mods_bulkAddMods: `Add Missing Mods`,
|
||||
cheats_administratorRequirement: `You must be an administrator to use this feature. To become an administrator, add <code>|DISPLAYNAME|</code> to <code>administratorNames</code> in the config.json.`,
|
||||
cheats_server: `Server`,
|
||||
cheats_skipTutorial: `Skip Tutorial`,
|
||||
cheats_skipAllDialogue: `Skip All Dialogue`,
|
||||
cheats_unlockAllScans: `Unlock All Scans`,
|
||||
@ -106,6 +112,9 @@ dict = {
|
||||
cheats_account: `Account`,
|
||||
cheats_unlockAllFocusSchools: `Unlock All Focus Schools`,
|
||||
cheats_helminthUnlockAll: `Fully Level Up Helminth`,
|
||||
cheats_changeSupportedSyndicate: `Supported syndicate`,
|
||||
cheats_changeButton: `Change`,
|
||||
cheats_none: `None`,
|
||||
import_importNote: `You can provide a full or partial inventory response (client respresentation) here. All fields that are supported by the importer <b>will be overwritten</b> in your account.`,
|
||||
import_submit: `Submit`,
|
||||
}
|
@ -73,6 +73,11 @@ dict = {
|
||||
inventory_bulkRankUpSpaceWeapons: `Максимальный ранг всего оружия арчвингов`,
|
||||
inventory_bulkRankUpSentinels: `Максимальный ранг всех стражей`,
|
||||
inventory_bulkRankUpSentinelWeapons: `Максимальный ранг всего оружия стражей`,
|
||||
currency_RegularCredits: `Кредиты`,
|
||||
currency_PremiumCredits: `Платина`,
|
||||
currency_FusionPoints: `Эндо`,
|
||||
currency_PrimeTokens: `Королевские Айя`,
|
||||
currency_owned: `У тебя есть |COUNT|.`,
|
||||
powersuit_archonShardsLabel: `Ячейки осколков архонта`,
|
||||
powersuit_archonShardsDescription: `Вы можете использовать эти неограниченные ячейки для установки множества улучшений.`,
|
||||
mods_addRiven: `Добавить Мод Разлома`,
|
||||
@ -82,6 +87,7 @@ dict = {
|
||||
mods_mods: `Моды`,
|
||||
mods_bulkAddMods: `Добавить отсутствующие моды`,
|
||||
cheats_administratorRequirement: `Вы должны быть администратором для использования этой функции. Чтобы стать администратором, добавьте <code>\"|DISPLAYNAME|\"</code> в <code>administratorNames</code> в config.json.`,
|
||||
cheats_server: `Сервер`,
|
||||
cheats_skipTutorial: `Пропустить обучение`,
|
||||
cheats_skipAllDialogue: `Пропустить все диалоги`,
|
||||
cheats_unlockAllScans: `Разблокировать все сканирования`,
|
||||
@ -107,6 +113,9 @@ dict = {
|
||||
cheats_account: `Аккаунт`,
|
||||
cheats_unlockAllFocusSchools: `Разблокировать все школы фокуса`,
|
||||
cheats_helminthUnlockAll: `Полностью улучшить Гельминта`,
|
||||
cheats_changeSupportedSyndicate: `Поддерживаемый синдикат`,
|
||||
cheats_changeButton: `Изменить`,
|
||||
cheats_none: `Отсутствует`,
|
||||
import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
|
||||
import_submit: `Отправить`,
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user