Compare commits
9 Commits
3e80d96b39
...
7aaa81277f
Author | SHA1 | Date | |
---|---|---|---|
7aaa81277f | |||
653091bbae | |||
8659928dca | |||
054abee62c | |||
04d39ed973 | |||
b0f0b61d49 | |||
23f8901505 | |||
d3d966a503 | |||
48598c145f |
20
src/controllers/api/cancelGuildAdvertisementController.ts
Normal file
20
src/controllers/api/cancelGuildAdvertisementController.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { GuildAd } from "@/src/models/guildModel";
|
||||
import { getGuildForRequestEx, hasGuildPermission } from "@/src/services/guildService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { GuildPermission } from "@/src/types/guildTypes";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const cancelGuildAdvertisementController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId, "GuildId");
|
||||
const guild = await getGuildForRequestEx(req, inventory);
|
||||
if (!(await hasGuildPermission(guild, accountId, GuildPermission.Advertiser))) {
|
||||
res.status(400).end();
|
||||
return;
|
||||
}
|
||||
|
||||
await GuildAd.deleteOne({ GuildId: guild._id });
|
||||
|
||||
res.end();
|
||||
};
|
@ -99,6 +99,11 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
|
||||
inventory.SpectreLoadouts.push(inventory.PendingSpectreLoadouts[pendingLoadoutIndex]);
|
||||
inventory.PendingSpectreLoadouts.splice(pendingLoadoutIndex, 1);
|
||||
}
|
||||
} else if (recipe.secretIngredientAction == "SIA_UNBRAND") {
|
||||
inventory.BrandedSuits!.splice(
|
||||
inventory.BrandedSuits!.findIndex(x => x.equals(pendingRecipe.SuitToUnbrand)),
|
||||
1
|
||||
);
|
||||
}
|
||||
|
||||
let InventoryChanges = {};
|
||||
@ -111,15 +116,23 @@ export const claimCompletedRecipeController: RequestHandler = async (req, res) =
|
||||
]);
|
||||
}
|
||||
if (req.query.rush) {
|
||||
const end = Math.trunc(pendingRecipe.CompletionDate.getTime() / 1000);
|
||||
const start = end - recipe.buildTime;
|
||||
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)));
|
||||
InventoryChanges = {
|
||||
...InventoryChanges,
|
||||
...updateCurrency(inventory, recipe.skipBuildTimePrice, true)
|
||||
...updateCurrency(inventory, cost, true)
|
||||
};
|
||||
}
|
||||
if (recipe.secretIngredientAction != "SIA_UNBRAND") {
|
||||
InventoryChanges = {
|
||||
...InventoryChanges,
|
||||
...(await addItem(inventory, recipe.resultType, recipe.num, false))
|
||||
};
|
||||
}
|
||||
InventoryChanges = {
|
||||
...InventoryChanges,
|
||||
...(await addItem(inventory, recipe.resultType, recipe.num, false))
|
||||
};
|
||||
await inventory.save();
|
||||
res.json({ InventoryChanges });
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
|
||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import {
|
||||
addGuildMemberMiscItemContribution,
|
||||
getDojoClient,
|
||||
getGuildForRequestEx,
|
||||
hasAccessToDojo,
|
||||
@ -141,8 +142,7 @@ const processContribution = (
|
||||
ItemCount: ingredientContribution.ItemCount * -1
|
||||
});
|
||||
|
||||
guildMember.MiscItemsContributed ??= [];
|
||||
guildMember.MiscItemsContributed.push(ingredientContribution);
|
||||
addGuildMemberMiscItemContribution(guildMember, ingredientContribution);
|
||||
}
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
inventoryChanges.MiscItems = miscItemChanges;
|
||||
|
@ -1,4 +1,9 @@
|
||||
import { GuildMember } from "@/src/models/guildModel";
|
||||
import {
|
||||
addGuildMemberMiscItemContribution,
|
||||
addVaultMiscItems,
|
||||
getGuildForRequestEx
|
||||
} from "@/src/services/guildService";
|
||||
import { addVaultMiscItems, getGuildForRequestEx } from "@/src/services/guildService";
|
||||
import {
|
||||
addFusionTreasures,
|
||||
@ -33,14 +38,8 @@ export const contributeToVaultController: RequestHandler = async (req, res) => {
|
||||
if (request.MiscItems.length) {
|
||||
addVaultMiscItems(guild, request.MiscItems);
|
||||
|
||||
guildMember.MiscItemsContributed ??= [];
|
||||
for (const item of request.MiscItems) {
|
||||
const miscItemContribution = guildMember.MiscItemsContributed.find(x => x.ItemType == item.ItemType);
|
||||
if (miscItemContribution) {
|
||||
miscItemContribution.ItemCount += item.ItemCount;
|
||||
} else {
|
||||
guildMember.MiscItemsContributed.push(item);
|
||||
}
|
||||
addGuildMemberMiscItemContribution(guildMember, item);
|
||||
|
||||
addMiscItems(inventory, [{ ...item, ItemCount: item.ItemCount * -1 }]);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ export const evolveWeaponController: RequestHandler = async (req, res) => {
|
||||
recipe.ingredients.map(x => ({ ItemType: x.ItemType, ItemCount: x.ItemCount * -1 }))
|
||||
);
|
||||
|
||||
const item = inventory[payload.Category].find(item => item._id.toString() == (req.query.ItemId as string))!;
|
||||
const item = inventory[payload.Category].id(req.query.ItemId as string)!;
|
||||
item.Features ??= 0;
|
||||
item.Features |= EquipmentFeatures.INCARNON_GENESIS;
|
||||
|
||||
@ -39,7 +39,7 @@ export const evolveWeaponController: RequestHandler = async (req, res) => {
|
||||
}
|
||||
]);
|
||||
|
||||
const item = inventory[payload.Category].find(item => item._id.toString() == (req.query.ItemId as string))!;
|
||||
const item = inventory[payload.Category].id(req.query.ItemId as string)!;
|
||||
item.Features! &= ~EquipmentFeatures.INCARNON_GENESIS;
|
||||
} else {
|
||||
throw new Error(`unexpected evolve weapon action: ${payload.Action}`);
|
||||
|
@ -18,17 +18,15 @@ export const focusController: RequestHandler = async (req, res) => {
|
||||
case FocusOperation.InstallLens: {
|
||||
const request = JSON.parse(String(req.body)) as ILensInstallRequest;
|
||||
const inventory = await getInventory(accountId);
|
||||
for (const item of inventory[request.Category]) {
|
||||
if (item._id.toString() == request.WeaponId) {
|
||||
item.FocusLens = request.LensType;
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: request.LensType,
|
||||
ItemCount: -1
|
||||
} satisfies IMiscItem
|
||||
]);
|
||||
break;
|
||||
}
|
||||
const item = inventory[request.Category].id(request.WeaponId);
|
||||
if (item) {
|
||||
item.FocusLens = request.LensType;
|
||||
addMiscItems(inventory, [
|
||||
{
|
||||
ItemType: request.LensType,
|
||||
ItemCount: -1
|
||||
} satisfies IMiscItem
|
||||
]);
|
||||
}
|
||||
await inventory.save();
|
||||
res.json({
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { RequestHandler } from "express";
|
||||
import {
|
||||
addGuildMemberMiscItemContribution,
|
||||
getGuildForRequestEx,
|
||||
getGuildVault,
|
||||
hasAccessToDojo,
|
||||
@ -146,8 +147,7 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
ItemCount: miscItem.ItemCount * -1
|
||||
});
|
||||
|
||||
guildMember.MiscItemsContributed ??= [];
|
||||
guildMember.MiscItemsContributed.push(miscItem);
|
||||
addGuildMemberMiscItemContribution(guildMember, miscItem);
|
||||
}
|
||||
}
|
||||
addMiscItems(inventory, miscItemChanges);
|
||||
|
@ -28,7 +28,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
// shard installation
|
||||
const request = getJSONfromString<IShardInstallRequest>(String(req.body));
|
||||
const inventory = await getInventory(accountId);
|
||||
const suit = inventory.Suits.find(suit => suit._id.toString() == request.SuitId.$oid)!;
|
||||
const suit = inventory.Suits.id(request.SuitId.$oid)!;
|
||||
if (!suit.ArchonCrystalUpgrades || suit.ArchonCrystalUpgrades.length != 5) {
|
||||
suit.ArchonCrystalUpgrades = [{}, {}, {}, {}, {}];
|
||||
}
|
||||
@ -56,7 +56,7 @@ export const infestedFoundryController: RequestHandler = async (req, res) => {
|
||||
// shard removal
|
||||
const request = getJSONfromString<IShardUninstallRequest>(String(req.body));
|
||||
const inventory = await getInventory(accountId);
|
||||
const suit = inventory.Suits.find(suit => suit._id.toString() == request.SuitId.$oid)!;
|
||||
const suit = inventory.Suits.id(request.SuitId.$oid)!;
|
||||
|
||||
const miscItemChanges: IMiscItem[] = [];
|
||||
if (suit.ArchonCrystalUpgrades![request.Slot].Color) {
|
||||
|
@ -12,9 +12,7 @@ export const nameWeaponController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const body = getJSONfromString<INameWeaponRequest>(String(req.body));
|
||||
const item = inventory[req.query.Category as string as TEquipmentKey].find(
|
||||
item => item._id.toString() == (req.query.ItemId as string)
|
||||
)!;
|
||||
const item = inventory[req.query.Category as string as TEquipmentKey].id(req.query.ItemId as string)!;
|
||||
if (body.ItemName != "") {
|
||||
item.ItemName = body.ItemName;
|
||||
} else {
|
||||
|
75
src/controllers/api/postGuildAdvertisementController.ts
Normal file
75
src/controllers/api/postGuildAdvertisementController.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { getJSONfromString } from "@/src/helpers/stringHelpers";
|
||||
import { GuildAd, GuildMember } from "@/src/models/guildModel";
|
||||
import {
|
||||
addGuildMemberMiscItemContribution,
|
||||
addVaultMiscItems,
|
||||
getGuildForRequestEx,
|
||||
getVaultMiscItemCount,
|
||||
hasGuildPermissionEx
|
||||
} from "@/src/services/guildService";
|
||||
import { getInventory } from "@/src/services/inventoryService";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { getVendorManifestByTypeName, preprocessVendorManifest } from "@/src/services/serversideVendorsService";
|
||||
import { GuildPermission } from "@/src/types/guildTypes";
|
||||
import { IPurchaseParams } from "@/src/types/purchaseTypes";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const postGuildAdvertisementController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId, "GuildId MiscItems");
|
||||
const guild = await getGuildForRequestEx(req, inventory);
|
||||
const guildMember = (await GuildMember.findOne({ accountId, guildId: guild._id }))!;
|
||||
if (!hasGuildPermissionEx(guild, guildMember, GuildPermission.Advertiser)) {
|
||||
res.status(400).end();
|
||||
return;
|
||||
}
|
||||
const payload = getJSONfromString<IPostGuildAdvertisementRequest>(String(req.body));
|
||||
|
||||
// Handle resource cost
|
||||
const vendor = preprocessVendorManifest(
|
||||
getVendorManifestByTypeName("/Lotus/Types/Game/VendorManifests/Hubs/GuildAdvertisementVendorManifest")!
|
||||
);
|
||||
const offer = vendor.VendorInfo.ItemManifest.find(x => x.StoreItem == payload.PurchaseParams.StoreItem)!;
|
||||
if (getVaultMiscItemCount(guild, offer.ItemPrices![0].ItemType) >= offer.ItemPrices![0].ItemCount) {
|
||||
addVaultMiscItems(guild, [
|
||||
{
|
||||
ItemType: offer.ItemPrices![0].ItemType,
|
||||
ItemCount: offer.ItemPrices![0].ItemCount * -1
|
||||
}
|
||||
]);
|
||||
} else {
|
||||
const miscItem = inventory.MiscItems.find(x => x.ItemType == offer.ItemPrices![0].ItemType);
|
||||
if (!miscItem || miscItem.ItemCount < offer.ItemPrices![0].ItemCount) {
|
||||
res.status(400).json("Insufficient funds");
|
||||
return;
|
||||
}
|
||||
miscItem.ItemCount -= offer.ItemPrices![0].ItemCount;
|
||||
addGuildMemberMiscItemContribution(guildMember, offer.ItemPrices![0]);
|
||||
await guildMember.save();
|
||||
await inventory.save();
|
||||
}
|
||||
|
||||
// Create or update ad
|
||||
await GuildAd.findOneAndUpdate(
|
||||
{ GuildId: guild._id },
|
||||
{
|
||||
Emblem: guild.Emblem,
|
||||
Expiry: new Date(Date.now() + 12 * 3600 * 1000),
|
||||
Features: payload.Features,
|
||||
GuildName: guild.Name,
|
||||
MemberCount: await GuildMember.countDocuments({ guildId: guild._id, status: 0 }),
|
||||
RecruitMsg: payload.RecruitMsg,
|
||||
Tier: guild.Tier
|
||||
},
|
||||
{ upsert: true }
|
||||
);
|
||||
|
||||
res.end();
|
||||
};
|
||||
|
||||
interface IPostGuildAdvertisementRequest {
|
||||
Features: number;
|
||||
RecruitMsg: string;
|
||||
Languages: string[];
|
||||
PurchaseParams: IPurchaseParams;
|
||||
}
|
@ -13,7 +13,42 @@ import { InventorySlot } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||
export const sellController: RequestHandler = async (req, res) => {
|
||||
const payload = JSON.parse(String(req.body)) as ISellRequest;
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const requiredFields = new Set();
|
||||
if (payload.SellCurrency == "SC_RegularCredits") {
|
||||
requiredFields.add("RegularCredits");
|
||||
} else if (payload.SellCurrency == "SC_FusionPoints") {
|
||||
requiredFields.add("FusionPoints");
|
||||
} else {
|
||||
requiredFields.add("MiscItems");
|
||||
}
|
||||
for (const key of Object.keys(payload.Items)) {
|
||||
requiredFields.add(key);
|
||||
}
|
||||
if (requiredFields.has("Upgrades")) {
|
||||
requiredFields.add("RawUpgrades");
|
||||
}
|
||||
if (payload.Items.Suits) {
|
||||
requiredFields.add(InventorySlot.SUITS);
|
||||
}
|
||||
if (payload.Items.LongGuns || payload.Items.Pistols || payload.Items.Melee) {
|
||||
requiredFields.add(InventorySlot.WEAPONS);
|
||||
}
|
||||
if (payload.Items.SpaceSuits) {
|
||||
requiredFields.add(InventorySlot.SPACESUITS);
|
||||
}
|
||||
if (payload.Items.SpaceGuns || payload.Items.SpaceMelee) {
|
||||
requiredFields.add(InventorySlot.SPACEWEAPONS);
|
||||
}
|
||||
if (payload.Items.Sentinels || payload.Items.SentinelWeapons) {
|
||||
requiredFields.add(InventorySlot.SENTINELS);
|
||||
}
|
||||
if (payload.Items.OperatorAmps) {
|
||||
requiredFields.add(InventorySlot.AMPS);
|
||||
}
|
||||
if (payload.Items.Hoverboards) {
|
||||
requiredFields.add(InventorySlot.SPACESUITS);
|
||||
}
|
||||
const inventory = await getInventory(accountId, Array.from(requiredFields).join(" "));
|
||||
|
||||
// Give currency
|
||||
if (payload.SellCurrency == "SC_RegularCredits") {
|
||||
|
@ -6,12 +6,10 @@ import { WeaponTypeInternal } from "@/src/services/itemDataService";
|
||||
|
||||
export const setWeaponSkillTreeController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const inventory = await getInventory(accountId, req.query.Category as string);
|
||||
const payload = getJSONfromString<ISetWeaponSkillTreeRequest>(String(req.body));
|
||||
|
||||
const item = inventory[req.query.Category as WeaponTypeInternal].find(
|
||||
item => item._id.toString() == (req.query.ItemId as string)
|
||||
)!;
|
||||
const item = inventory[req.query.Category as WeaponTypeInternal].id(req.query.ItemId as string)!;
|
||||
item.SkillTree = payload.SkillTree;
|
||||
|
||||
await inventory.save();
|
||||
|
@ -111,6 +111,8 @@ export const startRecipeController: RequestHandler = async (req, res) => {
|
||||
inventory.PendingSpectreLoadouts.push(spectreLoadout);
|
||||
logger.debug("pending spectre loadout", spectreLoadout);
|
||||
}
|
||||
} else if (recipe.secretIngredientAction == "SIA_UNBRAND") {
|
||||
pr.SuitToUnbrand = new Types.ObjectId(startRecipeRequest.Ids[recipe.ingredients.length + 0]);
|
||||
}
|
||||
|
||||
await inventory.save();
|
||||
|
@ -5,7 +5,7 @@ import { getInventory } from "@/src/services/inventoryService";
|
||||
export const popArchonCrystalUpgradeController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const suit = inventory.Suits.find(suit => suit._id.toString() == (req.query.oid as string));
|
||||
const suit = inventory.Suits.id(req.query.oid as string);
|
||||
if (suit && suit.ArchonCrystalUpgrades) {
|
||||
suit.ArchonCrystalUpgrades = suit.ArchonCrystalUpgrades.filter(
|
||||
x => x.UpgradeType != (req.query.type as string)
|
||||
|
@ -5,7 +5,7 @@ import { getInventory } from "@/src/services/inventoryService";
|
||||
export const pushArchonCrystalUpgradeController: RequestHandler = async (req, res) => {
|
||||
const accountId = await getAccountIdForRequest(req);
|
||||
const inventory = await getInventory(accountId);
|
||||
const suit = inventory.Suits.find(suit => suit._id.toString() == (req.query.oid as string));
|
||||
const suit = inventory.Suits.id(req.query.oid as string);
|
||||
if (suit) {
|
||||
suit.ArchonCrystalUpgrades ??= [];
|
||||
const count = (req.query.count as number | undefined) ?? 1;
|
||||
|
26
src/controllers/dynamic/getGuildAdsController.ts
Normal file
26
src/controllers/dynamic/getGuildAdsController.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
|
||||
import { GuildAd } from "@/src/models/guildModel";
|
||||
import { IGuildAdInfoClient } from "@/src/types/guildTypes";
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const getGuildAdsController: RequestHandler = async (req, res) => {
|
||||
const ads = await GuildAd.find(req.query.tier ? { Tier: req.query.tier } : {});
|
||||
const guildAdInfos: IGuildAdInfoClient[] = [];
|
||||
for (const ad of ads) {
|
||||
guildAdInfos.push({
|
||||
_id: toOid(ad.GuildId),
|
||||
CrossPlatformEnabled: true,
|
||||
Emblem: ad.Emblem,
|
||||
Expiry: toMongoDate(ad.Expiry),
|
||||
Features: ad.Features,
|
||||
GuildName: ad.GuildName,
|
||||
MemberCount: ad.MemberCount,
|
||||
OriginalPlatform: 0,
|
||||
RecruitMsg: ad.RecruitMsg,
|
||||
Tier: ad.Tier
|
||||
});
|
||||
}
|
||||
res.json({
|
||||
GuildAdInfos: guildAdInfos
|
||||
});
|
||||
};
|
@ -10,7 +10,8 @@ import {
|
||||
IGuildLogRoomChange,
|
||||
IGuildLogEntryRoster,
|
||||
IGuildLogEntryContributable,
|
||||
IDojoLeaderboardEntry
|
||||
IDojoLeaderboardEntry,
|
||||
IGuildAdDatabase
|
||||
} from "@/src/types/guildTypes";
|
||||
import { Document, Model, model, Schema, Types } from "mongoose";
|
||||
import { fusionTreasuresSchema, typeCountSchema } from "./inventoryModels/inventoryModel";
|
||||
@ -165,6 +166,7 @@ const guildSchema = new Schema<IGuildDatabase>(
|
||||
Ranks: { type: [guildRankSchema], default: defaultRanks },
|
||||
TradeTax: { type: Number, default: 0 },
|
||||
Tier: { type: Number, default: 1 },
|
||||
Emblem: { type: Boolean },
|
||||
DojoComponents: { type: [dojoComponentSchema], default: [] },
|
||||
DojoCapacity: { type: Number, default: 100 },
|
||||
DojoEnergy: { type: Number, default: 5 },
|
||||
@ -225,3 +227,19 @@ const guildMemberSchema = new Schema<IGuildMemberDatabase>({
|
||||
guildMemberSchema.index({ accountId: 1, guildId: 1 }, { unique: true });
|
||||
|
||||
export const GuildMember = model<IGuildMemberDatabase>("GuildMember", guildMemberSchema);
|
||||
|
||||
const guildAdSchema = new Schema<IGuildAdDatabase>({
|
||||
GuildId: { type: Schema.Types.ObjectId, required: true },
|
||||
Emblem: Boolean,
|
||||
Expiry: { type: Date, required: true },
|
||||
Features: { type: Number, required: true },
|
||||
GuildName: { type: String, required: true },
|
||||
MemberCount: { type: Number, required: true },
|
||||
RecruitMsg: { type: String, required: true },
|
||||
Tier: { type: Number, required: true }
|
||||
});
|
||||
|
||||
guildAdSchema.index({ GuildId: 1 }, { unique: true });
|
||||
guildAdSchema.index({ Expiry: 1 }, { expireAfterSeconds: 0 });
|
||||
|
||||
export const GuildAd = model<IGuildAdDatabase>("GuildAd", guildAdSchema);
|
||||
|
@ -903,7 +903,8 @@ const pendingRecipeSchema = new Schema<IPendingRecipeDatabase>(
|
||||
CompletionDate: Date,
|
||||
LongGuns: { type: [EquipmentSchema], default: undefined },
|
||||
Pistols: { type: [EquipmentSchema], default: undefined },
|
||||
Melee: { type: [EquipmentSchema], default: undefined }
|
||||
Melee: { type: [EquipmentSchema], default: undefined },
|
||||
SuitToUnbrand: { type: Schema.Types.ObjectId, default: undefined }
|
||||
},
|
||||
{ id: false }
|
||||
);
|
||||
@ -920,6 +921,7 @@ pendingRecipeSchema.set("toJSON", {
|
||||
delete returnedObject.LongGuns;
|
||||
delete returnedObject.Pistols;
|
||||
delete returnedObject.Melees;
|
||||
delete returnedObject.SuitToUnbrand;
|
||||
(returnedObject as IPendingRecipeClient).CompletionDate = {
|
||||
$date: { $numberLong: (returnedObject as IPendingRecipeDatabase).CompletionDate.getTime().toString() }
|
||||
};
|
||||
@ -1484,7 +1486,9 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
|
||||
EchoesHexConquestHardModeStatus: { type: Number, default: undefined },
|
||||
EchoesHexConquestCacheScoreMission: { type: Number, default: undefined },
|
||||
EchoesHexConquestActiveFrameVariants: { type: [String], default: undefined },
|
||||
EchoesHexConquestActiveStickers: { type: [String], default: undefined }
|
||||
EchoesHexConquestActiveStickers: { type: [String], default: undefined },
|
||||
|
||||
BrandedSuits: { type: [Schema.Types.ObjectId], default: undefined }
|
||||
},
|
||||
{ timestamps: { createdAt: "Created", updatedAt: false } }
|
||||
);
|
||||
@ -1516,6 +1520,9 @@ inventorySchema.set("toJSON", {
|
||||
if (inventoryDatabase.EntratiVaultCountResetDate) {
|
||||
inventoryResponse.EntratiVaultCountResetDate = toMongoDate(inventoryDatabase.EntratiVaultCountResetDate);
|
||||
}
|
||||
if (inventoryDatabase.BrandedSuits) {
|
||||
inventoryResponse.BrandedSuits = inventoryDatabase.BrandedSuits.map(toOid);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -9,6 +9,7 @@ import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonContro
|
||||
import { archonFusionController } from "@/src/controllers/api/archonFusionController";
|
||||
import { artifactsController } from "@/src/controllers/api/artifactsController";
|
||||
import { artifactTransmutationController } from "@/src/controllers/api/artifactTransmutationController";
|
||||
import { cancelGuildAdvertisementController } from "@/src/controllers/api/cancelGuildAdvertisementController";
|
||||
import { changeDojoRootController } from "@/src/controllers/api/changeDojoRootController";
|
||||
import { changeGuildRankController } from "@/src/controllers/api/changeGuildRankController";
|
||||
import { checkDailyMissionBonusController } from "@/src/controllers/api/checkDailyMissionBonusController";
|
||||
@ -80,6 +81,7 @@ import { nameWeaponController } from "@/src/controllers/api/nameWeaponController
|
||||
import { nemesisController } from "@/src/controllers/api/nemesisController";
|
||||
import { placeDecoInComponentController } from "@/src/controllers/api/placeDecoInComponentController";
|
||||
import { playerSkillsController } from "@/src/controllers/api/playerSkillsController";
|
||||
import { postGuildAdvertisementController } from "@/src/controllers/api/postGuildAdvertisementController";
|
||||
import { projectionManagerController } from "@/src/controllers/api/projectionManagerController";
|
||||
import { purchaseController } from "@/src/controllers/api/purchaseController";
|
||||
import { queueDojoComponentDestructionController } from "@/src/controllers/api/queueDojoComponentDestructionController";
|
||||
@ -131,6 +133,7 @@ const apiRouter = express.Router();
|
||||
// get
|
||||
apiRouter.get("/abandonLibraryDailyTask.php", abandonLibraryDailyTaskController);
|
||||
apiRouter.get("/abortDojoComponentDestruction.php", abortDojoComponentDestructionController);
|
||||
apiRouter.get("/cancelGuildAdvertisement.php", cancelGuildAdvertisementController);
|
||||
apiRouter.get("/changeGuildRank.php", changeGuildRankController);
|
||||
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
|
||||
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
|
||||
@ -228,6 +231,7 @@ apiRouter.post("/nameWeapon.php", nameWeaponController);
|
||||
apiRouter.post("/nemesis.php", nemesisController);
|
||||
apiRouter.post("/placeDecoInComponent.php", placeDecoInComponentController);
|
||||
apiRouter.post("/playerSkills.php", playerSkillsController);
|
||||
apiRouter.post("/postGuildAdvertisement.php", postGuildAdvertisementController);
|
||||
apiRouter.post("/projectionManager.php", projectionManagerController);
|
||||
apiRouter.post("/purchase.php", purchaseController);
|
||||
apiRouter.post("/redeemPromoCode.php", redeemPromoCodeController);
|
||||
|
@ -1,11 +1,13 @@
|
||||
import express from "express";
|
||||
import { aggregateSessionsController } from "@/src/controllers/dynamic/aggregateSessionsController";
|
||||
import { getGuildAdsController } from "@/src/controllers/dynamic/getGuildAdsController";
|
||||
import { getProfileViewingDataController } from "@/src/controllers/dynamic/getProfileViewingDataController";
|
||||
import { worldStateController } from "@/src/controllers/dynamic/worldStateController";
|
||||
|
||||
const dynamicController = express.Router();
|
||||
|
||||
dynamicController.get("/aggregateSessions.php", aggregateSessionsController);
|
||||
dynamicController.get("/getGuildAds.php", getGuildAdsController);
|
||||
dynamicController.get("/getProfileViewingData.php", getProfileViewingDataController);
|
||||
dynamicController.get("/worldState.php", worldStateController);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Request } from "express";
|
||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||
import { addRecipes, getInventory } from "@/src/services/inventoryService";
|
||||
import { Guild, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
|
||||
import { Guild, GuildAd, GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel";
|
||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import {
|
||||
GuildPermission,
|
||||
@ -298,6 +298,10 @@ const moveResourcesToVault = (guild: TGuildDatabaseDocument, component: IDojoCon
|
||||
}
|
||||
};
|
||||
|
||||
export const getVaultMiscItemCount = (guild: TGuildDatabaseDocument, itemType: string): number => {
|
||||
return guild.VaultMiscItems?.find(x => x.ItemType == itemType)?.ItemCount ?? 0;
|
||||
};
|
||||
|
||||
export const addVaultMiscItems = (guild: TGuildDatabaseDocument, miscItems: ITypeCount[]): void => {
|
||||
guild.VaultMiscItems ??= [];
|
||||
for (const miscItem of miscItems) {
|
||||
@ -310,6 +314,16 @@ export const addVaultMiscItems = (guild: TGuildDatabaseDocument, miscItems: ITyp
|
||||
}
|
||||
};
|
||||
|
||||
export const addGuildMemberMiscItemContribution = (guildMember: IGuildMemberDatabase, item: ITypeCount): void => {
|
||||
guildMember.MiscItemsContributed ??= [];
|
||||
const miscItemContribution = guildMember.MiscItemsContributed.find(x => x.ItemType == item.ItemType);
|
||||
if (miscItemContribution) {
|
||||
miscItemContribution.ItemCount += item.ItemCount;
|
||||
} else {
|
||||
guildMember.MiscItemsContributed.push(item);
|
||||
}
|
||||
};
|
||||
|
||||
export const processDojoBuildMaterialsGathered = (guild: TGuildDatabaseDocument, build: IDojoBuild): void => {
|
||||
if (build.guildXpValue) {
|
||||
guild.ClaimedXP ??= [];
|
||||
@ -513,4 +527,6 @@ export const deleteGuild = async (guildId: Types.ObjectId): Promise<void> => {
|
||||
contextInfo: guildId.toString(),
|
||||
acceptAction: "GUILD_INVITE"
|
||||
});
|
||||
|
||||
await GuildAd.deleteOne({ GuildId: guildId });
|
||||
};
|
||||
|
@ -24,7 +24,6 @@ import {
|
||||
ExportGear,
|
||||
ExportKeys,
|
||||
ExportRecipes,
|
||||
ExportRegions,
|
||||
ExportResources,
|
||||
ExportSentinels,
|
||||
ExportWarframes,
|
||||
@ -34,7 +33,6 @@ import {
|
||||
IMissionReward,
|
||||
IPowersuit,
|
||||
IRecipe,
|
||||
IRegion,
|
||||
TReward
|
||||
} from "warframe-public-export-plus";
|
||||
import questCompletionItems from "@/static/fixed_responses/questCompletionRewards.json";
|
||||
@ -192,16 +190,6 @@ export const getLevelKeyRewards = (
|
||||
};
|
||||
};
|
||||
|
||||
export const getNode = (nodeName: string): IRegion => {
|
||||
const node = ExportRegions[nodeName];
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!node) {
|
||||
throw new Error(`Node ${nodeName} not found`);
|
||||
}
|
||||
|
||||
return node;
|
||||
};
|
||||
|
||||
export const getQuestCompletionItems = (questKey: string): ITypeCount[] | undefined => {
|
||||
if (questKey in questCompletionItems) {
|
||||
return questCompletionItems[questKey as keyof typeof questCompletionItems];
|
||||
|
@ -4,6 +4,7 @@ import {
|
||||
ExportRegions,
|
||||
ExportRewards,
|
||||
IMissionReward as IMissionRewardExternal,
|
||||
IRegion,
|
||||
IReward
|
||||
} from "warframe-public-export-plus";
|
||||
import { IMissionInventoryUpdateRequest, IRewardInfo } from "../types/requestTypes";
|
||||
@ -30,9 +31,9 @@ import {
|
||||
updateSyndicate
|
||||
} from "@/src/services/inventoryService";
|
||||
import { updateQuestKey } from "@/src/services/questService";
|
||||
import { HydratedDocument } from "mongoose";
|
||||
import { HydratedDocument, Types } from "mongoose";
|
||||
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||
import { getLevelKeyRewards, getNode, toStoreItem } from "@/src/services/itemDataService";
|
||||
import { getLevelKeyRewards, toStoreItem } from "@/src/services/itemDataService";
|
||||
import { InventoryDocumentProps, TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||
import { getEntriesUnsafe } from "@/src/utils/ts-utils";
|
||||
import { IEquipmentClient } from "@/src/types/inventoryTypes/commonInventoryTypes";
|
||||
@ -45,6 +46,7 @@ import kuriaMessage75 from "@/static/fixed_responses/kuriaMessages/seventyFivePe
|
||||
import kuriaMessage100 from "@/static/fixed_responses/kuriaMessages/oneHundredPercent.json";
|
||||
import conservationAnimals from "@/static/fixed_responses/conservationAnimals.json";
|
||||
import { getInfNodes } from "@/src/helpers/nemesisHelpers";
|
||||
import { Loadout } from "../models/inventoryModels/loadoutModel";
|
||||
|
||||
const getRotations = (rotationCount: number): number[] => {
|
||||
if (rotationCount === 0) return [0];
|
||||
@ -89,6 +91,31 @@ export const addMissionInventoryUpdates = async (
|
||||
if (inventoryUpdates.RewardInfo && inventoryUpdates.RewardInfo.NemesisAbandonedRewards) {
|
||||
inventory.NemesisAbandonedRewards = inventoryUpdates.RewardInfo.NemesisAbandonedRewards;
|
||||
}
|
||||
if (
|
||||
inventoryUpdates.MissionFailed &&
|
||||
inventoryUpdates.MissionStatus == "GS_FAILURE" &&
|
||||
inventoryUpdates.EndOfMatchUpload &&
|
||||
inventoryUpdates.ObjectiveReached
|
||||
) {
|
||||
const loadout = (await Loadout.findById(inventory.LoadOutPresets, "NORMAL"))!;
|
||||
const config = loadout.NORMAL.id(inventory.CurrentLoadOutIds[0].$oid)!;
|
||||
const SuitId = new Types.ObjectId(config.s!.ItemId.$oid);
|
||||
|
||||
inventory.BrandedSuits ??= [];
|
||||
if (!inventory.BrandedSuits.find(x => x.equals(SuitId))) {
|
||||
inventory.BrandedSuits.push(SuitId);
|
||||
|
||||
await createMessage(inventory.accountOwnerId.toString(), [
|
||||
{
|
||||
sndr: "/Lotus/Language/Menu/Mailbox_WarframeSender",
|
||||
msg: "/Lotus/Language/G1Quests/BrandedMessage",
|
||||
sub: "/Lotus/Language/G1Quests/BrandedTitle",
|
||||
att: ["/Lotus/Types/Recipes/Components/BrandRemovalBlueprint"],
|
||||
highPriority: true // I cannot find any content of this within the last 10 years so I can only assume that highPriority is set (it certainly would make sense), but I just don't know for sure that it is so on live.
|
||||
}
|
||||
]);
|
||||
}
|
||||
}
|
||||
for (const [key, value] of getEntriesUnsafe(inventoryUpdates)) {
|
||||
if (value === undefined) {
|
||||
logger.error(`Inventory update key ${key} has no value `);
|
||||
@ -443,15 +470,15 @@ export const addMissionRewards = async (
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
missions &&
|
||||
missions.Tag != "" // https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1013
|
||||
) {
|
||||
const node = getNode(missions.Tag);
|
||||
// ignoring tags not in ExportRegions, because it can just be garbage:
|
||||
// - https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1013
|
||||
// - https://onlyg.it/OpenWF/SpaceNinjaServer/issues/1365
|
||||
if (missions && missions.Tag in ExportRegions) {
|
||||
const node = ExportRegions[missions.Tag];
|
||||
|
||||
//node based credit rewards for mission completion
|
||||
if (node.missionIndex !== 28) {
|
||||
const levelCreditReward = getLevelCreditRewards(missions.Tag);
|
||||
const levelCreditReward = getLevelCreditRewards(node);
|
||||
missionCompletionCredits += levelCreditReward;
|
||||
inventory.RegularCredits += levelCreditReward;
|
||||
logger.debug(`levelCreditReward ${levelCreditReward}`);
|
||||
@ -634,8 +661,8 @@ export const addFixedLevelRewards = (
|
||||
return missionBonusCredits;
|
||||
};
|
||||
|
||||
function getLevelCreditRewards(nodeName: string): number {
|
||||
const minEnemyLevel = getNode(nodeName).minEnemyLevel;
|
||||
function getLevelCreditRewards(node: IRegion): number {
|
||||
const minEnemyLevel = node.minEnemyLevel;
|
||||
|
||||
return 1000 + (minEnemyLevel - 1) * 100;
|
||||
|
||||
|
@ -84,9 +84,7 @@ export const handleInventoryItemConfigChange = async (
|
||||
continue;
|
||||
}
|
||||
|
||||
const oldLoadoutConfig = loadout[loadoutSlot].find(
|
||||
loadout => loadout._id.toString() === loadoutId
|
||||
);
|
||||
const oldLoadoutConfig = loadout[loadoutSlot].id(loadoutId);
|
||||
|
||||
const { ItemId, ...loadoutConfigItemIdRemoved } = loadoutConfig;
|
||||
const loadoutConfigDatabase: ILoadoutConfigDatabase = {
|
||||
|
@ -61,19 +61,17 @@ export const handleSetShipDecorations = async (
|
||||
if (placedDecoration.MoveId) {
|
||||
//moved within the same room
|
||||
if (placedDecoration.OldRoom === placedDecoration.Room) {
|
||||
const existingDecorationIndex = roomToPlaceIn.PlacedDecos.findIndex(
|
||||
deco => deco._id.toString() === placedDecoration.MoveId
|
||||
);
|
||||
const existingDecoration = roomToPlaceIn.PlacedDecos.id(placedDecoration.MoveId);
|
||||
|
||||
if (existingDecorationIndex === -1) {
|
||||
if (!existingDecoration) {
|
||||
throw new Error("decoration to be moved not found");
|
||||
}
|
||||
|
||||
roomToPlaceIn.PlacedDecos[existingDecorationIndex].Pos = placedDecoration.Pos;
|
||||
roomToPlaceIn.PlacedDecos[existingDecorationIndex].Rot = placedDecoration.Rot;
|
||||
existingDecoration.Pos = placedDecoration.Pos;
|
||||
existingDecoration.Rot = placedDecoration.Rot;
|
||||
|
||||
if (placedDecoration.Scale) {
|
||||
roomToPlaceIn.PlacedDecos[existingDecorationIndex].Scale = placedDecoration.Scale;
|
||||
existingDecoration.Scale = placedDecoration.Scale;
|
||||
}
|
||||
|
||||
await personalRooms.save();
|
||||
|
@ -28,6 +28,7 @@ export interface IGuildDatabase {
|
||||
Ranks: IGuildRank[];
|
||||
TradeTax: number;
|
||||
Tier: number;
|
||||
Emblem?: boolean;
|
||||
|
||||
DojoComponents: IDojoComponentDatabase[];
|
||||
DojoCapacity: number;
|
||||
@ -223,3 +224,27 @@ export interface IDojoLeaderboardEntry {
|
||||
r: number; // rank
|
||||
n: string; // displayName
|
||||
}
|
||||
|
||||
export interface IGuildAdInfoClient {
|
||||
_id: IOid; // Guild ID
|
||||
CrossPlatformEnabled: boolean;
|
||||
Emblem?: boolean;
|
||||
Expiry: IMongoDate;
|
||||
Features: number;
|
||||
GuildName: string;
|
||||
MemberCount: number;
|
||||
OriginalPlatform: number;
|
||||
RecruitMsg: string;
|
||||
Tier: number;
|
||||
}
|
||||
|
||||
export interface IGuildAdDatabase {
|
||||
GuildId: Types.ObjectId;
|
||||
Emblem?: boolean;
|
||||
Expiry: Date;
|
||||
Features: number;
|
||||
GuildName: string;
|
||||
MemberCount: number;
|
||||
RecruitMsg: string;
|
||||
Tier: number;
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ export interface IInventoryDatabase
|
||||
| "NextRefill"
|
||||
| "Nemesis"
|
||||
| "EntratiVaultCountResetDate"
|
||||
| "BrandedSuits"
|
||||
| TEquipmentKey
|
||||
>,
|
||||
InventoryDatabaseEquipment {
|
||||
@ -73,6 +74,7 @@ export interface IInventoryDatabase
|
||||
NextRefill?: Date;
|
||||
Nemesis?: INemesisDatabase;
|
||||
EntratiVaultCountResetDate?: Date;
|
||||
BrandedSuits?: Types.ObjectId[];
|
||||
}
|
||||
|
||||
export interface IQuestKeyDatabase {
|
||||
@ -346,6 +348,7 @@ export interface IInventoryClient extends IDailyAffiliations, InventoryClientEqu
|
||||
EchoesHexConquestCacheScoreMission?: number;
|
||||
EchoesHexConquestActiveFrameVariants?: string[];
|
||||
EchoesHexConquestActiveStickers?: string[];
|
||||
BrandedSuits?: IOid[];
|
||||
}
|
||||
|
||||
export interface IAffiliation {
|
||||
@ -857,10 +860,11 @@ export interface IPendingRecipeDatabase {
|
||||
LongGuns?: IEquipmentDatabase[];
|
||||
Pistols?: IEquipmentDatabase[];
|
||||
Melee?: IEquipmentDatabase[];
|
||||
SuitToUnbrand?: Types.ObjectId;
|
||||
}
|
||||
|
||||
export interface IPendingRecipeClient
|
||||
extends Omit<IPendingRecipeDatabase, "CompletionDate" | "LongGuns" | "Pistols" | "Melee"> {
|
||||
extends Omit<IPendingRecipeDatabase, "CompletionDate" | "LongGuns" | "Pistols" | "Melee" | "SuitToUnbrand"> {
|
||||
CompletionDate: IMongoDate;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user