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) {
|
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();
|
||||||
|
@ -94,10 +94,10 @@ const processContribution = (
|
|||||||
component.RegularCredits += request.VaultCredits;
|
component.RegularCredits += request.VaultCredits;
|
||||||
guild.VaultRegularCredits! -= 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 ??= 0;
|
||||||
guild.VaultRegularCredits += component.RegularCredits - scaleRequiredCount(meta.price);
|
guild.VaultRegularCredits += component.RegularCredits - scaleRequiredCount(guild.Tier, meta.price);
|
||||||
component.RegularCredits = scaleRequiredCount(meta.price);
|
component.RegularCredits = scaleRequiredCount(guild.Tier, meta.price);
|
||||||
}
|
}
|
||||||
|
|
||||||
component.MiscItems ??= [];
|
component.MiscItems ??= [];
|
||||||
@ -108,10 +108,10 @@ const processContribution = (
|
|||||||
const ingredientMeta = meta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!;
|
const ingredientMeta = meta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!;
|
||||||
if (
|
if (
|
||||||
componentMiscItem.ItemCount + ingredientContribution.ItemCount >
|
componentMiscItem.ItemCount + ingredientContribution.ItemCount >
|
||||||
scaleRequiredCount(ingredientMeta.ItemCount)
|
scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount)
|
||||||
) {
|
) {
|
||||||
ingredientContribution.ItemCount =
|
ingredientContribution.ItemCount =
|
||||||
scaleRequiredCount(ingredientMeta.ItemCount) - componentMiscItem.ItemCount;
|
scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount) - componentMiscItem.ItemCount;
|
||||||
}
|
}
|
||||||
componentMiscItem.ItemCount += ingredientContribution.ItemCount;
|
componentMiscItem.ItemCount += ingredientContribution.ItemCount;
|
||||||
} else {
|
} else {
|
||||||
@ -129,10 +129,10 @@ const processContribution = (
|
|||||||
const ingredientMeta = meta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!;
|
const ingredientMeta = meta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!;
|
||||||
if (
|
if (
|
||||||
componentMiscItem.ItemCount + ingredientContribution.ItemCount >
|
componentMiscItem.ItemCount + ingredientContribution.ItemCount >
|
||||||
scaleRequiredCount(ingredientMeta.ItemCount)
|
scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount)
|
||||||
) {
|
) {
|
||||||
ingredientContribution.ItemCount =
|
ingredientContribution.ItemCount =
|
||||||
scaleRequiredCount(ingredientMeta.ItemCount) - componentMiscItem.ItemCount;
|
scaleRequiredCount(guild.Tier, ingredientMeta.ItemCount) - componentMiscItem.ItemCount;
|
||||||
}
|
}
|
||||||
componentMiscItem.ItemCount += ingredientContribution.ItemCount;
|
componentMiscItem.ItemCount += ingredientContribution.ItemCount;
|
||||||
} else {
|
} else {
|
||||||
@ -150,11 +150,14 @@ const processContribution = (
|
|||||||
inventoryChanges.MiscItems = miscItemChanges;
|
inventoryChanges.MiscItems = miscItemChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (component.RegularCredits >= scaleRequiredCount(meta.price)) {
|
if (component.RegularCredits >= scaleRequiredCount(guild.Tier, meta.price)) {
|
||||||
let fullyFunded = true;
|
let fullyFunded = true;
|
||||||
for (const ingredient of meta.ingredients) {
|
for (const ingredient of meta.ingredients) {
|
||||||
const componentMiscItem = component.MiscItems.find(x => x.ItemType == ingredient.ItemType);
|
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;
|
fullyFunded = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { GuildMember } from "@/src/models/guildModel";
|
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 { addFusionTreasures, addMiscItems, addShipDecorations, getInventory } from "@/src/services/inventoryService";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { IFusionTreasure, IMiscItem, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
|
import { IFusionTreasure, IMiscItem, ITypeCount } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
@ -23,11 +23,17 @@ export const contributeToVaultController: RequestHandler = async (req, res) => {
|
|||||||
guildMember.RegularCreditsContributed += request.RegularCredits;
|
guildMember.RegularCreditsContributed += request.RegularCredits;
|
||||||
}
|
}
|
||||||
if (request.MiscItems.length) {
|
if (request.MiscItems.length) {
|
||||||
guild.VaultMiscItems ??= [];
|
addVaultMiscItems(guild, request.MiscItems);
|
||||||
|
|
||||||
guildMember.MiscItemsContributed ??= [];
|
guildMember.MiscItemsContributed ??= [];
|
||||||
for (const item of request.MiscItems) {
|
for (const item of request.MiscItems) {
|
||||||
guild.VaultMiscItems.push(item);
|
const miscItemContribution = guildMember.MiscItemsContributed.find(x => x.ItemType == item.ItemType);
|
||||||
|
if (miscItemContribution) {
|
||||||
|
miscItemContribution.ItemCount += item.ItemCount;
|
||||||
|
} else {
|
||||||
guildMember.MiscItemsContributed.push(item);
|
guildMember.MiscItemsContributed.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
addMiscItems(inventory, [{ ...item, ItemCount: item.ItemCount * -1 }]);
|
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 { getDojoClient, getGuildForRequestEx, hasAccessToDojo, scaleRequiredCount } from "@/src/services/guildService";
|
||||||
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
|
import { getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
@ -36,10 +36,10 @@ export const dojoComponentRushController: RequestHandler = async (req, res) => {
|
|||||||
if (request.DecoId) {
|
if (request.DecoId) {
|
||||||
const deco = component.Decos!.find(x => x._id.equals(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)!;
|
const meta = Object.values(ExportDojoRecipes.decos).find(x => x.resultType == deco.Type)!;
|
||||||
processContribution(deco, meta, platinumDonated);
|
processContribution(guild, deco, meta, platinumDonated);
|
||||||
} else {
|
} else {
|
||||||
const meta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!;
|
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));
|
const entry = guild.RoomChanges?.find(x => x.componentId.equals(component._id));
|
||||||
if (entry) {
|
if (entry) {
|
||||||
@ -61,8 +61,13 @@ export const dojoComponentRushController: RequestHandler = async (req, res) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const processContribution = (component: IDojoContributable, meta: IDojoBuild, platinumDonated: number): void => {
|
const processContribution = (
|
||||||
const fullPlatinumCost = scaleRequiredCount(meta.skipTimePrice);
|
guild: TGuildDatabaseDocument,
|
||||||
|
component: IDojoContributable,
|
||||||
|
meta: IDojoBuild,
|
||||||
|
platinumDonated: number
|
||||||
|
): void => {
|
||||||
|
const fullPlatinumCost = scaleRequiredCount(guild.Tier, meta.skipTimePrice);
|
||||||
const fullDurationSeconds = meta.time;
|
const fullDurationSeconds = meta.time;
|
||||||
const secondsPerPlatinum = fullDurationSeconds / fullPlatinumCost;
|
const secondsPerPlatinum = fullDurationSeconds / fullPlatinumCost;
|
||||||
component.CompletionTime = new Date(
|
component.CompletionTime = new Date(
|
||||||
|
@ -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);
|
||||||
@ -66,17 +69,17 @@ export const guildTechController: RequestHandler = async (req, res) => {
|
|||||||
guild.TechProjects[
|
guild.TechProjects[
|
||||||
guild.TechProjects.push({
|
guild.TechProjects.push({
|
||||||
ItemType: data.RecipeType,
|
ItemType: data.RecipeType,
|
||||||
ReqCredits: config.noDojoResearchCosts ? 0 : scaleRequiredCount(recipe.price),
|
ReqCredits: config.noDojoResearchCosts ? 0 : scaleRequiredCount(guild.Tier, recipe.price),
|
||||||
ReqItems: recipe.ingredients.map(x => ({
|
ReqItems: recipe.ingredients.map(x => ({
|
||||||
ItemType: x.ItemType,
|
ItemType: x.ItemType,
|
||||||
ItemCount: config.noDojoResearchCosts ? 0 : scaleRequiredCount(x.ItemCount)
|
ItemCount: config.noDojoResearchCosts ? 0 : scaleRequiredCount(guild.Tier, x.ItemCount)
|
||||||
})),
|
})),
|
||||||
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
|
||||||
|
@ -13,16 +13,18 @@ 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";
|
||||||
import { getRandomInt } from "./rngService";
|
import { getRandomInt } from "./rngService";
|
||||||
import { Inbox } from "../models/inboxModel";
|
import { Inbox } from "../models/inboxModel";
|
||||||
|
import { ITypeCount } from "../types/inventoryTypes/inventoryTypes";
|
||||||
|
|
||||||
export const getGuildForRequest = async (req: Request): Promise<TGuildDatabaseDocument> => {
|
export const getGuildForRequest = async (req: Request): Promise<TGuildDatabaseDocument> => {
|
||||||
const accountId = await getAccountIdForRequest(req);
|
const accountId = await getAccountIdForRequest(req);
|
||||||
@ -152,6 +154,27 @@ export const getDojoClient = async (
|
|||||||
entry.entryType = 1;
|
entry.entryType = 1;
|
||||||
needSave = true;
|
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 (dojoComponent.DestructionTime) {
|
||||||
if (Date.now() >= dojoComponent.DestructionTime.getTime()) {
|
if (Date.now() >= dojoComponent.DestructionTime.getTime()) {
|
||||||
@ -189,22 +212,26 @@ 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;
|
||||||
}
|
}
|
||||||
if (needSave) {
|
if (needSave) {
|
||||||
await guild.save();
|
await guild.save();
|
||||||
}
|
}
|
||||||
|
dojo.Tier = guild.Tier;
|
||||||
return dojo;
|
return dojo;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const scaleRequiredCount = (count: number): number => {
|
const guildTierScalingFactors = [0.01, 0.03, 0.1, 0.3, 1];
|
||||||
// The recipes in the export are for Moon clans. For now we'll just assume we only have Ghost clans.
|
export const scaleRequiredCount = (tier: number, count: number): number => {
|
||||||
return Math.max(1, Math.trunc(count / 100));
|
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
|
||||||
@ -223,6 +250,21 @@ export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: Types
|
|||||||
guild.RoomChanges.splice(index, 1);
|
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 = (
|
export const removeDojoDeco = (
|
||||||
@ -248,15 +290,7 @@ const moveResourcesToVault = (guild: TGuildDatabaseDocument, component: IDojoCon
|
|||||||
guild.VaultRegularCredits += component.RegularCredits;
|
guild.VaultRegularCredits += component.RegularCredits;
|
||||||
}
|
}
|
||||||
if (component.MiscItems) {
|
if (component.MiscItems) {
|
||||||
guild.VaultMiscItems ??= [];
|
addVaultMiscItems(guild, component.MiscItems);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (component.RushPlatinum) {
|
if (component.RushPlatinum) {
|
||||||
guild.VaultPremiumCredits ??= 0;
|
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 => {
|
export const processDojoBuildMaterialsGathered = (guild: TGuildDatabaseDocument, build: IDojoBuild): void => {
|
||||||
if (build.guildXpValue) {
|
if (build.guildXpValue) {
|
||||||
guild.ClaimedXP ??= [];
|
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> => {
|
export const deleteGuild = async (guildId: Types.ObjectId): Promise<void> => {
|
||||||
await Guild.deleteOne({ _id: guildId });
|
await Guild.deleteOne({ _id: guildId });
|
||||||
await GuildMember.deleteMany({ guildId });
|
await GuildMember.deleteMany({ guildId });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user