forked from OpenWF/SpaceNinjaServer
feat: clan polychrome research (#1177)
Reviewed-on: OpenWF/SpaceNinjaServer#1177
This commit is contained in:
parent
56a372ee6f
commit
ab11f67f0b
@ -4,6 +4,7 @@ import {
|
||||
getGuildVault,
|
||||
hasAccessToDojo,
|
||||
hasGuildPermission,
|
||||
removePigmentsFromGuildMembers,
|
||||
scaleRequiredCount
|
||||
} from "@/src/services/guildService";
|
||||
import { ExportDojoRecipes, IDojoResearch } from "warframe-public-export-plus";
|
||||
@ -28,8 +29,7 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
const inventory = await getInventory(accountId);
|
||||
const guild = await getGuildForRequestEx(req, inventory);
|
||||
const data = JSON.parse(String(req.body)) as TGuildTechRequest;
|
||||
const action = data.Action.split(",")[0];
|
||||
if (action == "Sync") {
|
||||
if (data.Action == "Sync") {
|
||||
let needSave = false;
|
||||
const techProjects: ITechProjectClient[] = [];
|
||||
if (guild.TechProjects) {
|
||||
@ -53,18 +53,18 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
await guild.save();
|
||||
}
|
||||
res.json({ TechProjects: techProjects });
|
||||
} else if (action == "Start") {
|
||||
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
|
||||
} else if (data.Action == "Start") {
|
||||
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Tech))) {
|
||||
res.status(400).send("-1").end();
|
||||
return;
|
||||
}
|
||||
const recipe = ExportDojoRecipes.research[data.RecipeType!];
|
||||
const recipe = ExportDojoRecipes.research[data.RecipeType];
|
||||
guild.TechProjects ??= [];
|
||||
if (!guild.TechProjects.find(x => x.ItemType == data.RecipeType)) {
|
||||
const techProject =
|
||||
guild.TechProjects[
|
||||
guild.TechProjects.push({
|
||||
ItemType: data.RecipeType!,
|
||||
ItemType: data.RecipeType,
|
||||
ReqCredits: config.noDojoResearchCosts ? 0 : scaleRequiredCount(recipe.price),
|
||||
ReqItems: recipe.ingredients.map(x => ({
|
||||
ItemType: x.ItemType,
|
||||
@ -76,16 +76,20 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
setTechLogState(guild, techProject.ItemType, 5);
|
||||
if (config.noDojoResearchCosts) {
|
||||
processFundedProject(guild, techProject, recipe);
|
||||
} else {
|
||||
if (data.RecipeType.substring(0, 39) == "/Lotus/Types/Items/Research/DojoColors/") {
|
||||
guild.ActiveDojoColorResearch = data.RecipeType;
|
||||
}
|
||||
}
|
||||
}
|
||||
await guild.save();
|
||||
res.end();
|
||||
} else if (action == "Contribute") {
|
||||
} else if (data.Action == "Contribute") {
|
||||
if (!hasAccessToDojo(inventory)) {
|
||||
res.status(400).send("-1").end();
|
||||
return;
|
||||
}
|
||||
const contributions = data as IGuildTechContributeFields;
|
||||
const contributions = data;
|
||||
const techProject = guild.TechProjects!.find(x => x.ItemType == contributions.RecipeType)!;
|
||||
|
||||
if (contributions.VaultCredits) {
|
||||
@ -136,8 +140,12 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
|
||||
if (techProject.ReqCredits == 0 && !techProject.ReqItems.find(x => x.ItemCount > 0)) {
|
||||
// This research is now fully funded.
|
||||
const recipe = ExportDojoRecipes.research[data.RecipeType!];
|
||||
const recipe = ExportDojoRecipes.research[data.RecipeType];
|
||||
processFundedProject(guild, techProject, recipe);
|
||||
if (data.RecipeType.substring(0, 39) == "/Lotus/Types/Items/Research/DojoColors/") {
|
||||
guild.ActiveDojoColorResearch = "";
|
||||
await removePigmentsFromGuildMembers(guild._id);
|
||||
}
|
||||
}
|
||||
|
||||
await guild.save();
|
||||
@ -146,12 +154,12 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
InventoryChanges: inventoryChanges,
|
||||
Vault: getGuildVault(guild)
|
||||
});
|
||||
} else if (action == "Buy") {
|
||||
} else if (data.Action.split(",")[0] == "Buy") {
|
||||
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
|
||||
res.status(400).send("-1").end();
|
||||
return;
|
||||
}
|
||||
const purchase = data as IGuildTechBuyFields;
|
||||
const purchase = data as IGuildTechBuyRequest;
|
||||
const quantity = parseInt(data.Action.split(",")[1]);
|
||||
const recipeChanges = [
|
||||
{
|
||||
@ -173,13 +181,12 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
Recipes: recipeChanges
|
||||
}
|
||||
});
|
||||
} else if (action == "Fabricate") {
|
||||
} else if (data.Action == "Fabricate") {
|
||||
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Fabricator))) {
|
||||
res.status(400).send("-1").end();
|
||||
return;
|
||||
}
|
||||
const payload = data as IGuildTechFabricateRequest;
|
||||
const recipe = ExportDojoRecipes.fabrications[payload.RecipeType];
|
||||
const recipe = ExportDojoRecipes.fabrications[data.RecipeType];
|
||||
const inventoryChanges: IInventoryChanges = updateCurrency(inventory, recipe.price, false);
|
||||
inventoryChanges.MiscItems = recipe.ingredients.map(x => ({
|
||||
ItemType: x.ItemType,
|
||||
@ -190,6 +197,31 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
||||
await inventory.save();
|
||||
// Not a mistake: This response uses `inventoryChanges` instead of `InventoryChanges`.
|
||||
res.json({ inventoryChanges: inventoryChanges });
|
||||
} else if (data.Action == "Pause") {
|
||||
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Tech))) {
|
||||
res.status(400).send("-1").end();
|
||||
return;
|
||||
}
|
||||
const project = guild.TechProjects!.find(x => x.ItemType == data.RecipeType)!;
|
||||
project.State = -2;
|
||||
guild.ActiveDojoColorResearch = "";
|
||||
await guild.save();
|
||||
await removePigmentsFromGuildMembers(guild._id);
|
||||
res.end();
|
||||
} else if (data.Action == "Unpause") {
|
||||
if (!hasAccessToDojo(inventory) || !(await hasGuildPermission(guild, accountId, GuildPermission.Tech))) {
|
||||
res.status(400).send("-1").end();
|
||||
return;
|
||||
}
|
||||
const project = guild.TechProjects!.find(x => x.ItemType == data.RecipeType)!;
|
||||
project.State = 0;
|
||||
guild.ActiveDojoColorResearch = data.RecipeType;
|
||||
const entry = guild.TechChanges?.find(x => x.details == data.RecipeType);
|
||||
if (entry) {
|
||||
entry.dateTime = new Date();
|
||||
}
|
||||
await guild.save();
|
||||
res.end();
|
||||
} else {
|
||||
throw new Error(`unknown guildTech action: ${data.Action}`);
|
||||
}
|
||||
@ -233,20 +265,24 @@ const setTechLogState = (
|
||||
};
|
||||
|
||||
type TGuildTechRequest =
|
||||
| ({
|
||||
Action: string;
|
||||
} & Partial<IGuildTechStartFields> &
|
||||
Partial<IGuildTechContributeFields>)
|
||||
| IGuildTechFabricateRequest;
|
||||
| { Action: "Sync" | "SomethingElseThatWeMightNotKnowAbout" }
|
||||
| IGuildTechBasicRequest
|
||||
| IGuildTechContributeRequest;
|
||||
|
||||
interface IGuildTechStartFields {
|
||||
interface IGuildTechBasicRequest {
|
||||
Action: "Start" | "Fabricate" | "Pause" | "Unpause";
|
||||
Mode: "Guild";
|
||||
RecipeType: string;
|
||||
}
|
||||
|
||||
type IGuildTechBuyFields = IGuildTechStartFields;
|
||||
interface IGuildTechBuyRequest {
|
||||
Action: string;
|
||||
Mode: "Guild";
|
||||
RecipeType: string;
|
||||
}
|
||||
|
||||
interface IGuildTechContributeFields {
|
||||
interface IGuildTechContributeRequest {
|
||||
Action: "Contribute";
|
||||
ResearchId: "";
|
||||
RecipeType: string;
|
||||
RegularCredits: number;
|
||||
@ -254,9 +290,3 @@ interface IGuildTechContributeFields {
|
||||
VaultCredits: number;
|
||||
VaultMiscItems: IMiscItem[];
|
||||
}
|
||||
|
||||
interface IGuildTechFabricateRequest {
|
||||
Action: "Fabricate";
|
||||
Mode: "Guild";
|
||||
RecipeType: string;
|
||||
}
|
||||
|
@ -152,6 +152,7 @@ const guildSchema = new Schema<IGuildDatabase>(
|
||||
VaultShipDecorations: { type: [typeCountSchema], default: undefined },
|
||||
VaultFusionTreasures: { type: [fusionTreasuresSchema], default: undefined },
|
||||
TechProjects: { type: [techProjectSchema], default: undefined },
|
||||
ActiveDojoColorResearch: { type: String, default: "" },
|
||||
Class: { type: Number, default: 0 },
|
||||
XP: { type: Number, default: 0 },
|
||||
ClaimedXP: { type: [String], default: undefined },
|
||||
|
@ -93,6 +93,7 @@ export const getGuildClient = async (guild: TGuildDatabaseDocument, accountId: s
|
||||
TradeTax: guild.TradeTax,
|
||||
Tier: 1,
|
||||
Vault: getGuildVault(guild),
|
||||
ActiveDojoColorResearch: guild.ActiveDojoColorResearch,
|
||||
Class: guild.Class,
|
||||
XP: guild.XP,
|
||||
IsContributor: !!guild.CeremonyContributors?.find(x => x.equals(accountId)),
|
||||
@ -350,3 +351,17 @@ export const hasGuildPermissionEx = (
|
||||
const rank = guild.Ranks[member.rank];
|
||||
return (rank.Permissions & perm) != 0;
|
||||
};
|
||||
|
||||
export const removePigmentsFromGuildMembers = async (guildId: string | Types.ObjectId): Promise<void> => {
|
||||
const members = await GuildMember.find({ guildId, status: 0 }, "accountId");
|
||||
for (const member of members) {
|
||||
const inventory = await getInventory(member.accountId.toString(), "MiscItems");
|
||||
const index = inventory.MiscItems.findIndex(
|
||||
x => x.ItemType == "/Lotus/Types/Items/Research/DojoColors/GenericDojoColorPigment"
|
||||
);
|
||||
if (index != -1) {
|
||||
inventory.MiscItems.splice(index, 1);
|
||||
await inventory.save();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ export interface IGuildClient {
|
||||
TradeTax: number;
|
||||
Tier: number;
|
||||
Vault: IGuildVault;
|
||||
ActiveDojoColorResearch: string;
|
||||
Class: number;
|
||||
XP: number;
|
||||
IsContributor: boolean;
|
||||
@ -38,6 +39,7 @@ export interface IGuildDatabase {
|
||||
VaultFusionTreasures?: IFusionTreasure[];
|
||||
|
||||
TechProjects?: ITechProjectDatabase[];
|
||||
ActiveDojoColorResearch: string;
|
||||
|
||||
Class: number;
|
||||
XP: number;
|
||||
|
Loading…
x
Reference in New Issue
Block a user