Compare commits
No commits in common. "13c68a75c1447b8cf7301c611a353c35e6dbb25f" and "9823729aa83087b2c5106215afb865ce007b6731" have entirely different histories.
13c68a75c1
...
9823729aa8
24
.github/workflows/docker.yml
vendored
24
.github/workflows/docker.yml
vendored
@ -1,24 +0,0 @@
|
|||||||
name: Build Docker image
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
jobs:
|
|
||||||
docker:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Set up Docker buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Log in to container registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
username: openwf
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: Build and push
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: |
|
|
||||||
openwf/spaceninjaserver:latest
|
|
||||||
openwf/spaceninjaserver:${{ github.sha }}
|
|
@ -1,7 +1,7 @@
|
|||||||
services:
|
services:
|
||||||
spaceninjaserver:
|
openwf:
|
||||||
# build: .
|
# build: .
|
||||||
image: openwf/spaceninjaserver:latest
|
image: ghcr.io/spaceninjaserver/SpaceNinjaServer:latest
|
||||||
environment:
|
environment:
|
||||||
APP_MONGODB_URL: mongodb://openwfagent:spaceninjaserver@mongodb:27017/
|
APP_MONGODB_URL: mongodb://openwfagent:spaceninjaserver@mongodb:27017/
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ export const artifactsController: RequestHandler = async (req, res) => {
|
|||||||
const { Upgrade, LevelDiff, Cost, FusionPointCost } = artifactsData;
|
const { Upgrade, LevelDiff, Cost, FusionPointCost } = artifactsData;
|
||||||
|
|
||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
const { Upgrades } = inventory;
|
const { Upgrades, RawUpgrades } = inventory;
|
||||||
const { ItemType, UpgradeFingerprint, ItemId } = Upgrade;
|
const { ItemType, UpgradeFingerprint, ItemId } = Upgrade;
|
||||||
|
|
||||||
const safeUpgradeFingerprint = UpgradeFingerprint || '{"lvl":0}';
|
const safeUpgradeFingerprint = UpgradeFingerprint || '{"lvl":0}';
|
||||||
@ -32,7 +32,13 @@ export const artifactsController: RequestHandler = async (req, res) => {
|
|||||||
ItemType
|
ItemType
|
||||||
}) - 1;
|
}) - 1;
|
||||||
|
|
||||||
addMods(inventory, [{ ItemType, ItemCount: -1 }]);
|
const rawItemIndex = RawUpgrades.findIndex(rawUpgrade => rawUpgrade.ItemType === ItemType);
|
||||||
|
RawUpgrades[rawItemIndex].ItemCount--;
|
||||||
|
if (RawUpgrades[rawItemIndex].ItemCount > 0) {
|
||||||
|
inventory.markModified(`RawUpgrades.${rawItemIndex}.UpgradeFingerprint`);
|
||||||
|
} else {
|
||||||
|
RawUpgrades.splice(rawItemIndex, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.infiniteCredits) {
|
if (!config.infiniteCredits) {
|
||||||
|
@ -195,7 +195,7 @@ export const getInventoryResponse = async (
|
|||||||
|
|
||||||
if (config.universalPolarityEverywhere) {
|
if (config.universalPolarityEverywhere) {
|
||||||
const Polarity: IPolarity[] = [];
|
const Polarity: IPolarity[] = [];
|
||||||
for (let i = 0; i != 12; ++i) {
|
for (let i = 0; i != 10; ++i) {
|
||||||
Polarity.push({
|
Polarity.push({
|
||||||
Slot: i,
|
Slot: i,
|
||||||
Value: ArtifactPolarity.Any
|
Value: ArtifactPolarity.Any
|
||||||
|
@ -3,23 +3,12 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
|
|||||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||||
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { ExportMisc } from "warframe-public-export-plus";
|
|
||||||
|
|
||||||
export const addXpController: RequestHandler = async (req, res) => {
|
export const addXpController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const inventory = await getInventory(accountId);
|
const inventory = await getInventory(accountId);
|
||||||
const request = req.body as IAddXpRequest;
|
const request = req.body as IAddXpRequest;
|
||||||
for (const [category, gear] of Object.entries(request)) {
|
for (const [category, gear] of Object.entries(request)) {
|
||||||
for (const clientItem of gear) {
|
|
||||||
const dbItem = inventory[category as TEquipmentKey].id(clientItem.ItemId.$oid);
|
|
||||||
if (dbItem) {
|
|
||||||
if (dbItem.ItemType in ExportMisc.uniqueLevelCaps) {
|
|
||||||
if ((dbItem.Polarized ?? 0) < 5) {
|
|
||||||
dbItem.Polarized = 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addGearExpByCategory(inventory, gear, category as TEquipmentKey);
|
addGearExpByCategory(inventory, gear, category as TEquipmentKey);
|
||||||
}
|
}
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
|
@ -1,23 +1,19 @@
|
|||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { Account } from "@/src/models/loginModel";
|
import { Account } from "@/src/models/loginModel";
|
||||||
import { Inbox } from "@/src/models/inboxModel";
|
|
||||||
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
|
import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
||||||
import { PersonalRooms } from "@/src/models/personalRoomsModel";
|
import { PersonalRooms } from "@/src/models/personalRoomsModel";
|
||||||
import { Ship } from "@/src/models/shipModel";
|
import { Ship } from "@/src/models/shipModel";
|
||||||
import { Stats } from "@/src/models/statsModel";
|
|
||||||
|
|
||||||
export const deleteAccountController: RequestHandler = async (req, res) => {
|
export const deleteAccountController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
Account.deleteOne({ _id: accountId }),
|
Account.deleteOne({ _id: accountId }),
|
||||||
Inbox.deleteMany({ ownerId: accountId }),
|
|
||||||
Inventory.deleteOne({ accountOwnerId: accountId }),
|
Inventory.deleteOne({ accountOwnerId: accountId }),
|
||||||
Loadout.deleteOne({ loadoutOwnerId: accountId }),
|
Loadout.deleteOne({ loadoutOwnerId: accountId }),
|
||||||
PersonalRooms.deleteOne({ personalRoomsOwnerId: accountId }),
|
PersonalRooms.deleteOne({ personalRoomsOwnerId: accountId }),
|
||||||
Ship.deleteOne({ ShipOwnerId: accountId }),
|
Ship.deleteOne({ ShipOwnerId: accountId })
|
||||||
Stats.deleteOne({ accountOwnerId: accountId })
|
|
||||||
]);
|
]);
|
||||||
res.end();
|
res.end();
|
||||||
};
|
};
|
||||||
|
@ -1,23 +1,15 @@
|
|||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
// This endpoint is specific to the OpenWF Bootstrapper: https://openwf.io/bootstrapper-manual
|
|
||||||
|
|
||||||
interface ITunables {
|
interface ITunables {
|
||||||
prohibit_skip_mission_start_timer?: boolean;
|
prohibit_skip_mission_start_timer?: any;
|
||||||
prohibit_fov_override?: boolean;
|
prohibit_fov_override?: any;
|
||||||
prohibit_freecam?: boolean;
|
|
||||||
prohibit_teleport?: boolean;
|
|
||||||
prohibit_scripts?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const tunablesController: RequestHandler = (_req, res) => {
|
const tunablesController: RequestHandler = (_req, res) => {
|
||||||
const tunables: ITunables = {};
|
const tunablesSet: ITunables = {};
|
||||||
//tunables.prohibit_skip_mission_start_timer = true;
|
//tunablesSet.prohibit_skip_mission_start_timer = 1;
|
||||||
//tunables.prohibit_fov_override = true;
|
//tunablesSet.prohibit_fov_override = 1;
|
||||||
//tunables.prohibit_freecam = true;
|
res.json(tunablesSet);
|
||||||
//tunables.prohibit_teleport = true;
|
|
||||||
//tunables.prohibit_scripts = true;
|
|
||||||
res.json(tunables);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export { tunablesController };
|
export { tunablesController };
|
||||||
|
@ -1,14 +1,6 @@
|
|||||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
|
||||||
import { getStats, uploadStats } from "@/src/services/statsService";
|
|
||||||
import { IStatsUpload } from "@/src/types/statTypes";
|
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
const uploadController: RequestHandler = async (req, res) => {
|
const uploadController: RequestHandler = (_req, res) => {
|
||||||
const payload = getJSONfromString<IStatsUpload>(String(req.body));
|
|
||||||
const accountId = await getAccountIdForRequest(req);
|
|
||||||
const playerStats = await getStats(accountId);
|
|
||||||
await uploadStats(playerStats, payload);
|
|
||||||
res.status(200).end();
|
res.status(200).end();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,33 +1,31 @@
|
|||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { IStatsView } from "@/src/types/statTypes";
|
||||||
import { config } from "@/src/services/configService";
|
import { config } from "@/src/services/configService";
|
||||||
import allScans from "@/static/fixed_responses/allScans.json";
|
import allScans from "@/static/fixed_responses/allScans.json";
|
||||||
import { ExportEnemies } from "warframe-public-export-plus";
|
import { ExportEnemies } from "warframe-public-export-plus";
|
||||||
import { getInventory } from "@/src/services/inventoryService";
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
import { getStats } from "@/src/services/statsService";
|
|
||||||
import { IStatsView } from "@/src/types/statTypes";
|
|
||||||
|
|
||||||
const viewController: RequestHandler = async (req, res) => {
|
const viewController: RequestHandler = async (req, res) => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
const inventory = await getInventory(accountId, "XPInfo");
|
const inventory = await getInventory(accountId, "XPInfo");
|
||||||
const playerStats = await getStats(accountId);
|
|
||||||
|
|
||||||
const responseJson: IStatsView = playerStats.toJSON();
|
const responseJson: IStatsView = {};
|
||||||
responseJson.Weapons ??= [];
|
responseJson.Weapons = [];
|
||||||
for (const item of inventory.XPInfo) {
|
for (const item of inventory.XPInfo) {
|
||||||
const weaponIndex = responseJson.Weapons.findIndex(element => element.type == item.ItemType);
|
responseJson.Weapons.push({
|
||||||
if (weaponIndex !== -1) {
|
type: item.ItemType,
|
||||||
responseJson.Weapons[weaponIndex].xp == item.XP;
|
xp: item.XP
|
||||||
} else {
|
});
|
||||||
responseJson.Weapons.push({ type: item.ItemType, xp: item.XP });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (config.unlockAllScans) {
|
if (config.unlockAllScans) {
|
||||||
const scans = new Set(allScans);
|
const scans = new Set(allScans);
|
||||||
for (const type of Object.keys(ExportEnemies.avatars)) {
|
for (const type of Object.keys(ExportEnemies.avatars)) {
|
||||||
if (!scans.has(type)) scans.add(type);
|
if (!scans.has(type)) {
|
||||||
|
scans.add(type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
responseJson.Scans ??= [];
|
responseJson.Scans = [];
|
||||||
for (const type of scans) {
|
for (const type of scans) {
|
||||||
responseJson.Scans.push({ type: type, scans: 9999 });
|
responseJson.Scans.push({ type: type, scans: 9999 });
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import {
|
|||||||
ISettings,
|
ISettings,
|
||||||
IInfestedFoundryDatabase,
|
IInfestedFoundryDatabase,
|
||||||
IHelminthResource,
|
IHelminthResource,
|
||||||
IMissionDatabase,
|
|
||||||
IConsumedSuit,
|
IConsumedSuit,
|
||||||
IQuestStage,
|
IQuestStage,
|
||||||
IQuestKeyDatabase,
|
IQuestKeyDatabase,
|
||||||
@ -483,15 +482,6 @@ const helminthResourceSchema = new Schema<IHelminthResource>(
|
|||||||
{ _id: false }
|
{ _id: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
const missionSchema = new Schema<IMissionDatabase>(
|
|
||||||
{
|
|
||||||
Tag: String,
|
|
||||||
Completes: { type: Number, default: 0 },
|
|
||||||
Tier: { type: Number, required: false }
|
|
||||||
},
|
|
||||||
{ _id: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
const questProgressSchema = new Schema<IQuestStage>(
|
const questProgressSchema = new Schema<IQuestStage>(
|
||||||
{
|
{
|
||||||
c: Number,
|
c: Number,
|
||||||
@ -1007,7 +997,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
|||||||
ShipDecorations: [typeCountSchema],
|
ShipDecorations: [typeCountSchema],
|
||||||
|
|
||||||
//Railjack/Components(https://warframe.fandom.com/wiki/Railjack/Components)
|
//Railjack/Components(https://warframe.fandom.com/wiki/Railjack/Components)
|
||||||
CrewShipRawSalvage: [typeCountSchema],
|
CrewShipRawSalvage: [Schema.Types.Mixed],
|
||||||
|
|
||||||
//Default RailJack
|
//Default RailJack
|
||||||
CrewShipAmmo: [typeCountSchema],
|
CrewShipAmmo: [typeCountSchema],
|
||||||
@ -1020,7 +1010,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
|||||||
CrewShipSalvagedWeapons: [Schema.Types.Mixed],
|
CrewShipSalvagedWeapons: [Schema.Types.Mixed],
|
||||||
|
|
||||||
//Complete Mission\Quests
|
//Complete Mission\Quests
|
||||||
Missions: [missionSchema],
|
Missions: [Schema.Types.Mixed],
|
||||||
QuestKeys: [questKeysSchema],
|
QuestKeys: [questKeysSchema],
|
||||||
ActiveQuest: { type: String, default: "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain" }, //TODO: check after mission starting gear
|
ActiveQuest: { type: String, default: "/Lotus/Types/Keys/VorsPrize/VorsPrizeQuestKeyChain" }, //TODO: check after mission starting gear
|
||||||
//item like DojoKey or Boss missions key
|
//item like DojoKey or Boss missions key
|
||||||
|
@ -1,101 +0,0 @@
|
|||||||
import { Document, Schema, Types, model } from "mongoose";
|
|
||||||
import { IEnemy, IMission, IScan, ITutorial, IAbility, IWeapon, IStatsDatabase } from "@/src/types/statTypes";
|
|
||||||
|
|
||||||
const abilitySchema = new Schema<IAbility>(
|
|
||||||
{
|
|
||||||
type: { type: String, required: true },
|
|
||||||
used: Number
|
|
||||||
},
|
|
||||||
{ _id: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
const enemySchema = new Schema<IEnemy>(
|
|
||||||
{
|
|
||||||
type: { type: String, required: true },
|
|
||||||
executions: Number,
|
|
||||||
headshots: Number,
|
|
||||||
kills: Number,
|
|
||||||
assists: Number,
|
|
||||||
deaths: Number
|
|
||||||
},
|
|
||||||
{ _id: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
const missionSchema = new Schema<IMission>(
|
|
||||||
{
|
|
||||||
type: { type: String, required: true },
|
|
||||||
highScore: Number
|
|
||||||
},
|
|
||||||
{ _id: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
const scanSchema = new Schema<IScan>(
|
|
||||||
{
|
|
||||||
type: { type: String, required: true },
|
|
||||||
scans: Number
|
|
||||||
},
|
|
||||||
{ _id: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
const tutorialSchema = new Schema<ITutorial>(
|
|
||||||
{
|
|
||||||
stage: Number
|
|
||||||
},
|
|
||||||
{ _id: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
const weaponSchema = new Schema<IWeapon>(
|
|
||||||
{
|
|
||||||
type: { type: String, required: true },
|
|
||||||
equipTime: Number,
|
|
||||||
hits: Number,
|
|
||||||
kills: Number,
|
|
||||||
xp: Number,
|
|
||||||
assists: Number,
|
|
||||||
headshots: Number,
|
|
||||||
fired: Number
|
|
||||||
},
|
|
||||||
{ _id: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
const statsSchema = new Schema<IStatsDatabase>({
|
|
||||||
accountOwnerId: { type: Schema.Types.ObjectId, required: true },
|
|
||||||
CiphersSolved: Number,
|
|
||||||
CiphersFailed: Number,
|
|
||||||
CipherTime: Number,
|
|
||||||
Weapons: { type: [weaponSchema], default: [] },
|
|
||||||
Enemies: { type: [enemySchema], default: [] },
|
|
||||||
MeleeKills: Number,
|
|
||||||
MissionsCompleted: Number,
|
|
||||||
MissionsQuit: Number,
|
|
||||||
MissionsFailed: Number,
|
|
||||||
TimePlayedSec: Number,
|
|
||||||
PickupCount: Number,
|
|
||||||
Tutorial: { type: Map, of: tutorialSchema, default: {} },
|
|
||||||
Abilities: { type: [abilitySchema], default: [] },
|
|
||||||
Rating: Number,
|
|
||||||
Income: Number,
|
|
||||||
Rank: Number,
|
|
||||||
PlayerLevel: Number,
|
|
||||||
Scans: { type: [scanSchema], default: [] },
|
|
||||||
Missions: { type: [missionSchema], default: [] },
|
|
||||||
Deaths: Number,
|
|
||||||
HealCount: Number,
|
|
||||||
ReviveCount: Number
|
|
||||||
});
|
|
||||||
|
|
||||||
statsSchema.set("toJSON", {
|
|
||||||
transform(_document, returnedObject) {
|
|
||||||
delete returnedObject._id;
|
|
||||||
delete returnedObject.__v;
|
|
||||||
delete returnedObject.accountOwnerId;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export const Stats = model<IStatsDatabase>("Stats", statsSchema);
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
||||||
export type TStatsDatabaseDocument = Document<unknown, {}, IStatsDatabase> & {
|
|
||||||
_id: Types.ObjectId;
|
|
||||||
__v: number;
|
|
||||||
} & IStatsDatabase;
|
|
@ -155,7 +155,7 @@ export const importInventory = (db: TInventoryDatabaseDocument, client: Partial<
|
|||||||
if (client.Upgrades !== undefined) {
|
if (client.Upgrades !== undefined) {
|
||||||
replaceArray<IUpgradeDatabase>(db.Upgrades, client.Upgrades.map(convertUpgrade));
|
replaceArray<IUpgradeDatabase>(db.Upgrades, client.Upgrades.map(convertUpgrade));
|
||||||
}
|
}
|
||||||
for (const key of ["RawUpgrades", "MiscItems", "Consumables"] as const) {
|
for (const key of ["RawUpgrades", "MiscItems"] as const) {
|
||||||
if (client[key] !== undefined) {
|
if (client[key] !== undefined) {
|
||||||
db[key].splice(0, db[key].length);
|
db[key].splice(0, db[key].length);
|
||||||
client[key].forEach(x => {
|
client[key].forEach(x => {
|
||||||
|
@ -240,14 +240,7 @@ export const addItem = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (ExportResources[typeName].productCategory == "CrewShips") {
|
} else if (ExportResources[typeName].productCategory == "CrewShips") {
|
||||||
const inventoryChanges = {
|
const inventoryChanges = addCrewShip(inventory, typeName);
|
||||||
...addCrewShip(inventory, typeName),
|
|
||||||
// fix to unlock railjack modding, item bellow supposed to be obtained from archwing quest
|
|
||||||
...(!inventory.CrewShipHarnesses?.length
|
|
||||||
? addCrewShipHarness(inventory, "/Lotus/Types/Game/CrewShip/RailJack/DefaultHarness")
|
|
||||||
: {})
|
|
||||||
};
|
|
||||||
|
|
||||||
return { InventoryChanges: inventoryChanges };
|
return { InventoryChanges: inventoryChanges };
|
||||||
} else if (ExportResources[typeName].productCategory == "ShipDecorations") {
|
} else if (ExportResources[typeName].productCategory == "ShipDecorations") {
|
||||||
const changes = [
|
const changes = [
|
||||||
@ -322,6 +315,7 @@ export const addItem = async (
|
|||||||
}
|
}
|
||||||
if (typeName in ExportWeapons) {
|
if (typeName in ExportWeapons) {
|
||||||
const weapon = ExportWeapons[typeName];
|
const weapon = ExportWeapons[typeName];
|
||||||
|
// Many non-weapon items are "Pistols" in Public Export, so some duck typing is needed.
|
||||||
if (weapon.totalDamage != 0) {
|
if (weapon.totalDamage != 0) {
|
||||||
const inventoryChanges = addEquipment(inventory, weapon.productCategory, typeName);
|
const inventoryChanges = addEquipment(inventory, weapon.productCategory, typeName);
|
||||||
updateSlots(inventory, InventorySlot.WEAPONS, 0, 1);
|
updateSlots(inventory, InventorySlot.WEAPONS, 0, 1);
|
||||||
@ -331,20 +325,6 @@ export const addItem = async (
|
|||||||
WeaponBin: { count: 1, platinum: 0, Slots: -1 }
|
WeaponBin: { count: 1, platinum: 0, Slots: -1 }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else {
|
|
||||||
// Modular weapon parts
|
|
||||||
const miscItemChanges = [
|
|
||||||
{
|
|
||||||
ItemType: typeName,
|
|
||||||
ItemCount: quantity
|
|
||||||
} satisfies IMiscItem
|
|
||||||
];
|
|
||||||
addMiscItems(inventory, miscItemChanges);
|
|
||||||
return {
|
|
||||||
InventoryChanges: {
|
|
||||||
MiscItems: miscItemChanges
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeName in creditBundles) {
|
if (typeName in creditBundles) {
|
||||||
@ -830,17 +810,6 @@ const addCrewShip = (
|
|||||||
return inventoryChanges;
|
return inventoryChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
const addCrewShipHarness = (
|
|
||||||
inventory: TInventoryDatabaseDocument,
|
|
||||||
typeName: string,
|
|
||||||
inventoryChanges: IInventoryChanges = {}
|
|
||||||
): IInventoryChanges => {
|
|
||||||
const index = inventory.CrewShipHarnesses.push({ ItemType: typeName }) - 1;
|
|
||||||
inventoryChanges.CrewShipHarnesses ??= [];
|
|
||||||
(inventoryChanges.CrewShipHarnesses as object[]).push(inventory.CrewShipHarnesses[index].toJSON());
|
|
||||||
return inventoryChanges;
|
|
||||||
};
|
|
||||||
|
|
||||||
//TODO: wrong id is not erroring
|
//TODO: wrong id is not erroring
|
||||||
export const addGearExpByCategory = (
|
export const addGearExpByCategory = (
|
||||||
inventory: TInventoryDatabaseDocument,
|
inventory: TInventoryDatabaseDocument,
|
||||||
@ -854,10 +823,12 @@ export const addGearExpByCategory = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const item = category.id(ItemId.$oid);
|
const itemIndex = ItemId ? category.findIndex(item => item._id?.equals(ItemId.$oid)) : -1;
|
||||||
if (item) {
|
if (itemIndex !== -1) {
|
||||||
|
const item = category[itemIndex];
|
||||||
item.XP ??= 0;
|
item.XP ??= 0;
|
||||||
item.XP += XP;
|
item.XP += XP;
|
||||||
|
inventory.markModified(`${categoryName}.${itemIndex}.XP`);
|
||||||
|
|
||||||
const xpinfoIndex = inventory.XPInfo.findIndex(x => x.ItemType == item.ItemType);
|
const xpinfoIndex = inventory.XPInfo.findIndex(x => x.ItemType == item.ItemType);
|
||||||
if (xpinfoIndex !== -1) {
|
if (xpinfoIndex !== -1) {
|
||||||
@ -906,6 +877,7 @@ export const addShipDecorations = (
|
|||||||
|
|
||||||
if (itemIndex !== -1) {
|
if (itemIndex !== -1) {
|
||||||
ShipDecorations[itemIndex].ItemCount += ItemCount;
|
ShipDecorations[itemIndex].ItemCount += ItemCount;
|
||||||
|
inventory.markModified(`ShipDecorations.${itemIndex}.ItemCount`);
|
||||||
} else {
|
} else {
|
||||||
ShipDecorations.push({ ItemCount, ItemType });
|
ShipDecorations.push({ ItemCount, ItemType });
|
||||||
}
|
}
|
||||||
@ -920,43 +892,13 @@ export const addConsumables = (inventory: TInventoryDatabaseDocument, itemsArray
|
|||||||
|
|
||||||
if (itemIndex !== -1) {
|
if (itemIndex !== -1) {
|
||||||
Consumables[itemIndex].ItemCount += ItemCount;
|
Consumables[itemIndex].ItemCount += ItemCount;
|
||||||
|
inventory.markModified(`Consumables.${itemIndex}.ItemCount`);
|
||||||
} else {
|
} else {
|
||||||
Consumables.push({ ItemCount, ItemType });
|
Consumables.push({ ItemCount, ItemType });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addCrewShipRawSalvage = (
|
|
||||||
inventory: TInventoryDatabaseDocument,
|
|
||||||
itemsArray: ITypeCount[] | undefined
|
|
||||||
): void => {
|
|
||||||
const { CrewShipRawSalvage } = inventory;
|
|
||||||
|
|
||||||
itemsArray?.forEach(({ ItemCount, ItemType }) => {
|
|
||||||
const itemIndex = CrewShipRawSalvage.findIndex(i => i.ItemType === ItemType);
|
|
||||||
|
|
||||||
if (itemIndex !== -1) {
|
|
||||||
CrewShipRawSalvage[itemIndex].ItemCount += ItemCount;
|
|
||||||
} else {
|
|
||||||
CrewShipRawSalvage.push({ ItemCount, ItemType });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const addCrewShipAmmo = (inventory: TInventoryDatabaseDocument, itemsArray: ITypeCount[] | undefined): void => {
|
|
||||||
const { CrewShipAmmo } = inventory;
|
|
||||||
|
|
||||||
itemsArray?.forEach(({ ItemCount, ItemType }) => {
|
|
||||||
const itemIndex = CrewShipAmmo.findIndex(i => i.ItemType === ItemType);
|
|
||||||
|
|
||||||
if (itemIndex !== -1) {
|
|
||||||
CrewShipAmmo[itemIndex].ItemCount += ItemCount;
|
|
||||||
} else {
|
|
||||||
CrewShipAmmo.push({ ItemCount, ItemType });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const addRecipes = (inventory: TInventoryDatabaseDocument, itemsArray: ITypeCount[] | undefined): void => {
|
export const addRecipes = (inventory: TInventoryDatabaseDocument, itemsArray: ITypeCount[] | undefined): void => {
|
||||||
const { Recipes } = inventory;
|
const { Recipes } = inventory;
|
||||||
|
|
||||||
@ -965,6 +907,7 @@ export const addRecipes = (inventory: TInventoryDatabaseDocument, itemsArray: IT
|
|||||||
|
|
||||||
if (itemIndex !== -1) {
|
if (itemIndex !== -1) {
|
||||||
Recipes[itemIndex].ItemCount += ItemCount;
|
Recipes[itemIndex].ItemCount += ItemCount;
|
||||||
|
inventory.markModified(`Recipes.${itemIndex}.ItemCount`);
|
||||||
} else {
|
} else {
|
||||||
Recipes.push({ ItemCount, ItemType });
|
Recipes.push({ ItemCount, ItemType });
|
||||||
}
|
}
|
||||||
@ -1003,6 +946,7 @@ export const addFusionTreasures = (
|
|||||||
|
|
||||||
if (itemIndex !== -1) {
|
if (itemIndex !== -1) {
|
||||||
FusionTreasures[itemIndex].ItemCount += ItemCount;
|
FusionTreasures[itemIndex].ItemCount += ItemCount;
|
||||||
|
inventory.markModified(`FusionTreasures.${itemIndex}.ItemCount`);
|
||||||
} else {
|
} else {
|
||||||
FusionTreasures.push({ ItemCount, ItemType, Sockets });
|
FusionTreasures.push({ ItemCount, ItemType, Sockets });
|
||||||
}
|
}
|
||||||
@ -1073,6 +1017,7 @@ export const addChallenges = (
|
|||||||
|
|
||||||
if (itemIndex !== -1) {
|
if (itemIndex !== -1) {
|
||||||
category[itemIndex].Progress += Progress;
|
category[itemIndex].Progress += Progress;
|
||||||
|
inventory.markModified(`ChallengeProgress.${itemIndex}.ItemCount`);
|
||||||
} else {
|
} else {
|
||||||
category.push({ Name, Progress });
|
category.push({ Name, Progress });
|
||||||
}
|
}
|
||||||
@ -1085,6 +1030,7 @@ export const addMissionComplete = (inventory: TInventoryDatabaseDocument, { Tag,
|
|||||||
|
|
||||||
if (itemIndex !== -1) {
|
if (itemIndex !== -1) {
|
||||||
Missions[itemIndex].Completes += Completes;
|
Missions[itemIndex].Completes += Completes;
|
||||||
|
inventory.markModified(`Missions.${itemIndex}.Completes`);
|
||||||
} else {
|
} else {
|
||||||
Missions.push({ Tag, Completes });
|
Missions.push({ Tag, Completes });
|
||||||
}
|
}
|
||||||
@ -1100,6 +1046,7 @@ export const addBooster = (ItemType: string, time: number, inventory: TInventory
|
|||||||
if (itemIndex !== -1) {
|
if (itemIndex !== -1) {
|
||||||
const existingBooster = Boosters[itemIndex];
|
const existingBooster = Boosters[itemIndex];
|
||||||
existingBooster.ExpiryDate = Math.max(existingBooster.ExpiryDate, currentTime) + time;
|
existingBooster.ExpiryDate = Math.max(existingBooster.ExpiryDate, currentTime) + time;
|
||||||
|
inventory.markModified(`Boosters.${itemIndex}.ExpiryDate`);
|
||||||
} else {
|
} else {
|
||||||
Boosters.push({ ItemType, ExpiryDate: currentTime + time });
|
Boosters.push({ ItemType, ExpiryDate: currentTime + time });
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@ import { Loadout } from "@/src/models/inventoryModels/loadoutModel";
|
|||||||
import { PersonalRooms } from "@/src/models/personalRoomsModel";
|
import { PersonalRooms } from "@/src/models/personalRoomsModel";
|
||||||
import { Request } from "express";
|
import { Request } from "express";
|
||||||
import { config } from "@/src/services/configService";
|
import { config } from "@/src/services/configService";
|
||||||
import { createStats } from "@/src/services/statsService";
|
|
||||||
|
|
||||||
export const isCorrectPassword = (requestPassword: string, databasePassword: string): boolean => {
|
export const isCorrectPassword = (requestPassword: string, databasePassword: string): boolean => {
|
||||||
return requestPassword === databasePassword;
|
return requestPassword === databasePassword;
|
||||||
@ -25,7 +24,6 @@ export const createAccount = async (accountData: IDatabaseAccount): Promise<IDat
|
|||||||
const shipId = await createShip(account._id);
|
const shipId = await createShip(account._id);
|
||||||
await createInventory(account._id, { loadOutPresetId: loadoutId, ship: shipId });
|
await createInventory(account._id, { loadOutPresetId: loadoutId, ship: shipId });
|
||||||
await createPersonalRooms(account._id, shipId);
|
await createPersonalRooms(account._id, shipId);
|
||||||
await createStats(account._id.toString());
|
|
||||||
return account.toJSON();
|
return account.toJSON();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof Error) {
|
if (error instanceof Error) {
|
||||||
|
@ -6,8 +6,6 @@ import { equipmentKeys, IInventoryDatabase, TEquipmentKey } from "@/src/types/in
|
|||||||
import {
|
import {
|
||||||
addChallenges,
|
addChallenges,
|
||||||
addConsumables,
|
addConsumables,
|
||||||
addCrewShipAmmo,
|
|
||||||
addCrewShipRawSalvage,
|
|
||||||
addFocusXpIncreases,
|
addFocusXpIncreases,
|
||||||
addFusionTreasures,
|
addFusionTreasures,
|
||||||
addGearExpByCategory,
|
addGearExpByCategory,
|
||||||
@ -124,7 +122,6 @@ export const addMissionInventoryUpdates = (
|
|||||||
addMods(inventory, value);
|
addMods(inventory, value);
|
||||||
break;
|
break;
|
||||||
case "MiscItems":
|
case "MiscItems":
|
||||||
case "BonusMiscItems":
|
|
||||||
addMiscItems(inventory, value);
|
addMiscItems(inventory, value);
|
||||||
break;
|
break;
|
||||||
case "Consumables":
|
case "Consumables":
|
||||||
@ -139,12 +136,6 @@ export const addMissionInventoryUpdates = (
|
|||||||
case "FusionTreasures":
|
case "FusionTreasures":
|
||||||
addFusionTreasures(inventory, value);
|
addFusionTreasures(inventory, value);
|
||||||
break;
|
break;
|
||||||
case "CrewShipRawSalvage":
|
|
||||||
addCrewShipRawSalvage(inventory, value);
|
|
||||||
break;
|
|
||||||
case "CrewShipAmmo":
|
|
||||||
addCrewShipAmmo(inventory, value);
|
|
||||||
break;
|
|
||||||
case "FusionBundles": {
|
case "FusionBundles": {
|
||||||
let fusionPoints = 0;
|
let fusionPoints = 0;
|
||||||
for (const fusionBundle of value) {
|
for (const fusionBundle of value) {
|
||||||
@ -204,6 +195,7 @@ export const addMissionRewards = async (
|
|||||||
) => {
|
) => {
|
||||||
if (!rewardInfo) {
|
if (!rewardInfo) {
|
||||||
logger.warn("no reward info provided");
|
logger.warn("no reward info provided");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: check double reward merging
|
//TODO: check double reward merging
|
||||||
@ -295,9 +287,9 @@ function getLevelCreditRewards(nodeName: string): number {
|
|||||||
//TODO: get dark sektor fixed credit rewards and railjack bonus
|
//TODO: get dark sektor fixed credit rewards and railjack bonus
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRandomMissionDrops(RewardInfo: IRewardInfo | undefined): IRngResult[] {
|
function getRandomMissionDrops(RewardInfo: IRewardInfo): IRngResult[] {
|
||||||
const drops: IRngResult[] = [];
|
const drops: IRngResult[] = [];
|
||||||
if (RewardInfo && RewardInfo.node in ExportRegions) {
|
if (RewardInfo.node in ExportRegions) {
|
||||||
const region = ExportRegions[RewardInfo.node];
|
const region = ExportRegions[RewardInfo.node];
|
||||||
const rewardManifests = region.rewardManifests ?? [];
|
const rewardManifests = region.rewardManifests ?? [];
|
||||||
|
|
||||||
|
@ -1,283 +0,0 @@
|
|||||||
import { Stats, TStatsDatabaseDocument } from "@/src/models/statsModel";
|
|
||||||
import { IStatsUpload } from "@/src/types/statTypes";
|
|
||||||
|
|
||||||
export const createStats = async (accountId: string): Promise<TStatsDatabaseDocument> => {
|
|
||||||
const stats = new Stats({ accountOwnerId: accountId });
|
|
||||||
await stats.save();
|
|
||||||
return stats;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getStats = async (accountOwnerId: string): Promise<TStatsDatabaseDocument> => {
|
|
||||||
let stats = await Stats.findOne({ accountOwnerId: accountOwnerId });
|
|
||||||
|
|
||||||
if (!stats) stats = await createStats(accountOwnerId);
|
|
||||||
|
|
||||||
return stats;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const uploadStats = async (playerStats: TStatsDatabaseDocument, payload: IStatsUpload): Promise<void> => {
|
|
||||||
if (payload.add) {
|
|
||||||
const {
|
|
||||||
MISSION_COMPLETE,
|
|
||||||
PICKUP_ITEM,
|
|
||||||
SCAN,
|
|
||||||
USE_ABILITY,
|
|
||||||
FIRE_WEAPON,
|
|
||||||
HIT_ENTITY_ITEM,
|
|
||||||
HEADSHOT_ITEM,
|
|
||||||
KILL_ENEMY_ITEM,
|
|
||||||
KILL_ENEMY,
|
|
||||||
EXECUTE_ENEMY,
|
|
||||||
HEADSHOT,
|
|
||||||
DIE,
|
|
||||||
MELEE_KILL,
|
|
||||||
INCOME,
|
|
||||||
CIPHER
|
|
||||||
} = payload.add;
|
|
||||||
|
|
||||||
if (MISSION_COMPLETE) {
|
|
||||||
for (const [key, value] of Object.entries(MISSION_COMPLETE)) {
|
|
||||||
switch (key) {
|
|
||||||
case "GS_SUCCESS":
|
|
||||||
playerStats.MissionsCompleted ??= 0;
|
|
||||||
playerStats.MissionsCompleted += value;
|
|
||||||
break;
|
|
||||||
case "GS_QUIT":
|
|
||||||
playerStats.MissionsQuit ??= 0;
|
|
||||||
playerStats.MissionsQuit += value;
|
|
||||||
break;
|
|
||||||
case "GS_FAILURE":
|
|
||||||
playerStats.MissionsFailed ??= 0;
|
|
||||||
playerStats.MissionsFailed += value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PICKUP_ITEM) {
|
|
||||||
for (const value of Object.values(PICKUP_ITEM)) {
|
|
||||||
playerStats.PickupCount ??= 0;
|
|
||||||
playerStats.PickupCount += value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SCAN) {
|
|
||||||
playerStats.Scans ??= [];
|
|
||||||
for (const [key, scans] of Object.entries(SCAN)) {
|
|
||||||
const scan = playerStats.Scans.find(element => element.type === key);
|
|
||||||
if (scan) {
|
|
||||||
scan.scans ??= 0;
|
|
||||||
scan.scans += scans;
|
|
||||||
} else {
|
|
||||||
playerStats.Scans.push({ type: key, scans });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (USE_ABILITY) {
|
|
||||||
playerStats.Abilities ??= [];
|
|
||||||
for (const [key, used] of Object.entries(USE_ABILITY)) {
|
|
||||||
const ability = playerStats.Abilities.find(element => element.type === key);
|
|
||||||
if (ability) {
|
|
||||||
ability.used ??= 0;
|
|
||||||
ability.used += used;
|
|
||||||
} else {
|
|
||||||
playerStats.Abilities.push({ type: key, used });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FIRE_WEAPON) {
|
|
||||||
playerStats.Weapons ??= [];
|
|
||||||
for (const [key, fired] of Object.entries(FIRE_WEAPON)) {
|
|
||||||
const weapon = playerStats.Weapons.find(element => element.type === key);
|
|
||||||
if (weapon) {
|
|
||||||
weapon.fired ??= 0;
|
|
||||||
weapon.fired += fired;
|
|
||||||
} else {
|
|
||||||
playerStats.Weapons.push({ type: key, fired });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HIT_ENTITY_ITEM) {
|
|
||||||
playerStats.Weapons ??= [];
|
|
||||||
for (const [key, hits] of Object.entries(HIT_ENTITY_ITEM)) {
|
|
||||||
const weapon = playerStats.Weapons.find(element => element.type === key);
|
|
||||||
if (weapon) {
|
|
||||||
weapon.hits ??= 0;
|
|
||||||
weapon.hits += hits;
|
|
||||||
} else {
|
|
||||||
playerStats.Weapons.push({ type: key, hits });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HEADSHOT_ITEM) {
|
|
||||||
playerStats.Weapons ??= [];
|
|
||||||
for (const [key, headshots] of Object.entries(HEADSHOT_ITEM)) {
|
|
||||||
const weapon = playerStats.Weapons.find(element => element.type === key);
|
|
||||||
if (weapon) {
|
|
||||||
weapon.headshots ??= 0;
|
|
||||||
weapon.headshots += headshots;
|
|
||||||
} else {
|
|
||||||
playerStats.Weapons.push({ type: key, headshots });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KILL_ENEMY_ITEM) {
|
|
||||||
playerStats.Weapons ??= [];
|
|
||||||
for (const [key, kills] of Object.entries(KILL_ENEMY_ITEM)) {
|
|
||||||
const weapon = playerStats.Weapons.find(element => element.type === key);
|
|
||||||
if (weapon) {
|
|
||||||
weapon.kills ??= 0;
|
|
||||||
weapon.kills += kills;
|
|
||||||
} else {
|
|
||||||
playerStats.Weapons.push({ type: key, kills });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (KILL_ENEMY) {
|
|
||||||
playerStats.Enemies ??= [];
|
|
||||||
for (const [key, kills] of Object.entries(KILL_ENEMY)) {
|
|
||||||
const enemy = playerStats.Enemies.find(element => element.type === key);
|
|
||||||
if (enemy) {
|
|
||||||
enemy.kills ??= 0;
|
|
||||||
enemy.kills += kills;
|
|
||||||
} else {
|
|
||||||
playerStats.Enemies.push({ type: key, kills });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (EXECUTE_ENEMY) {
|
|
||||||
playerStats.Enemies ??= [];
|
|
||||||
for (const [key, executions] of Object.entries(EXECUTE_ENEMY)) {
|
|
||||||
const enemy = playerStats.Enemies.find(element => element.type === key);
|
|
||||||
if (enemy) {
|
|
||||||
enemy.executions ??= 0;
|
|
||||||
enemy.executions += executions;
|
|
||||||
} else {
|
|
||||||
playerStats.Enemies.push({ type: key, executions });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HEADSHOT) {
|
|
||||||
playerStats.Enemies ??= [];
|
|
||||||
for (const [key, headshots] of Object.entries(HEADSHOT)) {
|
|
||||||
const enemy = playerStats.Enemies.find(element => element.type === key);
|
|
||||||
if (enemy) {
|
|
||||||
enemy.headshots ??= 0;
|
|
||||||
enemy.headshots += headshots;
|
|
||||||
} else {
|
|
||||||
playerStats.Enemies.push({ type: key, headshots });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DIE) {
|
|
||||||
playerStats.Enemies ??= [];
|
|
||||||
for (const [key, deaths] of Object.entries(DIE)) {
|
|
||||||
playerStats.Deaths ??= 0;
|
|
||||||
playerStats.Deaths += deaths;
|
|
||||||
const enemy = playerStats.Enemies.find(element => element.type === key);
|
|
||||||
if (enemy) {
|
|
||||||
enemy.deaths ??= 0;
|
|
||||||
enemy.deaths += deaths;
|
|
||||||
} else {
|
|
||||||
playerStats.Enemies.push({ type: key, deaths });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MELEE_KILL) {
|
|
||||||
playerStats.MeleeKills ??= 0;
|
|
||||||
for (const kills of Object.values(MELEE_KILL)) {
|
|
||||||
playerStats.MeleeKills += kills;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (INCOME) {
|
|
||||||
playerStats.Income ??= 0;
|
|
||||||
playerStats.Income += INCOME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CIPHER) {
|
|
||||||
if (CIPHER["0"] > 0) {
|
|
||||||
playerStats.CiphersFailed ??= 0;
|
|
||||||
playerStats.CiphersFailed += CIPHER["0"];
|
|
||||||
}
|
|
||||||
if (CIPHER["1"] > 0) {
|
|
||||||
playerStats.CiphersSolved ??= 0;
|
|
||||||
playerStats.CiphersSolved += CIPHER["1"];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.timers) {
|
|
||||||
const { EQUIP_WEAPON, CURRENT_MISSION_TIME, CIPHER_TIME } = payload.timers;
|
|
||||||
|
|
||||||
if (EQUIP_WEAPON) {
|
|
||||||
playerStats.Weapons ??= [];
|
|
||||||
for (const [key, equipTime] of Object.entries(EQUIP_WEAPON)) {
|
|
||||||
const weapon = playerStats.Weapons.find(element => element.type === key);
|
|
||||||
if (weapon) {
|
|
||||||
weapon.equipTime ??= 0;
|
|
||||||
weapon.equipTime += equipTime;
|
|
||||||
} else {
|
|
||||||
playerStats.Weapons.push({ type: key, equipTime });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CURRENT_MISSION_TIME) {
|
|
||||||
playerStats.TimePlayedSec ??= 0;
|
|
||||||
playerStats.TimePlayedSec += CURRENT_MISSION_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CIPHER_TIME) {
|
|
||||||
playerStats.CipherTime ??= 0;
|
|
||||||
playerStats.CipherTime += CIPHER_TIME;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.max) {
|
|
||||||
const { WEAPON_XP, MISSION_SCORE } = payload.max;
|
|
||||||
|
|
||||||
if (WEAPON_XP) {
|
|
||||||
playerStats.Weapons ??= [];
|
|
||||||
for (const [key, xp] of Object.entries(WEAPON_XP)) {
|
|
||||||
const weapon = playerStats.Weapons.find(element => element.type === key);
|
|
||||||
if (weapon) {
|
|
||||||
weapon.xp = xp;
|
|
||||||
} else {
|
|
||||||
playerStats.Weapons.push({ type: key, xp });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MISSION_SCORE) {
|
|
||||||
playerStats.Missions ??= [];
|
|
||||||
for (const [key, highScore] of Object.entries(MISSION_SCORE)) {
|
|
||||||
const mission = playerStats.Missions.find(element => element.type === key);
|
|
||||||
if (mission) {
|
|
||||||
mission.highScore = highScore;
|
|
||||||
} else {
|
|
||||||
playerStats.Missions.push({ type: key, highScore });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload.set) {
|
|
||||||
const { ELO_RATING, RANK, PLAYER_LEVEL } = payload.set;
|
|
||||||
if (ELO_RATING) playerStats.Rating = ELO_RATING;
|
|
||||||
if (RANK) playerStats.Rank = RANK;
|
|
||||||
if (PLAYER_LEVEL) playerStats.PlayerLevel = PLAYER_LEVEL;
|
|
||||||
}
|
|
||||||
|
|
||||||
await playerStats.save();
|
|
||||||
};
|
|
@ -753,13 +753,10 @@ export interface ILotusCustomization extends IItemConfig {
|
|||||||
Persona: string;
|
Persona: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMissionDatabase {
|
export interface IMission {
|
||||||
Tag: string;
|
|
||||||
Completes: number;
|
Completes: number;
|
||||||
Tier?: number;
|
Tier?: number;
|
||||||
}
|
Tag: string;
|
||||||
|
|
||||||
export interface IMission extends IMissionDatabase {
|
|
||||||
RewardsCooldownTime?: IMongoDate;
|
RewardsCooldownTime?: IMongoDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,23 +35,18 @@ export interface IUpdateChallengeProgressRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type IMissionInventoryUpdateRequest = {
|
export type IMissionInventoryUpdateRequest = {
|
||||||
MiscItems?: ITypeCount[];
|
|
||||||
Recipes?: ITypeCount[];
|
|
||||||
FusionBundles?: ITypeCount[];
|
|
||||||
Consumables?: ITypeCount[];
|
|
||||||
FusionBundels?: ITypeCount[];
|
|
||||||
CrewShipRawSalvage?: ITypeCount[];
|
|
||||||
CrewShipAmmo?: ITypeCount[];
|
|
||||||
BonusMiscItems?: ITypeCount[];
|
|
||||||
|
|
||||||
AffiliationChanges?: IAffiliationChange[];
|
AffiliationChanges?: IAffiliationChange[];
|
||||||
crossPlaySetting?: string;
|
crossPlaySetting?: string;
|
||||||
rewardsMultiplier?: number;
|
rewardsMultiplier?: number;
|
||||||
GoalTag: string;
|
GoalTag: string;
|
||||||
LevelKeyName: string;
|
LevelKeyName: string;
|
||||||
ActiveBoosters?: IBooster[];
|
ActiveBoosters?: IBooster[];
|
||||||
|
FusionBundles?: ITypeCount[];
|
||||||
RawUpgrades?: IRawUpgrade[];
|
RawUpgrades?: IRawUpgrade[];
|
||||||
|
MiscItems?: ITypeCount[];
|
||||||
|
Consumables?: ITypeCount[];
|
||||||
FusionTreasures?: IFusionTreasure[];
|
FusionTreasures?: IFusionTreasure[];
|
||||||
|
Recipes?: ITypeCount[];
|
||||||
QuestKeys?: Omit<IQuestKeyDatabase, "CompletionDate">[];
|
QuestKeys?: Omit<IQuestKeyDatabase, "CompletionDate">[];
|
||||||
RegularCredits?: number;
|
RegularCredits?: number;
|
||||||
MissionFailed: boolean;
|
MissionFailed: boolean;
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import { Types } from "mongoose";
|
|
||||||
|
|
||||||
export interface IStatsView {
|
export interface IStatsView {
|
||||||
CiphersSolved?: number;
|
CiphersSolved?: number;
|
||||||
CiphersFailed?: number;
|
CiphersFailed?: number;
|
||||||
@ -25,32 +23,28 @@ export interface IStatsView {
|
|||||||
ReviveCount?: number;
|
ReviveCount?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IStatsDatabase extends IStatsView {
|
|
||||||
accountOwnerId: Types.ObjectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IAbility {
|
export interface IAbility {
|
||||||
type: string;
|
|
||||||
used: number;
|
used: number;
|
||||||
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEnemy {
|
export interface IEnemy {
|
||||||
type: string;
|
|
||||||
executions?: number;
|
executions?: number;
|
||||||
headshots?: number;
|
headshots?: number;
|
||||||
kills?: number;
|
kills?: number;
|
||||||
|
type: string;
|
||||||
assists?: number;
|
assists?: number;
|
||||||
deaths?: number;
|
deaths?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IMission {
|
export interface IMission {
|
||||||
type: string;
|
|
||||||
highScore: number;
|
highScore: number;
|
||||||
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IScan {
|
export interface IScan {
|
||||||
type: string;
|
|
||||||
scans: number;
|
scans: number;
|
||||||
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITutorial {
|
export interface ITutorial {
|
||||||
@ -58,91 +52,12 @@ export interface ITutorial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface IWeapon {
|
export interface IWeapon {
|
||||||
type: string;
|
|
||||||
equipTime?: number;
|
equipTime?: number;
|
||||||
hits?: number;
|
hits?: number;
|
||||||
kills?: number;
|
kills?: number;
|
||||||
xp?: number;
|
xp?: number;
|
||||||
assists?: number;
|
assists?: number;
|
||||||
|
type: string;
|
||||||
headshots?: number;
|
headshots?: number;
|
||||||
fired?: number;
|
fired?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IStatsUpload {
|
|
||||||
displayName: string;
|
|
||||||
guildId?: string;
|
|
||||||
PS?: string;
|
|
||||||
add?: IStatsAdd;
|
|
||||||
set?: IStatsSet;
|
|
||||||
max?: IStatsMax;
|
|
||||||
timers?: IStatsTimers;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IStatsAdd {
|
|
||||||
GEAR_USED?: IUploadEntry;
|
|
||||||
SCAN?: IUploadEntry;
|
|
||||||
MISSION_COMPLETE?: IUploadEntry;
|
|
||||||
HEADSHOT_ITEM?: IUploadEntry;
|
|
||||||
HEADSHOT?: IUploadEntry;
|
|
||||||
PLAYER_COUNT?: IUploadEntry;
|
|
||||||
HOST_MIGRATION?: IUploadEntry;
|
|
||||||
PICKUP_ITEM?: IUploadEntry;
|
|
||||||
FIRE_WEAPON?: IUploadEntry;
|
|
||||||
HIT_ENTITY_ITEM?: IUploadEntry;
|
|
||||||
DESTROY_DECORATION?: IUploadEntry;
|
|
||||||
KILL_ENEMY?: IUploadEntry;
|
|
||||||
TAKE_DAMAGE?: IUploadEntry;
|
|
||||||
SQUAD_KILL_ENEMY?: IUploadEntry;
|
|
||||||
RECEIVE_UPGRADE?: IUploadEntry;
|
|
||||||
USE_ABILITY?: IUploadEntry;
|
|
||||||
SQUAD_VIP_KILL?: IUploadEntry;
|
|
||||||
HEAL_BUDDY?: IUploadEntry;
|
|
||||||
INCOME?: number;
|
|
||||||
CIPHER?: IUploadEntry;
|
|
||||||
EQUIP_COSMETIC?: IUploadEntry;
|
|
||||||
EQUIP_UPGRADE?: IUploadEntry;
|
|
||||||
KILL_BOSS?: IUploadEntry;
|
|
||||||
MISSION_TYPE?: IUploadEntry;
|
|
||||||
MISSION_FACTION?: IUploadEntry;
|
|
||||||
MISSION_PLAYED?: IUploadEntry;
|
|
||||||
MISSION_PLAYED_TIME?: IUploadEntry;
|
|
||||||
MEDALS_TOP?: IUploadEntry;
|
|
||||||
INPUT_ACTIVITY_TIME?: IUploadEntry;
|
|
||||||
KILL_ENEMY_ITEM?: IUploadEntry;
|
|
||||||
TAKE_DAMAGE_ITEM?: IUploadEntry;
|
|
||||||
SQUAD_KILL_ENEMY_ITEM?: IUploadEntry;
|
|
||||||
MELEE_KILL?: IUploadEntry;
|
|
||||||
SQUAD_MELEE_KILL?: IUploadEntry;
|
|
||||||
MELEE_KILL_ITEM?: IUploadEntry;
|
|
||||||
SQUAD_MELEE_KILL_ITEM?: IUploadEntry;
|
|
||||||
DIE?: IUploadEntry;
|
|
||||||
DIE_ITEM?: IUploadEntry;
|
|
||||||
EXECUTE_ENEMY?: IUploadEntry;
|
|
||||||
EXECUTE_ENEMY_ITEM?: IUploadEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IUploadEntry {
|
|
||||||
[key: string]: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IStatsMax {
|
|
||||||
WEAPON_XP?: IUploadEntry;
|
|
||||||
MISSION_SCORE?: IUploadEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IStatsSet {
|
|
||||||
ELO_RATING?: number;
|
|
||||||
RANK?: number;
|
|
||||||
PLAYER_LEVEL?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IStatsTimers {
|
|
||||||
IN_SHIP_TIME?: number;
|
|
||||||
IN_SHIP_VIEW_TIME?: IUploadEntry;
|
|
||||||
EQUIP_WEAPON?: IUploadEntry;
|
|
||||||
MISSION_TIME?: IUploadEntry;
|
|
||||||
REGION_TIME?: IUploadEntry;
|
|
||||||
PLATFORM_TIME?: IUploadEntry;
|
|
||||||
CURRENT_MISSION_TIME?: number;
|
|
||||||
CIPHER_TIME?: number;
|
|
||||||
}
|
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 28 KiB |
@ -73,7 +73,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="w-100">
|
<div class="w-100">
|
||||||
<div data-route="/webui/" data-title="Login | OpenWF WebUI">
|
<div data-route="/webui/" data-title="Login | OpenWF WebUI">
|
||||||
<p>Login using your OpenWF account credentials (same as in-game when connecting to this server).</p>
|
<p>Login using your OpenWF account credentials.</p>
|
||||||
<form onsubmit="doLogin();return false;">
|
<form onsubmit="doLogin();return false;">
|
||||||
<label for="email">Email address</label>
|
<label for="email">Email address</label>
|
||||||
<input class="form-control" type="email" id="email" required />
|
<input class="form-control" type="email" id="email" required />
|
||||||
@ -368,7 +368,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div data-route="/webui/cheats, /webui/settings" data-title="Cheats | OpenWF WebUI">
|
<div data-route="/webui/cheats, /webui/settings" data-title="Cheats | OpenWF WebUI">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
<div class="col-md-6">
|
<div class="col-lg-4">
|
||||||
<div class="card mb-3">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Server</h5>
|
<h5 class="card-header">Server</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -479,7 +479,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-lg-4">
|
||||||
<div class="card mb-3">
|
<div class="card mb-3">
|
||||||
<h5 class="card-header">Account</h5>
|
<h5 class="card-header">Account</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -488,6 +488,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="card mb-3">
|
||||||
|
<h5 class="card-header">Client</h5>
|
||||||
|
<div id="client-cheats-nok" class="card-body">
|
||||||
|
Client cheats are currently unavailable. This could be because your client is not running or using a DLL without an HTTP interface.
|
||||||
|
</div>
|
||||||
|
<div id="client-cheats-ok" class="card-body d-none">
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="skip_mission_start_timer" />
|
||||||
|
<label class="form-check-label" for="skip_mission_start_timer">
|
||||||
|
Skip Mission Start Timer
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-group mt-3">
|
||||||
|
<label class="form-label" for="fov_override">FOV Override (0 to disable)</label>
|
||||||
|
<input id="fov_override" class="form-range" type="range" min="0" value="0" max="2260000" step="10000">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-route="/webui/import" data-title="Import | OpenWF WebUI">
|
<div data-route="/webui/import" data-title="Import | OpenWF WebUI">
|
||||||
|
@ -915,6 +915,34 @@ single.getRoute("/webui/cheats").on("beforeload", function () {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|
||||||
|
fetch("http://localhost:61558/ping", { mode: "no-cors" })
|
||||||
|
.then(() => {
|
||||||
|
$("#client-cheats-ok").removeClass("d-none");
|
||||||
|
$("#client-cheats-nok").addClass("d-none");
|
||||||
|
|
||||||
|
fetch("http://localhost:61558/skip_mission_start_timer")
|
||||||
|
.then(res => res.text())
|
||||||
|
.then(res => {
|
||||||
|
document.getElementById("skip_mission_start_timer").checked = res == "1";
|
||||||
|
});
|
||||||
|
document.getElementById("skip_mission_start_timer").onchange = function () {
|
||||||
|
fetch("http://localhost:61558/skip_mission_start_timer?" + this.checked);
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch("http://localhost:61558/fov_override")
|
||||||
|
.then(res => res.text())
|
||||||
|
.then(res => {
|
||||||
|
document.getElementById("fov_override").value = parseFloat(res) * 10000;
|
||||||
|
});
|
||||||
|
document.getElementById("fov_override").oninput = function () {
|
||||||
|
fetch("http://localhost:61558/fov_override?" + this.value);
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.catch(function () {
|
||||||
|
$("#client-cheats-nok").removeClass("d-none");
|
||||||
|
$("#client-cheats-ok").addClass("d-none");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function doUnlockAllFocusSchools() {
|
function doUnlockAllFocusSchools() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user