consider that research may be completed by lowering tier
All checks were successful
Build / build (18) (push) Successful in 1m18s
Build / build (22) (push) Successful in 1m21s
Build / build (22) (pull_request) Successful in 1m22s
Build / build (20) (push) Successful in 44s
Build / build (18) (pull_request) Successful in 45s
Build / build (20) (pull_request) Successful in 1m14s

This commit is contained in:
Sainan 2025-03-30 13:23:41 +02:00
parent fec842f4f9
commit a7f252468a
3 changed files with 82 additions and 64 deletions

View File

@ -32,7 +32,7 @@ export const abortDojoComponentController: RequestHandler = async (req, res) =>
if (request.DecoId) { if (request.DecoId) {
removeDojoDeco(guild, request.ComponentId, request.DecoId); removeDojoDeco(guild, request.ComponentId, request.DecoId);
} else { } else {
removeDojoRoom(guild, request.ComponentId); await removeDojoRoom(guild, request.ComponentId);
} }
await guild.save(); await guild.save();

View File

@ -4,10 +4,13 @@ import {
getGuildVault, getGuildVault,
hasAccessToDojo, hasAccessToDojo,
hasGuildPermission, hasGuildPermission,
processFundedGuildTechProject,
processGuildTechProjectContributionsUpdate,
removePigmentsFromGuildMembers, removePigmentsFromGuildMembers,
scaleRequiredCount scaleRequiredCount,
setGuildTechLogState
} from "@/src/services/guildService"; } from "@/src/services/guildService";
import { ExportDojoRecipes, IDojoResearch } from "warframe-public-export-plus"; import { ExportDojoRecipes } from "warframe-public-export-plus";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { import {
addItem, addItem,
@ -20,8 +23,8 @@ import {
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes"; import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
import { IInventoryChanges } from "@/src/types/purchaseTypes"; import { IInventoryChanges } from "@/src/types/purchaseTypes";
import { config } from "@/src/services/configService"; import { config } from "@/src/services/configService";
import { GuildPermission, ITechProjectClient, ITechProjectDatabase } from "@/src/types/guildTypes"; import { GuildPermission, ITechProjectClient } from "@/src/types/guildTypes";
import { GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel"; import { GuildMember } from "@/src/models/guildModel";
import { toMongoDate } from "@/src/helpers/inventoryHelpers"; import { toMongoDate } from "@/src/helpers/inventoryHelpers";
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
@ -44,7 +47,7 @@ export const guildTechController: RequestHandler = async (req, res) => {
if (project.CompletionDate) { if (project.CompletionDate) {
techProject.CompletionDate = toMongoDate(project.CompletionDate); techProject.CompletionDate = toMongoDate(project.CompletionDate);
if (Date.now() >= project.CompletionDate.getTime()) { if (Date.now() >= project.CompletionDate.getTime()) {
needSave ||= setTechLogState(guild, project.ItemType, 4, project.CompletionDate); needSave ||= setGuildTechLogState(guild, project.ItemType, 4, project.CompletionDate);
} }
} }
techProjects.push(techProject); techProjects.push(techProject);
@ -74,9 +77,9 @@ export const guildTechController: RequestHandler = async (req, res) => {
State: 0 State: 0
}) - 1 }) - 1
]; ];
setTechLogState(guild, techProject.ItemType, 5); setGuildTechLogState(guild, techProject.ItemType, 5);
if (config.noDojoResearchCosts) { if (config.noDojoResearchCosts) {
processFundedProject(guild, techProject, recipe); processFundedGuildTechProject(guild, techProject, recipe);
} else { } else {
if (data.RecipeType.substring(0, 39) == "/Lotus/Types/Items/Research/DojoColors/") { if (data.RecipeType.substring(0, 39) == "/Lotus/Types/Items/Research/DojoColors/") {
guild.ActiveDojoColorResearch = data.RecipeType; guild.ActiveDojoColorResearch = data.RecipeType;
@ -151,15 +154,8 @@ export const guildTechController: RequestHandler = async (req, res) => {
const inventoryChanges: IInventoryChanges = updateCurrency(inventory, contributions.RegularCredits, false); const inventoryChanges: IInventoryChanges = updateCurrency(inventory, contributions.RegularCredits, false);
inventoryChanges.MiscItems = miscItemChanges; inventoryChanges.MiscItems = miscItemChanges;
if (techProject.ReqCredits == 0 && !techProject.ReqItems.find(x => x.ItemCount > 0)) { // Check if research is fully funded now.
// This research is now fully funded. await processGuildTechProjectContributionsUpdate(guild, techProject);
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(); await guild.save();
await inventory.save(); await inventory.save();
@ -238,43 +234,6 @@ export const guildTechController: RequestHandler = async (req, res) => {
} }
}; };
const processFundedProject = (
guild: TGuildDatabaseDocument,
techProject: ITechProjectDatabase,
recipe: IDojoResearch
): void => {
techProject.State = 1;
techProject.CompletionDate = new Date(Date.now() + (config.noDojoResearchTime ? 0 : recipe.time) * 1000);
if (recipe.guildXpValue) {
guild.XP += recipe.guildXpValue;
}
setTechLogState(guild, techProject.ItemType, config.noDojoResearchTime ? 4 : 3, techProject.CompletionDate);
};
const setTechLogState = (
guild: TGuildDatabaseDocument,
type: string,
state: number,
dateTime: Date | undefined = undefined
): boolean => {
guild.TechChanges ??= [];
const entry = guild.TechChanges.find(x => x.details == type);
if (entry) {
if (entry.entryType == state) {
return false;
}
entry.dateTime = dateTime;
entry.entryType = state;
} else {
guild.TechChanges.push({
dateTime: dateTime,
entryType: state,
details: type
});
}
return true;
};
type TGuildTechRequest = type TGuildTechRequest =
| { Action: "Sync" | "SomethingElseThatWeMightNotKnowAbout" } | { Action: "Sync" | "SomethingElseThatWeMightNotKnowAbout" }
| IGuildTechBasicRequest | IGuildTechBasicRequest

View File

@ -13,11 +13,12 @@ import {
IGuildClient, IGuildClient,
IGuildMemberClient, IGuildMemberClient,
IGuildMemberDatabase, IGuildMemberDatabase,
IGuildVault IGuildVault,
ITechProjectDatabase
} from "@/src/types/guildTypes"; } from "@/src/types/guildTypes";
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers"; import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
import { Types } from "mongoose"; import { Types } from "mongoose";
import { ExportDojoRecipes, IDojoBuild } from "warframe-public-export-plus"; import { ExportDojoRecipes, IDojoBuild, IDojoResearch } from "warframe-public-export-plus";
import { logger } from "../utils/logger"; import { logger } from "../utils/logger";
import { config } from "./configService"; import { config } from "./configService";
import { Account } from "../models/loginModel"; import { Account } from "../models/loginModel";
@ -171,7 +172,7 @@ export const getDojoClient = async (
} }
if (newTier) { if (newTier) {
logger.debug(`clan finished building barracks, updating to tier ${newTier}`); logger.debug(`clan finished building barracks, updating to tier ${newTier}`);
setGuildTier(guild, newTier); await setGuildTier(guild, newTier);
needSave = true; needSave = true;
} }
} }
@ -211,7 +212,7 @@ export const getDojoClient = async (
if (roomsToRemove.length) { if (roomsToRemove.length) {
logger.debug(`removing now-destroyed rooms`, roomsToRemove); logger.debug(`removing now-destroyed rooms`, roomsToRemove);
for (const id of roomsToRemove) { for (const id of roomsToRemove) {
removeDojoRoom(guild, id); await removeDojoRoom(guild, id);
} }
needSave = true; needSave = true;
} }
@ -227,7 +228,10 @@ export const scaleRequiredCount = (tier: number, count: number): number => {
return Math.max(1, Math.trunc(count * guildTierScalingFactors[tier - 1])); return Math.max(1, Math.trunc(count * guildTierScalingFactors[tier - 1]));
}; };
export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: Types.ObjectId | string): void => { export const removeDojoRoom = async (
guild: TGuildDatabaseDocument,
componentId: Types.ObjectId | string
): Promise<void> => {
const component = guild.DojoComponents.splice( const component = guild.DojoComponents.splice(
guild.DojoComponents.findIndex(x => x._id.equals(componentId)), guild.DojoComponents.findIndex(x => x._id.equals(componentId)),
1 1
@ -249,16 +253,16 @@ export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: Types
switch (component.pf) { switch (component.pf) {
case "/Lotus/Levels/ClanDojo/ClanDojoBarracksShadow.level": case "/Lotus/Levels/ClanDojo/ClanDojoBarracksShadow.level":
setGuildTier(guild, 1); await setGuildTier(guild, 1);
break; break;
case "/Lotus/Levels/ClanDojo/ClanDojoBarracksStorm.level": case "/Lotus/Levels/ClanDojo/ClanDojoBarracksStorm.level":
setGuildTier(guild, 2); await setGuildTier(guild, 2);
break; break;
case "/Lotus/Levels/ClanDojo/ClanDojoBarracksMountain.level": case "/Lotus/Levels/ClanDojo/ClanDojoBarracksMountain.level":
setGuildTier(guild, 3); await setGuildTier(guild, 3);
break; break;
case "/Lotus/Levels/ClanDojo/ClanDojoBarracksMoon.level": case "/Lotus/Levels/ClanDojo/ClanDojoBarracksMoon.level":
setGuildTier(guild, 4); await setGuildTier(guild, 4);
break; break;
} }
}; };
@ -404,7 +408,59 @@ export const removePigmentsFromGuildMembers = async (guildId: string | Types.Obj
} }
}; };
const setGuildTier = (guild: TGuildDatabaseDocument, newTier: number): void => { export const processGuildTechProjectContributionsUpdate = async (
guild: TGuildDatabaseDocument,
techProject: ITechProjectDatabase
): Promise<void> => {
if (techProject.ReqCredits == 0 && !techProject.ReqItems.find(x => x.ItemCount > 0)) {
// This research is now fully funded.
const recipe = ExportDojoRecipes.research[techProject.ItemType];
processFundedGuildTechProject(guild, techProject, recipe);
if (techProject.ItemType.substring(0, 39) == "/Lotus/Types/Items/Research/DojoColors/") {
guild.ActiveDojoColorResearch = "";
await removePigmentsFromGuildMembers(guild._id);
}
}
};
export const processFundedGuildTechProject = (
guild: TGuildDatabaseDocument,
techProject: ITechProjectDatabase,
recipe: IDojoResearch
): void => {
techProject.State = 1;
techProject.CompletionDate = new Date(Date.now() + (config.noDojoResearchTime ? 0 : recipe.time) * 1000);
if (recipe.guildXpValue) {
guild.XP += recipe.guildXpValue;
}
setGuildTechLogState(guild, techProject.ItemType, config.noDojoResearchTime ? 4 : 3, techProject.CompletionDate);
};
export const setGuildTechLogState = (
guild: TGuildDatabaseDocument,
type: string,
state: number,
dateTime: Date | undefined = undefined
): boolean => {
guild.TechChanges ??= [];
const entry = guild.TechChanges.find(x => x.details == type);
if (entry) {
if (entry.entryType == state) {
return false;
}
entry.dateTime = dateTime;
entry.entryType = state;
} else {
guild.TechChanges.push({
dateTime: dateTime,
entryType: state,
details: type
});
}
return true;
};
const setGuildTier = async (guild: TGuildDatabaseDocument, newTier: number): Promise<void> => {
const oldTier = guild.Tier; const oldTier = guild.Tier;
guild.Tier = newTier; guild.Tier = newTier;
if (guild.TechProjects) { if (guild.TechProjects) {
@ -436,6 +492,9 @@ const setGuildTier = (guild: TGuildDatabaseDocument, newTier: number): void => {
project.ReqItems[i].ItemCount = 0; project.ReqItems[i].ItemCount = 0;
} }
} }
// Check if research is fully funded now due to lowered requirements.
await processGuildTechProjectContributionsUpdate(guild, project);
} }
} }
}; };