Compare commits

..

11 Commits

Author SHA1 Message Date
5329a6cc94 更新 static/webui/translations/zh.js
All checks were successful
Build / build (pull_request) Successful in 1m23s
2025-06-26 21:37:58 -07:00
0ab8b395ef 更新 static/webui/translations/zh.js
All checks were successful
Build / build (pull_request) Successful in 1m16s
2025-06-26 21:09:09 -07:00
06d4aca22a 更新 static/webui/translations/zh.js
All checks were successful
Build / build (pull_request) Successful in 1m16s
2025-06-26 20:49:11 -07:00
2c38939290 merge upstream 2025-06-26 20:20:57 -07:00
584a79d0f8 更新 static/webui/translations/zh.js
All checks were successful
Build / build (pull_request) Successful in 1m0s
2025-06-26 00:00:29 -07:00
9eb4570218 更新 static/webui/translations/zh.js
All checks were successful
Build / build (pull_request) Successful in 54s
2025-06-26 00:00:03 -07:00
fb1c4c6a57 更新 static/webui/translations/zh.js
All checks were successful
Build / build (pull_request) Successful in 52s
2025-06-25 22:15:44 -07:00
cfff91ca5d merge upstream 2025-06-25 22:03:38 -07:00
2e2a31008a 更新 static/webui/translations/zh.js
All checks were successful
Build / build (pull_request) Successful in 53s
2025-06-24 21:57:11 -07:00
922042c0d7 更新 static/webui/translations/zh.js
All checks were successful
Build / build (pull_request) Successful in 1m21s
2025-06-24 21:56:43 -07:00
cf31ecd977 更新 static/webui/translations/zh.js
All checks were successful
Build / build (pull_request) Successful in 52s
2025-06-24 21:51:54 -07:00
21 changed files with 116 additions and 208 deletions

8
package-lock.json generated
View File

