Compare commits

..

10 Commits

Author SHA1 Message Date
bac58a56fb use same tagsForOlderGoals for incompatible goals
All checks were successful
Build / build (pull_request) Successful in 1m30s
2025-08-16 19:02:14 +02:00
cfa01b32d8 feat: warframe anniversary goals
Also adds `useAnniversaryTagForOldGoals` to display old Goals in GUI
Re #1103
2025-08-16 19:02:14 +02:00
d0743654dd feat: orphix venom (#2637)
All checks were successful
Build / build (push) Successful in 1m27s
Build Docker image / docker-amd64 (push) Successful in 1m14s
Build Docker image / docker-arm64 (push) Successful in 1m10s
Without rotation on last mission
Re #1103
Thanks to https://wiki.warframe.com/w/World_State/Example

Reviewed-on: #2637
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-16 09:52:58 -07:00
cddd2cdd2b chore: fix inconsistencies with getGuildEventScoreController (#2641)
Some checks failed
Build Docker image / docker-amd64 (push) Waiting to run
Build / build (push) Has been cancelled
Build Docker image / docker-arm64 (push) Has been cancelled
bring it more in line with the rest of the codebase

Reviewed-on: #2641
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-16 09:52:36 -07:00
62a6042c9c fix(webui): save ProgressOverride value (#2638)
All checks were successful
Build / build (push) Successful in 1m39s
Build Docker image / docker-arm64 (push) Successful in 1m22s
Build Docker image / docker-amd64 (push) Successful in 1m23s
Reviewed-on: #2638
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-16 05:42:09 -07:00
e8d4d84d6e chore(webui): update uk (#2639)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker-arm64 (push) Has been cancelled
Build Docker image / docker-amd64 (push) Has been cancelled
Reviewed-on: #2639
Co-authored-by: LoseFace <loseface@noreply.localhost>
Co-committed-by: LoseFace <loseface@noreply.localhost>
2025-08-16 05:41:12 -07:00
62881aaa36 feat: articula customizations (#2636)
Some checks failed
Build / build (push) Has been cancelled
Build Docker image / docker-amd64 (push) Has been cancelled
Build Docker image / docker-arm64 (push) Has been cancelled
Reviewed-on: #2636
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-16 05:40:16 -07:00
df316e3a7a feat: conclave challenges rotation (#2635)
Some checks failed
Build Docker image / docker-amd64 (push) Waiting to run
Build / build (push) Has been cancelled
Build Docker image / docker-arm64 (push) Has been cancelled
Re #1192

Reviewed-on: #2635
Reviewed-by: Sainan <63328889+sainan@users.noreply.github.com>
Co-authored-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
Co-committed-by: AMelonInsideLemon <166175391+AMelonInsideLemon@users.noreply.github.com>
2025-08-16 05:39:23 -07:00
264e9cfc98 fix: use flat rush cost at <50% progress (#2634)
Some checks failed
Build Docker image / docker-arm64 (push) Waiting to run
Build / build (push) Has been cancelled
Build Docker image / docker-amd64 (push) Has been cancelled
otherwise the cost would be increased instead of decreased

Reviewed-on: #2634
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-16 05:39:00 -07:00
5d5554a80e feat: h-09 apex turret sumdali reward (#2633)
Some checks failed
Build Docker image / docker-amd64 (push) Waiting to run
Build / build (push) Has been cancelled
Build Docker image / docker-arm64 (push) Has been cancelled
Closes #2630

Reviewed-on: #2633
Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com>
Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
2025-08-16 05:38:48 -07:00
35 changed files with 848 additions and 198 deletions

View File

@ -68,6 +68,7 @@
"resourceBoost": false,
"tennoLiveRelay": false,
"wolfHunt": false,
"orphixVenom": false,
"longShadow": false,
"hallowedFlame": false,
"anniversary": null,

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.80",
"warframe-public-export-plus": "^0.5.81",
"warframe-riven-info": "^0.1.2",
"winston": "^3.17.0",
"winston-daily-rotate-file": "^5.0.0",
@ -5507,9 +5507,9 @@
}
},
"node_modules/warframe-public-export-plus": {
"version": "0.5.80",
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.80.tgz",
"integrity": "sha512-K5f1Ws3szVdnO0tBcxlNdhXoGHIw09cjHel7spKPGL7aF/vmEkbBGRmYQFvs8n5cGo+v+3qIDMre54Ghb3t0Iw=="
"version": "0.5.81",
"resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.81.tgz",
"integrity": "sha512-kh3e21XThVDSwdC3TJsMsXZnlZ4B/21HdeJkKcjuTygpCd842EPEKS3lRZl3mpXFOmdha744vAW1XEyHfiLofg=="
},
"node_modules/warframe-riven-info": {
"version": "0.1.2",

View File

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

View File

@ -102,7 +102,10 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
const secondsElapsed = Math.trunc(Date.now() / 1000) - start;
const progress = secondsElapsed / recipe.buildTime;
logger.debug(`rushing recipe at ${Math.trunc(progress * 100)}% completion`);
const cost = Math.round(recipe.skipBuildTimePrice * (1 - (progress - 0.5)));
const cost =
progress > 0.5
? Math.round(recipe.skipBuildTimePrice * (1 - (progress - 0.5)))
: recipe.skipBuildTimePrice;
InventoryChanges = {
...InventoryChanges,
...updateCurrency(inventory, cost, true)

View File

@ -11,7 +11,7 @@ export const getGuildEventScoreController: RequestHandler = async (req, res) =>
if (guild && guild.GoalProgress && goalId) {
const goal = guild.GoalProgress.find(x => x.goalId.toString() == goalId);
if (goal) {
return res.json({
res.json({
Tier: guild.Tier,
GoalProgress: {
Count: goal.Count,
@ -19,7 +19,8 @@ export const getGuildEventScoreController: RequestHandler = async (req, res) =>
_id: { $oid: goal.goalId }
}
});
return;
}
}
return res.json({});
res.json({});
};

View File

@ -1,23 +1,19 @@
import { getAccountIdForRequest } from "@/src/services/loginService";
import { IPictureFrameInfo, ISetPlacedDecoInfoRequest } from "@/src/types/personalRoomsTypes";
import { ISetPlacedDecoInfoRequest } from "@/src/types/personalRoomsTypes";
import { RequestHandler } from "express";
import { handleSetPlacedDecoInfo } from "@/src/services/shipCustomizationsService";
export const setPlacedDecoInfoController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const payload = JSON.parse(req.body as string) as ISetPlacedDecoInfoRequest;
//console.log(JSON.stringify(payload, null, 2));
await handleSetPlacedDecoInfo(accountId, payload);
res.json({
DecoId: payload.DecoId,
IsPicture: true,
PictureFrameInfo: payload.PictureFrameInfo,
BootLocation: payload.BootLocation
...payload,
IsPicture: !!payload.PictureFrameInfo
} satisfies ISetPlacedDecoInfoResponse);
};
interface ISetPlacedDecoInfoResponse {
DecoId: string;
interface ISetPlacedDecoInfoResponse extends ISetPlacedDecoInfoRequest {
IsPicture: boolean;
PictureFrameInfo?: IPictureFrameInfo;
BootLocation?: string;
}

View File

@ -25,7 +25,7 @@ export const EquipmentSelectionSchema = new Schema<IEquipmentSelection>(
}
);
const loadoutConfigSchema = new Schema<ILoadoutConfigDatabase>(
export const loadoutConfigSchema = new Schema<ILoadoutConfigDatabase>(
{
FocusSchool: String,
PresetIcon: String,

View File

@ -8,7 +8,7 @@ const leaderboardEntrySchema = new Schema<ILeaderboardEntryDatabase>(
displayName: { type: String, required: true },
score: { type: Number, required: true },
guildId: Schema.Types.ObjectId,
expiry: { type: Date, required: true },
expiry: Date,
guildTier: Number
},
{ id: false }

View File

@ -1,6 +1,7 @@
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
import {
IApartmentDatabase,
ICustomizationInfoDatabase,
IFavouriteLoadoutDatabase,
IGardeningDatabase,
IOrbiterClient,
@ -11,12 +12,13 @@ import {
IPlantClient,
IPlantDatabase,
IPlanterDatabase,
IRoom,
IRoomDatabase,
ITailorShopDatabase,
PersonalRoomsModelType
} from "@/src/types/personalRoomsTypes";
import { Schema, Types, model } from "mongoose";
import { colorSchema, shipCustomizationSchema } from "@/src/models/commonModel";
import { loadoutConfigSchema } from "@/src/models/inventoryModels/loadoutModel";
export const pictureFrameInfoSchema = new Schema<IPictureFrameInfo>(
{
@ -34,7 +36,20 @@ export const pictureFrameInfoSchema = new Schema<IPictureFrameInfo>(
TextColorB: Number,
TextOrientation: Number
},
{ id: false, _id: false }
{ _id: false }
);
export const customizationInfoSchema = new Schema<ICustomizationInfoDatabase>(
{
Anim: String,
AnimPose: Number,
LoadOutPreset: loadoutConfigSchema,
VehiclePreset: loadoutConfigSchema,
EquippedWeapon: String,
AvatarType: String,
LoadOutType: String
},
{ _id: false }
);
const placedDecosSchema = new Schema<IPlacedDecosDatabase>(
@ -44,7 +59,9 @@ const placedDecosSchema = new Schema<IPlacedDecosDatabase>(
Rot: [Number],
Scale: Number,
Sockets: Number,
PictureFrameInfo: { type: pictureFrameInfoSchema, default: undefined }
PictureFrameInfo: { type: pictureFrameInfoSchema, default: undefined },
CustomizationInfo: { type: customizationInfoSchema, default: undefined },
AnimPoseItem: String
},
{ id: false }
);
@ -60,7 +77,7 @@ placedDecosSchema.set("toJSON", {
}
});
const roomSchema = new Schema<IRoom>(
const roomSchema = new Schema<IRoomDatabase>(
{
Name: String,
MaxCapacity: Number,

View File

@ -97,7 +97,19 @@ const statsSchema = new Schema<IStatsDatabase>({
SentinelGameScore: Number,
CaliberChicksScore: Number,
OlliesCrashCourseScore: Number,
DojoObstacleScore: Number
DojoObstacleScore: Number,
Halloween16: Number,
AmalgamEventScoreMax: Number,
Halloween19ScoreMax: Number,
FlotillaEventScore: Number,
FlotillaSpaceBadgesTier1: Number,
FlotillaSpaceBadgesTier2: Number,
FlotillaSpaceBadgesTier3: Number,
FlotillaGroundBadgesTier1: Number,
FlotillaGroundBadgesTier2: Number,
FlotillaGroundBadgesTier3: Number,
MechSurvivalScoreMax: Number
});
statsSchema.set("toJSON", {

View File

@ -62,7 +62,7 @@ import { getFriendsController } from "@/src/controllers/api/getFriendsController
import { getGuildContributionsController } from "@/src/controllers/api/getGuildContributionsController";
import { getGuildController } from "@/src/controllers/api/getGuildController";
import { getGuildDojoController } from "@/src/controllers/api/getGuildDojoController";
import { getGuildEventScoreController } from "@/src/controllers/api/getGuildEventScore";
import { getGuildEventScoreController } from "@/src/controllers/api/getGuildEventScoreController";
import { getGuildLogController } from "@/src/controllers/api/getGuildLogController";
import { getIgnoredUsersController } from "@/src/controllers/api/getIgnoredUsersController";
import { getNewRewardSeedController } from "@/src/controllers/api/getNewRewardSeedController";

View File

@ -8,5 +8,6 @@ const statsRouter = express.Router();
statsRouter.get("/view.php", viewController);
statsRouter.post("/upload.php", uploadController);
statsRouter.post("/leaderboardWeekly.php", leaderboardController);
statsRouter.post("/leaderboardArchived.php", leaderboardController);
export { statsRouter };

View File

@ -80,6 +80,7 @@ export interface IConfig {
tennoLiveRelay?: boolean;
baroTennoConRelay?: boolean;
wolfHunt?: boolean;
orphixVenom?: boolean;
longShadow?: boolean;
hallowedFlame?: boolean;
anniversary?: number;

View File

@ -896,5 +896,20 @@ export const goalGuildRewardByTag: Record<string, { guildGoals: number[][]; rewa
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DuviriMurmurEventSilverTrophyRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/DuviriMurmurEventGoldTrophyRecipe"
]
},
MechSurvival: {
guildGoals: [
[1390, 5860, 13920, 18850],
[3510, 22275, 69120, 137250],
[11700, 75250, 230400, 457500],
[35100, 222750, 691200, 1372500],
[117000, 742500, 2304000, 4575000]
],
rewards: [
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/MechEventTrophyTerracottaRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/MechEventTrophyBronzeRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/MechEventTrophySilverRecipe",
"/Lotus/Levels/ClanDojo/ComponentPropRecipes/MechEventTrophyGoldRecipe"
]
}
};

View File

@ -47,16 +47,22 @@ import {
import {
IApartmentClient,
IApartmentDatabase,
ICustomizationInfoClient,
ICustomizationInfoDatabase,
IFavouriteLoadout,
IFavouriteLoadoutDatabase,
IGetShipResponse,
IOrbiterClient,
IOrbiterDatabase,
IPersonalRoomsDatabase,
IPlacedDecosClient,
IPlacedDecosDatabase,
IPlantClient,
IPlantDatabase,
IPlanterClient,
IPlanterDatabase,
IRoomClient,
IRoomDatabase,
ITailorShop,
ITailorShopDatabase
} from "@/src/types/personalRoomsTypes";
@ -446,6 +452,30 @@ export const importLoadOutPresets = (db: ILoadoutDatabase, client: ILoadOutPrese
db.DRIFTER = client.DRIFTER.map(convertLoadOutConfig);
};
export const convertCustomizationInfo = (client: ICustomizationInfoClient): ICustomizationInfoDatabase => {
return {
...client,
LoadOutPreset: client.LoadOutPreset ? convertLoadOutConfig(client.LoadOutPreset) : undefined,
VehiclePreset: client.VehiclePreset ? convertLoadOutConfig(client.VehiclePreset) : undefined
};
};
const convertDeco = (client: IPlacedDecosClient): IPlacedDecosDatabase => {
const { id, ...rest } = client;
return {
...rest,
CustomizationInfo: client.CustomizationInfo ? convertCustomizationInfo(client.CustomizationInfo) : undefined,
_id: new Types.ObjectId(id.$oid)
};
};
const convertRoom = (client: IRoomClient): IRoomDatabase => {
return {
...client,
PlacedDecos: client.PlacedDecos ? client.PlacedDecos.map(convertDeco) : []
};
};
const convertShip = (client: IOrbiterClient): IOrbiterDatabase => {
return {
...client,
@ -453,6 +483,7 @@ const convertShip = (client: IOrbiterClient): IOrbiterDatabase => {
...client.ShipInterior,
Colors: Array.isArray(client.ShipInterior.Colors) ? {} : client.ShipInterior.Colors
},
Rooms: client.Rooms.map(convertRoom),
FavouriteLoadoutId: client.FavouriteLoadoutId ? new Types.ObjectId(client.FavouriteLoadoutId.$oid) : undefined
};
};
@ -481,6 +512,7 @@ const convertFavouriteLoadout = (client: IFavouriteLoadout): IFavouriteLoadoutDa
const convertApartment = (client: IApartmentClient): IApartmentDatabase => {
return {
...client,
Rooms: client.Rooms.map(convertRoom),
Gardening: { Planters: client.Gardening.Planters.map(convertPlanter) },
FavouriteLoadouts: client.FavouriteLoadouts ? client.FavouriteLoadouts.map(convertFavouriteLoadout) : []
};
@ -489,6 +521,7 @@ const convertApartment = (client: IApartmentClient): IApartmentDatabase => {
const convertTailorShop = (client: ITailorShop): ITailorShopDatabase => {
return {
...client,
Rooms: client.Rooms.map(convertRoom),
Colors: Array.isArray(client.Colors) ? {} : client.Colors,
FavouriteLoadouts: client.FavouriteLoadouts ? client.FavouriteLoadouts.map(convertFavouriteLoadout) : []
};

View File

@ -1,38 +1,66 @@
import { Guild } from "@/src/models/guildModel";
import { Leaderboard, TLeaderboardEntryDocument } from "@/src/models/leaderboardModel";
import { ILeaderboardEntryClient } from "@/src/types/leaderboardTypes";
import { handleGuildGoalProgress } from "@/src/services/guildService";
import { getWorldState } from "@/src/services/worldStateService";
import { Types } from "mongoose";
export const submitLeaderboardScore = async (
schedule: "weekly" | "daily",
schedule: "weekly" | "daily" | "events",
leaderboard: string,
ownerId: string,
displayName: string,
score: number,
guildId: string | undefined
): Promise<void> => {
let expiry: Date;
let expiry: Date | undefined;
if (schedule == "daily") {
expiry = new Date(Math.trunc(Date.now() / 86400000) * 86400000 + 86400000);
} else {
} else if (schedule == "weekly") {
const EPOCH = 1734307200 * 1000; // Monday
const week = Math.trunc((Date.now() - EPOCH) / 604800000);
const weekStart = EPOCH + week * 604800000;
const weekEnd = weekStart + 604800000;
expiry = new Date(weekEnd);
}
if (guildId) {
const guild = (await Guild.findById(guildId, "Name Tier GoalProgress VaultDecoRecipes"))!;
if (schedule == "events") {
const prevAccount = await Leaderboard.findOne(
{ leaderboard: `${schedule}.accounts.${leaderboard}`, ownerId },
"score"
);
const delta = score - (prevAccount?.score ?? 0);
if (delta > 0) {
await Leaderboard.findOneAndUpdate(
{ leaderboard: `${schedule}.guilds.${leaderboard}`, ownerId: guildId },
{ $inc: { score: delta }, $set: { displayName: guild.Name, guildTier: guild.Tier } },
{ upsert: true }
);
const goal = getWorldState().Goals.find(x => x.ScoreMaxTag == leaderboard);
if (goal) {
await handleGuildGoalProgress(guild, {
Count: delta,
Tag: goal.Tag,
goalId: new Types.ObjectId(goal._id.$oid)
});
}
}
} else {
await Leaderboard.findOneAndUpdate(
{ leaderboard: `${schedule}.guilds.${leaderboard}`, ownerId: guildId },
{ $max: { score }, $set: { displayName: guild.Name, guildTier: guild.Tier, expiry } },
{ upsert: true, new: true }
);
}
}
await Leaderboard.findOneAndUpdate(
{ leaderboard: `${schedule}.accounts.${leaderboard}`, ownerId },
{ $max: { score }, $set: { displayName, guildId, expiry } },
{ upsert: true }
);
if (guildId) {
const guild = (await Guild.findById(guildId, "Name Tier"))!;
await Leaderboard.findOneAndUpdate(
{ leaderboard: `${schedule}.guilds.${leaderboard}`, ownerId: guildId },
{ $max: { score }, $set: { displayName: guild.Name, guildTier: guild.Tier, expiry } },
{ upsert: true }
);
}
};
export const getLeaderboard = async (
@ -43,6 +71,7 @@ export const getLeaderboard = async (
guildId: string | undefined,
guildTier: number | undefined
): Promise<ILeaderboardEntryClient[]> => {
leaderboard = leaderboard.replace("archived", guildTier || guildId ? "events.guilds" : "events.accounts");
const filter: { leaderboard: string; guildId?: string; guildTier?: number } = { leaderboard };
if (guildId) {
filter.guildId = guildId;

View File

@ -652,7 +652,12 @@ export const addMissionInventoryUpdates = async (
}
}
if (currentMissionKey && currentMissionKey in goalMessagesByKey) {
const totalCount = (goalProgress?.Count ?? 0) + uploadProgress.Count;
let countBeforeUpload = goalProgress?.Count ?? 0;
let totalCount = countBeforeUpload + uploadProgress.Count;
if (goal.Best) {
countBeforeUpload = goalProgress?.Best ?? 0;
totalCount = uploadProgress.Best;
}
let reward;
if (goal.InterimGoals && goal.InterimRewards) {
@ -660,7 +665,7 @@ export const addMissionInventoryUpdates = async (
if (
goal.InterimGoals[i] &&
goal.InterimGoals[i] <= totalCount &&
(!goalProgress || goalProgress.Count < goal.InterimGoals[i]) &&
(!goalProgress || countBeforeUpload < goal.InterimGoals[i]) &&
goal.InterimRewards[i]
) {
reward = goal.InterimRewards[i];
@ -672,7 +677,7 @@ export const addMissionInventoryUpdates = async (
!reward &&
goal.Goal &&
goal.Goal <= totalCount &&
(!goalProgress || goalProgress.Count < goal.Goal) &&
(!goalProgress || countBeforeUpload < goal.Goal) &&
goal.Reward
) {
reward = goal.Reward;
@ -681,7 +686,7 @@ export const addMissionInventoryUpdates = async (
!reward &&
goal.BonusGoal &&
goal.BonusGoal <= totalCount &&
(!goalProgress || goalProgress.Count < goal.BonusGoal) &&
(!goalProgress || countBeforeUpload < goal.BonusGoal) &&
goal.BonusReward
) {
reward = goal.BonusReward;
@ -1105,6 +1110,12 @@ export const addMissionRewards = async (
}
}
}
if (rewardInfo.GoalProgressAmount && goal.Tag.startsWith("MechSurvival")) {
MissionRewards.push({
StoreItem: "/Lotus/StoreItems/Types/Items/MiscItems/MechSurvivalEventCreds",
ItemCount: Math.trunc(rewardInfo.GoalProgressAmount / 10)
});
}
}
}
@ -1323,6 +1334,27 @@ export const addMissionRewards = async (
logger.error(`unknown droptable ${si.DropTable} for DROP_BLUEPRINT`);
}
}
// e.g. H-09 Apex Turret Sumdali
if (si.DROP_MISC_ITEM) {
const resourceDroptable = droptables.find(x => x.type == "resource");
if (resourceDroptable) {
for (let i = 0; i != si.DROP_MISC_ITEM.length; ++i) {
const reward = getRandomReward(resourceDroptable.items)!;
logger.debug(`stripped droptable (resources pool) rolled`, reward);
if (Object.keys(await addItem(inventory, reward.type)).length == 0) {
logger.debug(`item already owned, skipping`);
} else {
MissionRewards.push({
StoreItem: toStoreItem(reward.type),
ItemCount: 1,
FromEnemyCache: true // to show "identified"
});
}
}
} else {
logger.error(`unknown droptable ${si.DropTable} for DROP_BLUEPRINT`);
}
}
}
}
@ -2414,6 +2446,36 @@ const goalMessagesByKey: Record<string, { sndr: string; msg: string; sub: string
sub: "/Lotus/Language/G1Quests/ProjectNightwatchTacAlertMissionFourTitle",
icon: "/Lotus/Interface/Icons/Npcs/Lotus_d.png"
},
"/Lotus/Types/Keys/MechSurvivalCorpusShip": {
sndr: "/Lotus/Language/Bosses/DeimosFather",
msg: "/Lotus/Language/Inbox/MechEvent2020Tier1CompleteDesc",
sub: "/Lotus/Language/Inbox/MechEvent2020Tier1CompleteTitle",
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
},
"/Lotus/Types/Keys/MechSurvivalGrineerGalleon": {
sndr: "/Lotus/Language/Bosses/DeimosFather",
msg: "/Lotus/Language/Inbox/MechEvent2020Tier2CompleteDesc",
sub: "/Lotus/Language/Inbox/MechEvent2020Tier2CompleteTitle",
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
},
"/Lotus/Types/Keys/MechSurvivalGasCity": {
sndr: "/Lotus/Language/Bosses/DeimosFather",
msg: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteDesc",
sub: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteTitle",
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
},
"/Lotus/Types/Keys/MechSurvivalCorpusShipEndurance": {
sndr: "/Lotus/Language/Bosses/DeimosFather",
msg: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteDesc",
sub: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteTitle",
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
},
"/Lotus/Types/Keys/MechSurvivalGrineerGalleonEndurance": {
sndr: "/Lotus/Language/Bosses/DeimosFather",
msg: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteDesc",
sub: "/Lotus/Language/Inbox/MechEvent2020Tier3CompleteTitle",
icon: "/Lotus/Interface/Icons/Npcs/Entrati/Father.png"
},
"/Lotus/Types/Keys/TacAlertKeyAnniversary2019E": {
sndr: "/Lotus/Language/Bosses/Lotus",
msg: "/Lotus/Language/Messages/Anniversary2024RewardMsgB",

View File

@ -19,6 +19,7 @@ import { Guild } from "@/src/models/guildModel";
import { hasGuildPermission } from "@/src/services/guildService";
import { GuildPermission } from "@/src/types/guildTypes";
import { ExportResources } from "warframe-public-export-plus";
import { convertCustomizationInfo } from "@/src/services/importService";
export const setShipCustomizations = async (
accountId: string,
@ -269,6 +270,8 @@ export const handleSetPlacedDecoInfo = async (accountId: string, req: ISetPlaced
}
placedDeco.PictureFrameInfo = req.PictureFrameInfo;
placedDeco.CustomizationInfo = req.CustomizationInfo ? convertCustomizationInfo(req.CustomizationInfo) : undefined;
placedDeco.AnimPoseItem = req.AnimPoseItem;
await personalRooms.save();
};

View File

@ -382,6 +382,29 @@ export const updateStats = async (accountOwnerId: string, payload: IStatsUpdate)
);
break;
case "Halloween16":
case "AmalgamEventScoreMax":
case "Halloween19ScoreMax":
case "FlotillaEventScore":
case "FlotillaSpaceBadgesTier1":
case "FlotillaSpaceBadgesTier2":
case "FlotillaSpaceBadgesTier3":
case "FlotillaGroundBadgesTier1":
case "FlotillaGroundBadgesTier2":
case "FlotillaGroundBadgesTier3":
case "MechSurvivalScoreMax":
playerStats[category] ??= 0;
if (data > playerStats[category]) playerStats[category] = data as number;
await submitLeaderboardScore(
"events",
category,
accountOwnerId,
payload.displayName,
data as number,
payload.guildId
);
break;
default:
if (!ignoredCategories.includes(category)) {
unknownCategories[action] ??= [];

View File

@ -8,6 +8,7 @@ import syndicateMissions from "@/static/fixed_responses/worldState/syndicateMiss
import darvoDeals from "@/static/fixed_responses/worldState/darvoDeals.json";
import invasionNodes from "@/static/fixed_responses/worldState/invasionNodes.json";
import invasionRewards from "@/static/fixed_responses/worldState/invasionRewards.json";
import pvpChallenges from "@/static/fixed_responses/worldState/pvpChallenges.json";
import { buildConfig } from "@/src/services/buildConfigService";
import { unixTimesInMs } from "@/src/constants/timeConstants";
import { config } from "@/src/services/configService";
@ -22,6 +23,7 @@ import {
ILiteSortie,
IPrimeVaultTrader,
IPrimeVaultTraderOffer,
IPVPChallengeInstance,
ISeasonChallenge,
ISortie,
ISortieMission,
@ -1402,6 +1404,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
DailyDeals: [],
EndlessXpChoices: [],
KnownCalendarSeasons: [],
PVPChallengeInstances: [],
...staticWorldState,
SyndicateMissions: [...staticWorldState.SyndicateMissions],
InGameMarket: {
@ -1536,7 +1539,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
Personal: true,
Bounty: true,
ClampNodeScores: true,
Node: "EventNode28", // Incompatible with Wolf Hunt (2025), Warframe Anniversary
Node: "EventNode28", // Incompatible with Wolf Hunt (2025), Orphix Venom, Warframe Anniversary
MissionKeyName: "/Lotus/Types/Keys/GalleonRobberyAlertB",
Desc: "/Lotus/Language/Events/GalleonRobberyEventMissionTitle",
Icon: "/Lotus/Interface/Icons/Player/GalleonRobberiesEvent.png",
@ -2182,7 +2185,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
"/Lotus/Types/Keys/WolfTacAlertReduxD"
],
ConcurrentNodeReqs: [1, 2, 3],
ConcurrentNodes: ["EventNode28", "EventNode39", "EventNode40"], // Incompatible with Galleon Of Ghouls, Warframe Anniversary
ConcurrentNodes: ["EventNode28", "EventNode39", "EventNode40"], // Incompatible with Galleon Of Ghouls, Orphix Venom, Warframe Anniversary
MissionKeyName: "/Lotus/Types/Keys/WolfTacAlertReduxA",
Faction: "FC_GRINEER",
Desc: "/Lotus/Language/Alerts/WolfAlert",
@ -2450,7 +2453,7 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
"/Lotus/Types/Keys/TacAlertKeyProxyRebellionFour"
],
ConcurrentNodeReqs: [1, 2, 3],
ConcurrentNodes: ["EventNode7", "EventNode4", "EventNode17"], // Incompatible with Warframe Anniversary
ConcurrentNodes: ["EventNode7", "EventNode4", "EventNode17"], // Incompatible with Orphix venom, Warframe Anniversary
MissionKeyName: "/Lotus/Types/Keys/TacAlertKeyProxyRebellionOne",
Faction: "FC_CORPUS",
Desc: "/Lotus/Language/Alerts/TacAlertProxyRebellion",
@ -2549,6 +2552,83 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
});
}
if (config.worldState?.orphixVenom) {
worldState.Goals.push(
{
_id: { $oid: "5fdcccb875d5ad500dc477d0" },
Activation: { $date: { $numberLong: "1608320400000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: 0,
Goal: 500,
Success: 0,
Personal: true,
Best: true,
Node: "EventNode17", // Incompatible with Proxy Rebellion
MissionKeyName: "/Lotus/Types/Keys/MechSurvivalCorpusShip",
Faction: "FC_SENTIENT",
Desc: "/Lotus/Language/Events/MechEventMissionTier1",
Icon: "/Lotus/Interface/Icons/Categories/IconMech256.png",
Tag: "MechSurvivalA",
ScoreVar: "MechSurvivalScore",
Reward: {
items: ["/Lotus/StoreItems/Upgrades/Skins/Clan/MechEventEmblemItem"]
}
},
{
_id: { $oid: "5fdcccb875d5ad500dc477d1" },
Activation: { $date: { $numberLong: "1608320400000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: 0,
Goal: 1000,
Success: 0,
Personal: true,
Best: true,
Node: "EventNode28", // Incompatible with Galleon Of Ghouls, Wolf Hunt (2025)
MissionKeyName: "/Lotus/Types/Keys/MechSurvivalGrineerGalleon",
Faction: "FC_SENTIENT",
Desc: "/Lotus/Language/Events/MechEventMissionTier2",
Icon: "/Lotus/Interface/Icons/Categories/IconMech256.png",
Tag: "MechSurvivalB",
PrereqGoalTags: ["MechSurvivalA"],
ScoreVar: "MechSurvivalScore",
Reward: {
items: ["/Lotus/StoreItems/Types/Items/FusionTreasures/OroFusexJ"]
}
},
{
_id: { $oid: "5fdcccb875d5ad500dc477d2" },
Activation: { $date: { $numberLong: "1608320400000" } },
Expiry: { $date: { $numberLong: "2000000000000" } },
Count: 0,
Goal: 2000,
Success: 0,
Personal: true,
Best: true,
Node: "EventNode32",
MissionKeyName: "/Lotus/Types/Keys/MechSurvivalGasCity",
MissionKeyRotation: [
"/Lotus/Types/Keys/MechSurvivalGasCity",
"/Lotus/Types/Keys/MechSurvivalCorpusShipEndurance",
"/Lotus/Types/Keys/MechSurvivalGrineerGalleonEndurance"
],
MissionKeyRotationInterval: 3600, // 1 hour
Faction: "FC_SENTIENT",
Desc: "/Lotus/Language/Events/MechEventMissionTier3",
Icon: "/Lotus/Interface/Icons/Categories/IconMech256.png",
Tag: "MechSurvival",
PrereqGoalTags: ["MechSurvivalA", "MechSurvivalB"],
ScoreVar: "MechSurvivalScore",
ScoreMaxTag: "MechSurvivalScoreMax",
Reward: {
items: [
"/Lotus/StoreItems/Types/Items/MiscItems/FormaAura",
"/Lotus/StoreItems/Upgrades/Skins/Necramech/MechWeapon/MechEventMausolonSkin"
]
}
}
);
}
// Nightwave Challenges
const nightwaveSyndicateTag = getNightwaveSyndicateTag(buildLabel);
if (nightwaveSyndicateTag) {
@ -2869,6 +2949,23 @@ export const getWorldState = (buildLabel?: string): IWorldState => {
pushSyndicateMissions(worldState, sdy, rng.randomInt(0, 100_000), "ba6f84724fa48061", "SteelMeridianSyndicate");
}
{
const conclaveDayStart = EPOCH + day * unixTimesInMs.day + 5 * unixTimesInMs.hour + 30 * unixTimesInMs.minute;
const conclaveDayEnd = conclaveDayStart + unixTimesInMs.day;
const conclaveWeekStart = weekStart + 40 * unixTimesInMs.minute - 2 * unixTimesInMs.day;
const conclaveWeekEnd = conclaveWeekStart + unixTimesInMs.week;
pushConclaveWeakly(worldState.PVPChallengeInstances, week);
pushConclaveDailys(worldState.PVPChallengeInstances, day);
if (isBeforeNextExpectedWorldStateRefresh(timeMs, conclaveDayEnd)) {
pushConclaveDailys(worldState.PVPChallengeInstances, day + 1);
}
if (isBeforeNextExpectedWorldStateRefresh(timeMs, conclaveWeekEnd)) {
pushConclaveWeakly(worldState.PVPChallengeInstances, week + 1);
}
}
// Archon Hunt cycling every week
worldState.LiteSorties.push(getLiteSortie(week));
if (isBeforeNextExpectedWorldStateRefresh(timeMs, weekEnd)) {
@ -3254,3 +3351,136 @@ const updateDailyDeal = async (): Promise<void> => {
export const updateWorldStateCollections = async (): Promise<void> => {
await Promise.all([updateFissures(), updateDailyDeal()]);
};
const pushConclaveDaily = (
activeChallenges: IPVPChallengeInstance[],
PVPMode: string,
pool: {
key: string;
ScriptParamValue: number;
PVPModeAllowed: string[];
SyndicateXP: number;
DuringSingleMatch?: boolean;
}[],
day: number,
id: number
): void => {
const conclaveDayStart = EPOCH + day * unixTimesInMs.day + 5 * unixTimesInMs.hour + 30 * unixTimesInMs.minute;
const conclaveDayEnd = conclaveDayStart + unixTimesInMs.day;
const challengeId = day * 8 + id;
const rng = new SRng(new SRng(challengeId).randomInt(0, 100_000));
let challenge: {
key: string;
ScriptParamValue: number;
PVPModeAllowed?: string[];
SyndicateXP?: number;
DuringSingleMatch?: boolean;
};
do {
challenge = rng.randomElement(pool)!;
} while (
activeChallenges.some(x => x.challengeTypeRefID == challenge.key) &&
activeChallenges.some(x => x.PVPMode == PVPMode)
);
activeChallenges.push({
_id: {
$oid: "689ec5d985b55902" + challengeId.toString().padStart(8, "0")
},
challengeTypeRefID: challenge.key,
startDate: { $date: { $numberLong: conclaveDayStart.toString() } },
endDate: { $date: { $numberLong: conclaveDayEnd.toString() } },
params: [{ n: "ScriptParamValue", v: challenge.ScriptParamValue }],
isGenerated: true,
PVPMode,
subChallenges: [],
Category: "PVPChallengeTypeCategory_DAILY"
});
};
const pushConclaveDailys = (activeChallenges: IPVPChallengeInstance[], day: number): void => {
const modes = [
"PVPMODE_SPEEDBALL",
"PVPMODE_CAPTURETHEFLAG",
"PVPMODE_DEATHMATCH",
"PVPMODE_TEAMDEATHMATCH"
] as const;
const challengesMap: Record<
string,
{
key: string;
ScriptParamValue: number;
PVPModeAllowed: string[];
SyndicateXP: number;
DuringSingleMatch?: boolean;
}[]
> = {};
for (const mode of modes) {
challengesMap[mode] = Object.entries(pvpChallenges)
.filter(([_, challenge]) => challenge.PVPModeAllowed.includes(mode))
.map(([key, challenge]) => ({ key, ...challenge }));
}
modes.forEach((mode, index) => {
pushConclaveDaily(activeChallenges, mode, challengesMap[mode], day, index * 2);
pushConclaveDaily(activeChallenges, mode, challengesMap[mode], day, index * 2 + 1);
});
};
const pushConclaveWeakly = (activeChallenges: IPVPChallengeInstance[], week: number): void => {
const weekStart = EPOCH + week * unixTimesInMs.week;
const conclaveWeekStart = weekStart + 40 * unixTimesInMs.minute - 2 * unixTimesInMs.day;
const conclaveWeekEnd = conclaveWeekStart + unixTimesInMs.week;
const conclaveIdStart = ((conclaveWeekStart / 1000) & 0xffffffff).toString(16).padStart(8, "0").padEnd(23, "0");
activeChallenges.push(
{
_id: { $oid: conclaveIdStart + "1" },
challengeTypeRefID: "/Lotus/PVPChallengeTypes/PVPTimedChallengeGameModeWins",
startDate: { $date: { $numberLong: conclaveWeekStart.toString() } },
endDate: { $date: { $numberLong: conclaveWeekEnd.toString() } },
params: [{ n: "ScriptParamValue", v: 6 }],
isGenerated: true,
PVPMode: "PVPMODE_ALL",
subChallenges: [],
Category: "PVPChallengeTypeCategory_WEEKLY"
},
{
_id: { $oid: conclaveIdStart + "2" },
challengeTypeRefID: "/Lotus/PVPChallengeTypes/PVPTimedChallengeGameModeComplete",
startDate: { $date: { $numberLong: conclaveWeekStart.toString() } },
endDate: { $date: { $numberLong: conclaveWeekEnd.toString() } },
params: [{ n: "ScriptParamValue", v: 20 }],
isGenerated: true,
PVPMode: "PVPMODE_ALL",
subChallenges: [],
Category: "PVPChallengeTypeCategory_WEEKLY"
},
{
_id: { $oid: conclaveIdStart + "3" },
challengeTypeRefID: "/Lotus/PVPChallengeTypes/PVPTimedChallengeOtherChallengeCompleteANY",
startDate: { $date: { $numberLong: conclaveWeekStart.toString() } },
endDate: { $date: { $numberLong: conclaveWeekEnd.toString() } },
params: [{ n: "ScriptParamValue", v: 10 }],
isGenerated: true,
PVPMode: "PVPMODE_ALL",
subChallenges: [],
Category: "PVPChallengeTypeCategory_WEEKLY"
},
{
_id: { $oid: conclaveIdStart + "4" },
challengeTypeRefID: "/Lotus/PVPChallengeTypes/PVPTimedChallengeWeeklyStandardSet",
startDate: { $date: { $numberLong: conclaveWeekStart.toString() } },
endDate: { $date: { $numberLong: conclaveWeekEnd.toString() } },
params: [{ n: "ScriptParamValue", v: 0 }],
isGenerated: true,
PVPMode: "PVPMODE_NONE",
subChallenges: [
{ $oid: conclaveIdStart + "1" },
{ $oid: conclaveIdStart + "2" },
{ $oid: conclaveIdStart + "3" }
],
Category: "PVPChallengeTypeCategory_WEEKLY_ROOT"
}
);
};

View File

@ -6,7 +6,7 @@ export interface ILeaderboardEntryDatabase {
displayName: string;
score: number;
guildId?: Types.ObjectId;
expiry: Date;
expiry?: Date;
guildTier?: number;
}

View File

@ -1,6 +1,6 @@
import { IColor, IShipAttachments, IShipCustomization } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { Document, Model, Types } from "mongoose";
import { ILoadoutClient } from "@/src/types/saveLoadoutTypes";
import { ILoadoutClient, ILoadoutConfigClient, ILoadoutConfigDatabase } from "@/src/types/saveLoadoutTypes";
import { IMongoDate, IOid } from "@/src/types/commonTypes";
export interface IGetShipResponse {
@ -17,7 +17,7 @@ export interface IOrbiterClient {
Features: string[];
ShipId: IOid;
ShipInterior: IShipCustomization;
Rooms: IRoom[];
Rooms: IRoomClient[];
VignetteFish?: string[];
FavouriteLoadoutId?: IOid;
Wallpaper?: string;
@ -28,7 +28,7 @@ export interface IOrbiterClient {
export interface IOrbiterDatabase {
Features: string[];
Rooms: IRoom[];
Rooms: IRoomDatabase[];
ShipInterior?: IShipCustomization;
VignetteFish?: string[];
FavouriteLoadoutId?: Types.ObjectId;
@ -53,12 +53,18 @@ export interface IPersonalRoomsDatabase {
TailorShop: ITailorShopDatabase;
}
export interface IRoom {
export interface IRoomDatabase {
Name: string;
MaxCapacity: number;
PlacedDecos?: IPlacedDecosDatabase[];
}
export interface IRoomClient {
Name: string;
MaxCapacity: number;
PlacedDecos?: IPlacedDecosClient[];
}
export interface IPlantClient {
PlantType: string;
EndTime: IMongoDate;
@ -89,7 +95,7 @@ export interface IGardeningDatabase {
export interface IApartmentClient {
Gardening: IGardeningClient;
Rooms: IRoom[];
Rooms: IRoomClient[];
FavouriteLoadouts?: IFavouriteLoadout[];
VideoWallBackdrop?: string;
Soundscape?: string;
@ -97,7 +103,7 @@ export interface IApartmentClient {
export interface IApartmentDatabase {
Gardening: IGardeningDatabase;
Rooms: IRoom[];
Rooms: IRoomDatabase[];
FavouriteLoadouts: IFavouriteLoadoutDatabase[];
VideoWallBackdrop?: string;
Soundscape?: string;
@ -110,11 +116,14 @@ export interface IPlacedDecosDatabase {
Scale?: number;
Sockets?: number;
PictureFrameInfo?: IPictureFrameInfo;
CustomizationInfo?: ICustomizationInfoDatabase;
AnimPoseItem?: string;
_id: Types.ObjectId;
}
export interface IPlacedDecosClient extends Omit<IPlacedDecosDatabase, "_id"> {
export interface IPlacedDecosClient extends Omit<IPlacedDecosDatabase, "_id" | "CustomizationInfo"> {
id: IOid;
CustomizationInfo?: ICustomizationInfoClient;
}
export interface ISetShipCustomizationsRequest {
@ -166,11 +175,13 @@ export interface IResetShipDecorationsResponse {
}
export interface ISetPlacedDecoInfoRequest {
DecoType: string;
DecoType?: string;
DecoId: string;
Room: string;
PictureFrameInfo: IPictureFrameInfo;
PictureFrameInfo: IPictureFrameInfo; // IsPicture
CustomizationInfo?: ICustomizationInfoClient; // !IsPicture
BootLocation?: TBootLocation;
AnimPoseItem?: string; // !IsPicture
ComponentId?: string;
GuildId?: string;
}
@ -191,6 +202,21 @@ export interface IPictureFrameInfo {
TextOrientation: number;
}
export interface ICustomizationInfoClient {
Anim?: string;
AnimPose?: number;
LoadOutPreset?: ILoadoutConfigClient;
VehiclePreset?: ILoadoutConfigClient;
EquippedWeapon?: "SUIT_SLOT" | "LONG_GUN_SLOT" | "PISTOL_SLOT";
AvatarType?: string;
LoadOutType?: string; // "LOT_NORMAL"
}
export interface ICustomizationInfoDatabase extends Omit<ICustomizationInfoClient, "LoadOutPreset" | "VehiclePreset"> {
LoadOutPreset?: ILoadoutConfigDatabase;
VehiclePreset?: ILoadoutConfigDatabase;
}
export interface IFavouriteLoadout {
Tag: string;
LoadoutId: IOid;
@ -206,10 +232,11 @@ export interface ITailorShopDatabase {
Colors?: IColor;
CustomJson?: string;
LevelDecosVisible?: boolean;
Rooms: IRoom[];
Rooms: IRoomDatabase[];
}
export interface ITailorShop extends Omit<ITailorShopDatabase, "FavouriteLoadouts"> {
export interface ITailorShop extends Omit<ITailorShopDatabase, "Rooms" | "FavouriteLoadouts"> {
Rooms: IRoomClient[];
FavouriteLoadouts?: IFavouriteLoadout[];
}

View File

@ -117,6 +117,7 @@ export type IMissionInventoryUpdateRequest = {
DropTable: string;
DROP_MOD?: number[];
DROP_BLUEPRINT?: number[];
DROP_MISC_ITEM?: number[];
}[];
DeathMarks?: string[];
Nemesis?: number;
@ -205,6 +206,7 @@ export interface IRewardInfo {
Q?: boolean; // likely indicates that the bonus objective for this stage was completed
CheckpointCounter?: number; // starts at 1, is incremented with each job stage upload, and does not reset when starting a new job
challengeMissionId?: string;
GoalProgressAmount?: number;
}
export type IMissionStatus = "GS_SUCCESS" | "GS_FAILURE" | "GS_DUMPED" | "GS_QUIT" | "GS_INTERRUPTED";

View File

@ -32,6 +32,19 @@ export interface IStatsClient {
OlliesCrashCourseScore?: number;
DojoObstacleScore?: number;
// event scores
Halloween16?: number;
AmalgamEventScoreMax?: number;
Halloween19ScoreMax?: number;
FlotillaEventScore?: number;
FlotillaSpaceBadgesTier1?: number;
FlotillaSpaceBadgesTier2?: number;
FlotillaSpaceBadgesTier3?: number;
FlotillaGroundBadgesTier1?: number;
FlotillaGroundBadgesTier2?: number;
FlotillaGroundBadgesTier3?: number;
MechSurvivalScoreMax?: number;
// not in schema
PVP?: {
suitDeaths?: number;

View File

@ -56,7 +56,7 @@ export interface IGoal {
Success?: number;
Personal?: boolean;
Community?: boolean;
Best?: boolean; // Fist one on Event Tab
Best?: boolean; // Use Best instead of Count to check for reward
Bounty?: boolean; // Tactical Alert
ClampNodeScores?: boolean;
@ -88,9 +88,12 @@ export interface IGoal {
JobPreviousVersion?: IOid;
ScoreVar?: string;
ScoreMaxTag?: string;
ScoreMaxTag?: string; // Field in leaderboard
ScoreLocTag?: string;
MissionKeyRotation?: string[];
MissionKeyRotationInterval?: number;
NightLevel?: string;
}

View File

@ -0,0 +1,290 @@
{
"/Lotus/PVPChallengeTypes/PVPTimedChallengeFlagCaptureEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_CAPTURETHEFLAG"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeFlagCaptureMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_CAPTURETHEFLAG"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeFlagReturnEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_CAPTURETHEFLAG"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsComboEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsComboMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsHeadShotsEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsHeadShotsMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsMeleeEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsMeleeMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsMeleeHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsMultiMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPaybackEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPayback_MEDIUM": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPowerEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPowerMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPowerHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPrimaryEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPrimaryMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPrimaryHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsSecondaryEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsSecondaryMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsSecondaryHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreak_MEDIUM": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakDominationEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakDomination_MEDIUM": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakDominationHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakStoppedEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakStopped_MEDIUM": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakHARD": {
"ScriptParamValue": 2,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsTargetInAirEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsTargetInAirMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsTargetInAirHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsWhileSlidingEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsWhileSlidingMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsWhileSlidingHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 3000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeMatchCompleteEASY": {
"ScriptParamValue": 1,
"PVPModeAllowed": ["PVPMODE_CAPTURETHEFLAG", "PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeMatchCompleteMEDIUM": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_CAPTURETHEFLAG", "PVPMODE_DEATHMATCH", "PVPMODE_TEAMDEATHMATCH"],
"SyndicateXP": 1500
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballCatchesEASY": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballCatchesMEDIUM": {
"ScriptParamValue": 10,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballCatchesHARD": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballChecksEASY": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballChecksMEDIUM": {
"ScriptParamValue": 10,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballChecksHARD": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballGoalsEASY": {
"ScriptParamValue": 2,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballGoalsMEDIUM": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballGoalsHARD": {
"ScriptParamValue": 4,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballInterceptionsEASY": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballInterceptionsMEDIUM": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballInterceptionsHARD": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballPassesEASY": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballPassesMEDIUM": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballPassesHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000,
"DuringSingleMatch": true
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballStealsEASY": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 1000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballStealsMEDIUM": {
"ScriptParamValue": 6,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 3000
},
"/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballStealsHARD": {
"ScriptParamValue": 3,
"PVPModeAllowed": ["PVPMODE_SPEEDBALL"],
"SyndicateXP": 6000
}
}

View File

@ -311,140 +311,6 @@
"PrimeVaultAvailabilities": [false, false, false, false, false],
"PrimeTokenAvailability": true,
"LibraryInfo": { "LastCompletedTargetType": "/Lotus/Types/Game/Library/Targets/Research7Target" },
"PVPChallengeInstances": [
{
"_id": { "$oid": "6635562d036ce37f7f98e264" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeGameModeComplete",
"startDate": { "$date": { "$numberLong": "1714771501460" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 20 }],
"isGenerated": true,
"PVPMode": "PVPMODE_ALL",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_WEEKLY"
},
{
"_id": { "$oid": "6635562d036ce37f7f98e263" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeGameModeWins",
"startDate": { "$date": { "$numberLong": "1714771501460" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 6 }],
"isGenerated": true,
"PVPMode": "PVPMODE_ALL",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_WEEKLY"
},
{
"_id": { "$oid": "6635562d036ce37f7f98e265" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeOtherChallengeCompleteANY",
"startDate": { "$date": { "$numberLong": "1714771501460" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 10 }],
"isGenerated": true,
"PVPMode": "PVPMODE_ALL",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_WEEKLY"
},
{
"_id": { "$oid": "6635562d036ce37f7f98e266" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeWeeklyStandardSet",
"startDate": { "$date": { "$numberLong": "1714771501460" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 0 }],
"isGenerated": true,
"PVPMode": "PVPMODE_NONE",
"subChallenges": [{ "$oid": "6635562d036ce37f7f98e263" }, { "$oid": "6635562d036ce37f7f98e264" }, { "$oid": "6635562d036ce37f7f98e265" }],
"Category": "PVPChallengeTypeCategory_WEEKLY_ROOT"
},
{
"_id": { "$oid": "6639ca6967c1192987d75fee" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeFlagReturnEASY",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 1 }],
"isGenerated": true,
"PVPMode": "PVPMODE_CAPTURETHEFLAG",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75fed" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeMatchCompleteMEDIUM",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 4 }],
"isGenerated": true,
"PVPMode": "PVPMODE_CAPTURETHEFLAG",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75ff2" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeMatchCompleteEASY",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 1 }],
"isGenerated": true,
"PVPMode": "PVPMODE_DEATHMATCH",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75ff1" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsPayback_MEDIUM",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 3 }],
"isGenerated": true,
"PVPMode": "PVPMODE_DEATHMATCH",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75fef" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsStreakDominationEASY",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 1 }],
"isGenerated": true,
"PVPMode": "PVPMODE_TEAMDEATHMATCH",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75ff0" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeKillsWhileInAirHARD",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 3 }],
"isGenerated": true,
"PVPMode": "PVPMODE_TEAMDEATHMATCH",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75ff3" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballCatchesMEDIUM",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 10 }],
"isGenerated": true,
"PVPMode": "PVPMODE_SPEEDBALL",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
},
{
"_id": { "$oid": "6639ca6967c1192987d75ff4" },
"challengeTypeRefID": "/Lotus/PVPChallengeTypes/PVPTimedChallengeSpeedballInterceptionsEASY",
"startDate": { "$date": { "$numberLong": "1715063401824" } },
"endDate": { "$date": { "$numberLong": "2000000000000" } },
"params": [{ "n": "ScriptParamValue", "v": 3 }],
"isGenerated": true,
"PVPMode": "PVPMODE_SPEEDBALL",
"subChallenges": [],
"Category": "PVPChallengeTypeCategory_DAILY"
}
],
"PersistentEnemies": [],
"PVPAlternativeModes": [],
"PVPActiveTournaments": [],

View File

@ -945,7 +945,12 @@
<div class="form-check">
<input class="form-check-input" type="checkbox" id="worldState.wolfHunt" />
<label class="form-check-label" for="worldState.wolfHunt" data-loc="worldState_wolfHunt"></label>
<abbr data-loc-inc="worldState_galleonOfGhouls|worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
<abbr data-loc-inc="worldState_galleonOfGhouls|worldState_orphixVenom|worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="worldState.orphixVenom" />
<label class="form-check-label" for="worldState.orphixVenom" data-loc="worldState_orphixVenom"></label>
<abbr data-loc-inc="worldState_galleonOfGhouls|worldState_wolfHunt|worldState_proxyRebellion"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="worldState.longShadow" />
@ -978,7 +983,7 @@
<div class="form-group mt-2 d-flex gap-2">
<div class="flex-fill">
<label class="form-label" for="worldState.proxyRebellion" data-loc="worldState_proxyRebellion"></label>
<abbr data-loc-inc="worldState_anniversary"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
<abbr data-loc-inc="worldState_anniversary|worldState_orphixVenom"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M320 576C461.4 576 576 461.4 576 320C576 178.6 461.4 64 320 64C178.6 64 64 178.6 64 320C64 461.4 178.6 576 320 576zM320 200C333.3 200 344 210.7 344 224L344 336C344 349.3 333.3 360 320 360C306.7 360 296 349.3 296 336L296 224C296 210.7 306.7 200 320 200zM293.3 416C292.7 406.1 297.6 396.7 306.1 391.5C314.6 386.4 325.3 386.4 333.8 391.5C342.3 396.7 347.2 406.1 346.6 416C347.2 425.9 342.3 435.3 333.8 440.5C325.3 445.6 314.6 445.6 306.1 440.5C297.6 435.3 292.7 425.9 293.3 416z"/></svg></abbr>
<select class="form-control" id="worldState.proxyRebellion" data-default="false">
<option value="true" data-loc="enabled"></option>
<option value="false" data-loc="disabled"></option>
@ -1071,8 +1076,13 @@
</select>
</div>
<div class="flex-fill">
<label class="form-label" for="worldState.bellyOfTheBeastProgressOverride" data-loc="worldState_bellyOfTheBeastProgressOverride"></label>
<input id="worldState.bellyOfTheBeastProgressOverride" class="form-control" type="number" min="0" max="100" data-default="0" />
<form class="form-group" onsubmit="doSaveConfigInt('worldState.bellyOfTheBeastProgressOverride'); return false;">
<label class="form-label" for="worldState.bellyOfTheBeastProgressOverride" data-loc="worldState_bellyOfTheBeastProgressOverride"></label>
<div class="input-group">
<input id="worldState.bellyOfTheBeastProgressOverride" class="form-control" type="number" min="0" max="100" data-default="0" />
<button class="btn btn-secondary" type="submit" data-loc="cheats_save"></button>
</div>
</form>
</div>
</div>
<div class="form-group mt-2 d-flex gap-2">
@ -1084,8 +1094,13 @@
</select>
</div>
<div class="flex-fill">
<label class="form-label" for="worldState.eightClawProgressOverride" data-loc="worldState_eightClawProgressOverride"></label>
<input id="worldState.eightClawProgressOverride" class="form-control" type="number" min="0" max="100" data-default="0" />
<form class="form-group" onsubmit="doSaveConfigInt('worldState.eightClawProgressOverride'); return false;">
<label class="form-label" for="worldState.eightClawProgressOverride" data-loc="worldState_eightClawProgressOverride"></label>
<div class="input-group">
<input id="worldState.eightClawProgressOverride" class="form-control" type="number" min="0" max="100" data-default="0" />
<button class="btn btn-secondary" type="submit" data-loc="cheats_save"></button>
</div>
</form>
</div>
</div>
<div class="form-group mt-2">

View File

@ -253,6 +253,7 @@ dict = {
worldState_dogDays: `Hitzefrei`,
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
worldState_wolfHunt: `Wolfsjagd (2025)`,
worldState_orphixVenom: `Orphix Gift`,
worldState_longShadow: `Lange Schatten`,
worldState_hallowedFlame: `Geweihte Flamme`,
worldState_hallowedNightmares: `Geweihte Albträume`,

View File

@ -252,6 +252,7 @@ dict = {
worldState_dogDays: `Dog Days`,
worldState_dogDaysRewards: `Dog Days Rewards`,
worldState_wolfHunt: `Wolf Hunt (2025)`,
worldState_orphixVenom: `Orphix Venom`,
worldState_longShadow: `Long Shadow`,
worldState_hallowedFlame: `Hallowed Flame`,
worldState_hallowedNightmares: `Hallowed Nightmares`,

View File

@ -253,6 +253,7 @@ dict = {
worldState_dogDays: `Canícula`,
worldState_dogDaysRewards: `Recompensas de Canícula`,
worldState_wolfHunt: `Cacería del Lobo (2025)`,
worldState_orphixVenom: `Veneno de Orphix`,
worldState_longShadow: `Sombra Prolongada`,
worldState_hallowedFlame: `Llama Sagrada`,
worldState_hallowedNightmares: `Pesadillas Sagradas`,

View File

@ -253,6 +253,7 @@ dict = {
worldState_dogDays: `Bataille d'Eau`,
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
worldState_wolfHunt: `Chasse au Loup (2025)`,
worldState_orphixVenom: `Venin Orphix`,
worldState_longShadow: `La Propagation des Ombres`,
worldState_hallowedFlame: `Flamme Hantée`,
worldState_hallowedNightmares: `Cauchemars Hantés`,

View File

@ -253,6 +253,7 @@ dict = {
worldState_dogDays: `Знойные дни`,
worldState_dogDaysRewards: `Награды Знойных дней`,
worldState_wolfHunt: `Волчья Охота (2025)`,
worldState_orphixVenom: `Яд Орфикса`,
worldState_longShadow: `Длинная Тень`,
worldState_hallowedFlame: `Священное пламя`,
worldState_hallowedNightmares: `Священные кошмары`,

View File

@ -253,6 +253,7 @@ dict = {
worldState_dogDays: `Спекотні дні`,
worldState_dogDaysRewards: `Нагороди Спекотних днів`,
worldState_wolfHunt: `Полювання на Вовка (2025)`,
worldState_orphixVenom: `Орфіксова отрута`,
worldState_longShadow: `Довга тінь`,
worldState_hallowedFlame: `Священне полум'я`,
worldState_hallowedNightmares: `Священні жахіття`,
@ -310,7 +311,7 @@ dict = {
worldState_varziaFullyStocked: `Повний асортимент Варзії`,
worldState_varziaOverride: `Зміна ротації Варзії`,
import_importNote: `[UNTRANSLATED] You can provide a full or partial <code>inventory.php</code> or <code>getShip.php</code> response (client representation) here.`,
import_importNote: `Ви можете завантажити повну або часткову відповідь <code>inventory.php</code> або <code>getShip.php</code> (клієнтське представлення) тут.`,
import_importNote2: `Всі підтримувані поля <b>будуть перезаписані</b> у вашому акаунті.`,
import_submit: `Відправити`,
import_samples: `Приклад:`,

View File

@ -253,6 +253,7 @@ dict = {
worldState_dogDays: `三伏天`,
worldState_dogDaysRewards: `[UNTRANSLATED] Dog Days Rewards`,
worldState_wolfHunt: `恶狼狩猎 (2025)`,
worldState_orphixVenom: `奥影之毒`,
worldState_longShadow: `暗夜长影`,
worldState_hallowedFlame: `万圣之焰`,
worldState_hallowedNightmares: `万圣噩梦`,