feat: clan tiers (#1378)
Reviewed-on: #1378 Co-authored-by: Sainan <63328889+Sainan@users.noreply.github.com> Co-committed-by: Sainan <63328889+Sainan@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									fccdbf4a8e
								
							
						
					
					
						commit
						516f822e43
					
				| @ -32,7 +32,7 @@ export const abortDojoComponentController: RequestHandler = async (req, res) => | ||||
|     if (request.DecoId) { | ||||
|         removeDojoDeco(guild, request.ComponentId, request.DecoId); | ||||
|     } else { | ||||
|         removeDojoRoom(guild, request.ComponentId); | ||||
|         await removeDojoRoom(guild, request.ComponentId); | ||||
|     } | ||||
| 
 | ||||
|     await guild.save(); | ||||
|  | ||||
| @ -94,10 +94,10 @@ const processContribution = ( | ||||
|         component.RegularCredits += request.VaultCredits; | ||||
|         guild.VaultRegularCredits! -= request.VaultCredits; | ||||
|     } | ||||
|     if (component.RegularCredits > scaleRequiredCount(meta.price)) { | ||||
|     if (component.RegularCredits > scaleRequiredCount(guild.Tier, meta.price)) { | ||||
|         guild.VaultRegularCredits ??= 0; | ||||
|         guild.VaultRegularCredits += component.RegularCredits - scaleRequiredCount(meta.price); | ||||
|         component.RegularCredits = scaleRequiredCount(meta.price); | ||||
|         guild.VaultRegularCredits += component.RegularCredits - scaleRequiredCount(guild.Tier, meta.price); | ||||
|         component.RegularCredits = scaleRequiredCount(guild.Tier, meta.price); | ||||
|     } | ||||
| 
 | ||||
|     component.MiscItems ??= []; | ||||
| @ -108,10 +108,10 @@ const processContribution = ( | ||||
|                 const ingredientMeta = meta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!; | ||||
|                 if ( | ||||
|                     componentMiscItem.ItemCount + ingredientContribution.ItemCount > | ||||
|                     scaleRequiredCount(ingredientMeta.ItemCount) | ||||
|                     scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount) | ||||
|                 ) { | ||||
|                     ingredientContribution.ItemCount = | ||||
|                         scaleRequiredCount(ingredientMeta.ItemCount) - componentMiscItem.ItemCount; | ||||
|                         scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount) - componentMiscItem.ItemCount; | ||||
|                 } | ||||
|                 componentMiscItem.ItemCount += ingredientContribution.ItemCount; | ||||
|             } else { | ||||
| @ -129,10 +129,10 @@ const processContribution = ( | ||||
|                 const ingredientMeta = meta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!; | ||||
|                 if ( | ||||
|                     componentMiscItem.ItemCount + ingredientContribution.ItemCount > | ||||
|                     scaleRequiredCount(ingredientMeta.ItemCount) | ||||
|                     scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount) | ||||
|                 ) { | ||||
|                     ingredientContribution.ItemCount = | ||||
|                         scaleRequiredCount(ingredientMeta.ItemCount) - componentMiscItem.ItemCount; | ||||
|                         scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount) - componentMiscItem.ItemCount; | ||||
|                 } | ||||
|                 componentMiscItem.ItemCount += ingredientContribution.ItemCount; | ||||
|             } else { | ||||
| @ -150,11 +150,14 @@ const processContribution = ( | ||||
|         inventoryChanges.MiscItems = miscItemChanges; | ||||
|     } | ||||
| 
 | ||||
|     if (component.RegularCredits >= scaleRequiredCount(meta.price)) { | ||||
|     if (component.RegularCredits >= scaleRequiredCount(guild.Tier, meta.price)) { | ||||
|         let fullyFunded = true; | ||||
|         for (const ingredient of meta.ingredients) { | ||||
|             const componentMiscItem = component.MiscItems.find(x => x.ItemType == ingredient.ItemType); | ||||
|             if (!componentMiscItem || componentMiscItem.ItemCount < scaleRequiredCount(ingredient.ItemCount)) { | ||||
|             if ( | ||||
|                 !componentMiscItem || | ||||
|                 componentMiscItem.ItemCount < scaleRequiredCount(guild.Tier, ingredient.ItemCount) | ||||
|             ) { | ||||
|                 fullyFunded = false; | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| import { GuildMember } from "@/src/models/guildModel"; | ||||
| import { getGuildForRequestEx } from "@/src/services/guildService"; | ||||
| import { addVaultMiscItems, getGuildForRequestEx } from "@/src/services/guildService"; | ||||
| import { addFusionTreasures, addMiscItems, addShipDecorations, getInventory } from "@/src/services/inventoryService"; | ||||
| import { getAccountIdForRequest } from "@/src/services/loginService"; | ||||
| import { IFusionTreasure, IMiscItem, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes"; | ||||
| @ -23,11 +23,17 @@ export const contributeToVaultController: RequestHandler = async (req, res) => { | ||||
|         guildMember.RegularCreditsContributed += request.RegularCredits; | ||||
|     } | ||||
|     if (request.MiscItems.length) { | ||||
|         guild.VaultMiscItems ??= []; | ||||
|         addVaultMiscItems(guild, request.MiscItems); | ||||
| 
 | ||||
|         guildMember.MiscItemsContributed ??= []; | ||||
|         for (const item of request.MiscItems) { | ||||
|             guild.VaultMiscItems.push(item); | ||||
|             guildMember.MiscItemsContributed.push(item); | ||||
|             const miscItemContribution = guildMember.MiscItemsContributed.find(x => x.ItemType == item.ItemType); | ||||
|             if (miscItemContribution) { | ||||
|                 miscItemContribution.ItemCount += item.ItemCount; | ||||
|             } else { | ||||
|                 guildMember.MiscItemsContributed.push(item); | ||||
|             } | ||||
| 
 | ||||
|             addMiscItems(inventory, [{ ...item, ItemCount: item.ItemCount * -1 }]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import { GuildMember } from "@/src/models/guildModel"; | ||||
| import { GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel"; | ||||
| import { getDojoClient, getGuildForRequestEx, hasAccessToDojo, scaleRequiredCount } from "@/src/services/guildService"; | ||||
| import { getInventory, updateCurrency } from "@/src/services/inventoryService"; | ||||
| import { getAccountIdForRequest } from "@/src/services/loginService"; | ||||
| @ -36,10 +36,10 @@ export const dojoComponentRushController: RequestHandler = async (req, res) => { | ||||
|     if (request.DecoId) { | ||||
|         const deco = component.Decos!.find(x => x._id.equals(request.DecoId))!; | ||||
|         const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == deco.Type)!; | ||||
|         processContribution(deco, meta, platinumDonated); | ||||
|         processContribution(guild, deco, meta, platinumDonated); | ||||
|     } else { | ||||
|         const meta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!; | ||||
|         processContribution(component, meta, platinumDonated); | ||||
|         processContribution(guild, component, meta, platinumDonated); | ||||
| 
 | ||||
|         const entry = guild.RoomChanges?.find(x => x.componentId.equals(component._id)); | ||||
|         if (entry) { | ||||
| @ -61,8 +61,13 @@ export const dojoComponentRushController: RequestHandler = async (req, res) => { | ||||
|     }); | ||||
| }; | ||||
| 
 | ||||
| const processContribution = (component: IDojoContributable, meta: IDojoBuild, platinumDonated: number): void => { | ||||
|     const fullPlatinumCost = scaleRequiredCount(meta.skipTimePrice); | ||||
| const processContribution = ( | ||||
|     guild: TGuildDatabaseDocument, | ||||
|     component: IDojoContributable, | ||||
|     meta: IDojoBuild, | ||||
|     platinumDonated: number | ||||
| ): void => { | ||||
|     const fullPlatinumCost = scaleRequiredCount(guild.Tier, meta.skipTimePrice); | ||||
|     const fullDurationSeconds = meta.time; | ||||
|     const secondsPerPlatinum = fullDurationSeconds / fullPlatinumCost; | ||||
|     component.CompletionTime = new Date( | ||||
|  | ||||
| @ -4,10 +4,13 @@ import { | ||||
|     getGuildVault, | ||||
|     hasAccessToDojo, | ||||
|     hasGuildPermission, | ||||
|     processFundedGuildTechProject, | ||||
|     processGuildTechProjectContributionsUpdate, | ||||
|     removePigmentsFromGuildMembers, | ||||
|     scaleRequiredCount | ||||
|     scaleRequiredCount, | ||||
|     setGuildTechLogState | ||||
| } 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 { | ||||
|     addItem, | ||||
| @ -20,8 +23,8 @@ import { | ||||
| import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes"; | ||||
| import { IInventoryChanges } from "@/src/types/purchaseTypes"; | ||||
| import { config } from "@/src/services/configService"; | ||||
| import { GuildPermission, ITechProjectClient, ITechProjectDatabase } from "@/src/types/guildTypes"; | ||||
| import { GuildMember, TGuildDatabaseDocument } from "@/src/models/guildModel"; | ||||
| import { GuildPermission, ITechProjectClient } from "@/src/types/guildTypes"; | ||||
| import { GuildMember } from "@/src/models/guildModel"; | ||||
| import { toMongoDate } from "@/src/helpers/inventoryHelpers"; | ||||
| import { logger } from "@/src/utils/logger"; | ||||
| 
 | ||||
| @ -44,7 +47,7 @@ export const guildTechController: RequestHandler = async (req, res) => { | ||||
|                 if (project.CompletionDate) { | ||||
|                     techProject.CompletionDate = toMongoDate(project.CompletionDate); | ||||
|                     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); | ||||
| @ -66,17 +69,17 @@ export const guildTechController: RequestHandler = async (req, res) => { | ||||
|                 guild.TechProjects[ | ||||
|                     guild.TechProjects.push({ | ||||
|                         ItemType: data.RecipeType, | ||||
|                         ReqCredits: config.noDojoResearchCosts ? 0 : scaleRequiredCount(recipe.price), | ||||
|                         ReqCredits: config.noDojoResearchCosts ? 0 : scaleRequiredCount(guild.Tier, recipe.price), | ||||
|                         ReqItems: recipe.ingredients.map(x => ({ | ||||
|                             ItemType: x.ItemType, | ||||
|                             ItemCount: config.noDojoResearchCosts ? 0 : scaleRequiredCount(x.ItemCount) | ||||
|                             ItemCount: config.noDojoResearchCosts ? 0 : scaleRequiredCount(guild.Tier, x.ItemCount) | ||||
|                         })), | ||||
|                         State: 0 | ||||
|                     }) - 1 | ||||
|                 ]; | ||||
|             setTechLogState(guild, techProject.ItemType, 5); | ||||
|             setGuildTechLogState(guild, techProject.ItemType, 5); | ||||
|             if (config.noDojoResearchCosts) { | ||||
|                 processFundedProject(guild, techProject, recipe); | ||||
|                 processFundedGuildTechProject(guild, techProject, recipe); | ||||
|             } else { | ||||
|                 if (data.RecipeType.substring(0, 39) == "/Lotus/Types/Items/Research/DojoColors/") { | ||||
|                     guild.ActiveDojoColorResearch = data.RecipeType; | ||||
| @ -151,15 +154,8 @@ export const guildTechController: RequestHandler = async (req, res) => { | ||||
|         const inventoryChanges: IInventoryChanges = updateCurrency(inventory, contributions.RegularCredits, false); | ||||
|         inventoryChanges.MiscItems = miscItemChanges; | ||||
| 
 | ||||
|         if (techProject.ReqCredits == 0 && !techProject.ReqItems.find(x => x.ItemCount > 0)) { | ||||
|             // This research is now fully funded.
 | ||||
|             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); | ||||
|             } | ||||
|         } | ||||
|         // Check if research is fully funded now.
 | ||||
|         await processGuildTechProjectContributionsUpdate(guild, techProject); | ||||
| 
 | ||||
|         await guild.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 = | ||||
|     | { Action: "Sync" | "SomethingElseThatWeMightNotKnowAbout" } | ||||
|     | IGuildTechBasicRequest | ||||
|  | ||||
| @ -13,16 +13,18 @@ import { | ||||
|     IGuildClient, | ||||
|     IGuildMemberClient, | ||||
|     IGuildMemberDatabase, | ||||
|     IGuildVault | ||||
|     IGuildVault, | ||||
|     ITechProjectDatabase | ||||
| } from "@/src/types/guildTypes"; | ||||
| import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers"; | ||||
| 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 { config } from "./configService"; | ||||
| import { Account } from "../models/loginModel"; | ||||
| import { getRandomInt } from "./rngService"; | ||||
| import { Inbox } from "../models/inboxModel"; | ||||
| import { ITypeCount } from "../types/inventoryTypes/inventoryTypes"; | ||||
| 
 | ||||
| export const getGuildForRequest = async (req: Request): Promise<TGuildDatabaseDocument> => { | ||||
|     const accountId = await getAccountIdForRequest(req); | ||||
| @ -152,6 +154,27 @@ export const getDojoClient = async ( | ||||
|                         entry.entryType = 1; | ||||
|                         needSave = true; | ||||
|                     } | ||||
| 
 | ||||
|                     let newTier: number | undefined; | ||||
|                     switch (dojoComponent.pf) { | ||||
|                         case "/Lotus/Levels/ClanDojo/ClanDojoBarracksShadow.level": | ||||
|                             newTier = 2; | ||||
|                             break; | ||||
|                         case "/Lotus/Levels/ClanDojo/ClanDojoBarracksStorm.level": | ||||
|                             newTier = 3; | ||||
|                             break; | ||||
|                         case "/Lotus/Levels/ClanDojo/ClanDojoBarracksMountain.level": | ||||
|                             newTier = 4; | ||||
|                             break; | ||||
|                         case "/Lotus/Levels/ClanDojo/ClanDojoBarracksMoon.level": | ||||
|                             newTier = 5; | ||||
|                             break; | ||||
|                     } | ||||
|                     if (newTier) { | ||||
|                         logger.debug(`clan finished building barracks, updating to tier ${newTier}`); | ||||
|                         await setGuildTier(guild, newTier); | ||||
|                         needSave = true; | ||||
|                     } | ||||
|                 } | ||||
|                 if (dojoComponent.DestructionTime) { | ||||
|                     if (Date.now() >= dojoComponent.DestructionTime.getTime()) { | ||||
| @ -189,22 +212,26 @@ export const getDojoClient = async ( | ||||
|     if (roomsToRemove.length) { | ||||
|         logger.debug(`removing now-destroyed rooms`, roomsToRemove); | ||||
|         for (const id of roomsToRemove) { | ||||
|             removeDojoRoom(guild, id); | ||||
|             await removeDojoRoom(guild, id); | ||||
|         } | ||||
|         needSave = true; | ||||
|     } | ||||
|     if (needSave) { | ||||
|         await guild.save(); | ||||
|     } | ||||
|     dojo.Tier = guild.Tier; | ||||
|     return dojo; | ||||
| }; | ||||
| 
 | ||||
| export const scaleRequiredCount = (count: number): number => { | ||||
|     // The recipes in the export are for Moon clans. For now we'll just assume we only have Ghost clans.
 | ||||
|     return Math.max(1, Math.trunc(count / 100)); | ||||
| const guildTierScalingFactors = [0.01, 0.03, 0.1, 0.3, 1]; | ||||
| export const scaleRequiredCount = (tier: number, count: number): number => { | ||||
|     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( | ||||
|         guild.DojoComponents.findIndex(x => x._id.equals(componentId)), | ||||
|         1 | ||||
| @ -223,6 +250,21 @@ export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: Types | ||||
|             guild.RoomChanges.splice(index, 1); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     switch (component.pf) { | ||||
|         case "/Lotus/Levels/ClanDojo/ClanDojoBarracksShadow.level": | ||||
|             await setGuildTier(guild, 1); | ||||
|             break; | ||||
|         case "/Lotus/Levels/ClanDojo/ClanDojoBarracksStorm.level": | ||||
|             await setGuildTier(guild, 2); | ||||
|             break; | ||||
|         case "/Lotus/Levels/ClanDojo/ClanDojoBarracksMountain.level": | ||||
|             await setGuildTier(guild, 3); | ||||
|             break; | ||||
|         case "/Lotus/Levels/ClanDojo/ClanDojoBarracksMoon.level": | ||||
|             await setGuildTier(guild, 4); | ||||
|             break; | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| export const removeDojoDeco = ( | ||||
| @ -248,15 +290,7 @@ const moveResourcesToVault = (guild: TGuildDatabaseDocument, component: IDojoCon | ||||
|         guild.VaultRegularCredits += component.RegularCredits; | ||||
|     } | ||||
|     if (component.MiscItems) { | ||||
|         guild.VaultMiscItems ??= []; | ||||
|         for (const componentMiscItem of component.MiscItems) { | ||||
|             const vaultMiscItem = guild.VaultMiscItems.find(x => x.ItemType == componentMiscItem.ItemType); | ||||
|             if (vaultMiscItem) { | ||||
|                 vaultMiscItem.ItemCount += componentMiscItem.ItemCount; | ||||
|             } else { | ||||
|                 guild.VaultMiscItems.push(componentMiscItem); | ||||
|             } | ||||
|         } | ||||
|         addVaultMiscItems(guild, component.MiscItems); | ||||
|     } | ||||
|     if (component.RushPlatinum) { | ||||
|         guild.VaultPremiumCredits ??= 0; | ||||
| @ -264,6 +298,18 @@ const moveResourcesToVault = (guild: TGuildDatabaseDocument, component: IDojoCon | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| export const addVaultMiscItems = (guild: TGuildDatabaseDocument, miscItems: ITypeCount[]): void => { | ||||
|     guild.VaultMiscItems ??= []; | ||||
|     for (const miscItem of miscItems) { | ||||
|         const vaultMiscItem = guild.VaultMiscItems.find(x => x.ItemType == miscItem.ItemType); | ||||
|         if (vaultMiscItem) { | ||||
|             vaultMiscItem.ItemCount += miscItem.ItemCount; | ||||
|         } else { | ||||
|             guild.VaultMiscItems.push(miscItem); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| export const processDojoBuildMaterialsGathered = (guild: TGuildDatabaseDocument, build: IDojoBuild): void => { | ||||
|     if (build.guildXpValue) { | ||||
|         guild.ClaimedXP ??= []; | ||||
| @ -362,6 +408,102 @@ export const removePigmentsFromGuildMembers = async (guildId: string | Types.Obj | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 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.
 | ||||
| 
 | ||||
|         if ( | ||||
|             techProject.State == 0 && | ||||
|             techProject.ItemType.substring(0, 39) == "/Lotus/Types/Items/Research/DojoColors/" | ||||
|         ) { | ||||
|             guild.ActiveDojoColorResearch = ""; | ||||
|             await removePigmentsFromGuildMembers(guild._id); | ||||
|         } | ||||
| 
 | ||||
|         const recipe = ExportDojoRecipes.research[techProject.ItemType]; | ||||
|         processFundedGuildTechProject(guild, techProject, recipe); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 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; | ||||
|     guild.Tier = newTier; | ||||
|     if (guild.TechProjects) { | ||||
|         for (const project of guild.TechProjects) { | ||||
|             if (project.State == 1) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|             const meta = ExportDojoRecipes.research[project.ItemType]; | ||||
| 
 | ||||
|             { | ||||
|                 const numContributed = scaleRequiredCount(oldTier, meta.price) - project.ReqCredits; | ||||
|                 project.ReqCredits = scaleRequiredCount(newTier, meta.price) - numContributed; | ||||
|                 if (project.ReqCredits < 0) { | ||||
|                     guild.VaultRegularCredits ??= 0; | ||||
|                     guild.VaultRegularCredits += project.ReqCredits * -1; | ||||
|                     project.ReqCredits = 0; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             for (let i = 0; i != project.ReqItems.length; ++i) { | ||||
|                 const numContributed = | ||||
|                     scaleRequiredCount(oldTier, meta.ingredients[i].ItemCount) - project.ReqItems[i].ItemCount; | ||||
|                 project.ReqItems[i].ItemCount = | ||||
|                     scaleRequiredCount(newTier, meta.ingredients[i].ItemCount) - numContributed; | ||||
|                 if (project.ReqItems[i].ItemCount < 0) { | ||||
|                     project.ReqItems[i].ItemCount *= -1; | ||||
|                     addVaultMiscItems(guild, [project.ReqItems[i]]); | ||||
|                     project.ReqItems[i].ItemCount = 0; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // Check if research is fully funded now due to lowered requirements.
 | ||||
|             await processGuildTechProjectContributionsUpdate(guild, project); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| export const deleteGuild = async (guildId: Types.ObjectId): Promise<void> => { | ||||
|     await Guild.deleteOne({ _id: guildId }); | ||||
|     await GuildMember.deleteMany({ guildId }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user