Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
3d21813a79 | |||
7cad831702 | |||
0f2b6c68cd | |||
4fcac6dc37 | |||
d2cae012a7 | |||
b36d524953 | |||
abb5b8880f | |||
4895b4630b | |||
690b872b5e | |||
d77fe60cd8 | |||
3cae42c7d6 | |||
bbccee0637 | |||
31e24c27ad | |||
4acd87aae6 | |||
d8ff601be7 | |||
d79e7c0274 |
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
@ -8,8 +8,7 @@
|
|||||||
"type": "node",
|
"type": "node",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug and Watch",
|
"name": "Debug and Watch",
|
||||||
"runtimeArgs": ["-r", "tsconfig-paths/register", "-r", "ts-node/register", "--watch-path", "src"],
|
"args": ["${workspaceFolder}/scripts/dev.js"],
|
||||||
"args": ["${workspaceFolder}/src/index.ts"],
|
|
||||||
"console": "integratedTerminal"
|
"console": "integratedTerminal"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
8
package-lock.json
generated
8
package-lock.json
generated
@ -23,7 +23,7 @@
|
|||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"typescript": "^5.5",
|
"typescript": "^5.5",
|
||||||
"undici": "^7.10.0",
|
"undici": "^7.10.0",
|
||||||
"warframe-public-export-plus": "^0.5.72",
|
"warframe-public-export-plus": "^0.5.74",
|
||||||
"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",
|
||||||
@ -3386,9 +3386,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/warframe-public-export-plus": {
|
"node_modules/warframe-public-export-plus": {
|
||||||
"version": "0.5.72",
|
"version": "0.5.74",
|
||||||
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.72.tgz",
|
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.74.tgz",
|
||||||
"integrity": "sha512-oOZgtU6L0MGcPRKfA6+bonu+Db1kie1lVdLmA7/DbheTPweNkBEx3Hx3Seib+hEaFW+nLj3T5GtmGxGcFHCHfg=="
|
"integrity": "sha512-pA7dxA0lKn9w/2Sc97oxnn+CEzL1SrT9XriNLTDF4Xp+2SBEpGcfbqbdR9ljPQJopIbrc9Zy02R+uBQVomcwyA=="
|
||||||
},
|
},
|
||||||
"node_modules/warframe-riven-info": {
|
"node_modules/warframe-riven-info": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
"ncp": "^2.0.0",
|
"ncp": "^2.0.0",
|
||||||
"typescript": "^5.5",
|
"typescript": "^5.5",
|
||||||
"undici": "^7.10.0",
|
"undici": "^7.10.0",
|
||||||
"warframe-public-export-plus": "^0.5.72",
|
"warframe-public-export-plus": "^0.5.74",
|
||||||
"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",
|
||||||
|
@ -1,16 +1,12 @@
|
|||||||
|
import { getAccountForRequest } from "@/src/services/loginService";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
const checkDailyMissionBonusController: RequestHandler = (_req, res) => {
|
export const checkDailyMissionBonusController: RequestHandler = async (req, res) => {
|
||||||
const data = Buffer.from([
|
const account = await getAccountForRequest(req);
|
||||||
0x44, 0x61, 0x69, 0x6c, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x3a,
|
const today = Math.trunc(Date.now() / 86400000) * 86400;
|
||||||
0x31, 0x2d, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x50, 0x56, 0x50, 0x57, 0x69, 0x6e, 0x42, 0x6f, 0x6e, 0x75, 0x73,
|
if (account.DailyFirstWinDate != today) {
|
||||||
0x3a, 0x31, 0x0a
|
res.send("DailyMissionBonus:1-DailyPVPWinBonus:1\n");
|
||||||
]);
|
} else {
|
||||||
res.writeHead(200, {
|
res.send("DailyMissionBonus:0-DailyPVPWinBonus:1\n");
|
||||||
"Content-Type": "text/html",
|
}
|
||||||
"Content-Length": data.length
|
|
||||||
});
|
|
||||||
res.end(data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export { checkDailyMissionBonusController };
|
|
||||||
|
@ -88,7 +88,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
|
|||||||
AffiliationMods,
|
AffiliationMods,
|
||||||
SyndicateXPItemReward,
|
SyndicateXPItemReward,
|
||||||
ConquestCompletedMissionsCount
|
ConquestCompletedMissionsCount
|
||||||
} = await addMissionRewards(inventory, missionReport, firstCompletion);
|
} = await addMissionRewards(account, inventory, missionReport, firstCompletion);
|
||||||
|
|
||||||
if (missionReport.EndOfMatchUpload) {
|
if (missionReport.EndOfMatchUpload) {
|
||||||
inventory.RewardSeed = generateRewardSeed();
|
inventory.RewardSeed = generateRewardSeed();
|
||||||
|
@ -57,7 +57,11 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) =
|
|||||||
component.DecoCapacity -= meta.capacityCost;
|
component.DecoCapacity -= meta.capacityCost;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)![0];
|
const [itemType, meta] = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)!;
|
||||||
|
if (!itemType || meta.dojoCapacityCost === undefined) {
|
||||||
|
throw new Error(`unknown deco type: ${deco.Type}`);
|
||||||
|
}
|
||||||
|
component.DecoCapacity -= meta.dojoCapacityCost;
|
||||||
if (deco.Sockets !== undefined) {
|
if (deco.Sockets !== undefined) {
|
||||||
guild.VaultFusionTreasures!.find(x => x.ItemType == itemType && x.Sockets == deco.Sockets)!.ItemCount -=
|
guild.VaultFusionTreasures!.find(x => x.ItemType == itemType && x.Sockets == deco.Sockets)!.ItemCount -=
|
||||||
1;
|
1;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||||
import { getAccountForRequest } from "@/src/services/loginService";
|
import { getAccountForRequest } from "@/src/services/loginService";
|
||||||
import { addChallenges, getInventory } from "@/src/services/inventoryService";
|
import { addCalendarProgress, addChallenges, getInventory } from "@/src/services/inventoryService";
|
||||||
import { IChallengeProgress, ISeasonChallenge } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { IChallengeProgress, ISeasonChallenge } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { IAffiliationMods } from "@/src/types/purchaseTypes";
|
import { IAffiliationMods } from "@/src/types/purchaseTypes";
|
||||||
import { getEntriesUnsafe } from "@/src/utils/ts-utils";
|
import { getEntriesUnsafe } from "@/src/utils/ts-utils";
|
||||||
@ -25,13 +25,17 @@ export const updateChallengeProgressController: RequestHandler = async (req, res
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
for (const [key, value] of getEntriesUnsafe(challenges)) {
|
for (const [key, value] of getEntriesUnsafe(challenges)) {
|
||||||
|
if (value === undefined) {
|
||||||
|
logger.error(`Challenge progress update key ${key} has no value`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case "ChallengesFixVersion":
|
case "ChallengesFixVersion":
|
||||||
inventory.ChallengesFixVersion = value;
|
inventory.ChallengesFixVersion = value;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "SeasonChallengeHistory":
|
case "SeasonChallengeHistory":
|
||||||
value!.forEach(({ challenge, id }) => {
|
value.forEach(({ challenge, id }) => {
|
||||||
const itemIndex = inventory.SeasonChallengeHistory.findIndex(i => i.challenge === challenge);
|
const itemIndex = inventory.SeasonChallengeHistory.findIndex(i => i.challenge === challenge);
|
||||||
if (itemIndex !== -1) {
|
if (itemIndex !== -1) {
|
||||||
inventory.SeasonChallengeHistory[itemIndex].id = id;
|
inventory.SeasonChallengeHistory[itemIndex].id = id;
|
||||||
@ -41,6 +45,10 @@ export const updateChallengeProgressController: RequestHandler = async (req, res
|
|||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "CalendarProgress":
|
||||||
|
addCalendarProgress(inventory, value);
|
||||||
|
break;
|
||||||
|
|
||||||
case "ChallengeProgress":
|
case "ChallengeProgress":
|
||||||
case "SeasonChallengeCompletions":
|
case "SeasonChallengeCompletions":
|
||||||
case "ChallengePTS":
|
case "ChallengePTS":
|
||||||
@ -63,5 +71,6 @@ interface IUpdateChallengeProgressRequest {
|
|||||||
ChallengeProgress?: IChallengeProgress[];
|
ChallengeProgress?: IChallengeProgress[];
|
||||||
SeasonChallengeHistory?: ISeasonChallenge[];
|
SeasonChallengeHistory?: ISeasonChallenge[];
|
||||||
SeasonChallengeCompletions?: ISeasonChallenge[];
|
SeasonChallengeCompletions?: ISeasonChallenge[];
|
||||||
|
CalendarProgress?: { challenge: string }[];
|
||||||
crossPlaySetting?: string;
|
crossPlaySetting?: string;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ export const completeAllMissionsController: RequestHandler = async (req, res) =>
|
|||||||
if (mission.Completes == 0) {
|
if (mission.Completes == 0) {
|
||||||
mission.Completes++;
|
mission.Completes++;
|
||||||
if (node.missionReward) {
|
if (node.missionReward) {
|
||||||
addFixedLevelRewards(node.missionReward, inventory, MissionRewards);
|
addFixedLevelRewards(node.missionReward, MissionRewards);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mission.Tier = 1;
|
mission.Tier = 1;
|
||||||
|
44
src/controllers/custom/configController.ts
Normal file
44
src/controllers/custom/configController.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import { RequestHandler } from "express";
|
||||||
|
import { config } from "@/src/services/configService";
|
||||||
|
import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
|
||||||
|
import { saveConfig } from "@/src/services/configWatcherService";
|
||||||
|
import { sendWsBroadcastExcept } from "@/src/services/webService";
|
||||||
|
|
||||||
|
export const getConfigController: RequestHandler = async (req, res) => {
|
||||||
|
const account = await getAccountForRequest(req);
|
||||||
|
if (isAdministrator(account)) {
|
||||||
|
const responseData: Record<string, boolean | string | number | null> = {};
|
||||||
|
for (const id of req.body as string[]) {
|
||||||
|
const [obj, idx] = configIdToIndexable(id);
|
||||||
|
responseData[id] = obj[idx] ?? null;
|
||||||
|
}
|
||||||
|
res.json(responseData);
|
||||||
|
} else {
|
||||||
|
res.status(401).end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const setConfigController: RequestHandler = async (req, res) => {
|
||||||
|
const account = await getAccountForRequest(req);
|
||||||
|
if (isAdministrator(account)) {
|
||||||
|
for (const [id, value] of Object.entries(req.body as Record<string, boolean | string | number>)) {
|
||||||
|
const [obj, idx] = configIdToIndexable(id);
|
||||||
|
obj[idx] = value;
|
||||||
|
}
|
||||||
|
sendWsBroadcastExcept(parseInt(String(req.query.wsid)), { config_reloaded: true });
|
||||||
|
await saveConfig();
|
||||||
|
res.end();
|
||||||
|
} else {
|
||||||
|
res.status(401).end();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const configIdToIndexable = (id: string): [Record<string, boolean | string | number | undefined>, string] => {
|
||||||
|
let obj = config as unknown as Record<string, never>;
|
||||||
|
const arr = id.split(".");
|
||||||
|
while (arr.length > 1) {
|
||||||
|
obj = obj[arr[0]];
|
||||||
|
arr.splice(0, 1);
|
||||||
|
}
|
||||||
|
return [obj, arr[0]];
|
||||||
|
};
|
@ -1,14 +0,0 @@
|
|||||||
import { RequestHandler } from "express";
|
|
||||||
import { config } from "@/src/services/configService";
|
|
||||||
import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
|
|
||||||
|
|
||||||
const getConfigDataController: RequestHandler = async (req, res) => {
|
|
||||||
const account = await getAccountForRequest(req);
|
|
||||||
if (isAdministrator(account)) {
|
|
||||||
res.json(config);
|
|
||||||
} else {
|
|
||||||
res.status(401).end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export { getConfigDataController };
|
|
@ -23,9 +23,9 @@ export const setBoosterController: RequestHandler = async (req, res) => {
|
|||||||
res.status(400).send("Invalid ItemType provided.");
|
res.status(400).send("Invalid ItemType provided.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const now = Math.floor(Date.now() / 1000);
|
const now = Math.trunc(Date.now() / 1000);
|
||||||
for (const { ItemType, ExpiryDate } of requests) {
|
for (const { ItemType, ExpiryDate } of requests) {
|
||||||
if (ExpiryDate < now) {
|
if (ExpiryDate <= now) {
|
||||||
// remove expired boosters
|
// remove expired boosters
|
||||||
const index = boosters.findIndex(item => item.ItemType === ItemType);
|
const index = boosters.findIndex(item => item.ItemType === ItemType);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
import { RequestHandler } from "express";
|
|
||||||
import { saveConfig } from "@/src/services/configWatcherService";
|
|
||||||
import { getAccountForRequest, isAdministrator } from "@/src/services/loginService";
|
|
||||||
import { config, IConfig } from "@/src/services/configService";
|
|
||||||
|
|
||||||
export const updateConfigDataController: RequestHandler = async (req, res) => {
|
|
||||||
const account = await getAccountForRequest(req);
|
|
||||||
if (isAdministrator(account)) {
|
|
||||||
const data = req.body as IUpdateConfigDataRequest;
|
|
||||||
config[data.key] = data.value;
|
|
||||||
await saveConfig();
|
|
||||||
res.end();
|
|
||||||
} else {
|
|
||||||
res.status(401).end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
interface IUpdateConfigDataRequest {
|
|
||||||
key: keyof IConfig;
|
|
||||||
value: never;
|
|
||||||
}
|
|
@ -25,7 +25,8 @@ const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
|
|||||||
LastLogin: { type: Date, default: 0 },
|
LastLogin: { type: Date, default: 0 },
|
||||||
LatestEventMessageDate: { type: Date, default: 0 },
|
LatestEventMessageDate: { type: Date, default: 0 },
|
||||||
LastLoginRewardDate: { type: Number, default: 0 },
|
LastLoginRewardDate: { type: Number, default: 0 },
|
||||||
LoginDays: { type: Number, default: 1 }
|
LoginDays: { type: Number, default: 1 },
|
||||||
|
DailyFirstWinDate: { type: Number, default: 0 }
|
||||||
},
|
},
|
||||||
opts
|
opts
|
||||||
);
|
);
|
||||||
|
@ -25,8 +25,7 @@ import { manageQuestsController } from "@/src/controllers/custom/manageQuestsCon
|
|||||||
import { setEvolutionProgressController } from "@/src/controllers/custom/setEvolutionProgressController";
|
import { setEvolutionProgressController } from "@/src/controllers/custom/setEvolutionProgressController";
|
||||||
import { setBoosterController } from "@/src/controllers/custom/setBoosterController";
|
import { setBoosterController } from "@/src/controllers/custom/setBoosterController";
|
||||||
|
|
||||||
import { getConfigDataController } from "@/src/controllers/custom/getConfigDataController";
|
import { getConfigController, setConfigController } from "@/src/controllers/custom/configController";
|
||||||
import { updateConfigDataController } from "@/src/controllers/custom/updateConfigDataController";
|
|
||||||
|
|
||||||
const customRouter = express.Router();
|
const customRouter = express.Router();
|
||||||
|
|
||||||
@ -55,7 +54,7 @@ customRouter.post("/manageQuests", manageQuestsController);
|
|||||||
customRouter.post("/setEvolutionProgress", setEvolutionProgressController);
|
customRouter.post("/setEvolutionProgress", setEvolutionProgressController);
|
||||||
customRouter.post("/setBooster", setBoosterController);
|
customRouter.post("/setBooster", setBoosterController);
|
||||||
|
|
||||||
customRouter.get("/config", getConfigDataController);
|
customRouter.post("/getConfig", getConfigController);
|
||||||
customRouter.post("/config", updateConfigDataController);
|
customRouter.post("/setConfig", setConfigController);
|
||||||
|
|
||||||
export { customRouter };
|
export { customRouter };
|
||||||
|
@ -349,7 +349,8 @@ export const removeDojoDeco = (
|
|||||||
component.DecoCapacity! += meta.capacityCost;
|
component.DecoCapacity! += meta.capacityCost;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)![0];
|
const [itemType, meta] = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)!;
|
||||||
|
component.DecoCapacity! += meta.dojoCapacityCost!;
|
||||||
if (deco.Sockets !== undefined) {
|
if (deco.Sockets !== undefined) {
|
||||||
addVaultFusionTreasures(guild, [
|
addVaultFusionTreasures(guild, [
|
||||||
{
|
{
|
||||||
|
@ -1832,6 +1832,15 @@ export const addChallenges = (
|
|||||||
return affiliationMods;
|
return affiliationMods;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const addCalendarProgress = (inventory: TInventoryDatabaseDocument, value: { challenge: string }[]): void => {
|
||||||
|
const calendarProgress = getCalendarProgress(inventory);
|
||||||
|
const currentSeason = getWorldState().KnownCalendarSeasons[0];
|
||||||
|
calendarProgress.SeasonProgress.LastCompletedChallengeDayIdx = currentSeason.Days.findIndex(
|
||||||
|
day => day.events.length != 0 && day.events[0].challenge == value[value.length - 1].challenge
|
||||||
|
);
|
||||||
|
checkCalendarChallengeCompletion(calendarProgress, currentSeason);
|
||||||
|
};
|
||||||
|
|
||||||
export const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag, Completes, Tier }: IMission): void => {
|
export const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag, Completes, Tier }: IMission): void => {
|
||||||
const { Missions } = inventory;
|
const { Missions } = inventory;
|
||||||
const itemIndex = Missions.findIndex(item => item.Tag === Tag);
|
const itemIndex = Missions.findIndex(item => item.Tag === Tag);
|
||||||
|
@ -144,7 +144,8 @@ export const claimLoginReward = async (
|
|||||||
case "RT_STORE_ITEM":
|
case "RT_STORE_ITEM":
|
||||||
case "RT_RECIPE":
|
case "RT_RECIPE":
|
||||||
case "RT_RANDOM_RECIPE":
|
case "RT_RANDOM_RECIPE":
|
||||||
return (await handleStoreItemAcquisition(reward.StoreItemType, inventory, reward.Amount)).InventoryChanges;
|
return (await handleStoreItemAcquisition(reward.StoreItemType, inventory, reward.Amount, undefined, true))
|
||||||
|
.InventoryChanges;
|
||||||
|
|
||||||
case "RT_CREDITS":
|
case "RT_CREDITS":
|
||||||
return updateCurrency(inventory, -reward.Amount, false);
|
return updateCurrency(inventory, -reward.Amount, false);
|
||||||
|
@ -14,6 +14,7 @@ import { IRngResult, SRng, getRandomElement, getRandomReward } from "@/src/servi
|
|||||||
import { equipmentKeys, IMission, ITypeCount, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { equipmentKeys, IMission, ITypeCount, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import {
|
import {
|
||||||
addBooster,
|
addBooster,
|
||||||
|
addCalendarProgress,
|
||||||
addChallenges,
|
addChallenges,
|
||||||
addConsumables,
|
addConsumables,
|
||||||
addCrewShipAmmo,
|
addCrewShipAmmo,
|
||||||
@ -33,10 +34,8 @@ import {
|
|||||||
addSkin,
|
addSkin,
|
||||||
addStanding,
|
addStanding,
|
||||||
applyClientEquipmentUpdates,
|
applyClientEquipmentUpdates,
|
||||||
checkCalendarChallengeCompletion,
|
|
||||||
combineInventoryChanges,
|
combineInventoryChanges,
|
||||||
generateRewardSeed,
|
generateRewardSeed,
|
||||||
getCalendarProgress,
|
|
||||||
getDialogue,
|
getDialogue,
|
||||||
giveNemesisPetRecipe,
|
giveNemesisPetRecipe,
|
||||||
giveNemesisWeaponRecipe,
|
giveNemesisWeaponRecipe,
|
||||||
@ -235,7 +234,7 @@ export const addMissionInventoryUpdates = async (
|
|||||||
}
|
}
|
||||||
for (const [key, value] of getEntriesUnsafe(inventoryUpdates)) {
|
for (const [key, value] of getEntriesUnsafe(inventoryUpdates)) {
|
||||||
if (value === undefined) {
|
if (value === undefined) {
|
||||||
logger.error(`Inventory update key ${key} has no value `);
|
logger.error(`Inventory update key ${key} has no value`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (key) {
|
switch (key) {
|
||||||
@ -671,12 +670,7 @@ export const addMissionInventoryUpdates = async (
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "CalendarProgress": {
|
case "CalendarProgress": {
|
||||||
const calendarProgress = getCalendarProgress(inventory);
|
addCalendarProgress(inventory, value);
|
||||||
const currentSeason = getWorldState().KnownCalendarSeasons[0];
|
|
||||||
calendarProgress.SeasonProgress.LastCompletedChallengeDayIdx = currentSeason.Days.findIndex(
|
|
||||||
x => x.events[0].challenge == value[value.length - 1].challenge
|
|
||||||
);
|
|
||||||
checkCalendarChallengeCompletion(calendarProgress, currentSeason);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "duviriCaveOffers": {
|
case "duviriCaveOffers": {
|
||||||
@ -968,6 +962,7 @@ const droptableAliases: Record<string, string> = {
|
|||||||
|
|
||||||
//TODO: return type of partial missioninventoryupdate response
|
//TODO: return type of partial missioninventoryupdate response
|
||||||
export const addMissionRewards = async (
|
export const addMissionRewards = async (
|
||||||
|
account: TAccountDocument,
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
{
|
{
|
||||||
wagerTier: wagerTier,
|
wagerTier: wagerTier,
|
||||||
@ -1015,13 +1010,17 @@ export const addMissionRewards = async (
|
|||||||
const fixedLevelRewards = getLevelKeyRewards(levelKeyName);
|
const fixedLevelRewards = getLevelKeyRewards(levelKeyName);
|
||||||
//logger.debug(`fixedLevelRewards ${fixedLevelRewards}`);
|
//logger.debug(`fixedLevelRewards ${fixedLevelRewards}`);
|
||||||
if (fixedLevelRewards.levelKeyRewards) {
|
if (fixedLevelRewards.levelKeyRewards) {
|
||||||
addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, MissionRewards, rewardInfo);
|
missionCompletionCredits += addFixedLevelRewards(
|
||||||
|
fixedLevelRewards.levelKeyRewards,
|
||||||
|
MissionRewards,
|
||||||
|
rewardInfo
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (fixedLevelRewards.levelKeyRewards2) {
|
if (fixedLevelRewards.levelKeyRewards2) {
|
||||||
for (const reward of fixedLevelRewards.levelKeyRewards2) {
|
for (const reward of fixedLevelRewards.levelKeyRewards2) {
|
||||||
//quest stage completion credit rewards
|
//quest stage completion credit rewards
|
||||||
if (reward.rewardType == "RT_CREDITS") {
|
if (reward.rewardType == "RT_CREDITS") {
|
||||||
missionCompletionCredits += reward.amount; // will be added to inventory in addCredits
|
missionCompletionCredits += reward.amount;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
MissionRewards.push({
|
MissionRewards.push({
|
||||||
@ -1050,12 +1049,11 @@ export const addMissionRewards = async (
|
|||||||
) {
|
) {
|
||||||
const levelCreditReward = getLevelCreditRewards(node);
|
const levelCreditReward = getLevelCreditRewards(node);
|
||||||
missionCompletionCredits += levelCreditReward;
|
missionCompletionCredits += levelCreditReward;
|
||||||
inventory.RegularCredits += levelCreditReward;
|
|
||||||
logger.debug(`levelCreditReward ${levelCreditReward}`);
|
logger.debug(`levelCreditReward ${levelCreditReward}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.missionReward) {
|
if (node.missionReward) {
|
||||||
missionCompletionCredits += addFixedLevelRewards(node.missionReward, inventory, MissionRewards, rewardInfo);
|
missionCompletionCredits += addFixedLevelRewards(node.missionReward, MissionRewards, rewardInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rewardInfo.sortieTag == "Mission1") {
|
if (rewardInfo.sortieTag == "Mission1") {
|
||||||
@ -1165,7 +1163,9 @@ export const addMissionRewards = async (
|
|||||||
combineInventoryChanges(inventoryChanges, inventoryChange.InventoryChanges);
|
combineInventoryChanges(inventoryChanges, inventoryChange.InventoryChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
const credits = addCredits(inventory, {
|
inventory.RegularCredits += missionCompletionCredits;
|
||||||
|
|
||||||
|
const credits = await addCredits(account, inventory, {
|
||||||
missionCompletionCredits,
|
missionCompletionCredits,
|
||||||
missionDropCredits: creditDrops ?? 0,
|
missionDropCredits: creditDrops ?? 0,
|
||||||
rngRewardCredits: inventoryChanges.RegularCredits ?? 0
|
rngRewardCredits: inventoryChanges.RegularCredits ?? 0
|
||||||
@ -1388,48 +1388,61 @@ export const addMissionRewards = async (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
//creditBonus is not entirely accurate.
|
export const addCredits = async (
|
||||||
//TODO: consider ActiveBoosters
|
account: TAccountDocument,
|
||||||
export const addCredits = (
|
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
{
|
{
|
||||||
missionDropCredits,
|
missionDropCredits,
|
||||||
missionCompletionCredits,
|
missionCompletionCredits,
|
||||||
rngRewardCredits
|
rngRewardCredits
|
||||||
}: { missionDropCredits: number; missionCompletionCredits: number; rngRewardCredits: number }
|
}: { missionDropCredits: number; missionCompletionCredits: number; rngRewardCredits: number }
|
||||||
): IMissionCredits => {
|
): Promise<IMissionCredits> => {
|
||||||
const hasDailyCreditBonus = true;
|
|
||||||
const totalCredits = missionDropCredits + missionCompletionCredits + rngRewardCredits;
|
|
||||||
|
|
||||||
const finalCredits: IMissionCredits = {
|
const finalCredits: IMissionCredits = {
|
||||||
MissionCredits: [missionDropCredits, missionDropCredits],
|
MissionCredits: [missionDropCredits, missionDropCredits],
|
||||||
CreditBonus: [missionCompletionCredits, missionCompletionCredits],
|
CreditsBonus: [missionCompletionCredits, missionCompletionCredits],
|
||||||
TotalCredits: [totalCredits, totalCredits]
|
TotalCredits: [0, 0]
|
||||||
};
|
};
|
||||||
|
|
||||||
if (hasDailyCreditBonus) {
|
const today = Math.trunc(Date.now() / 86400000) * 86400;
|
||||||
|
if (account.DailyFirstWinDate != today) {
|
||||||
|
account.DailyFirstWinDate = today;
|
||||||
|
await account.save();
|
||||||
|
|
||||||
|
logger.debug(`daily first win, doubling missionCompletionCredits (${missionCompletionCredits})`);
|
||||||
|
|
||||||
|
finalCredits.DailyMissionBonus = true;
|
||||||
inventory.RegularCredits += missionCompletionCredits;
|
inventory.RegularCredits += missionCompletionCredits;
|
||||||
finalCredits.CreditBonus[1] *= 2;
|
finalCredits.CreditsBonus[1] *= 2;
|
||||||
finalCredits.MissionCredits[1] *= 2;
|
|
||||||
finalCredits.TotalCredits[1] *= 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasDailyCreditBonus) {
|
const totalCredits = finalCredits.MissionCredits[1] + finalCredits.CreditsBonus[1] + rngRewardCredits;
|
||||||
return finalCredits;
|
finalCredits.TotalCredits = [totalCredits, totalCredits];
|
||||||
|
|
||||||
|
if (config.worldState?.creditBoost) {
|
||||||
|
inventory.RegularCredits += finalCredits.TotalCredits[1];
|
||||||
|
finalCredits.TotalCredits[1] += finalCredits.TotalCredits[1];
|
||||||
}
|
}
|
||||||
return { ...finalCredits, DailyMissionBonus: true };
|
const now = Math.trunc(Date.now() / 1000); // TOVERIFY: Should we maybe subtract mission time as to apply credit boosters that expired during mission?
|
||||||
|
if ((inventory.Boosters.find(x => x.ItemType == "/Lotus/Types/Boosters/CreditBooster")?.ExpiryDate ?? 0) > now) {
|
||||||
|
inventory.RegularCredits += finalCredits.TotalCredits[1];
|
||||||
|
finalCredits.TotalCredits[1] += finalCredits.TotalCredits[1];
|
||||||
|
}
|
||||||
|
if ((inventory.Boosters.find(x => x.ItemType == "/Lotus/Types/Boosters/CreditBlessing")?.ExpiryDate ?? 0) > now) {
|
||||||
|
inventory.RegularCredits += finalCredits.TotalCredits[1];
|
||||||
|
finalCredits.TotalCredits[1] += finalCredits.TotalCredits[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalCredits;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addFixedLevelRewards = (
|
export const addFixedLevelRewards = (
|
||||||
rewards: IMissionRewardExternal,
|
rewards: IMissionRewardExternal,
|
||||||
inventory: TInventoryDatabaseDocument,
|
|
||||||
MissionRewards: IMissionReward[],
|
MissionRewards: IMissionReward[],
|
||||||
rewardInfo?: IRewardInfo
|
rewardInfo?: IRewardInfo
|
||||||
): number => {
|
): number => {
|
||||||
let missionBonusCredits = 0;
|
let missionBonusCredits = 0;
|
||||||
if (rewards.credits) {
|
if (rewards.credits) {
|
||||||
missionBonusCredits += rewards.credits;
|
missionBonusCredits += rewards.credits;
|
||||||
inventory.RegularCredits += rewards.credits;
|
|
||||||
}
|
}
|
||||||
if (rewards.items) {
|
if (rewards.items) {
|
||||||
for (const item of rewards.items) {
|
for (const item of rewards.items) {
|
||||||
@ -1603,6 +1616,27 @@ function getRandomMissionDrops(
|
|||||||
? "/Lotus/Types/Game/MissionDecks/DuviriEncounterRewards/DuviriKullervoSteelPathRNGRewards"
|
? "/Lotus/Types/Game/MissionDecks/DuviriEncounterRewards/DuviriKullervoSteelPathRNGRewards"
|
||||||
: "/Lotus/Types/Game/MissionDecks/DuviriEncounterRewards/DuviriKullervoNormalRNGRewards"
|
: "/Lotus/Types/Game/MissionDecks/DuviriEncounterRewards/DuviriKullervoNormalRNGRewards"
|
||||||
];
|
];
|
||||||
|
} else if (RewardInfo.T == 17) {
|
||||||
|
if (mission?.Tier == 1) {
|
||||||
|
logger.warn(`non-steel path duviri murmur tier used on steel path?!`);
|
||||||
|
}
|
||||||
|
/*if (operation eight claw is active) {
|
||||||
|
drops.push({
|
||||||
|
StoreItem: "/Lotus/StoreItems/Types/Gameplay/DuviriMITW/Resources/DuviriMurmurItemEvent",
|
||||||
|
ItemCount: 10
|
||||||
|
});
|
||||||
|
}*/
|
||||||
|
rewardManifests = ["/Lotus/Types/Game/MissionDecks/DuviriEncounterRewards/DuviriMurmurFinalChestRewards"];
|
||||||
|
} else if (RewardInfo.T == 19) {
|
||||||
|
/*if (operation eight claw is active) {
|
||||||
|
drops.push({
|
||||||
|
StoreItem: "/Lotus/StoreItems/Types/Gameplay/DuviriMITW/Resources/DuviriMurmurItemEvent",
|
||||||
|
ItemCount: 15
|
||||||
|
});
|
||||||
|
}*/
|
||||||
|
rewardManifests = [
|
||||||
|
"/Lotus/Types/Game/MissionDecks/DuviriEncounterRewards/DuviriMurmurFinalSteelChestRewards"
|
||||||
|
];
|
||||||
} else if (RewardInfo.T == 70) {
|
} else if (RewardInfo.T == 70) {
|
||||||
// Orowyrm chest, gives 10 Pathos Clamps, or 15 on Steel Path.
|
// Orowyrm chest, gives 10 Pathos Clamps, or 15 on Steel Path.
|
||||||
drops.push({
|
drops.push({
|
||||||
|
@ -331,7 +331,7 @@ export const giveKeyChainMissionReward = async (
|
|||||||
const fixedLevelRewards = getLevelKeyRewards(missionName);
|
const fixedLevelRewards = getLevelKeyRewards(missionName);
|
||||||
if (fixedLevelRewards.levelKeyRewards) {
|
if (fixedLevelRewards.levelKeyRewards) {
|
||||||
const missionRewards: { StoreItem: string; ItemCount: number }[] = [];
|
const missionRewards: { StoreItem: string; ItemCount: number }[] = [];
|
||||||
addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, missionRewards);
|
inventory.RegularCredits += addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, missionRewards);
|
||||||
|
|
||||||
for (const reward of missionRewards) {
|
for (const reward of missionRewards) {
|
||||||
await addItem(inventory, fromStoreItem(reward.StoreItem), reward.ItemCount);
|
await addItem(inventory, fromStoreItem(reward.StoreItem), reward.ItemCount);
|
||||||
|
@ -149,7 +149,8 @@ export const handleInventoryItemConfigChange = async (
|
|||||||
} else {
|
} else {
|
||||||
const inventoryItem = inventory.WeaponSkins.id(itemId);
|
const inventoryItem = inventory.WeaponSkins.id(itemId);
|
||||||
if (!inventoryItem) {
|
if (!inventoryItem) {
|
||||||
throw new Error(`inventory item WeaponSkins not found with id ${itemId}`);
|
logger.warn(`inventory item WeaponSkins not found with id ${itemId}`);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if ("Favorite" in itemConfigEntries) {
|
if ("Favorite" in itemConfigEntries) {
|
||||||
inventoryItem.Favorite = itemConfigEntries.Favorite;
|
inventoryItem.Favorite = itemConfigEntries.Favorite;
|
||||||
@ -177,7 +178,8 @@ export const handleInventoryItemConfigChange = async (
|
|||||||
const inventoryItem = inventory[equipmentName].id(itemId);
|
const inventoryItem = inventory[equipmentName].id(itemId);
|
||||||
|
|
||||||
if (!inventoryItem) {
|
if (!inventoryItem) {
|
||||||
throw new Error(`inventory item ${equipmentName} not found with id ${itemId}`);
|
logger.warn(`inventory item ${equipmentName} not found with id ${itemId}`);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [configId, config] of Object.entries(itemConfigEntries)) {
|
for (const [configId, config] of Object.entries(itemConfigEntries)) {
|
||||||
|
@ -281,6 +281,10 @@ const generateVendorManifest = (
|
|||||||
offersToAdd.push(item);
|
offersToAdd.push(item);
|
||||||
++offset;
|
++offset;
|
||||||
}
|
}
|
||||||
|
if (missingItemsPerBin[item.bin]) {
|
||||||
|
missingItemsPerBin[item.bin] -= 1;
|
||||||
|
numOffersThatNeedToMatchABin -= 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
numCountedOffers += 1 + item.duplicates;
|
numCountedOffers += 1 + item.duplicates;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,12 @@ export const handleSetShipDecorations = async (
|
|||||||
const roomToPlaceIn = rooms.find(room => room.Name === placedDecoration.Room);
|
const roomToPlaceIn = rooms.find(room => room.Name === placedDecoration.Room);
|
||||||
|
|
||||||
if (!roomToPlaceIn) {
|
if (!roomToPlaceIn) {
|
||||||
throw new Error("room not found");
|
throw new Error(`unknown room: ${placedDecoration.Room}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [itemType, meta] = Object.entries(ExportResources).find(arr => arr[1].deco == placedDecoration.Type)!;
|
||||||
|
if (!itemType || meta.capacityCost === undefined) {
|
||||||
|
throw new Error(`unknown deco type: ${placedDecoration.Type}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (placedDecoration.MoveId) {
|
if (placedDecoration.MoveId) {
|
||||||
@ -83,7 +88,7 @@ export const handleSetShipDecorations = async (
|
|||||||
OldRoom: placedDecoration.OldRoom,
|
OldRoom: placedDecoration.OldRoom,
|
||||||
NewRoom: placedDecoration.Room,
|
NewRoom: placedDecoration.Room,
|
||||||
IsApartment: placedDecoration.IsApartment,
|
IsApartment: placedDecoration.IsApartment,
|
||||||
MaxCapacityIncrease: 0 // TODO: calculate capacity change upon removal
|
MaxCapacityIncrease: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +101,7 @@ export const handleSetShipDecorations = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
oldRoom.PlacedDecos.pull({ _id: placedDecoration.MoveId });
|
oldRoom.PlacedDecos.pull({ _id: placedDecoration.MoveId });
|
||||||
|
oldRoom.MaxCapacity += meta.capacityCost;
|
||||||
|
|
||||||
const newDecoration = {
|
const newDecoration = {
|
||||||
Type: placedDecoration.Type,
|
Type: placedDecoration.Type,
|
||||||
@ -108,12 +114,14 @@ export const handleSetShipDecorations = async (
|
|||||||
|
|
||||||
//the new room is still roomToPlaceIn
|
//the new room is still roomToPlaceIn
|
||||||
roomToPlaceIn.PlacedDecos.push(newDecoration);
|
roomToPlaceIn.PlacedDecos.push(newDecoration);
|
||||||
|
roomToPlaceIn.MaxCapacity -= meta.capacityCost;
|
||||||
|
|
||||||
await personalRooms.save();
|
await personalRooms.save();
|
||||||
return {
|
return {
|
||||||
OldRoom: placedDecoration.OldRoom,
|
OldRoom: placedDecoration.OldRoom,
|
||||||
NewRoom: placedDecoration.Room,
|
NewRoom: placedDecoration.Room,
|
||||||
IsApartment: placedDecoration.IsApartment,
|
IsApartment: placedDecoration.IsApartment,
|
||||||
MaxCapacityIncrease: 0 // TODO: calculate capacity change upon removal
|
MaxCapacityIncrease: -meta.capacityCost
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,11 +129,11 @@ export const handleSetShipDecorations = async (
|
|||||||
const decoIndex = roomToPlaceIn.PlacedDecos.findIndex(x => x._id.equals(placedDecoration.RemoveId));
|
const decoIndex = roomToPlaceIn.PlacedDecos.findIndex(x => x._id.equals(placedDecoration.RemoveId));
|
||||||
const deco = roomToPlaceIn.PlacedDecos[decoIndex];
|
const deco = roomToPlaceIn.PlacedDecos[decoIndex];
|
||||||
roomToPlaceIn.PlacedDecos.splice(decoIndex, 1);
|
roomToPlaceIn.PlacedDecos.splice(decoIndex, 1);
|
||||||
|
roomToPlaceIn.MaxCapacity += meta.capacityCost;
|
||||||
await personalRooms.save();
|
await personalRooms.save();
|
||||||
|
|
||||||
if (!config.unlockAllShipDecorations) {
|
if (!config.unlockAllShipDecorations) {
|
||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)![0];
|
|
||||||
if (deco.Sockets !== undefined) {
|
if (deco.Sockets !== undefined) {
|
||||||
addFusionTreasures(inventory, [{ ItemType: itemType, Sockets: deco.Sockets, ItemCount: 1 }]);
|
addFusionTreasures(inventory, [{ ItemType: itemType, Sockets: deco.Sockets, ItemCount: 1 }]);
|
||||||
} else {
|
} else {
|
||||||
@ -138,24 +146,20 @@ export const handleSetShipDecorations = async (
|
|||||||
DecoId: placedDecoration.RemoveId,
|
DecoId: placedDecoration.RemoveId,
|
||||||
Room: placedDecoration.Room,
|
Room: placedDecoration.Room,
|
||||||
IsApartment: placedDecoration.IsApartment,
|
IsApartment: placedDecoration.IsApartment,
|
||||||
MaxCapacityIncrease: 0
|
MaxCapacityIncrease: 0 // Client already implies the capacity being refunded.
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
if (!config.unlockAllShipDecorations) {
|
|
||||||
const inventory = await getInventory(accountId);
|
|
||||||
const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == placedDecoration.Type)![0];
|
|
||||||
if (placedDecoration.Sockets !== undefined) {
|
|
||||||
addFusionTreasures(inventory, [
|
|
||||||
{ ItemType: itemType, Sockets: placedDecoration.Sockets, ItemCount: -1 }
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
addShipDecorations(inventory, [{ ItemType: itemType, ItemCount: -1 }]);
|
|
||||||
}
|
|
||||||
await inventory.save();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle capacity
|
if (!config.unlockAllShipDecorations) {
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == placedDecoration.Type)![0];
|
||||||
|
if (placedDecoration.Sockets !== undefined) {
|
||||||
|
addFusionTreasures(inventory, [{ ItemType: itemType, Sockets: placedDecoration.Sockets, ItemCount: -1 }]);
|
||||||
|
} else {
|
||||||
|
addShipDecorations(inventory, [{ ItemType: itemType, ItemCount: -1 }]);
|
||||||
|
}
|
||||||
|
await inventory.save();
|
||||||
|
}
|
||||||
|
|
||||||
//place decoration
|
//place decoration
|
||||||
const decoId = new Types.ObjectId();
|
const decoId = new Types.ObjectId();
|
||||||
@ -167,10 +171,16 @@ export const handleSetShipDecorations = async (
|
|||||||
Sockets: placedDecoration.Sockets,
|
Sockets: placedDecoration.Sockets,
|
||||||
_id: decoId
|
_id: decoId
|
||||||
});
|
});
|
||||||
|
roomToPlaceIn.MaxCapacity -= meta.capacityCost;
|
||||||
|
|
||||||
await personalRooms.save();
|
await personalRooms.save();
|
||||||
|
|
||||||
return { DecoId: decoId.toString(), Room: placedDecoration.Room, IsApartment: placedDecoration.IsApartment };
|
return {
|
||||||
|
DecoId: decoId.toString(),
|
||||||
|
Room: placedDecoration.Room,
|
||||||
|
IsApartment: placedDecoration.IsApartment,
|
||||||
|
MaxCapacityIncrease: -meta.capacityCost
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlacedDecoInfoRequest): Promise<void> => {
|
export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlacedDecoInfoRequest): Promise<void> => {
|
||||||
|
@ -136,7 +136,10 @@ export const stopWebServer = async (): Promise<void> => {
|
|||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let lastWsid: number = 0;
|
||||||
|
|
||||||
interface IWsCustomData extends ws {
|
interface IWsCustomData extends ws {
|
||||||
|
id?: number;
|
||||||
accountId?: string;
|
accountId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +153,7 @@ interface IWsMsgFromClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface IWsMsgToClient {
|
interface IWsMsgToClient {
|
||||||
|
//wsid?: number;
|
||||||
reload?: boolean;
|
reload?: boolean;
|
||||||
ports?: {
|
ports?: {
|
||||||
http: number | undefined;
|
http: number | undefined;
|
||||||
@ -174,6 +178,10 @@ const wsOnConnect = (ws: ws, req: http.IncomingMessage): void => {
|
|||||||
ws.close();
|
ws.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(ws as IWsCustomData).id = ++lastWsid;
|
||||||
|
ws.send(JSON.stringify({ wsid: lastWsid }));
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||||
ws.on("message", async msg => {
|
ws.on("message", async msg => {
|
||||||
const data = JSON.parse(String(msg)) as IWsMsgFromClient;
|
const data = JSON.parse(String(msg)) as IWsMsgFromClient;
|
||||||
@ -268,3 +276,21 @@ export const sendWsBroadcastTo = (accountId: string, data: IWsMsgToClient): void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const sendWsBroadcastExcept = (wsid: number | undefined, data: IWsMsgToClient): void => {
|
||||||
|
const msg = JSON.stringify(data);
|
||||||
|
if (wsServer) {
|
||||||
|
for (const client of wsServer.clients) {
|
||||||
|
if ((client as IWsCustomData).id != wsid) {
|
||||||
|
client.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wssServer) {
|
||||||
|
for (const client of wssServer.clients) {
|
||||||
|
if ((client as IWsCustomData).id != wsid) {
|
||||||
|
client.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -372,7 +372,7 @@ const getSeasonChallengePools = (syndicateTag: string): IRotatingSeasonChallenge
|
|||||||
hardWeekly: syndicate.weeklyChallenges!.filter(x =>
|
hardWeekly: syndicate.weeklyChallenges!.filter(x =>
|
||||||
x.startsWith("/Lotus/Types/Challenges/Seasons/WeeklyHard/")
|
x.startsWith("/Lotus/Types/Challenges/Seasons/WeeklyHard/")
|
||||||
),
|
),
|
||||||
hasWeeklyPermanent: !!syndicate.weeklyChallenges!.find(x =>
|
hasWeeklyPermanent: syndicate.weeklyChallenges!.some(x =>
|
||||||
x.startsWith("/Lotus/Types/Challenges/Seasons/Weekly/SeasonWeeklyPermanent")
|
x.startsWith("/Lotus/Types/Challenges/Seasons/Weekly/SeasonWeeklyPermanent")
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
@ -25,6 +25,7 @@ export interface IDatabaseAccount extends IDatabaseAccountRequiredFields {
|
|||||||
LatestEventMessageDate: Date;
|
LatestEventMessageDate: Date;
|
||||||
LastLoginRewardDate: number;
|
LastLoginRewardDate: number;
|
||||||
LoginDays: number;
|
LoginDays: number;
|
||||||
|
DailyFirstWinDate: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Includes virtual ID
|
// Includes virtual ID
|
||||||
|
@ -17,9 +17,9 @@ export interface IMissionReward {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IMissionCredits {
|
export interface IMissionCredits {
|
||||||
MissionCredits: number[];
|
MissionCredits: [number, number];
|
||||||
CreditBonus: number[];
|
CreditsBonus: [number, number]; // "Credit Reward"; `CreditsBonus[1]` is `CreditsBonus[0] * 2` if DailyMissionBonus
|
||||||
TotalCredits: number[];
|
TotalCredits: [number, number];
|
||||||
DailyMissionBonus?: boolean;
|
DailyMissionBonus?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DojoRemasterTrophyGoldARecipe",
|
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DojoRemasterTrophyGoldARecipe",
|
||||||
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DojoRemasterTrophyPlatinumARecipe",
|
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DojoRemasterTrophyPlatinumARecipe",
|
||||||
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DojoRemasterTrophySilverARecipe",
|
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DojoRemasterTrophySilverARecipe",
|
||||||
|
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DuviriMurmurEventBronzeTrophyRecipe",
|
||||||
|
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DuviriMurmurEventClayTrophyRecipe",
|
||||||
|
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DuviriMurmurEventGoldTrophyRecipe",
|
||||||
|
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DuviriMurmurEventSilverTrophyRecipe",
|
||||||
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/EntratiEventBaseTrophyRecipe",
|
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/EntratiEventBaseTrophyRecipe",
|
||||||
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/EntratiEventBronzeTrophyRecipe",
|
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/EntratiEventBronzeTrophyRecipe",
|
||||||
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/EntratiEventGoldTrophyRecipe",
|
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/EntratiEventGoldTrophyRecipe",
|
||||||
|
@ -98,9 +98,9 @@
|
|||||||
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3 mb-3">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="currency_RegularCredits"></h5>
|
<h5 class="card-header" data-loc="currency_RegularCredits"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p class="card-text" id="RegularCredits-owned"></p>
|
<p class="card-text" id="RegularCredits-owned"></p>
|
||||||
@ -112,7 +112,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="currency_PremiumCredits"></h5>
|
<h5 class="card-header" data-loc="currency_PremiumCredits"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p class="card-text" id="PremiumCredits-owned"></p>
|
<p class="card-text" id="PremiumCredits-owned"></p>
|
||||||
@ -124,7 +124,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="currency_FusionPoints"></h5>
|
<h5 class="card-header" data-loc="currency_FusionPoints"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p class="card-text" id="FusionPoints-owned"></p>
|
<p class="card-text" id="FusionPoints-owned"></p>
|
||||||
@ -136,7 +136,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="currency_PrimeTokens"></h5>
|
<h5 class="card-header" data-loc="currency_PrimeTokens"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p class="card-text" id="PrimeTokens-owned"></p>
|
<p class="card-text" id="PrimeTokens-owned"></p>
|
||||||
@ -148,9 +148,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3 mb-3">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_suits"></h5>
|
<h5 class="card-header" data-loc="inventory_suits"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Suits');return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Suits');return false;">
|
||||||
@ -164,7 +164,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_longGuns"></h5>
|
<h5 class="card-header" data-loc="inventory_longGuns"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="handleModularSelection('LongGuns');return false;">
|
<form class="input-group mb-3" onsubmit="handleModularSelection('LongGuns');return false;">
|
||||||
@ -183,9 +183,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3 mb-3">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_pistols"></h5>
|
<h5 class="card-header" data-loc="inventory_pistols"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="handleModularSelection('Pistols');return false;">
|
<form class="input-group mb-3" onsubmit="handleModularSelection('Pistols');return false;">
|
||||||
@ -204,7 +204,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_melee"></h5>
|
<h5 class="card-header" data-loc="inventory_melee"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="handleModularSelection('Melee');return false;">
|
<form class="input-group mb-3" onsubmit="handleModularSelection('Melee');return false;">
|
||||||
@ -223,9 +223,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3 mb-3">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_spaceSuits"></h5>
|
<h5 class="card-header" data-loc="inventory_spaceSuits"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceSuits');return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceSuits');return false;">
|
||||||
@ -239,7 +239,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_spaceGuns"></h5>
|
<h5 class="card-header" data-loc="inventory_spaceGuns"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceGuns');return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceGuns');return false;">
|
||||||
@ -253,9 +253,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3 mb-3">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_spaceMelee"></h5>
|
<h5 class="card-header" data-loc="inventory_spaceMelee"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceMelee');return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceMelee');return false;">
|
||||||
@ -269,7 +269,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_mechSuits"></h5>
|
<h5 class="card-header" data-loc="inventory_mechSuits"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('MechSuits');return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireEquipment('MechSuits');return false;">
|
||||||
@ -283,9 +283,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3 mb-3">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_sentinels"></h5>
|
<h5 class="card-header" data-loc="inventory_sentinels"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Sentinels');return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Sentinels');return false;">
|
||||||
@ -299,7 +299,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_moaPets"></h5>
|
<h5 class="card-header" data-loc="inventory_moaPets"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="handleModularSelection('MoaPets');return false;">
|
<form class="input-group mb-3" onsubmit="handleModularSelection('MoaPets');return false;">
|
||||||
@ -325,9 +325,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3 mb-3">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_kubrowPets"></h5>
|
<h5 class="card-header" data-loc="inventory_kubrowPets"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="handleModularSelection('KubrowPets');return false;">
|
<form class="input-group mb-3" onsubmit="handleModularSelection('KubrowPets');return false;">
|
||||||
@ -349,7 +349,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_sentinelWeapons"></h5>
|
<h5 class="card-header" data-loc="inventory_sentinelWeapons"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SentinelWeapons');return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SentinelWeapons');return false;">
|
||||||
@ -363,9 +363,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3 mb-3">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_operatorAmps"></h5>
|
<h5 class="card-header" data-loc="inventory_operatorAmps"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="handleModularSelection('OperatorAmps');return false;">
|
<form class="input-group mb-3" onsubmit="handleModularSelection('OperatorAmps');return false;">
|
||||||
@ -384,7 +384,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_hoverboards"></h5>
|
<h5 class="card-header" data-loc="inventory_hoverboards"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireModularEquipment('HoverBoards');return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireModularEquipment('HoverBoards');return false;">
|
||||||
@ -401,9 +401,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-3">
|
<div class="row g-3 mb-3">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_evolutionProgress"></h5>
|
<h5 class="card-header" data-loc="inventory_evolutionProgress"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireEvolution();return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireEvolution();return false;">
|
||||||
@ -417,7 +417,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3" style="height: 400px;">
|
<div class="card" style="height: 400px;">
|
||||||
<h5 class="card-header" data-loc="inventory_Boosters"></h5>
|
<h5 class="card-header" data-loc="inventory_Boosters"></h5>
|
||||||
<div class="card-body overflow-auto">
|
<div class="card-body overflow-auto">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireBoosters();return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireBoosters();return false;">
|
||||||
@ -431,7 +431,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="mb-2 d-flex flex-wrap gap-2">
|
<div class="mb-2 d-flex flex-wrap gap-2">
|
||||||
@ -458,7 +458,7 @@
|
|||||||
<div id="powersuit-route" data-route="~ /webui/powersuit/(.+)" data-title="Inventory | OpenWF WebUI">
|
<div id="powersuit-route" data-route="~ /webui/powersuit/(.+)" data-title="Inventory | OpenWF WebUI">
|
||||||
<h3 class="mb-0"></h3>
|
<h3 class="mb-0"></h3>
|
||||||
<p class="text-body-secondary"></p>
|
<p class="text-body-secondary"></p>
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="powersuit_archonShardsLabel"></h5>
|
<h5 class="card-header" data-loc="powersuit_archonShardsLabel"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<p>
|
<p>
|
||||||
@ -498,7 +498,7 @@
|
|||||||
<a href="riven-tool/" target="_blank" data-loc="mods_fingerprintHelp"></a>
|
<a href="riven-tool/" target="_blank" data-loc="mods_fingerprintHelp"></a>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="mods_rivens"></h5>
|
<h5 class="card-header" data-loc="mods_rivens"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-hover w-100">
|
<table class="table table-hover w-100">
|
||||||
@ -521,7 +521,7 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
||||||
<div class="card-body d-flex flex-wrap gap-2">
|
<div class="card-body d-flex flex-wrap gap-2">
|
||||||
<button class="btn btn-primary" onclick="doAddAllMods();" data-loc="mods_addMissingUnrankedMods"></button>
|
<button class="btn btn-primary" onclick="doAddAllMods();" data-loc="mods_addMissingUnrankedMods"></button>
|
||||||
@ -535,7 +535,7 @@
|
|||||||
<div data-route="/webui/quests" data-title="Quests | OpenWF WebUI">
|
<div data-route="/webui/quests" data-title="Quests | OpenWF WebUI">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="quests_list"></h5>
|
<h5 class="card-header" data-loc="quests_list"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form class="input-group mb-3" onsubmit="doAcquireEquipment('QuestKeys');return false;">
|
<form class="input-group mb-3" onsubmit="doAcquireEquipment('QuestKeys');return false;">
|
||||||
@ -549,7 +549,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
<h5 class="card-header" data-loc="general_bulkActions"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="d-flex flex-wrap gap-2">
|
<div class="d-flex flex-wrap gap-2">
|
||||||
@ -565,13 +565,13 @@
|
|||||||
<div data-route="/webui/cheats, /webui/settings" data-title="Cheats | OpenWF WebUI">
|
<div data-route="/webui/cheats, /webui/settings" data-title="Cheats | OpenWF WebUI">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="card mb-3">
|
<div class="card">
|
||||||
<h5 class="card-header" data-loc="cheats_server"></h5>
|
<h5 class="card-header" data-loc="cheats_server"></h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div id="server-settings-no-perms" class="d-none">
|
<div class="d-none config-admin-hide">
|
||||||
<p class="card-text" data-loc="cheats_administratorRequirement"></p>
|
<p class="card-text" data-loc="cheats_administratorRequirement"></p>
|
||||||
</div>
|
</div>
|
||||||
<div id="server-settings" class="d-none">
|
<div class="d-none config-admin-show config-form">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" id="skipTutorial" />
|
<input class="form-check-input" type="checkbox" id="skipTutorial" />
|
||||||
<label class="form-check-label" for="skipTutorial" data-loc="cheats_skipTutorial"></label>
|
<label class="form-check-label" for="skipTutorial" data-loc="cheats_skipTutorial"></label>
|
||||||
@ -807,6 +807,93 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card d-none config-admin-show config-form">
|
||||||
|
<h5 class="card-header" data-loc="worldState"></h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="worldState.creditBoost" />
|
||||||
|
<label class="form-check-label" for="worldState.creditBoost" data-loc="worldState_creditBoost"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="worldState.affinityBoost" />
|
||||||
|
<label class="form-check-label" for="worldState.affinityBoost" data-loc="worldState_affinityBoost"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="worldState.resourceBoost" />
|
||||||
|
<label class="form-check-label" for="worldState.resourceBoost" data-loc="worldState_resourceBoost"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="worldState.starDays" />
|
||||||
|
<label class="form-check-label" for="worldState.starDays" data-loc="worldState_starDays"></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mt-2">
|
||||||
|
<label class="form-label" for="changeSyndicate" data-loc="worldState_galleonOfGhouls"></label>
|
||||||
|
<select class="form-control" id="worldState.galleonOfGhouls">
|
||||||
|
<option value="0" data-loc="disabled"></option>
|
||||||
|
<option value="1" data-loc="worldState_we1"></option>
|
||||||
|
<option value="2" data-loc="worldState_we2"></option>
|
||||||
|
<option value="3" data-loc="worldState_we3"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mt-2">
|
||||||
|
<label class="form-label" for="changeSyndicate" data-loc="worldState_eidolonOverride"></label>
|
||||||
|
<select class="form-control" id="worldState.eidolonOverride">
|
||||||
|
<option value="" data-loc="disabled"></option>
|
||||||
|
<option value="day" data-loc="worldState_day"></option>
|
||||||
|
<option value="night" data-loc="worldState_night"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mt-2">
|
||||||
|
<label class="form-label" for="changeSyndicate" data-loc="worldState_vallisOverride"></label>
|
||||||
|
<select class="form-control" id="worldState.vallisOverride">
|
||||||
|
<option value="" data-loc="disabled"></option>
|
||||||
|
<option value="warm" data-loc="worldState_warm"></option>
|
||||||
|
<option value="cold" data-loc="worldState_cold"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mt-2">
|
||||||
|
<label class="form-label" for="changeSyndicate" data-loc="worldState_duviriOverride"></label>
|
||||||
|
<select class="form-control" id="worldState.duviriOverride">
|
||||||
|
<option value="" data-loc="disabled"></option>
|
||||||
|
<option value="joy" data-loc="worldState_joy"></option>
|
||||||
|
<option value="anger" data-loc="worldState_anger"></option>
|
||||||
|
<option value="envy" data-loc="worldState_envy"></option>
|
||||||
|
<option value="sorrow" data-loc="worldState_sorrow"></option>
|
||||||
|
<option value="fear" data-loc="worldState_fear"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mt-2">
|
||||||
|
<label class="form-label" for="changeSyndicate" data-loc="worldState_nightwaveOverride"></label>
|
||||||
|
<select class="form-control" id="worldState.nightwaveOverride">
|
||||||
|
<option value="" data-loc="disabled"></option>
|
||||||
|
<option value="RadioLegionIntermission13Syndicate" data-loc="worldState_RadioLegionIntermission13Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission12Syndicate" data-loc="worldState_RadioLegionIntermission12Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission11Syndicate" data-loc="worldState_RadioLegionIntermission11Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission10Syndicate" data-loc="worldState_RadioLegionIntermission10Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission9Syndicate" data-loc="worldState_RadioLegionIntermission9Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission8Syndicate" data-loc="worldState_RadioLegionIntermission8Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission7Syndicate" data-loc="worldState_RadioLegionIntermission7Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission6Syndicate" data-loc="worldState_RadioLegionIntermission6Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission5Syndicate" data-loc="worldState_RadioLegionIntermission5Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission4Syndicate" data-loc="worldState_RadioLegionIntermission4Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission3Syndicate" data-loc="worldState_RadioLegionIntermission3Syndicate"></option>
|
||||||
|
<option value="RadioLegion3Syndicate" data-loc="worldState_RadioLegion3Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermission2Syndicate" data-loc="worldState_RadioLegionIntermission2Syndicate"></option>
|
||||||
|
<option value="RadioLegion2Syndicate" data-loc="worldState_RadioLegion2Syndicate"></option>
|
||||||
|
<option value="RadioLegionIntermissionSyndicate" data-loc="worldState_RadioLegionIntermissionSyndicate"></option>
|
||||||
|
<option value="RadioLegionSyndicate" data-loc="worldState_RadioLegionSyndicate"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mt-2">
|
||||||
|
<label class="form-label" for="changeSyndicate" data-loc="worldState_fissures"></label>
|
||||||
|
<select class="form-control" id="worldState.allTheFissures">
|
||||||
|
<option value="" data-loc="normal"></option>
|
||||||
|
<option value="normal" data-loc="worldState_allAtOnceNormal"></option>
|
||||||
|
<option value="hard" data-loc="worldState_allAtOnceSteelPath"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
|
|
||||||
let auth_pending = false,
|
let auth_pending = false,
|
||||||
did_initial_auth = false,
|
did_initial_auth = false,
|
||||||
ws_is_open = false;
|
ws_is_open = false,
|
||||||
|
wsid = 0;
|
||||||
const sendAuth = isRegister => {
|
const sendAuth = isRegister => {
|
||||||
if (ws_is_open && localStorage.getItem("email") && localStorage.getItem("password")) {
|
if (ws_is_open && localStorage.getItem("email") && localStorage.getItem("password")) {
|
||||||
auth_pending = true;
|
auth_pending = true;
|
||||||
@ -34,6 +35,9 @@ function openWebSocket() {
|
|||||||
};
|
};
|
||||||
window.ws.onmessage = e => {
|
window.ws.onmessage = e => {
|
||||||
const msg = JSON.parse(e.data);
|
const msg = JSON.parse(e.data);
|
||||||
|
if ("wsid" in msg) {
|
||||||
|
wsid = msg.wsid;
|
||||||
|
}
|
||||||
if ("reload" in msg) {
|
if ("reload" in msg) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
getWebSocket().then(() => {
|
getWebSocket().then(() => {
|
||||||
@ -1847,16 +1851,28 @@ function doAcquireMod() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const uiConfigs = [...$("#server-settings input[id]")].map(x => x.id);
|
const uiConfigs = [...$(".config-form input[id], .config-form select[id]")].map(x => x.id);
|
||||||
|
|
||||||
for (const id of uiConfigs) {
|
for (const id of uiConfigs) {
|
||||||
const elm = document.getElementById(id);
|
const elm = document.getElementById(id);
|
||||||
if (elm.type == "checkbox") {
|
if (elm.tagName == "SELECT") {
|
||||||
|
elm.onchange = function () {
|
||||||
|
let value = this.value;
|
||||||
|
if (!isNaN(parseInt(value))) {
|
||||||
|
value = parseInt(value);
|
||||||
|
}
|
||||||
|
$.post({
|
||||||
|
url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
|
||||||
|
contentType: "application/json",
|
||||||
|
data: JSON.stringify({ [id]: value })
|
||||||
|
});
|
||||||
|
};
|
||||||
|
} else if (elm.type == "checkbox") {
|
||||||
elm.onchange = function () {
|
elm.onchange = function () {
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/config?" + window.authz,
|
url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify({ key: id, value: this.checked })
|
data: JSON.stringify({ [id]: this.checked })
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
if (["infiniteCredits", "infinitePlatinum", "infiniteEndo", "infiniteRegalAya"].indexOf(id) != -1) {
|
if (["infiniteCredits", "infinitePlatinum", "infiniteEndo", "infiniteRegalAya"].indexOf(id) != -1) {
|
||||||
updateInventory();
|
updateInventory();
|
||||||
@ -1869,9 +1885,9 @@ for (const id of uiConfigs) {
|
|||||||
function doSaveConfig(id) {
|
function doSaveConfig(id) {
|
||||||
const elm = document.getElementById(id);
|
const elm = document.getElementById(id);
|
||||||
$.post({
|
$.post({
|
||||||
url: "/custom/config?" + window.authz,
|
url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
data: JSON.stringify({ key: id, value: parseInt(elm.value) })
|
data: JSON.stringify({ [id]: parseInt(elm.value) })
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1882,26 +1898,29 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
|
|||||||
interval = setInterval(() => {
|
interval = setInterval(() => {
|
||||||
if (window.authz) {
|
if (window.authz) {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
fetch("/custom/config?" + window.authz).then(async res => {
|
$.post({
|
||||||
if (res.status == 200) {
|
url: "/custom/getConfig?" + window.authz,
|
||||||
|
contentType: "application/json",
|
||||||
|
data: JSON.stringify(uiConfigs)
|
||||||
|
})
|
||||||
|
.done(json => {
|
||||||
//window.is_admin = true;
|
//window.is_admin = true;
|
||||||
$("#server-settings-no-perms").addClass("d-none");
|
$(".config-admin-hide").addClass("d-none");
|
||||||
$("#server-settings").removeClass("d-none");
|
$(".config-admin-show").removeClass("d-none");
|
||||||
res.json().then(json =>
|
Object.entries(json).forEach(entry => {
|
||||||
Object.entries(json).forEach(entry => {
|
const [key, value] = entry;
|
||||||
const [key, value] = entry;
|
var x = document.getElementById(`${key}`);
|
||||||
var x = document.getElementById(`${key}`);
|
if (x != null) {
|
||||||
if (x != null) {
|
if (x.type == "checkbox") {
|
||||||
if (x.type == "checkbox") {
|
x.checked = value;
|
||||||
x.checked = value;
|
} else if (x.type == "number") {
|
||||||
} else if (x.type == "number") {
|
x.setAttribute("value", `${value}`);
|
||||||
x.setAttribute("value", `${value}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
);
|
});
|
||||||
} else {
|
})
|
||||||
if ((await res.text()) == "Log-in expired") {
|
.fail(res => {
|
||||||
|
if (res.responseText == "Log-in expired") {
|
||||||
revalidateAuthz().then(() => {
|
revalidateAuthz().then(() => {
|
||||||
if (single.getCurrentPath() == "/webui/cheats") {
|
if (single.getCurrentPath() == "/webui/cheats") {
|
||||||
single.loadRoute("/webui/cheats");
|
single.loadRoute("/webui/cheats");
|
||||||
@ -1909,11 +1928,10 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
//window.is_admin = false;
|
//window.is_admin = false;
|
||||||
$("#server-settings-no-perms").removeClass("d-none");
|
$(".config-admin-hide").removeClass("d-none");
|
||||||
$("#server-settings").addClass("d-none");
|
$(".config-admin-show").addClass("d-none");
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, 10);
|
}, 10);
|
||||||
});
|
});
|
||||||
@ -2275,14 +2293,13 @@ function doAcquireBoosters() {
|
|||||||
const ExpiryDate = Date.now() / 1000 + 3 * 24 * 60 * 60; // default 3 days
|
const ExpiryDate = Date.now() / 1000 + 3 * 24 * 60 * 60; // default 3 days
|
||||||
setBooster(uniqueName, ExpiryDate, () => {
|
setBooster(uniqueName, ExpiryDate, () => {
|
||||||
$("#acquire-type-Boosters").val("");
|
$("#acquire-type-Boosters").val("");
|
||||||
updateInventory();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function doChangeBoosterExpiry(ItemType, ExpiryDateInput) {
|
function doChangeBoosterExpiry(ItemType, ExpiryDateInput) {
|
||||||
console.log("Changing booster expiry for", ItemType, "to", ExpiryDateInput.value);
|
console.log("Changing booster expiry for", ItemType, "to", ExpiryDateInput.value);
|
||||||
// cast local datetime string to unix timestamp
|
// cast local datetime string to unix timestamp
|
||||||
const ExpiryDate = new Date(ExpiryDateInput.value).getTime() / 1000;
|
const ExpiryDate = Math.trunc(new Date(ExpiryDateInput.value).getTime() / 1000);
|
||||||
if (isNaN(ExpiryDate)) {
|
if (isNaN(ExpiryDate)) {
|
||||||
ExpiryDateInput.addClass("is-invalid").focus();
|
ExpiryDateInput.addClass("is-invalid").focus();
|
||||||
return false;
|
return false;
|
||||||
|
@ -186,6 +186,51 @@ dict = {
|
|||||||
cheats_changeSupportedSyndicate: `Unterstütztes Syndikat`,
|
cheats_changeSupportedSyndicate: `Unterstütztes Syndikat`,
|
||||||
cheats_changeButton: `Ändern`,
|
cheats_changeButton: `Ändern`,
|
||||||
cheats_none: `Keines`,
|
cheats_none: `Keines`,
|
||||||
|
|
||||||
|
worldState: `[UNTRANSLATED] World State`,
|
||||||
|
worldState_creditBoost: `[UNTRANSLATED] Credit Boost`,
|
||||||
|
worldState_affinityBoost: `[UNTRANSLATED] Affinity Boost`,
|
||||||
|
worldState_resourceBoost: `[UNTRANSLATED] Resource Boost`,
|
||||||
|
worldState_starDays: `[UNTRANSLATED] Star Days`,
|
||||||
|
worldState_galleonOfGhouls: `[UNTRANSLATED] Galleon of Ghouls`,
|
||||||
|
disabled: `[UNTRANSLATED] Disabled`,
|
||||||
|
worldState_we1: `[UNTRANSLATED] Weekend 1`,
|
||||||
|
worldState_we2: `[UNTRANSLATED] Weekend 2`,
|
||||||
|
worldState_we3: `[UNTRANSLATED] Weekend 3`,
|
||||||
|
worldState_eidolonOverride: `[UNTRANSLATED] Eidolon Override`,
|
||||||
|
worldState_day: `[UNTRANSLATED] Day`,
|
||||||
|
worldState_night: `[UNTRANSLATED] Night`,
|
||||||
|
worldState_vallisOverride: `[UNTRANSLATED] Orb Vallis Override`,
|
||||||
|
worldState_warm: `[UNTRANSLATED] Warm`,
|
||||||
|
worldState_cold: `[UNTRANSLATED] Cold`,
|
||||||
|
worldState_duviriOverride: `[UNTRANSLATED] Duviri Override`,
|
||||||
|
worldState_joy: `[UNTRANSLATED] Joy`,
|
||||||
|
worldState_anger: `[UNTRANSLATED] Anger`,
|
||||||
|
worldState_envy: `[UNTRANSLATED] Envy`,
|
||||||
|
worldState_sorrow: `[UNTRANSLATED] Sorrow`,
|
||||||
|
worldState_fear: `[UNTRANSLATED] Fear`,
|
||||||
|
worldState_nightwaveOverride: `[UNTRANSLATED] Nightwave Override`,
|
||||||
|
worldState_RadioLegionIntermission13Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 9`,
|
||||||
|
worldState_RadioLegionIntermission12Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 8`,
|
||||||
|
worldState_RadioLegionIntermission11Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 7`,
|
||||||
|
worldState_RadioLegionIntermission10Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 6`,
|
||||||
|
worldState_RadioLegionIntermission9Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 5`,
|
||||||
|
worldState_RadioLegionIntermission8Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 4`,
|
||||||
|
worldState_RadioLegionIntermission7Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 3`,
|
||||||
|
worldState_RadioLegionIntermission6Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 2`,
|
||||||
|
worldState_RadioLegionIntermission5Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 1`,
|
||||||
|
worldState_RadioLegionIntermission4Syndicate: `[UNTRANSLATED] Nora's Choice`,
|
||||||
|
worldState_RadioLegionIntermission3Syndicate: `[UNTRANSLATED] Intermission III`,
|
||||||
|
worldState_RadioLegion3Syndicate: `[UNTRANSLATED] Glassmaker`,
|
||||||
|
worldState_RadioLegionIntermission2Syndicate: `[UNTRANSLATED] Intermission II`,
|
||||||
|
worldState_RadioLegion2Syndicate: `[UNTRANSLATED] The Emissary`,
|
||||||
|
worldState_RadioLegionIntermissionSyndicate: `[UNTRANSLATED] Intermission I`,
|
||||||
|
worldState_RadioLegionSyndicate: `[UNTRANSLATED] The Wolf of Saturn Six`,
|
||||||
|
worldState_fissures: `[UNTRANSLATED] Fissures`,
|
||||||
|
normal: `[UNTRANSLATED] Normal`,
|
||||||
|
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
|
||||||
|
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
|
||||||
|
|
||||||
import_importNote: `Du kannst hier eine vollständige oder teilweise Inventarantwort (Client-Darstellung) einfügen. Alle Felder, die vom Importer unterstützt werden, <b>werden in deinem Account überschrieben</b>.`,
|
import_importNote: `Du kannst hier eine vollständige oder teilweise Inventarantwort (Client-Darstellung) einfügen. Alle Felder, die vom Importer unterstützt werden, <b>werden in deinem Account überschrieben</b>.`,
|
||||||
import_submit: `Absenden`,
|
import_submit: `Absenden`,
|
||||||
import_samples: `[UNTRANSLATED] Samples:`,
|
import_samples: `[UNTRANSLATED] Samples:`,
|
||||||
|
@ -185,6 +185,51 @@ dict = {
|
|||||||
cheats_changeSupportedSyndicate: `Supported syndicate`,
|
cheats_changeSupportedSyndicate: `Supported syndicate`,
|
||||||
cheats_changeButton: `Change`,
|
cheats_changeButton: `Change`,
|
||||||
cheats_none: `None`,
|
cheats_none: `None`,
|
||||||
|
|
||||||
|
worldState: `World State`,
|
||||||
|
worldState_creditBoost: `Credit Boost`,
|
||||||
|
worldState_affinityBoost: `Affinity Boost`,
|
||||||
|
worldState_resourceBoost: `Resource Boost`,
|
||||||
|
worldState_starDays: `Star Days`,
|
||||||
|
worldState_galleonOfGhouls: `Galleon of Ghouls`,
|
||||||
|
disabled: `Disabled`,
|
||||||
|
worldState_we1: `Weekend 1`,
|
||||||
|
worldState_we2: `Weekend 2`,
|
||||||
|
worldState_we3: `Weekend 3`,
|
||||||
|
worldState_eidolonOverride: `Eidolon Override`,
|
||||||
|
worldState_day: `Day`,
|
||||||
|
worldState_night: `Night`,
|
||||||
|
worldState_vallisOverride: `Orb Vallis Override`,
|
||||||
|
worldState_warm: `Warm`,
|
||||||
|
worldState_cold: `Cold`,
|
||||||
|
worldState_duviriOverride: `Duviri Override`,
|
||||||
|
worldState_joy: `Joy`,
|
||||||
|
worldState_anger: `Anger`,
|
||||||
|
worldState_envy: `Envy`,
|
||||||
|
worldState_sorrow: `Sorrow`,
|
||||||
|
worldState_fear: `Fear`,
|
||||||
|
worldState_nightwaveOverride: `Nightwave Override`,
|
||||||
|
worldState_RadioLegionIntermission13Syndicate: `Nora's Mix Vol. 9`,
|
||||||
|
worldState_RadioLegionIntermission12Syndicate: `Nora's Mix Vol. 8`,
|
||||||
|
worldState_RadioLegionIntermission11Syndicate: `Nora's Mix Vol. 7`,
|
||||||
|
worldState_RadioLegionIntermission10Syndicate: `Nora's Mix Vol. 6`,
|
||||||
|
worldState_RadioLegionIntermission9Syndicate: `Nora's Mix Vol. 5`,
|
||||||
|
worldState_RadioLegionIntermission8Syndicate: `Nora's Mix Vol. 4`,
|
||||||
|
worldState_RadioLegionIntermission7Syndicate: `Nora's Mix Vol. 3`,
|
||||||
|
worldState_RadioLegionIntermission6Syndicate: `Nora's Mix Vol. 2`,
|
||||||
|
worldState_RadioLegionIntermission5Syndicate: `Nora's Mix Vol. 1`,
|
||||||
|
worldState_RadioLegionIntermission4Syndicate: `Nora's Choice`,
|
||||||
|
worldState_RadioLegionIntermission3Syndicate: `Intermission III`,
|
||||||
|
worldState_RadioLegion3Syndicate: `Glassmaker`,
|
||||||
|
worldState_RadioLegionIntermission2Syndicate: `Intermission II`,
|
||||||
|
worldState_RadioLegion2Syndicate: `The Emissary`,
|
||||||
|
worldState_RadioLegionIntermissionSyndicate: `Intermission I`,
|
||||||
|
worldState_RadioLegionSyndicate: `The Wolf of Saturn Six`,
|
||||||
|
worldState_fissures: `Fissures`,
|
||||||
|
normal: `Normal`,
|
||||||
|
worldState_allAtOnceNormal: `All At Once, Normal`,
|
||||||
|
worldState_allAtOnceSteelPath: `All At Once, Steel Path`,
|
||||||
|
|
||||||
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_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`,
|
import_submit: `Submit`,
|
||||||
import_samples: `Samples:`,
|
import_samples: `Samples:`,
|
||||||
|
@ -186,6 +186,51 @@ dict = {
|
|||||||
cheats_changeSupportedSyndicate: `Sindicatos disponibles`,
|
cheats_changeSupportedSyndicate: `Sindicatos disponibles`,
|
||||||
cheats_changeButton: `Cambiar`,
|
cheats_changeButton: `Cambiar`,
|
||||||
cheats_none: `Ninguno`,
|
cheats_none: `Ninguno`,
|
||||||
|
|
||||||
|
worldState: `[UNTRANSLATED] World State`,
|
||||||
|
worldState_creditBoost: `[UNTRANSLATED] Credit Boost`,
|
||||||
|
worldState_affinityBoost: `[UNTRANSLATED] Affinity Boost`,
|
||||||
|
worldState_resourceBoost: `[UNTRANSLATED] Resource Boost`,
|
||||||
|
worldState_starDays: `[UNTRANSLATED] Star Days`,
|
||||||
|
worldState_galleonOfGhouls: `[UNTRANSLATED] Galleon of Ghouls`,
|
||||||
|
disabled: `[UNTRANSLATED] Disabled`,
|
||||||
|
worldState_we1: `[UNTRANSLATED] Weekend 1`,
|
||||||
|
worldState_we2: `[UNTRANSLATED] Weekend 2`,
|
||||||
|
worldState_we3: `[UNTRANSLATED] Weekend 3`,
|
||||||
|
worldState_eidolonOverride: `[UNTRANSLATED] Eidolon Override`,
|
||||||
|
worldState_day: `[UNTRANSLATED] Day`,
|
||||||
|
worldState_night: `[UNTRANSLATED] Night`,
|
||||||
|
worldState_vallisOverride: `[UNTRANSLATED] Orb Vallis Override`,
|
||||||
|
worldState_warm: `[UNTRANSLATED] Warm`,
|
||||||
|
worldState_cold: `[UNTRANSLATED] Cold`,
|
||||||
|
worldState_duviriOverride: `[UNTRANSLATED] Duviri Override`,
|
||||||
|
worldState_joy: `[UNTRANSLATED] Joy`,
|
||||||
|
worldState_anger: `[UNTRANSLATED] Anger`,
|
||||||
|
worldState_envy: `[UNTRANSLATED] Envy`,
|
||||||
|
worldState_sorrow: `[UNTRANSLATED] Sorrow`,
|
||||||
|
worldState_fear: `[UNTRANSLATED] Fear`,
|
||||||
|
worldState_nightwaveOverride: `[UNTRANSLATED] Nightwave Override`,
|
||||||
|
worldState_RadioLegionIntermission13Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 9`,
|
||||||
|
worldState_RadioLegionIntermission12Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 8`,
|
||||||
|
worldState_RadioLegionIntermission11Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 7`,
|
||||||
|
worldState_RadioLegionIntermission10Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 6`,
|
||||||
|
worldState_RadioLegionIntermission9Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 5`,
|
||||||
|
worldState_RadioLegionIntermission8Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 4`,
|
||||||
|
worldState_RadioLegionIntermission7Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 3`,
|
||||||
|
worldState_RadioLegionIntermission6Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 2`,
|
||||||
|
worldState_RadioLegionIntermission5Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 1`,
|
||||||
|
worldState_RadioLegionIntermission4Syndicate: `[UNTRANSLATED] Nora's Choice`,
|
||||||
|
worldState_RadioLegionIntermission3Syndicate: `[UNTRANSLATED] Intermission III`,
|
||||||
|
worldState_RadioLegion3Syndicate: `[UNTRANSLATED] Glassmaker`,
|
||||||
|
worldState_RadioLegionIntermission2Syndicate: `[UNTRANSLATED] Intermission II`,
|
||||||
|
worldState_RadioLegion2Syndicate: `[UNTRANSLATED] The Emissary`,
|
||||||
|
worldState_RadioLegionIntermissionSyndicate: `[UNTRANSLATED] Intermission I`,
|
||||||
|
worldState_RadioLegionSyndicate: `[UNTRANSLATED] The Wolf of Saturn Six`,
|
||||||
|
worldState_fissures: `[UNTRANSLATED] Fissures`,
|
||||||
|
normal: `[UNTRANSLATED] Normal`,
|
||||||
|
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
|
||||||
|
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
|
||||||
|
|
||||||
import_importNote: `Puedes proporcionar una respuesta de inventario completa o parcial (representación del cliente) aquí. Todos los campos compatibles con el importador <b>serán sobrescritos</b> en tu cuenta.`,
|
import_importNote: `Puedes proporcionar una respuesta de inventario completa o parcial (representación del cliente) aquí. Todos los campos compatibles con el importador <b>serán sobrescritos</b> en tu cuenta.`,
|
||||||
import_submit: `Enviar`,
|
import_submit: `Enviar`,
|
||||||
import_samples: `Muestras:`,
|
import_samples: `Muestras:`,
|
||||||
|
@ -186,6 +186,51 @@ dict = {
|
|||||||
cheats_changeSupportedSyndicate: `Allégeance`,
|
cheats_changeSupportedSyndicate: `Allégeance`,
|
||||||
cheats_changeButton: `Changer`,
|
cheats_changeButton: `Changer`,
|
||||||
cheats_none: `Aucun`,
|
cheats_none: `Aucun`,
|
||||||
|
|
||||||
|
worldState: `[UNTRANSLATED] World State`,
|
||||||
|
worldState_creditBoost: `[UNTRANSLATED] Credit Boost`,
|
||||||
|
worldState_affinityBoost: `[UNTRANSLATED] Affinity Boost`,
|
||||||
|
worldState_resourceBoost: `[UNTRANSLATED] Resource Boost`,
|
||||||
|
worldState_starDays: `[UNTRANSLATED] Star Days`,
|
||||||
|
worldState_galleonOfGhouls: `[UNTRANSLATED] Galleon of Ghouls`,
|
||||||
|
disabled: `[UNTRANSLATED] Disabled`,
|
||||||
|
worldState_we1: `[UNTRANSLATED] Weekend 1`,
|
||||||
|
worldState_we2: `[UNTRANSLATED] Weekend 2`,
|
||||||
|
worldState_we3: `[UNTRANSLATED] Weekend 3`,
|
||||||
|
worldState_eidolonOverride: `[UNTRANSLATED] Eidolon Override`,
|
||||||
|
worldState_day: `[UNTRANSLATED] Day`,
|
||||||
|
worldState_night: `[UNTRANSLATED] Night`,
|
||||||
|
worldState_vallisOverride: `[UNTRANSLATED] Orb Vallis Override`,
|
||||||
|
worldState_warm: `[UNTRANSLATED] Warm`,
|
||||||
|
worldState_cold: `[UNTRANSLATED] Cold`,
|
||||||
|
worldState_duviriOverride: `[UNTRANSLATED] Duviri Override`,
|
||||||
|
worldState_joy: `[UNTRANSLATED] Joy`,
|
||||||
|
worldState_anger: `[UNTRANSLATED] Anger`,
|
||||||
|
worldState_envy: `[UNTRANSLATED] Envy`,
|
||||||
|
worldState_sorrow: `[UNTRANSLATED] Sorrow`,
|
||||||
|
worldState_fear: `[UNTRANSLATED] Fear`,
|
||||||
|
worldState_nightwaveOverride: `[UNTRANSLATED] Nightwave Override`,
|
||||||
|
worldState_RadioLegionIntermission13Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 9`,
|
||||||
|
worldState_RadioLegionIntermission12Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 8`,
|
||||||
|
worldState_RadioLegionIntermission11Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 7`,
|
||||||
|
worldState_RadioLegionIntermission10Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 6`,
|
||||||
|
worldState_RadioLegionIntermission9Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 5`,
|
||||||
|
worldState_RadioLegionIntermission8Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 4`,
|
||||||
|
worldState_RadioLegionIntermission7Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 3`,
|
||||||
|
worldState_RadioLegionIntermission6Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 2`,
|
||||||
|
worldState_RadioLegionIntermission5Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 1`,
|
||||||
|
worldState_RadioLegionIntermission4Syndicate: `[UNTRANSLATED] Nora's Choice`,
|
||||||
|
worldState_RadioLegionIntermission3Syndicate: `[UNTRANSLATED] Intermission III`,
|
||||||
|
worldState_RadioLegion3Syndicate: `[UNTRANSLATED] Glassmaker`,
|
||||||
|
worldState_RadioLegionIntermission2Syndicate: `[UNTRANSLATED] Intermission II`,
|
||||||
|
worldState_RadioLegion2Syndicate: `[UNTRANSLATED] The Emissary`,
|
||||||
|
worldState_RadioLegionIntermissionSyndicate: `[UNTRANSLATED] Intermission I`,
|
||||||
|
worldState_RadioLegionSyndicate: `[UNTRANSLATED] The Wolf of Saturn Six`,
|
||||||
|
worldState_fissures: `[UNTRANSLATED] Fissures`,
|
||||||
|
normal: `[UNTRANSLATED] Normal`,
|
||||||
|
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
|
||||||
|
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
|
||||||
|
|
||||||
import_importNote: `Import manuel. Toutes les modifcations supportées par l'inventaire <b>écraseront celles présentes dans la base de données</b>.`,
|
import_importNote: `Import manuel. Toutes les modifcations supportées par l'inventaire <b>écraseront celles présentes dans la base de données</b>.`,
|
||||||
import_submit: `Soumettre`,
|
import_submit: `Soumettre`,
|
||||||
import_samples: `Echantillons :`,
|
import_samples: `Echantillons :`,
|
||||||
|
@ -186,6 +186,51 @@ dict = {
|
|||||||
cheats_changeSupportedSyndicate: `Поддерживаемый синдикат`,
|
cheats_changeSupportedSyndicate: `Поддерживаемый синдикат`,
|
||||||
cheats_changeButton: `Изменить`,
|
cheats_changeButton: `Изменить`,
|
||||||
cheats_none: `Отсутствует`,
|
cheats_none: `Отсутствует`,
|
||||||
|
|
||||||
|
worldState: `[UNTRANSLATED] World State`,
|
||||||
|
worldState_creditBoost: `[UNTRANSLATED] Credit Boost`,
|
||||||
|
worldState_affinityBoost: `[UNTRANSLATED] Affinity Boost`,
|
||||||
|
worldState_resourceBoost: `[UNTRANSLATED] Resource Boost`,
|
||||||
|
worldState_starDays: `[UNTRANSLATED] Star Days`,
|
||||||
|
worldState_galleonOfGhouls: `[UNTRANSLATED] Galleon of Ghouls`,
|
||||||
|
disabled: `[UNTRANSLATED] Disabled`,
|
||||||
|
worldState_we1: `[UNTRANSLATED] Weekend 1`,
|
||||||
|
worldState_we2: `[UNTRANSLATED] Weekend 2`,
|
||||||
|
worldState_we3: `[UNTRANSLATED] Weekend 3`,
|
||||||
|
worldState_eidolonOverride: `[UNTRANSLATED] Eidolon Override`,
|
||||||
|
worldState_day: `[UNTRANSLATED] Day`,
|
||||||
|
worldState_night: `[UNTRANSLATED] Night`,
|
||||||
|
worldState_vallisOverride: `[UNTRANSLATED] Orb Vallis Override`,
|
||||||
|
worldState_warm: `[UNTRANSLATED] Warm`,
|
||||||
|
worldState_cold: `[UNTRANSLATED] Cold`,
|
||||||
|
worldState_duviriOverride: `[UNTRANSLATED] Duviri Override`,
|
||||||
|
worldState_joy: `[UNTRANSLATED] Joy`,
|
||||||
|
worldState_anger: `[UNTRANSLATED] Anger`,
|
||||||
|
worldState_envy: `[UNTRANSLATED] Envy`,
|
||||||
|
worldState_sorrow: `[UNTRANSLATED] Sorrow`,
|
||||||
|
worldState_fear: `[UNTRANSLATED] Fear`,
|
||||||
|
worldState_nightwaveOverride: `[UNTRANSLATED] Nightwave Override`,
|
||||||
|
worldState_RadioLegionIntermission13Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 9`,
|
||||||
|
worldState_RadioLegionIntermission12Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 8`,
|
||||||
|
worldState_RadioLegionIntermission11Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 7`,
|
||||||
|
worldState_RadioLegionIntermission10Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 6`,
|
||||||
|
worldState_RadioLegionIntermission9Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 5`,
|
||||||
|
worldState_RadioLegionIntermission8Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 4`,
|
||||||
|
worldState_RadioLegionIntermission7Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 3`,
|
||||||
|
worldState_RadioLegionIntermission6Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 2`,
|
||||||
|
worldState_RadioLegionIntermission5Syndicate: `[UNTRANSLATED] Nora's Mix Vol. 1`,
|
||||||
|
worldState_RadioLegionIntermission4Syndicate: `[UNTRANSLATED] Nora's Choice`,
|
||||||
|
worldState_RadioLegionIntermission3Syndicate: `[UNTRANSLATED] Intermission III`,
|
||||||
|
worldState_RadioLegion3Syndicate: `[UNTRANSLATED] Glassmaker`,
|
||||||
|
worldState_RadioLegionIntermission2Syndicate: `[UNTRANSLATED] Intermission II`,
|
||||||
|
worldState_RadioLegion2Syndicate: `[UNTRANSLATED] The Emissary`,
|
||||||
|
worldState_RadioLegionIntermissionSyndicate: `[UNTRANSLATED] Intermission I`,
|
||||||
|
worldState_RadioLegionSyndicate: `[UNTRANSLATED] The Wolf of Saturn Six`,
|
||||||
|
worldState_fissures: `[UNTRANSLATED] Fissures`,
|
||||||
|
normal: `[UNTRANSLATED] Normal`,
|
||||||
|
worldState_allAtOnceNormal: `[UNTRANSLATED] All At Once, Normal`,
|
||||||
|
worldState_allAtOnceSteelPath: `[UNTRANSLATED] All At Once, Steel Path`,
|
||||||
|
|
||||||
import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
|
import_importNote: `Вы можете загрузить полный или частичный ответ инвентаря (клиентское представление) здесь. Все поддерживаемые поля <b>будут перезаписаны</b> в вашем аккаунте.`,
|
||||||
import_submit: `Отправить`,
|
import_submit: `Отправить`,
|
||||||
import_samples: `[UNTRANSLATED] Samples:`,
|
import_samples: `[UNTRANSLATED] Samples:`,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Chinese translation by meb154 & bishan178
|
// Chinese translation by meb154, bishan178 & Corvus
|
||||||
dict = {
|
dict = {
|
||||||
general_inventoryUpdateNote: `注意:此处所做的更改只有在游戏同步仓库后才会生效。您可以通过访问星图来触发仓库更新。`,
|
general_inventoryUpdateNote: `注意:此处所做的更改只有在游戏同步仓库后才会生效。您可以通过访问星图来触发仓库更新。`,
|
||||||
general_addButton: `添加`,
|
general_addButton: `添加`,
|
||||||
@ -186,6 +186,51 @@ dict = {
|
|||||||
cheats_changeSupportedSyndicate: `支持的集团`,
|
cheats_changeSupportedSyndicate: `支持的集团`,
|
||||||
cheats_changeButton: `更改`,
|
cheats_changeButton: `更改`,
|
||||||
cheats_none: `无`,
|
cheats_none: `无`,
|
||||||
|
|
||||||
|
worldState: `世界状态配置`,
|
||||||
|
worldState_creditBoost: `现金加成`,
|
||||||
|
worldState_affinityBoost: `经验加成`,
|
||||||
|
worldState_resourceBoost: `资源加成`,
|
||||||
|
worldState_starDays: `活动:星日`,
|
||||||
|
worldState_galleonOfGhouls: `战术警报:尸鬼的帆船战舰`,
|
||||||
|
disabled: `关闭/取消配置`,
|
||||||
|
worldState_we1: `活动阶段:第一周`,
|
||||||
|
worldState_we2: `活动阶段:第二周`,
|
||||||
|
worldState_we3: `活动阶段:第三周`,
|
||||||
|
worldState_eidolonOverride: `夜灵平原/魔胎之境状态`,
|
||||||
|
worldState_day: `白昼/FASS`,
|
||||||
|
worldState_night: `黑夜/VOME`,
|
||||||
|
worldState_vallisOverride: `奥布山谷状态`,
|
||||||
|
worldState_warm: `温暖`,
|
||||||
|
worldState_cold: `寒冷`,
|
||||||
|
worldState_duviriOverride: `双衍王镜状态`,
|
||||||
|
worldState_joy: `喜悦`,
|
||||||
|
worldState_anger: `愤怒`,
|
||||||
|
worldState_envy: `嫉妒`,
|
||||||
|
worldState_sorrow: `悲伤`,
|
||||||
|
worldState_fear: `恐惧`,
|
||||||
|
worldState_nightwaveOverride: `午夜电波系列`,
|
||||||
|
worldState_RadioLegionIntermission13Syndicate: `诺拉的混选VOL.9`,
|
||||||
|
worldState_RadioLegionIntermission12Syndicate: `诺拉的混选VOL.8`,
|
||||||
|
worldState_RadioLegionIntermission11Syndicate: `诺拉的混选VOL.7`,
|
||||||
|
worldState_RadioLegionIntermission10Syndicate: `诺拉的混选VOL.6`,
|
||||||
|
worldState_RadioLegionIntermission9Syndicate: `诺拉的混选VOL.5`,
|
||||||
|
worldState_RadioLegionIntermission8Syndicate: `诺拉的混选VOL.4`,
|
||||||
|
worldState_RadioLegionIntermission7Syndicate: `诺拉的混选VOL.3`,
|
||||||
|
worldState_RadioLegionIntermission6Syndicate: `诺拉的混选VOL.2`,
|
||||||
|
worldState_RadioLegionIntermission5Syndicate: `诺拉的混选VOL.1`,
|
||||||
|
worldState_RadioLegionIntermission4Syndicate: `诺拉的精选`,
|
||||||
|
worldState_RadioLegionIntermission3Syndicate: `间歇III`,
|
||||||
|
worldState_RadioLegion3Syndicate: `系列3 — 玻璃匠`,
|
||||||
|
worldState_RadioLegionIntermission2Syndicate: `间歇II`,
|
||||||
|
worldState_RadioLegion2Syndicate: `系列2 — 使徒`,
|
||||||
|
worldState_RadioLegionIntermissionSyndicate: `间歇I`,
|
||||||
|
worldState_RadioLegionSyndicate: `系列1 — 土星六号之狼`,
|
||||||
|
worldState_fissures: `虚空裂缝难度设定`,
|
||||||
|
normal: `正常`,
|
||||||
|
worldState_allAtOnceNormal: `全部开启(普通)`,
|
||||||
|
worldState_allAtOnceSteelPath: `全部开启(钢铁之路)`,
|
||||||
|
|
||||||
import_importNote: `您可以在此处提供完整或部分库存响应(客户端表示)。支持的所有字段<b>将被覆盖</b>到您的账户中。`,
|
import_importNote: `您可以在此处提供完整或部分库存响应(客户端表示)。支持的所有字段<b>将被覆盖</b>到您的账户中。`,
|
||||||
import_submit: `提交`,
|
import_submit: `提交`,
|
||||||
import_samples: `示例:`,
|
import_samples: `示例:`,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user