@ -23,7 +23,7 @@
"ncp": "^2.0.0",
"typescript": "^5.5",
"undici": "^7.10.0",
"warframe-public-export-plus": "^0.5.73",
"warframe-public-export-plus": "^0.5.72",
"warframe-riven-info": "^0.1.2",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",
@ -3386,9 +3386,9 @@
}
},
"node_modules/warframe-public-export-plus": {
"version": "0.5.73",
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.73.tgz",
"integrity": "sha512-v5lmaq/rNICg7WIZcosyfz92RpmrNyfW6+/Pbi9Iu8HbZH74PfaQKT6suAyC9xQn6xp8/cG3NLinqlLZovbKpw=="
"version": "0.5.72",
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.72.tgz",
"integrity": "sha512-oOZgtU6L0MGcPRKfA6+bonu+Db1kie1lVdLmA7/DbheTPweNkBEx3Hx3Seib+hEaFW+nLj3T5GtmGxGcFHCHfg=="
},
"node_modules/warframe-riven-info": {
"version": "0.1.2",

View File

@ -37,7 +37,7 @@
"ncp": "^2.0.0",
"typescript": "^5.5",
"undici": "^7.10.0",
"warframe-public-export-plus": "^0.5.73",
"warframe-public-export-plus": "^0.5.72",
"warframe-riven-info": "^0.1.2",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",

View File

@ -1,12 +1,16 @@
import { getAccountForRequest } from "@/src/services/loginService";
import { RequestHandler } from "express";
export const checkDailyMissionBonusController: RequestHandler = async (req, res) => {
const account = await getAccountForRequest(req);
const today = Math.trunc(Date.now() / 86400000) * 86400;
if (account.DailyFirstWinDate != today) {
res.send("DailyMissionBonus:1-DailyPVPWinBonus:1\n");
} else {
res.send("DailyMissionBonus:0-DailyPVPWinBonus:1\n");
}
const checkDailyMissionBonusController: RequestHandler = (_req, res) => {
const data = Buffer.from([
0x44, 0x61, 0x69, 0x6c, 0x79, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x6f, 0x6e, 0x75, 0x73, 0x3a,
0x31, 0x2d, 0x44, 0x61, 0x69, 0x6c, 0x79, 0x50, 0x56, 0x50, 0x57, 0x69, 0x6e, 0x42, 0x6f, 0x6e, 0x75, 0x73,
0x3a, 0x31, 0x0a
]);
res.writeHead(200, {
"Content-Type": "text/html",
"Content-Length": data.length
});
res.end(data);
};
export { checkDailyMissionBonusController };

View File

@ -88,7 +88,7 @@ export const missionInventoryUpdateController: RequestHandler = async (req, res)
AffiliationMods,
SyndicateXPItemReward,
ConquestCompletedMissionsCount
} = await addMissionRewards(account, inventory, missionReport, firstCompletion);
} = await addMissionRewards(inventory, missionReport, firstCompletion);
if (missionReport.EndOfMatchUpload) {
inventory.RewardSeed = generateRewardSeed();

View File

@ -57,11 +57,7 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) =
component.DecoCapacity -= meta.capacityCost;
}
} else {
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;
const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)![0];
if (deco.Sockets !== undefined) {
guild.VaultFusionTreasures!.find(x => x.ItemType == itemType && x.Sockets == deco.Sockets)!.ItemCount -=
1;

View File

@ -26,7 +26,7 @@ export const completeAllMissionsController: RequestHandler = async (req, res) =>
if (mission.Completes == 0) {
mission.Completes++;
if (node.missionReward) {
addFixedLevelRewards(node.missionReward, MissionRewards);
addFixedLevelRewards(node.missionReward, inventory, MissionRewards);
}
}
mission.Tier = 1;

View File

@ -2,7 +2,6 @@ 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);
@ -25,7 +24,6 @@ export const setConfigController: RequestHandler = async (req, res) => {
const [obj, idx] = configIdToIndexable(id);
obj[idx] = value;
}
sendWsBroadcastExcept(parseInt(String(req.query.wsid)), { config_reloaded: true });
await saveConfig();
res.end();
} else {

View File

@ -23,9 +23,9 @@ export const setBoosterController: RequestHandler = async (req, res) => {
res.status(400).send("Invalid ItemType provided.");
return;
}
const now = Math.trunc(Date.now() / 1000);
const now = Math.floor(Date.now() / 1000);
for (const { ItemType, ExpiryDate } of requests) {
if (ExpiryDate <= now) {
if (ExpiryDate < now) {
// remove expired boosters
const index = boosters.findIndex(item => item.ItemType === ItemType);
if (index !== -1) {

View File

@ -25,8 +25,7 @@ const databaseAccountSchema = new Schema<IDatabaseAccountJson>(
LastLogin: { type: Date, default: 0 },
LatestEventMessageDate: { type: Date, default: 0 },
LastLoginRewardDate: { type: Number, default: 0 },
LoginDays: { type: Number, default: 1 },
DailyFirstWinDate: { type: Number, default: 0 }
LoginDays: { type: Number, default: 1 }
},
opts
);

View File

@ -349,8 +349,7 @@ export const removeDojoDeco = (
component.DecoCapacity! += meta.capacityCost;
}
} else {
const [itemType, meta] = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)!;
component.DecoCapacity! += meta.dojoCapacityCost!;
const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)![0];
if (deco.Sockets !== undefined) {
addVaultFusionTreasures(guild, [
{

View File

@ -962,7 +962,6 @@ const droptableAliases: Record<string, string> = {
//TODO: return type of partial missioninventoryupdate response
export const addMissionRewards = async (
account: TAccountDocument,
inventory: TInventoryDatabaseDocument,
{
wagerTier: wagerTier,
@ -1010,17 +1009,13 @@ export const addMissionRewards = async (
const fixedLevelRewards = getLevelKeyRewards(levelKeyName);
//logger.debug(`fixedLevelRewards ${fixedLevelRewards}`);
if (fixedLevelRewards.levelKeyRewards) {
missionCompletionCredits += addFixedLevelRewards(
fixedLevelRewards.levelKeyRewards,
MissionRewards,
rewardInfo
);
addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, MissionRewards, rewardInfo);
}
if (fixedLevelRewards.levelKeyRewards2) {
for (const reward of fixedLevelRewards.levelKeyRewards2) {
//quest stage completion credit rewards
if (reward.rewardType == "RT_CREDITS") {
missionCompletionCredits += reward.amount;
missionCompletionCredits += reward.amount; // will be added to inventory in addCredits
continue;
}
MissionRewards.push({
@ -1049,11 +1044,12 @@ export const addMissionRewards = async (
) {
const levelCreditReward = getLevelCreditRewards(node);
missionCompletionCredits += levelCreditReward;
inventory.RegularCredits += levelCreditReward;
logger.debug(`levelCreditReward ${levelCreditReward}`);
}
if (node.missionReward) {
missionCompletionCredits += addFixedLevelRewards(node.missionReward, MissionRewards, rewardInfo);
missionCompletionCredits += addFixedLevelRewards(node.missionReward, inventory, MissionRewards, rewardInfo);
}
if (rewardInfo.sortieTag == "Mission1") {
@ -1163,9 +1159,7 @@ export const addMissionRewards = async (
combineInventoryChanges(inventoryChanges, inventoryChange.InventoryChanges);
}
inventory.RegularCredits += missionCompletionCredits;
const credits = await addCredits(account, inventory, {
const credits = addCredits(inventory, {
missionCompletionCredits,
missionDropCredits: creditDrops ?? 0,
rngRewardCredits: inventoryChanges.RegularCredits ?? 0
@ -1388,61 +1382,48 @@ export const addMissionRewards = async (
};
};
export const addCredits = async (
account: TAccountDocument,
//creditBonus is not entirely accurate.
//TODO: consider ActiveBoosters
export const addCredits = (
inventory: TInventoryDatabaseDocument,
{
missionDropCredits,
missionCompletionCredits,
rngRewardCredits
}: { missionDropCredits: number; missionCompletionCredits: number; rngRewardCredits: number }
): Promise<IMissionCredits> => {
): IMissionCredits => {
const hasDailyCreditBonus = true;
const totalCredits = missionDropCredits + missionCompletionCredits + rngRewardCredits;
const finalCredits: IMissionCredits = {
MissionCredits: [missionDropCredits, missionDropCredits],
CreditsBonus: [missionCompletionCredits, missionCompletionCredits],
TotalCredits: [0, 0]
CreditBonus: [missionCompletionCredits, missionCompletionCredits],
TotalCredits: [totalCredits, totalCredits]
};
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;
if (hasDailyCreditBonus) {
inventory.RegularCredits += missionCompletionCredits;
finalCredits.CreditsBonus[1] *= 2;
finalCredits.CreditBonus[1] *= 2;
finalCredits.MissionCredits[1] *= 2;
finalCredits.TotalCredits[1] *= 2;
}
const totalCredits = finalCredits.MissionCredits[1] + finalCredits.CreditsBonus[1] + rngRewardCredits;
finalCredits.TotalCredits = [totalCredits, totalCredits];
if (config.worldState?.creditBoost) {
inventory.RegularCredits += finalCredits.TotalCredits[1];
finalCredits.TotalCredits[1] += finalCredits.TotalCredits[1];
if (!hasDailyCreditBonus) {
return finalCredits;
}
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;
return { ...finalCredits, DailyMissionBonus: true };
};
export const addFixedLevelRewards = (
rewards: IMissionRewardExternal,
inventory: TInventoryDatabaseDocument,
MissionRewards: IMissionReward[],
rewardInfo?: IRewardInfo
): number => {
let missionBonusCredits = 0;
if (rewards.credits) {
missionBonusCredits += rewards.credits;
inventory.RegularCredits += rewards.credits;
}
if (rewards.items) {
for (const item of rewards.items) {
@ -1616,27 +1597,6 @@ function getRandomMissionDrops(
? "/Lotus/Types/Game/MissionDecks/DuviriEncounterRewards/DuviriKullervoSteelPathRNGRewards"
: "/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) {
// Orowyrm chest, gives 10 Pathos Clamps, or 15 on Steel Path.
drops.push({

View File

@ -331,7 +331,7 @@ export const giveKeyChainMissionReward = async (
const fixedLevelRewards = getLevelKeyRewards(missionName);
if (fixedLevelRewards.levelKeyRewards) {
const missionRewards: { StoreItem: string; ItemCount: number }[] = [];
inventory.RegularCredits += addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, missionRewards);
addFixedLevelRewards(fixedLevelRewards.levelKeyRewards, inventory, missionRewards);
for (const reward of missionRewards) {
await addItem(inventory, fromStoreItem(reward.StoreItem), reward.ItemCount);

View File

@ -281,10 +281,6 @@ const generateVendorManifest = (
offersToAdd.push(item);
++offset;
}
if (missingItemsPerBin[item.bin]) {
missingItemsPerBin[item.bin] -= 1;
numOffersThatNeedToMatchABin -= 1;
}
} else {
numCountedOffers += 1 + item.duplicates;
}

View File

@ -59,12 +59,7 @@ export const handleSetShipDecorations = async (
const roomToPlaceIn = rooms.find(room => room.Name === placedDecoration.Room);
if (!roomToPlaceIn) {
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}`);
throw new Error("room not found");
}
if (placedDecoration.MoveId) {
@ -88,7 +83,7 @@ export const handleSetShipDecorations = async (
OldRoom: placedDecoration.OldRoom,
NewRoom: placedDecoration.Room,
IsApartment: placedDecoration.IsApartment,
MaxCapacityIncrease: 0
MaxCapacityIncrease: 0 // TODO: calculate capacity change upon removal
};
}
@ -101,7 +96,6 @@ export const handleSetShipDecorations = async (
}
oldRoom.PlacedDecos.pull({ _id: placedDecoration.MoveId });
oldRoom.MaxCapacity += meta.capacityCost;
const newDecoration = {
Type: placedDecoration.Type,
@ -114,14 +108,12 @@ export const handleSetShipDecorations = async (
//the new room is still roomToPlaceIn
roomToPlaceIn.PlacedDecos.push(newDecoration);
roomToPlaceIn.MaxCapacity -= meta.capacityCost;
await personalRooms.save();
return {
OldRoom: placedDecoration.OldRoom,
NewRoom: placedDecoration.Room,
IsApartment: placedDecoration.IsApartment,
MaxCapacityIncrease: -meta.capacityCost
MaxCapacityIncrease: 0 // TODO: calculate capacity change upon removal
};
}
@ -129,11 +121,11 @@ export const handleSetShipDecorations = async (
const decoIndex = roomToPlaceIn.PlacedDecos.findIndex(x => x._id.equals(placedDecoration.RemoveId));
const deco = roomToPlaceIn.PlacedDecos[decoIndex];
roomToPlaceIn.PlacedDecos.splice(decoIndex, 1);
roomToPlaceIn.MaxCapacity += meta.capacityCost;
await personalRooms.save();
if (!config.unlockAllShipDecorations) {
const inventory = await getInventory(accountId);
const itemType = Object.entries(ExportResources).find(arr => arr[1].deco == deco.Type)![0];
if (deco.Sockets !== undefined) {
addFusionTreasures(inventory, [{ ItemType: itemType, Sockets: deco.Sockets, ItemCount: 1 }]);
} else {
@ -146,20 +138,24 @@ export const handleSetShipDecorations = async (
DecoId: placedDecoration.RemoveId,
Room: placedDecoration.Room,
IsApartment: placedDecoration.IsApartment,
MaxCapacityIncrease: 0 // Client already implies the capacity being refunded.
MaxCapacityIncrease: 0
};
} 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();
}
}
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
//place decoration
const decoId = new Types.ObjectId();
@ -171,16 +167,10 @@ export const handleSetShipDecorations = async (
Sockets: placedDecoration.Sockets,
_id: decoId
});
roomToPlaceIn.MaxCapacity -= meta.capacityCost;
await personalRooms.save();
return {
DecoId: decoId.toString(),
Room: placedDecoration.Room,
IsApartment: placedDecoration.IsApartment,
MaxCapacityIncrease: -meta.capacityCost
};
return { DecoId: decoId.toString(), Room: placedDecoration.Room, IsApartment: placedDecoration.IsApartment };
};
export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlacedDecoInfoRequest): Promise<void> => {

View File

@ -136,10 +136,7 @@ export const stopWebServer = async (): Promise<void> => {
await Promise.all(promises);
};
let lastWsid: number = 0;
interface IWsCustomData extends ws {
id?: number;
accountId?: string;
}
@ -153,7 +150,6 @@ interface IWsMsgFromClient {
}
interface IWsMsgToClient {
//wsid?: number;
reload?: boolean;
ports?: {
http: number | undefined;
@ -178,10 +174,6 @@ const wsOnConnect = (ws: ws, req: http.IncomingMessage): void => {
ws.close();
return;
}
(ws as IWsCustomData).id = ++lastWsid;
ws.send(JSON.stringify({ wsid: lastWsid }));
// eslint-disable-next-line @typescript-eslint/no-misused-promises
ws.on("message", async msg => {
const data = JSON.parse(String(msg)) as IWsMsgFromClient;
@ -276,21 +268,3 @@ 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);
}
}
}
};

View File

@ -372,7 +372,7 @@ const getSeasonChallengePools = (syndicateTag: string): IRotatingSeasonChallenge
hardWeekly: syndicate.weeklyChallenges!.filter(x =>
x.startsWith("/Lotus/Types/Challenges/Seasons/WeeklyHard/")
),
hasWeeklyPermanent: syndicate.weeklyChallenges!.some(x =>
hasWeeklyPermanent: !!syndicate.weeklyChallenges!.find(x =>
x.startsWith("/Lotus/Types/Challenges/Seasons/Weekly/SeasonWeeklyPermanent")
)
};

View File

@ -25,7 +25,6 @@ export interface IDatabaseAccount extends IDatabaseAccountRequiredFields {
LatestEventMessageDate: Date;
LastLoginRewardDate: number;
LoginDays: number;
DailyFirstWinDate: number;
}
// Includes virtual ID

View File

@ -17,9 +17,9 @@ export interface IMissionReward {
}
export interface IMissionCredits {
MissionCredits: [number, number];
CreditsBonus: [number, number]; // "Credit Reward"; `CreditsBonus[1]` is `CreditsBonus[0] * 2` if DailyMissionBonus
TotalCredits: [number, number];
MissionCredits: number[];
CreditBonus: number[];
TotalCredits: number[];
DailyMissionBonus?: boolean;
}

View File

@ -20,10 +20,6 @@
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DojoRemasterTrophyGoldARecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DojoRemasterTrophyPlatinumARecipe",
"/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/EntratiEventBronzeTrophyRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/EntratiEventGoldTrophyRecipe",

View File

@ -98,9 +98,9 @@
<button class="btn btn-primary" type="submit" data-loc="general_addButton"></button>
</form>
</div>
<div class="row g-3 mb-3">
<div class="row g-3">
<div class="col-md-3">
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="currency_RegularCredits"></h5>
<div class="card-body">
<p class="card-text" id="RegularCredits-owned"></p>
@ -112,7 +112,7 @@
</div>
</div>
<div class="col-md-3">
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="currency_PremiumCredits"></h5>
<div class="card-body">
<p class="card-text" id="PremiumCredits-owned"></p>
@ -124,7 +124,7 @@
</div>
</div>
<div class="col-md-3">
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="currency_FusionPoints"></h5>
<div class="card-body">
<p class="card-text" id="FusionPoints-owned"></p>
@ -136,7 +136,7 @@
</div>
</div>
<div class="col-md-3">
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="currency_PrimeTokens"></h5>
<div class="card-body">
<p class="card-text" id="PrimeTokens-owned"></p>
@ -148,9 +148,9 @@
</div>
</div>
</div>
<div class="row g-3 mb-3">
<div class="row g-3">
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_suits"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Suits');return false;">
@ -164,7 +164,7 @@
</div>
</div>
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_longGuns"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="handleModularSelection('LongGuns');return false;">
@ -183,9 +183,9 @@
</div>
</div>
</div>
<div class="row g-3 mb-3">
<div class="row g-3">
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_pistols"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="handleModularSelection('Pistols');return false;">
@ -204,7 +204,7 @@
</div>
</div>
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_melee"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="handleModularSelection('Melee');return false;">
@ -223,9 +223,9 @@
</div>
</div>
</div>
<div class="row g-3 mb-3">
<div class="row g-3">
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_spaceSuits"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceSuits');return false;">
@ -239,7 +239,7 @@
</div>
</div>
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_spaceGuns"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceGuns');return false;">
@ -253,9 +253,9 @@
</div>
</div>
</div>
<div class="row g-3 mb-3">
<div class="row g-3">
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_spaceMelee"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SpaceMelee');return false;">
@ -269,7 +269,7 @@
</div>
</div>
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_mechSuits"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireEquipment('MechSuits');return false;">
@ -283,9 +283,9 @@
</div>
</div>
</div>
<div class="row g-3 mb-3">
<div class="row g-3">
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_sentinels"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireEquipment('Sentinels');return false;">
@ -299,7 +299,7 @@
</div>
</div>
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_moaPets"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="handleModularSelection('MoaPets');return false;">
@ -325,9 +325,9 @@
</div>
</div>
</div>
<div class="row g-3 mb-3">
<div class="row g-3">
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_kubrowPets"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="handleModularSelection('KubrowPets');return false;">
@ -349,7 +349,7 @@
</div>
</div>
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_sentinelWeapons"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireEquipment('SentinelWeapons');return false;">
@ -363,9 +363,9 @@
</div>
</div>
</div>
<div class="row g-3 mb-3">
<div class="row g-3">
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_operatorAmps"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="handleModularSelection('OperatorAmps');return false;">
@ -384,7 +384,7 @@
</div>
</div>
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_hoverboards"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireModularEquipment('HoverBoards');return false;">
@ -401,9 +401,9 @@
</div>
</div>
</div>
<div class="row g-3 mb-3">
<div class="row g-3">
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_evolutionProgress"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireEvolution();return false;">
@ -417,7 +417,7 @@
</div>
</div>
<div class="col-lg-6">
<div class="card" style="height: 400px;">
<div class="card mb-3" style="height: 400px;">
<h5 class="card-header" data-loc="inventory_Boosters"></h5>
<div class="card-body overflow-auto">
<form class="input-group mb-3" onsubmit="doAcquireBoosters();return false;">
@ -431,7 +431,7 @@
</div>
</div>
</div>
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="general_bulkActions"></h5>
<div class="card-body">
<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">
<h3 class="mb-0"></h3>
<p class="text-body-secondary"></p>
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="powersuit_archonShardsLabel"></h5>
<div class="card-body">
<p>
@ -498,7 +498,7 @@
<a href="riven-tool/" target="_blank" data-loc="mods_fingerprintHelp"></a>
</form>
</div>
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="mods_rivens"></h5>
<div class="card-body">
<table class="table table-hover w-100">
@ -521,7 +521,7 @@
</table>
</div>
</div>
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="general_bulkActions"></h5>
<div class="card-body d-flex flex-wrap gap-2">
<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 class="row g-3">
<div class="col-md-6">
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="quests_list"></h5>
<div class="card-body">
<form class="input-group mb-3" onsubmit="doAcquireEquipment('QuestKeys');return false;">
@ -549,7 +549,7 @@
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="general_bulkActions"></h5>
<div class="card-body">
<div class="d-flex flex-wrap gap-2">
@ -565,7 +565,7 @@
<div data-route="/webui/cheats, /webui/settings" data-title="Cheats | OpenWF WebUI">
<div class="row g-3">
<div class="col-md-6">
<div class="card">
<div class="card mb-3">
<h5 class="card-header" data-loc="cheats_server"></h5>
<div class="card-body">
<div class="d-none config-admin-hide">
@ -807,7 +807,7 @@
</form>
</div>
</div>
<div class="card d-none config-admin-show config-form">
<div class="card mb-3 d-none config-admin-show config-form">
<h5 class="card-header" data-loc="worldState"></h5>
<div class="card-body">
<div class="form-check">

View File

@ -10,8 +10,7 @@
let auth_pending = false,
did_initial_auth = false,
ws_is_open = false,
wsid = 0;
ws_is_open = false;
const sendAuth = isRegister => {
if (ws_is_open && localStorage.getItem("email") && localStorage.getItem("password")) {
auth_pending = true;
@ -35,9 +34,6 @@ function openWebSocket() {
};
window.ws.onmessage = e => {
const msg = JSON.parse(e.data);
if ("wsid" in msg) {
wsid = msg.wsid;
}
if ("reload" in msg) {
setTimeout(() => {
getWebSocket().then(() => {
@ -1862,7 +1858,7 @@ for (const id of uiConfigs) {
value = parseInt(value);
}
$.post({
url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
url: "/custom/setConfig?" + window.authz,
contentType: "application/json",
data: JSON.stringify({ [id]: value })
});
@ -1870,7 +1866,7 @@ for (const id of uiConfigs) {
} else if (elm.type == "checkbox") {
elm.onchange = function () {
$.post({
url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
url: "/custom/setConfig?" + window.authz,
contentType: "application/json",
data: JSON.stringify({ [id]: this.checked })
}).then(() => {
@ -1885,7 +1881,7 @@ for (const id of uiConfigs) {
function doSaveConfig(id) {
const elm = document.getElementById(id);
$.post({
url: "/custom/setConfig?" + window.authz + "&wsid=" + wsid,
url: "/custom/setConfig?" + window.authz,
contentType: "application/json",
data: JSON.stringify({ [id]: parseInt(elm.value) })
});
@ -2293,13 +2289,14 @@ function doAcquireBoosters() {
const ExpiryDate = Date.now() / 1000 + 3 * 24 * 60 * 60; // default 3 days
setBooster(uniqueName, ExpiryDate, () => {
$("#acquire-type-Boosters").val("");
updateInventory();
});
}
function doChangeBoosterExpiry(ItemType, ExpiryDateInput) {
console.log("Changing booster expiry for", ItemType, "to", ExpiryDateInput.value);
// cast local datetime string to unix timestamp
const ExpiryDate = Math.trunc(new Date(ExpiryDateInput.value).getTime() / 1000);
const ExpiryDate = new Date(ExpiryDateInput.value).getTime() / 1000;
if (isNaN(ExpiryDate)) {
ExpiryDateInput.addClass("is-invalid").focus();
return false;