Compare commits

..

15 Commits

Author SHA1 Message Date
785c6aa7ac chore: improve archwing mission detection
All checks were successful
Build / build (push) Successful in 44s
Build / build (pull_request) Successful in 1m33s
SettlementNode10 was not being excluded
2025-04-23 20:39:39 +02:00
bb8596fa87 fix(webui): use proper 'size' abbreviations for vallis & deimos fish (#1804)
All checks were successful
Build Docker image / docker (push) Successful in 37s
Build / build (push) Successful in 1m34s
Closes #1763

Reviewed-on: #1804
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-23 11:38:04 -07:00
a85539a686 feat: set IsNew flag on new sentinels (#1802)
Some checks failed
Build Docker image / docker (push) Has been cancelled
Build / build (push) Has been cancelled
Reviewed-on: #1802
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-23 11:37:52 -07:00
ada6a4bad0 fix: occupy correct slot for arch-guns (#1801)
Some checks failed
Build Docker image / docker (push) Has been cancelled
Build / build (push) Has been cancelled
Reviewed-on: #1801
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-23 11:37:43 -07:00
948104a9a6 fix: "logged in elsewhere" when logging in on account created via webui (#1800)
Some checks failed
Build Docker image / docker (push) Has been cancelled
Build / build (push) Has been cancelled
Reviewed-on: #1800
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-23 11:37:31 -07:00
7a8b12b372 chore: cap FusionPoints balance at 2147483647 (#1797)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
Same idea as with typeCountSchema. The game needs to be able to store these safely in an i32 on the C++ side.

Reviewed-on: #1797
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-23 11:37:10 -07:00
26d644a982 feat: handle scale for the dojo decos that need it (#1795)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
Closes #1785

Reviewed-on: #1795
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-23 11:36:57 -07:00
d6750cd84b chore: provide tileset for sortie missions (#1793)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
Closes #1788

Reviewed-on: #1793
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-23 11:36:32 -07:00
f3601ec43e chore: allow MT_CAPTURE for sorties (#1792)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
e.g. `SolNode1` is a capture mission but it should still be a valid node for sorties. Not that the mission will actually be a capture.

Reviewed-on: #1792
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-23 11:36:19 -07:00
15aaa28a4f feat: conquest progression & rewards (#1791)
Some checks failed
Build Docker image / docker (push) Has been cancelled
Build / build (push) Has been cancelled
Closes #1570

Co-authored-by: Jānis <janisslsm@noreply.localhost>
Reviewed-on: #1791
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-23 11:35:57 -07:00
ce5b0fc9e2 fix: limit MT_LANDSCAPE sortie missions to PoE (#1790)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
Closes #1789

Reviewed-on: #1790
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-23 11:35:29 -07:00
64290b72c0 chore(webui): update to Spanish translation (#1809)
All checks were successful
Build Docker image / docker (push) Successful in 1m9s
Build / build (push) Successful in 45s
Reviewed-on: #1809
Co-authored-by: hxedcl <hxedcl@noreply.localhost>
Co-committed-by: hxedcl <hxedcl@noreply.localhost>
2025-04-23 11:20:40 -07:00
570c6fe0d1 chore(webui): update German translation (#1806)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker (push) Has been cancelled
Reviewed-on: #1806
Co-authored-by: Animan8000 <animan8000@noreply.localhost>
Co-committed-by: Animan8000 <animan8000@noreply.localhost>
2025-04-23 11:20:25 -07:00
146dbd1b89 chore(webui): update to Spanish translation (#1803)
All checks were successful
Build Docker image / docker (push) Successful in 33s
Build / build (push) Successful in 1m31s
Reviewed-on: #1803
Co-authored-by: hxedcl <hxedcl@noreply.localhost>
Co-committed-by: hxedcl <hxedcl@noreply.localhost>
2025-04-22 18:52:46 -07:00
e17d43dcb6 chore: fix slotNames duplication (#1798)
All checks were successful
Build Docker image / docker (push) Successful in 54s
Build / build (push) Successful in 1m32s
Reviewed-on: #1798
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-04-22 15:20:50 -07:00
26 changed files with 541 additions and 72 deletions

8
package-lock.json generated
View File

@ -18,7 +18,7 @@
"morgan": "^1.10.0", "morgan": "^1.10.0",
"ncp": "^2.0.0", "ncp": "^2.0.0",
"typescript": "^5.5", "typescript": "^5.5",
"warframe-public-export-plus": "^0.5.56", "warframe-public-export-plus": "^0.5.57",
"warframe-riven-info": "^0.1.2", "warframe-riven-info": "^0.1.2",
"winston": "^3.17.0", "winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0" "winston-daily-rotate-file": "^5.0.0"
@ -3789,9 +3789,9 @@
} }
}, },
"node_modules/warframe-public-export-plus": { "node_modules/warframe-public-export-plus": {
"version": "0.5.56", "version": "0.5.57",
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.56.tgz", "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.57.tgz",
"integrity": "sha512-px+J7tUm6fkSzwKkvL73ySQReDq9oM1UrHSLM3vbYGBvELM892iBgPYG45okIhScCSdwmmXTiWZTf4x/I4qiNQ==" "integrity": "sha512-CKbg7/2hSDH7I7yYSWwkrP4N2rEAEK1vNEuehj+RD9vMvl1c4u6klHLMwdh+ULxXiW4djWIlNIhs5bi/fm58Mg=="
}, },
"node_modules/warframe-riven-info": { "node_modules/warframe-riven-info": {
"version": "0.1.2", "version": "0.1.2",

View File

@ -25,7 +25,7 @@
"morgan": "^1.10.0", "morgan": "^1.10.0",
"ncp": "^2.0.0", "ncp": "^2.0.0",
"typescript": "^5.5", "typescript": "^5.5",
"warframe-public-export-plus": "^0.5.56", "warframe-public-export-plus": "^0.5.57",
"warframe-riven-info": "^0.1.2", "warframe-riven-info": "^0.1.2",
"winston": "^3.17.0", "winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0" "winston-daily-rotate-file": "^5.0.0"

View File

@ -1,4 +1,4 @@
import { getInventory } from "@/src/services/inventoryService"; import { addFusionPoints, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
@ -17,7 +17,7 @@ export const claimLibraryDailyTaskRewardController: RequestHandler = async (req,
} }
syndicate.Standing += rewardStanding; syndicate.Standing += rewardStanding;
inventory.FusionPoints += 80 * rewardQuantity; addFusionPoints(inventory, 80 * rewardQuantity);
await inventory.save(); await inventory.save();
res.json({ res.json({

View File

@ -2,7 +2,7 @@ import { toMongoDate } from "@/src/helpers/inventoryHelpers";
import { getJSONfromString } from "@/src/helpers/stringHelpers"; import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { Guild } from "@/src/models/guildModel"; import { Guild } from "@/src/models/guildModel";
import { checkClanAscensionHasRequiredContributors } from "@/src/services/guildService"; import { checkClanAscensionHasRequiredContributors } from "@/src/services/guildService";
import { getInventory } from "@/src/services/inventoryService"; import { addFusionPoints, getInventory } from "@/src/services/inventoryService";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { Types } from "mongoose"; import { Types } from "mongoose";
@ -36,7 +36,7 @@ export const contributeGuildClassController: RequestHandler = async (req, res) =
// Either way, endo is given to the contributor. // Either way, endo is given to the contributor.
const inventory = await getInventory(accountId, "FusionPoints"); const inventory = await getInventory(accountId, "FusionPoints");
inventory.FusionPoints += guild.CeremonyEndo!; addFusionPoints(inventory, guild.CeremonyEndo!);
await inventory.save(); await inventory.save();
res.json({ res.json({

View File

@ -21,10 +21,12 @@ export const entratiLabConquestModeController: RequestHandler = async (req, res)
inventory.EntratiVaultCountResetDate = new Date(weekEnd); inventory.EntratiVaultCountResetDate = new Date(weekEnd);
if (inventory.EntratiLabConquestUnlocked) { if (inventory.EntratiLabConquestUnlocked) {
inventory.EntratiLabConquestUnlocked = 0; inventory.EntratiLabConquestUnlocked = 0;
inventory.EntratiLabConquestCacheScoreMission = 0;
inventory.EntratiLabConquestActiveFrameVariants = []; inventory.EntratiLabConquestActiveFrameVariants = [];
} }
if (inventory.EchoesHexConquestUnlocked) { if (inventory.EchoesHexConquestUnlocked) {
inventory.EchoesHexConquestUnlocked = 0; inventory.EchoesHexConquestUnlocked = 0;
inventory.EchoesHexConquestCacheScoreMission = 0;
inventory.EchoesHexConquestActiveFrameVariants = []; inventory.EchoesHexConquestActiveFrameVariants = [];
inventory.EchoesHexConquestActiveStickers = []; inventory.EchoesHexConquestActiveStickers = [];
} }

View File

@ -21,7 +21,11 @@ export const loginController: RequestHandler = async (request, response) => {
const myAddress = request.host.indexOf("warframe.com") == -1 ? request.host : config.myAddress; const myAddress = request.host.indexOf("warframe.com") == -1 ? request.host : config.myAddress;
if (!account && config.autoCreateAccount && loginRequest.ClientType != "webui") { if (
!account &&
((config.autoCreateAccount && loginRequest.ClientType != "webui") ||
loginRequest.ClientType == "webui-register")
) {
try { try {
const nameFromEmail = loginRequest.email.substring(0, loginRequest.email.indexOf("@")); const nameFromEmail = loginRequest.email.substring(0, loginRequest.email.indexOf("@"));
let name = nameFromEmail || loginRequest.email.substring(1) || "SpaceNinja"; let name = nameFromEmail || loginRequest.email.substring(1) || "SpaceNinja";
@ -37,7 +41,7 @@ export const loginController: RequestHandler = async (request, response) => {
password: loginRequest.password, password: loginRequest.password,
DisplayName: name, DisplayName: name,
CountryCode: loginRequest.lang.toUpperCase(), CountryCode: loginRequest.lang.toUpperCase(),
ClientType: loginRequest.ClientType, ClientType: loginRequest.ClientType == "webui-register" ? "webui" : loginRequest.ClientType,
CrossPlatformAllowed: true, CrossPlatformAllowed: true,
ForceLogoutVersion: 0, ForceLogoutVersion: 0,
ConsentNeeded: false, ConsentNeeded: false,
@ -59,6 +63,11 @@ export const loginController: RequestHandler = async (request, response) => {
return; return;
} }
if (loginRequest.ClientType == "webui-register") {
response.status(400).json({ error: "account already exists" });
return;
}
if (!isCorrectPassword(loginRequest.password, account.password)) { if (!isCorrectPassword(loginRequest.password, account.password)) {
response.status(400).json({ error: "incorrect login data" }); response.status(400).json({ error: "incorrect login data" });
return; return;

View File

@ -6,6 +6,7 @@ import { addMissionInventoryUpdates, addMissionRewards } from "@/src/services/mi
import { getInventory } from "@/src/services/inventoryService"; import { getInventory } from "@/src/services/inventoryService";
import { getInventoryResponse } from "./inventoryController"; import { getInventoryResponse } from "./inventoryController";
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
import { IMissionInventoryUpdateResponse } from "@/src/types/missionTypes";
/* /*
**** INPUT **** **** INPUT ****
@ -71,8 +72,14 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
return; return;
} }
const { MissionRewards, inventoryChanges, credits, AffiliationMods, SyndicateXPItemReward } = const {
await addMissionRewards(inventory, missionReport, firstCompletion); MissionRewards,
inventoryChanges,
credits,
AffiliationMods,
SyndicateXPItemReward,
ConquestCompletedMissionsCount
} = await addMissionRewards(inventory, missionReport, firstCompletion);
await inventory.save(); await inventory.save();
const inventoryResponse = await getInventoryResponse(inventory, true); const inventoryResponse = await getInventoryResponse(inventory, true);
@ -86,8 +93,9 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
...inventoryUpdates, ...inventoryUpdates,
//FusionPoints: inventoryChanges?.FusionPoints, // This in combination with InventoryJson or InventoryChanges seems to just double the number of endo shown, so unsure when this is needed. //FusionPoints: inventoryChanges?.FusionPoints, // This in combination with InventoryJson or InventoryChanges seems to just double the number of endo shown, so unsure when this is needed.
SyndicateXPItemReward, SyndicateXPItemReward,
AffiliationMods AffiliationMods,
}); ConquestCompletedMissionsCount
} satisfies IMissionInventoryUpdateResponse);
}; };
/* /*

View File

@ -37,6 +37,7 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) =
const deco = component.Decos.find(x => x._id.equals(request.MoveId))!; const deco = component.Decos.find(x => x._id.equals(request.MoveId))!;
deco.Pos = request.Pos; deco.Pos = request.Pos;
deco.Rot = request.Rot; deco.Rot = request.Rot;
deco.Scale = request.Scale;
} else { } else {
const deco = const deco =
component.Decos[ component.Decos[
@ -45,6 +46,7 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) =
Type: request.Type, Type: request.Type,
Pos: request.Pos, Pos: request.Pos,
Rot: request.Rot, Rot: request.Rot,
Scale: request.Scale,
Name: request.Name, Name: request.Name,
Sockets: request.Sockets Sockets: request.Sockets
}) - 1 }) - 1
@ -113,9 +115,9 @@ interface IPlaceDecoInComponentRequest {
Type: string; Type: string;
Pos: number[]; Pos: number[];
Rot: number[]; Rot: number[];
Scale?: number;
Name?: string; Name?: string;
Sockets?: number; Sockets?: number;
Scale?: number; // only provided alongside MoveId and seems to always be 1
MoveId?: string; MoveId?: string;
ShipDeco?: boolean; ShipDeco?: boolean;
VaultDeco?: boolean; VaultDeco?: boolean;

View File

@ -8,7 +8,8 @@ import {
addConsumables, addConsumables,
freeUpSlot, freeUpSlot,
combineInventoryChanges, combineInventoryChanges,
addCrewShipRawSalvage addCrewShipRawSalvage,
addFusionPoints
} from "@/src/services/inventoryService"; } from "@/src/services/inventoryService";
import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes"; import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
import { ExportDojoRecipes } from "warframe-public-export-plus"; import { ExportDojoRecipes } from "warframe-public-export-plus";
@ -69,7 +70,7 @@ export const sellController: RequestHandler = async (req, res) => {
if (payload.SellCurrency == "SC_RegularCredits") { if (payload.SellCurrency == "SC_RegularCredits") {
inventory.RegularCredits += payload.SellPrice; inventory.RegularCredits += payload.SellPrice;
} else if (payload.SellCurrency == "SC_FusionPoints") { } else if (payload.SellCurrency == "SC_FusionPoints") {
inventory.FusionPoints += payload.SellPrice; addFusionPoints(inventory, payload.SellPrice);
} else if (payload.SellCurrency == "SC_PrimeBucks") { } else if (payload.SellCurrency == "SC_PrimeBucks") {
addMiscItems(inventory, [ addMiscItems(inventory, [
{ {

View File

@ -1,12 +1,16 @@
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService"; import { addFusionPoints, getInventory } from "@/src/services/inventoryService";
export const addCurrencyController: RequestHandler = async (req, res) => { export const addCurrencyController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId);
const request = req.body as IAddCurrencyRequest; const request = req.body as IAddCurrencyRequest;
const inventory = await getInventory(accountId, request.currency);
if (request.currency == "FusionPoints") {
addFusionPoints(inventory, request.delta);
} else {
inventory[request.currency] += request.delta; inventory[request.currency] += request.delta;
}
await inventory.save(); await inventory.save();
res.end(); res.end();
}; };

View File

@ -115,6 +115,7 @@ const getItemListsController: RequestHandler = (req, response) => {
let name = getString(item.name, lang); let name = getString(item.name, lang);
if ("dissectionParts" in item) { if ("dissectionParts" in item) {
name = getString("/Lotus/Language/Fish/FishDisplayName", lang).split("|FISH_NAME|").join(name); name = getString("/Lotus/Language/Fish/FishDisplayName", lang).split("|FISH_NAME|").join(name);
if (item.syndicateTag == "CetusSyndicate") {
if (uniqueName.indexOf("Large") != -1) { if (uniqueName.indexOf("Large") != -1) {
name = name.split("|FISH_SIZE|").join(getString("/Lotus/Language/Fish/FishSizeLargeAbbrev", lang)); name = name.split("|FISH_SIZE|").join(getString("/Lotus/Language/Fish/FishSizeLargeAbbrev", lang));
} else if (uniqueName.indexOf("Medium") != -1) { } else if (uniqueName.indexOf("Medium") != -1) {
@ -122,6 +123,21 @@ const getItemListsController: RequestHandler = (req, response) => {
} else { } else {
name = name.split("|FISH_SIZE|").join(getString("/Lotus/Language/Fish/FishSizeSmallAbbrev", lang)); name = name.split("|FISH_SIZE|").join(getString("/Lotus/Language/Fish/FishSizeSmallAbbrev", lang));
} }
} else {
if (uniqueName.indexOf("Large") != -1) {
name = name
.split("|FISH_SIZE|")
.join(getString("/Lotus/Language/SolarisVenus/RobofishAgeCategoryElderAbbrev", lang));
} else if (uniqueName.indexOf("Medium") != -1) {
name = name
.split("|FISH_SIZE|")
.join(getString("/Lotus/Language/SolarisVenus/RobofishAgeCategoryMatureAbbrev", lang));
} else {
name = name
.split("|FISH_SIZE|")
.join(getString("/Lotus/Language/SolarisVenus/RobofishAgeCategoryYoungAbbrev", lang));
}
}
} }
if ( if (
name && name &&

View File

@ -23,6 +23,7 @@ const dojoDecoSchema = new Schema<IDojoDecoDatabase>({
Type: String, Type: String,
Pos: [Number], Pos: [Number],
Rot: [Number], Rot: [Number],
Scale: Number,
Name: String, Name: String,
Sockets: Number, Sockets: Number,
RegularCredits: Number, RegularCredits: Number,

View File

@ -222,6 +222,7 @@ export const getDojoClient = async (
Type: deco.Type, Type: deco.Type,
Pos: deco.Pos, Pos: deco.Pos,
Rot: deco.Rot, Rot: deco.Rot,
Scale: deco.Scale,
Name: deco.Name, Name: deco.Name,
Sockets: deco.Sockets, Sockets: deco.Sockets,
PictureFrameInfo: deco.PictureFrameInfo PictureFrameInfo: deco.PictureFrameInfo

View File

@ -37,6 +37,7 @@ import {
} from "../types/inventoryTypes/inventoryTypes"; } from "../types/inventoryTypes/inventoryTypes";
import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel"; import { TInventoryDatabaseDocument } from "../models/inventoryModels/inventoryModel";
import { ILoadoutConfigDatabase, ILoadoutDatabase } from "../types/saveLoadoutTypes"; import { ILoadoutConfigDatabase, ILoadoutDatabase } from "../types/saveLoadoutTypes";
import { slotNames } from "../types/purchaseTypes";
const convertDate = (value: IMongoDate): Date => { const convertDate = (value: IMongoDate): Date => {
return new Date(parseInt(value.$date.$numberLong)); return new Date(parseInt(value.$date.$numberLong));
@ -212,20 +213,7 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<
replaceArray<IOperatorConfigDatabase>(db[key], client[key].map(convertOperatorConfig)); replaceArray<IOperatorConfigDatabase>(db[key], client[key].map(convertOperatorConfig));
} }
} }
for (const key of [ for (const key of slotNames) {
"SuitBin",
"WeaponBin",
"SentinelBin",
"SpaceSuitBin",
"SpaceWeaponBin",
"PvpBonusLoadoutBin",
"PveBonusLoadoutBin",
"RandomModBin",
"MechBin",
"CrewMemberBin",
"OperatorAmpBin",
"CrewShipSalvageBin"
] as const) {
if (client[key] !== undefined) { if (client[key] !== undefined) {
replaceSlots(db[key], client[key]); replaceSlots(db[key], client[key]);
} }

View File

@ -532,7 +532,11 @@ export const addItem = async (
} }
return { return {
...inventoryChanges, ...inventoryChanges,
...occupySlot(inventory, InventorySlot.WEAPONS, premiumPurchase) ...occupySlot(
inventory,
productCategoryToInventoryBin(weapon.productCategory) ?? InventorySlot.WEAPONS,
premiumPurchase
)
}; };
} else { } else {
// Modular weapon parts // Modular weapon parts
@ -580,7 +584,7 @@ export const addItem = async (
} }
if (typeName in ExportFusionBundles) { if (typeName in ExportFusionBundles) {
const fusionPointsTotal = ExportFusionBundles[typeName].fusionPoints * quantity; const fusionPointsTotal = ExportFusionBundles[typeName].fusionPoints * quantity;
inventory.FusionPoints += fusionPointsTotal; addFusionPoints(inventory, fusionPointsTotal);
return { return {
FusionPoints: fusionPointsTotal FusionPoints: fusionPointsTotal
}; };
@ -821,7 +825,8 @@ const addSentinel = (
const features = premiumPurchase ? EquipmentFeatures.DOUBLE_CAPACITY : undefined; const features = premiumPurchase ? EquipmentFeatures.DOUBLE_CAPACITY : undefined;
const sentinelIndex = const sentinelIndex =
inventory.Sentinels.push({ ItemType: sentinelName, Configs: configs, XP: 0, Features: features }) - 1; inventory.Sentinels.push({ ItemType: sentinelName, Configs: configs, XP: 0, Features: features, IsNew: true }) -
1;
inventoryChanges.Sentinels ??= []; inventoryChanges.Sentinels ??= [];
inventoryChanges.Sentinels.push(inventory.Sentinels[sentinelIndex].toJSON<IEquipmentClient>()); inventoryChanges.Sentinels.push(inventory.Sentinels[sentinelIndex].toJSON<IEquipmentClient>());
@ -1069,6 +1074,15 @@ export const updateCurrency = (
return currencyChanges; return currencyChanges;
}; };
export const addFusionPoints = (inventory: TInventoryDatabaseDocument, add: number): number => {
if (inventory.FusionPoints + add > 2147483647) {
logger.warn(`capping FusionPoints balance at 2147483647`);
add = 2147483647 - inventory.FusionPoints;
}
inventory.FusionPoints += add;
return add;
};
const standingLimitBinToInventoryKey: Record< const standingLimitBinToInventoryKey: Record<
Exclude<TStandingLimitBin, "STANDING_LIMIT_BIN_NONE">, Exclude<TStandingLimitBin, "STANDING_LIMIT_BIN_NONE">,
keyof IDailyAffiliations keyof IDailyAffiliations

View File

@ -19,6 +19,7 @@ import {
addCrewShipRawSalvage, addCrewShipRawSalvage,
addEmailItem, addEmailItem,
addFocusXpIncreases, addFocusXpIncreases,
addFusionPoints,
addFusionTreasures, addFusionTreasures,
addGearExpByCategory, addGearExpByCategory,
addItem, addItem,
@ -43,7 +44,7 @@ import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/invento
import { getEntriesUnsafe } from "@/src/utils/ts-utils"; import { getEntriesUnsafe } from "@/src/utils/ts-utils";
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes"; import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { handleStoreItemAcquisition } from "./purchaseService"; import { handleStoreItemAcquisition } from "./purchaseService";
import { IMissionReward } from "../types/missionTypes"; import { IMissionCredits, IMissionReward } from "../types/missionTypes";
import { crackRelic } from "@/src/helpers/relicHelper"; import { crackRelic } from "@/src/helpers/relicHelper";
import { createMessage } from "./inboxService"; import { createMessage } from "./inboxService";
import kuriaMessage50 from "@/static/fixed_responses/kuriaMessages/fiftyPercent.json"; import kuriaMessage50 from "@/static/fixed_responses/kuriaMessages/fiftyPercent.json";
@ -287,14 +288,14 @@ export const addMissionInventoryUpdates = async (
addShipDecorations(inventory, value); addShipDecorations(inventory, value);
break; break;
case "FusionBundles": { case "FusionBundles": {
let fusionPoints = 0; let fusionPointsDelta = 0;
for (const fusionBundle of value) { for (const fusionBundle of value) {
const fusionPointsTotal = fusionPointsDelta += addFusionPoints(
ExportFusionBundles[fusionBundle.ItemType].fusionPoints * fusionBundle.ItemCount; inventory,
inventory.FusionPoints += fusionPointsTotal; ExportFusionBundles[fusionBundle.ItemType].fusionPoints * fusionBundle.ItemCount
fusionPoints += fusionPointsTotal; );
} }
inventoryChanges.FusionPoints = fusionPoints; inventoryChanges.FusionPoints = fusionPointsDelta;
break; break;
} }
case "EmailItems": { case "EmailItems": {
@ -586,8 +587,140 @@ interface AddMissionRewardsReturnType {
credits?: IMissionCredits; credits?: IMissionCredits;
AffiliationMods?: IAffiliationMods[]; AffiliationMods?: IAffiliationMods[];
SyndicateXPItemReward?: number; SyndicateXPItemReward?: number;
ConquestCompletedMissionsCount?: number;
} }
interface IConquestReward {
at: number;
pool: IRngResult[];
}
const labConquestRewards: IConquestReward[] = [
{
at: 5,
pool: ExportRewards[
"/Lotus/Types/Game/MissionDecks/EntratiLabConquestRewards/EntratiLabConquestSilverRewards"
][0] as IRngResult[]
},
{
at: 10,
pool: ExportRewards[
"/Lotus/Types/Game/MissionDecks/EntratiLabConquestRewards/EntratiLabConquestSilverRewards"
][0] as IRngResult[]
},
{
at: 15,
pool: [
{
type: "/Lotus/StoreItems/Types/Gameplay/EntratiLab/Resources/EntratiLanthornBundle",
itemCount: 3,
probability: 1
}
]
},
{
at: 20,
pool: ExportRewards[
"/Lotus/Types/Game/MissionDecks/EntratiLabConquestRewards/EntratiLabConquestGoldRewards"
][0] as IRngResult[]
},
{
at: 28,
pool: [
{
type: "/Lotus/StoreItems/Types/Items/MiscItems/DistillPoints",
itemCount: 20,
probability: 1
}
]
},
{
at: 31,
pool: ExportRewards[
"/Lotus/Types/Game/MissionDecks/EntratiLabConquestRewards/EntratiLabConquestGoldRewards"
][0] as IRngResult[]
},
{
at: 34,
pool: ExportRewards[
"/Lotus/Types/Game/MissionDecks/EntratiLabConquestRewards/EntratiLabConquestArcaneRewards"
][0] as IRngResult[]
},
{
at: 37,
pool: [
{
type: "/Lotus/StoreItems/Types/Items/MiscItems/DistillPoints",
itemCount: 50,
probability: 1
}
]
}
];
const hexConquestRewards: IConquestReward[] = [
{
at: 5,
pool: ExportRewards[
"/Lotus/Types/Game/MissionDecks/1999ConquestRewards/1999ConquestSilverRewards"
][0] as IRngResult[]
},
{
at: 10,
pool: ExportRewards[
"/Lotus/Types/Game/MissionDecks/1999ConquestRewards/1999ConquestSilverRewards"
][0] as IRngResult[]
},
{
at: 15,
pool: [
{
type: "/Lotus/StoreItems/Types/BoosterPacks/1999StickersPackEchoesArchimedea",
itemCount: 1,
probability: 1
}
]
},
{
at: 20,
pool: ExportRewards[
"/Lotus/Types/Game/MissionDecks/1999ConquestRewards/1999ConquestGoldRewards"
][0] as IRngResult[]
},
{
at: 28,
pool: [
{
type: "/Lotus/StoreItems/Types/Items/MiscItems/1999ConquestBucks",
itemCount: 6,
probability: 1
}
]
},
{
at: 31,
pool: ExportRewards[
"/Lotus/Types/Game/MissionDecks/1999ConquestRewards/1999ConquestGoldRewards"
][0] as IRngResult[]
},
{
at: 34,
pool: ExportRewards[
"/Lotus/Types/Game/MissionDecks/1999ConquestRewards/1999ConquestArcaneRewards"
][0] as IRngResult[]
},
{
at: 37,
pool: [
{
type: "/Lotus/StoreItems/Types/Items/MiscItems/1999ConquestBucks",
itemCount: 9,
probability: 1
}
]
}
];
//TODO: return type of partial missioninventoryupdate response //TODO: return type of partial missioninventoryupdate response
export const addMissionRewards = async ( export const addMissionRewards = async (
inventory: TInventoryDatabaseDocument, inventory: TInventoryDatabaseDocument,
@ -620,6 +753,7 @@ export const addMissionRewards = async (
const inventoryChanges: IInventoryChanges = {}; const inventoryChanges: IInventoryChanges = {};
const AffiliationMods: IAffiliationMods[] = []; const AffiliationMods: IAffiliationMods[] = [];
let SyndicateXPItemReward; let SyndicateXPItemReward;
let ConquestCompletedMissionsCount;
let missionCompletionCredits = 0; let missionCompletionCredits = 0;
//inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display //inventory change is what the client has not rewarded itself, also the client needs to know the credit changes for display
@ -691,6 +825,62 @@ export const addMissionRewards = async (
}); });
} }
if (rewardInfo.ConquestCompleted !== undefined) {
let score = 1;
if (rewardInfo.ConquestHardModeActive === 1) score += 3;
if (rewardInfo.ConquestPersonalModifiersActive !== undefined)
score += rewardInfo.ConquestPersonalModifiersActive;
if (rewardInfo.ConquestEquipmentSuggestionsFulfilled !== undefined)
score += rewardInfo.ConquestEquipmentSuggestionsFulfilled;
score *= rewardInfo.ConquestCompleted + 1;
if (rewardInfo.ConquestCompleted == 2 && rewardInfo.ConquestHardModeActive === 1) score += 1;
logger.debug(`completed conquest mission ${rewardInfo.ConquestCompleted + 1} for a score of ${score}`);
const conquestType = rewardInfo.ConquestType;
const conquestNode =
conquestType == "HexConquest" ? "EchoesHexConquestHardModeUnlocked" : "EntratiLabConquestHardModeUnlocked";
if (score >= 25 && inventory.NodeIntrosCompleted.indexOf(conquestNode) == -1)
inventory.NodeIntrosCompleted.push(conquestNode);
if (conquestType == "HexConquest") {
inventory.EchoesHexConquestCacheScoreMission ??= 0;
if (score > inventory.EchoesHexConquestCacheScoreMission) {
for (const reward of hexConquestRewards) {
if (score >= reward.at && inventory.EchoesHexConquestCacheScoreMission < reward.at) {
const rolled = getRandomReward(reward.pool)!;
logger.debug(`rolled hex conquest reward for reaching ${reward.at} points`, rolled);
MissionRewards.push({
StoreItem: rolled.type,
ItemCount: rolled.itemCount
});
}
}
inventory.EchoesHexConquestCacheScoreMission = score;
}
} else {
inventory.EntratiLabConquestCacheScoreMission ??= 0;
if (score > inventory.EntratiLabConquestCacheScoreMission) {
for (const reward of labConquestRewards) {
if (score >= reward.at && inventory.EntratiLabConquestCacheScoreMission < reward.at) {
const rolled = getRandomReward(reward.pool)!;
logger.debug(`rolled lab conquest reward for reaching ${reward.at} points`, rolled);
MissionRewards.push({
StoreItem: rolled.type,
ItemCount: rolled.itemCount
});
}
}
inventory.EntratiLabConquestCacheScoreMission = score;
}
}
ConquestCompletedMissionsCount = rewardInfo.ConquestCompleted == 2 ? 0 : rewardInfo.ConquestCompleted + 1;
}
for (const reward of MissionRewards) { for (const reward of MissionRewards) {
const inventoryChange = await handleStoreItemAcquisition( const inventoryChange = await handleStoreItemAcquisition(
reward.StoreItem, reward.StoreItem,
@ -882,16 +1072,16 @@ export const addMissionRewards = async (
} }
} }
return { inventoryChanges, MissionRewards, credits, AffiliationMods, SyndicateXPItemReward }; return {
inventoryChanges,
MissionRewards,
credits,
AffiliationMods,
SyndicateXPItemReward,
ConquestCompletedMissionsCount
};
}; };
interface IMissionCredits {
MissionCredits: number[];
CreditBonus: number[];
TotalCredits: number[];
DailyMissionBonus?: boolean;
}
//creditBonus is not entirely accurate. //creditBonus is not entirely accurate.
//TODO: consider ActiveBoosters //TODO: consider ActiveBoosters
export const addCredits = ( export const addCredits = (

View File

@ -1,10 +1,18 @@
import staticWorldState from "@/static/fixed_responses/worldState/worldState.json"; import staticWorldState from "@/static/fixed_responses/worldState/worldState.json";
import sortieTilesets from "@/static/fixed_responses/worldState/sortieTilesets.json";
import { buildConfig } from "@/src/services/buildConfigService"; import { buildConfig } from "@/src/services/buildConfigService";
import { unixTimesInMs } from "@/src/constants/timeConstants"; import { unixTimesInMs } from "@/src/constants/timeConstants";
import { config } from "@/src/services/configService"; import { config } from "@/src/services/configService";
import { CRng } from "@/src/services/rngService"; import { CRng } from "@/src/services/rngService";
import { eMissionType, ExportNightwave, ExportRegions, IRegion } from "warframe-public-export-plus"; import { eMissionType, ExportNightwave, ExportRegions, IRegion } from "warframe-public-export-plus";
import { ICalendarDay, ICalendarSeason, ILiteSortie, ISeasonChallenge, IWorldState } from "../types/worldStateTypes"; import {
ICalendarDay,
ICalendarSeason,
ILiteSortie,
ISeasonChallenge,
ISortieMission,
IWorldState
} from "../types/worldStateTypes";
const sortieBosses = [ const sortieBosses = [
"SORTIE_BOSS_HYENA", "SORTIE_BOSS_HYENA",
@ -263,12 +271,12 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
sortieFactionToFactionIndexes[sortieBossToFaction[boss]].includes(value.factionIndex!) && sortieFactionToFactionIndexes[sortieBossToFaction[boss]].includes(value.factionIndex!) &&
!isArchwingMission(value) && !isArchwingMission(value) &&
value.missionIndex != 0 && // Exclude MT_ASSASSINATION value.missionIndex != 0 && // Exclude MT_ASSASSINATION
value.missionIndex != 5 && // Exclude MT_CAPTURE
value.missionIndex != 10 && // Exclude MT_PVP (for relays) value.missionIndex != 10 && // Exclude MT_PVP (for relays)
value.missionIndex != 21 && // Exclude MT_PURIFY value.missionIndex != 21 && // Exclude MT_PURIFY
value.missionIndex != 22 && // Exclude MT_ARENA value.missionIndex != 22 && // Exclude MT_ARENA
value.missionIndex != 23 && // Exclude MT_JUNCTION value.missionIndex != 23 && // Exclude MT_JUNCTION
value.missionIndex <= 28 (value.missionIndex != 28 || value.systemIndex == 2) && // MT_LANDSCAPE only on Earth
value.missionIndex < 29
) { ) {
if (!availableMissionIndexes.includes(value.missionIndex)) { if (!availableMissionIndexes.includes(value.missionIndex)) {
availableMissionIndexes.push(value.missionIndex); availableMissionIndexes.push(value.missionIndex);
@ -277,7 +285,7 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
} }
} }
const selectedNodes: { missionType: string; modifierType: string; node: string }[] = []; const selectedNodes: ISortieMission[] = [];
const missionTypes = new Set(); const missionTypes = new Set();
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
@ -298,11 +306,21 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
const modifierType = rng.randomElement(filteredModifiers); const modifierType = rng.randomElement(filteredModifiers);
if (boss == "SORTIE_BOSS_PHORID") { if (boss == "SORTIE_BOSS_PHORID") {
selectedNodes.push({ missionType: "MT_ASSASSINATION", modifierType, node }); selectedNodes.push({
missionType: "MT_ASSASSINATION",
modifierType,
node,
tileset: sortieTilesets[node as keyof typeof sortieTilesets]
});
nodes.splice(randomIndex, 1); nodes.splice(randomIndex, 1);
continue; continue;
} else if (sortieBossNode[boss]) { } else if (sortieBossNode[boss]) {
selectedNodes.push({ missionType: "MT_ASSASSINATION", modifierType, node: sortieBossNode[boss] }); selectedNodes.push({
missionType: "MT_ASSASSINATION",
modifierType,
node: sortieBossNode[boss],
tileset: sortieTilesets[sortieBossNode[boss] as keyof typeof sortieTilesets]
});
continue; continue;
} }
} }
@ -321,7 +339,12 @@ const pushSortieIfRelevant = (worldState: IWorldState, day: number): void => {
const modifierType = rng.randomElement(filteredModifiers); const modifierType = rng.randomElement(filteredModifiers);
selectedNodes.push({ missionType, modifierType, node }); selectedNodes.push({
missionType,
modifierType,
node,
tileset: sortieTilesets[node as keyof typeof sortieTilesets]
});
nodes.splice(randomIndex, 1); nodes.splice(randomIndex, 1);
missionTypes.add(missionType); missionTypes.add(missionType);
} }

View File

@ -206,6 +206,7 @@ export interface IDojoDecoClient {
Type: string; Type: string;
Pos: number[]; Pos: number[];
Rot: number[]; Rot: number[];
Scale?: number;
Name?: string; // for teleporters Name?: string; // for teleporters
Sockets?: number; Sockets?: number;
RegularCredits?: number; RegularCredits?: number;

View File

@ -1,3 +1,5 @@
import { IAffiliationMods, IInventoryChanges } from "./purchaseTypes";
export const inventoryFields = ["RawUpgrades", "MiscItems", "Consumables", "Recipes"] as const; export const inventoryFields = ["RawUpgrades", "MiscItems", "Consumables", "Recipes"] as const;
export type IInventoryFieldType = (typeof inventoryFields)[number]; export type IInventoryFieldType = (typeof inventoryFields)[number];
@ -11,3 +13,20 @@ export interface IMissionReward {
FromEnemyCache?: boolean; FromEnemyCache?: boolean;
IsStrippedItem?: boolean; IsStrippedItem?: boolean;
} }
export interface IMissionCredits {
MissionCredits: number[];
CreditBonus: number[];
TotalCredits: number[];
DailyMissionBonus?: boolean;
}
export interface IMissionInventoryUpdateResponse extends Partial<IMissionCredits> {
ConquestCompletedMissionsCount?: number;
InventoryJson?: string;
MissionRewards?: IMissionReward[];
InventoryChanges?: IInventoryChanges;
FusionPoints?: number;
SyndicateXPItemReward?: number;
AffiliationMods?: IAffiliationMods[];
}

View File

@ -103,6 +103,7 @@ export const slotNames = [
"WeaponBin", "WeaponBin",
"MechBin", "MechBin",
"PveBonusLoadoutBin", "PveBonusLoadoutBin",
"PvpBonusLoadoutBin",
"SentinelBin", "SentinelBin",
"SpaceSuitBin", "SpaceSuitBin",
"SpaceWeaponBin", "SpaceWeaponBin",

View File

@ -125,6 +125,7 @@ export type IMissionInventoryUpdateRequest = {
wagerTier?: number; // the index wagerTier?: number; // the index
creditsFee?: number; // the index creditsFee?: number; // the index
InvasionProgress?: IInvasionProgressClient[]; InvasionProgress?: IInvasionProgressClient[];
ConquestMissionsCompleted?: number;
} & { } & {
[K in TEquipmentKey]?: IEquipmentClient[]; [K in TEquipmentKey]?: IEquipmentClient[];
}; };
@ -150,7 +151,12 @@ export interface IRewardInfo {
PurgatoryRewardQualifications?: string; PurgatoryRewardQualifications?: string;
rewardSeed?: number | bigint; rewardSeed?: number | bigint;
periodicMissionTag?: string; periodicMissionTag?: string;
ConquestType?: string;
ConquestCompleted?: number;
ConquestEquipmentSuggestionsFulfilled?: number;
ConquestPersonalModifiersActive?: number;
ConquestStickersActive?: number;
ConquestHardModeActive?: number;
// for bounties, only EOM_AFK and node are given from above, plus: // for bounties, only EOM_AFK and node are given from above, plus:
JobTier?: number; JobTier?: number;
jobId?: string; jobId?: string;

View File

@ -97,6 +97,13 @@ export interface ISortie {
}[]; }[];
} }
export interface ISortieMission {
missionType: string;
modifierType: string;
node: string;
tileset: string;
}
export interface ILiteSortie { export interface ILiteSortie {
_id: IOid; _id: IOid;
Activation: IMongoDate; Activation: IMongoDate;

View File

@ -0,0 +1,175 @@
{
"SettlementNode1": "CorpusShipTileset",
"SettlementNode11": "CorpusShipTileset",
"SettlementNode12": "CorpusShipTileset",
"SettlementNode14": "CorpusShipTileset",
"SettlementNode15": "CorpusShipTileset",
"SettlementNode2": "CorpusShipTileset",
"SettlementNode20": "CorpusShipTileset",
"SettlementNode3": "CorpusShipTileset",
"SolNode1": "CorpusOutpostTileset",
"SolNode10": "CorpusGasCityTileset",
"SolNode100": "CorpusGasCityTileset",
"SolNode101": "CorpusOutpostTileset",
"SolNode102": "CorpusShipTileset",
"SolNode103": "GrineerAsteroidTileset",
"SolNode104": "CorpusShipTileset",
"SolNode105": "GrineerOceanTilesetAnywhere",
"SolNode106": "GrineerSettlementTileset",
"SolNode107": "CorpusOutpostTileset",
"SolNode108": "GrineerAsteroidTileset",
"SolNode109": "CorpusOutpostTileset",
"SolNode11": "GrineerSettlementTileset",
"SolNode113": "GrineerSettlementTileset",
"SolNode118": "CorpusShipTileset",
"SolNode119": "GrineerAsteroidTileset",
"SolNode12": "GrineerAsteroidTileset",
"SolNode121": "CorpusGasCityTileset",
"SolNode122": "GrineerOceanTileset",
"SolNode123": "CorpusShipTileset",
"SolNode125": "CorpusGasCityTileset",
"SolNode126": "CorpusGasCityTileset",
"SolNode127": "CorpusShipTileset",
"SolNode128": "CorpusOutpostTileset",
"SolNode130": "GrineerAsteroidTileset",
"SolNode131": "GrineerShipyardsTileset",
"SolNode132": "GrineerShipyardsTileset",
"SolNode135": "GrineerGalleonTileset",
"SolNode137": "GrineerShipyardsTileset",
"SolNode138": "GrineerShipyardsTileset",
"SolNode139": "GrineerShipyardsTileset",
"SolNode14": "CorpusIcePlanetTilesetCaves",
"SolNode140": "GrineerShipyardsTileset",
"SolNode141": "GrineerShipyardsTileset",
"SolNode144": "GrineerShipyardsTileset",
"SolNode146": "GrineerAsteroidTileset",
"SolNode147": "GrineerShipyardsTileset",
"SolNode149": "GrineerShipyardsTileset",
"SolNode15": "GrineerGalleonTileset",
"SolNode16": "GrineerSettlementTileset",
"SolNode162": "InfestedCorpusShipTileset",
"SolNode164": "InfestedCorpusShipTileset",
"SolNode166": "InfestedCorpusShipTileset",
"SolNode17": "CorpusShipTileset",
"SolNode171": "InfestedCorpusShipTileset",
"SolNode172": "CorpusShipTileset",
"SolNode173": "InfestedCorpusShipTileset",
"SolNode175": "InfestedCorpusShipTileset",
"SolNode177": "GrineerGalleonTileset",
"SolNode18": "GrineerAsteroidTileset",
"SolNode181": "GrineerAsteroidTileset",
"SolNode184": "GrineerGalleonTileset",
"SolNode185": "GrineerGalleonTileset",
"SolNode187": "GrineerAsteroidTileset",
"SolNode188": "GrineerGalleonTileset",
"SolNode189": "GrineerGalleonTileset",
"SolNode19": "GrineerAsteroidTileset",
"SolNode191": "GrineerShipyardsTileset",
"SolNode193": "GrineerAsteroidTileset",
"SolNode195": "GrineerGalleonTileset",
"SolNode196": "GrineerGalleonTileset",
"SolNode2": "CorpusOutpostTileset",
"SolNode20": "GrineerGalleonTileset",
"SolNode203": "CorpusIcePlanetTileset",
"SolNode205": "CorpusIcePlanetTileset",
"SolNode209": "CorpusIcePlanetTileset",
"SolNode21": "CorpusOutpostTileset",
"SolNode210": "CorpusIcePlanetTileset",
"SolNode211": "CorpusIcePlanetTileset",
"SolNode212": "CorpusIcePlanetTileset",
"SolNode214": "CorpusIcePlanetTileset",
"SolNode215": "CorpusShipTileset",
"SolNode216": "CorpusIcePlanetTileset",
"SolNode217": "CorpusIcePlanetTileset",
"SolNode22": "CorpusOutpostTileset",
"SolNode220": "CorpusIcePlanetTileset",
"SolNode223": "GrineerAsteroidTileset",
"SolNode224": "GrineerGalleonTileset",
"SolNode225": "GrineerGalleonTileset",
"SolNode226": "GrineerGalleonTileset",
"SolNode228": "EidolonTileset",
"SolNode23": "CorpusShipTileset",
"SolNode24": "GrineerForestTileset",
"SolNode25": "CorpusGasCityTileset",
"SolNode26": "GrineerForestTileset",
"SolNode30": "GrineerSettlementTileset",
"SolNode300": "OrokinMoonTilesetGrineer",
"SolNode301": "OrokinMoonTilesetGrineer",
"SolNode302": "OrokinMoonTilesetCorpus",
"SolNode304": "OrokinMoonTilesetCorpus",
"SolNode305": "OrokinMoonTilesetGrineer",
"SolNode306": "OrokinMoonTilesetCorpus",
"SolNode307": "OrokinMoonTilesetCorpus",
"SolNode308": "OrokinMoonTilesetCorpus",
"SolNode31": "GrineerGalleonTileset",
"SolNode32": "GrineerGalleonTileset",
"SolNode36": "GrineerSettlementTileset",
"SolNode38": "CorpusOutpostTileset",
"SolNode39": "GrineerForestTileset",
"SolNode4": "CorpusShipTileset",
"SolNode400": "OrokinVoidTileset",
"SolNode401": "OrokinVoidTileset",
"SolNode402": "OrokinVoidTileset",
"SolNode403": "OrokinVoidTileset",
"SolNode404": "OrokinVoidTileset",
"SolNode405": "OrokinVoidTileset",
"SolNode406": "OrokinVoidTileset",
"SolNode407": "OrokinVoidTileset",
"SolNode408": "OrokinVoidTileset",
"SolNode409": "OrokinVoidTileset",
"SolNode41": "GrineerSettlementTileset",
"SolNode410": "OrokinVoidTileset",
"SolNode412": "OrokinVoidTileset",
"SolNode42": "GrineerGalleonTileset",
"SolNode43": "CorpusOutpostTileset",
"SolNode45": "GrineerSettlementTileset",
"SolNode46": "GrineerSettlementTileset",
"SolNode48": "CorpusOutpostTileset",
"SolNode49": "CorpusShipTileset",
"SolNode50": "GrineerAsteroidTileset",
"SolNode51": "CorpusOutpostTileset",
"SolNode53": "CorpusGasCityTileset",
"SolNode56": "CorpusShipTileset",
"SolNode57": "CorpusOutpostTileset",
"SolNode58": "GrineerSettlementTileset",
"SolNode59": "GrineerForestTileset",
"SolNode6": "CorpusOutpostTileset",
"SolNode61": "CorpusShipTileset",
"SolNode62": "CorpusIcePlanetTilesetCaves",
"SolNode64": "GrineerOceanTileset",
"SolNode66": "CorpusOutpostTileset",
"SolNode67": "GrineerAsteroidTileset",
"SolNode68": "GrineerGalleonTileset",
"SolNode70": "GrineerGalleonTileset",
"SolNode706": "OrokinDerelictTileset",
"SolNode707": "OrokinDerelictTileset",
"SolNode708": "OrokinDerelictTileset",
"SolNode709": "OrokinDerelictTileset",
"SolNode710": "OrokinDerelictTileset",
"SolNode711": "OrokinDerelictTileset",
"SolNode712": "OrokinDerelictTileset",
"SolNode713": "OrokinDerelictTileset",
"SolNode72": "CorpusOutpostTileset",
"SolNode73": "CorpusGasCityTileset",
"SolNode74": "CorpusGasCityTileset",
"SolNode741": "GrineerFortressTileset",
"SolNode742": "GrineerFortressTileset",
"SolNode743": "GrineerFortressTileset",
"SolNode744": "GrineerFortressTileset",
"SolNode745": "GrineerFortressTileset",
"SolNode746": "GrineerFortressTileset",
"SolNode747": "GrineerFortressTileset",
"SolNode748": "GrineerFortressTileset",
"SolNode75": "GrineerForestTileset",
"SolNode76": "CorpusShipTileset",
"SolNode78": "CorpusShipTileset",
"SolNode79": "GrineerForestTileset",
"SolNode81": "CorpusShipTileset",
"SolNode82": "GrineerGalleonTileset",
"SolNode84": "CorpusIcePlanetTilesetCaves",
"SolNode88": "CorpusShipTileset",
"SolNode93": "GrineerAsteroidTileset",
"SolNode96": "GrineerGalleonTileset",
"SolNode97": "CorpusGasCityTileset",
"SolNode99": "GrineerSettlementTileset"
}

View File

@ -13,6 +13,7 @@ function doLogin() {
} }
function loginFromLocalStorage() { function loginFromLocalStorage() {
const isRegister = registerSubmit;
doLoginRequest( doLoginRequest(
data => { data => {
if (single.getCurrentPath() == "/webui/") { if (single.getCurrentPath() == "/webui/") {
@ -28,7 +29,7 @@ function loginFromLocalStorage() {
}, },
() => { () => {
logout(); logout();
alert("Login failed"); alert(isRegister ? "Registration failed. Account already exists?" : "Login failed");
} }
); );
} }
@ -44,7 +45,7 @@ function doLoginRequest(succ_cb, fail_cb) {
s: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==", // signature of some kind s: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==", // signature of some kind
lang: "en", lang: "en",
date: 1501230947855458660, // ??? date: 1501230947855458660, // ???
ClientType: registerSubmit ? "" : "webui", ClientType: registerSubmit ? "webui-register" : "webui",
PS: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==" // anti-cheat data PS: "W0RFXVN0ZXZlIGxpa2VzIGJpZyBidXR0cw==" // anti-cheat data
}) })
}); });

View File

@ -60,7 +60,7 @@ dict = {
login_emailLabel: `E-Mail-Adresse`, login_emailLabel: `E-Mail-Adresse`,
login_passwordLabel: `Passwort`, login_passwordLabel: `Passwort`,
login_loginButton: `Anmelden`, login_loginButton: `Anmelden`,
login_registerButton: `[UNTRANSLATED] Register`, login_registerButton: `Registrieren`,
navbar_logout: `Abmelden`, navbar_logout: `Abmelden`,
navbar_renameAccount: `Account umbenennen`, navbar_renameAccount: `Account umbenennen`,
navbar_deleteAccount: `Account löschen`, navbar_deleteAccount: `Account löschen`,
@ -116,7 +116,7 @@ dict = {
mods_rivens: `Rivens`, mods_rivens: `Rivens`,
mods_mods: `Mods`, mods_mods: `Mods`,
mods_bulkAddMods: `Fehlende Mods hinzufügen`, mods_bulkAddMods: `Fehlende Mods hinzufügen`,
mods_removeUnranked: `[UNTRANSLATED] Remove Unranked Mods`, mods_removeUnranked: `Mods ohne Rang entfernen`,
cheats_administratorRequirement: `Du musst Administrator sein, um diese Funktion nutzen zu können. Um Administrator zu werden, füge <code>|DISPLAYNAME|</code> zu <code>administratorNames</code> in der config.json hinzu.`, cheats_administratorRequirement: `Du musst Administrator sein, um diese Funktion nutzen zu können. Um Administrator zu werden, füge <code>|DISPLAYNAME|</code> zu <code>administratorNames</code> in der config.json hinzu.`,
cheats_server: `Server`, cheats_server: `Server`,
cheats_skipTutorial: `Tutorial überspringen`, cheats_skipTutorial: `Tutorial überspringen`,

View File

@ -60,7 +60,7 @@ dict = {
login_emailLabel: `Dirección de correo electrónico`, login_emailLabel: `Dirección de correo electrónico`,
login_passwordLabel: `Contraseña`, login_passwordLabel: `Contraseña`,
login_loginButton: `Iniciar sesión`, login_loginButton: `Iniciar sesión`,
login_registerButton: `[UNTRANSLATED] Register`, login_registerButton: `Registrarse`,
navbar_logout: `Cerrar sesión`, navbar_logout: `Cerrar sesión`,
navbar_renameAccount: `Renombrar cuenta`, navbar_renameAccount: `Renombrar cuenta`,
navbar_deleteAccount: `Eliminar cuenta`, navbar_deleteAccount: `Eliminar cuenta`,
@ -116,7 +116,7 @@ dict = {
mods_rivens: `Agrietados`, mods_rivens: `Agrietados`,
mods_mods: `Mods`, mods_mods: `Mods`,
mods_bulkAddMods: `Agregar mods faltantes`, mods_bulkAddMods: `Agregar mods faltantes`,
mods_removeUnranked: `[UNTRANSLATED] Remove Unranked Mods`, mods_removeUnranked: `Quitar mods sin rango`,
cheats_administratorRequirement: `Debes ser administrador para usar esta función. Para convertirte en administrador, agrega <code>|DISPLAYNAME|</code> a <code>administratorNames</code> en el archivo config.json.`, cheats_administratorRequirement: `Debes ser administrador para usar esta función. Para convertirte en administrador, agrega <code>|DISPLAYNAME|</code> a <code>administratorNames</code> en el archivo config.json.`,
cheats_server: `Servidor`, cheats_server: `Servidor`,
cheats_skipTutorial: `Omitir tutorial`, cheats_skipTutorial: `Omitir tutorial`,