feat: dojo component "collecting materials" state
This commit is contained in:
parent
3442f15c6d
commit
fa793e49ca
19
src/controllers/api/abortDojoComponentController.ts
Normal file
19
src/controllers/api/abortDojoComponentController.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { getDojoClient, getGuildForRequestEx } from "@/src/services/guildService";
|
||||||
|
import { getInventory } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
|
export const abortDojoComponentController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
const guild = await getGuildForRequestEx(req, inventory);
|
||||||
|
const request = JSON.parse(String(req.body)) as IAbortDojoComponentRequest;
|
||||||
|
// TODO: Move already-contributed credits & items to the clan vault
|
||||||
|
guild.DojoComponents.pull({ _id: request.ComponentId });
|
||||||
|
await guild.save();
|
||||||
|
res.json(getDojoClient(guild, 0));
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface IAbortDojoComponentRequest {
|
||||||
|
ComponentId: string;
|
||||||
|
}
|
82
src/controllers/api/contributeToDojoComponentController.ts
Normal file
82
src/controllers/api/contributeToDojoComponentController.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import { getDojoClient, getGuildForRequestEx, scaleRequiredCount } from "@/src/services/guildService";
|
||||||
|
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||||
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
|
import { IMiscItem } from "@/src/types/inventoryTypes/inventoryTypes";
|
||||||
|
import { IInventoryChanges } from "@/src/types/purchaseTypes";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
||||||
|
|
||||||
|
export const contributeToDojoComponentController: RequestHandler = async (req, res) => {
|
||||||
|
const accountId = await getAccountIdForRequest(req);
|
||||||
|
const inventory = await getInventory(accountId);
|
||||||
|
const guild = await getGuildForRequestEx(req, inventory);
|
||||||
|
const request = JSON.parse(String(req.body)) as IContributeToDojoComponentRequest;
|
||||||
|
const component = guild.DojoComponents.id(request.ComponentId)!;
|
||||||
|
const componentMeta = Object.values(ExportDojoRecipes.rooms).find(x => x.resultType == component.pf)!;
|
||||||
|
|
||||||
|
component.RegularCredits ??= 0;
|
||||||
|
if (component.RegularCredits + request.RegularCredits > scaleRequiredCount(componentMeta.price)) {
|
||||||
|
request.RegularCredits = scaleRequiredCount(componentMeta.price) - component.RegularCredits;
|
||||||
|
}
|
||||||
|
component.RegularCredits += request.RegularCredits;
|
||||||
|
const inventoryChanges: IInventoryChanges = updateCurrency(inventory, request.RegularCredits, false);
|
||||||
|
|
||||||
|
component.MiscItems ??= [];
|
||||||
|
const miscItemChanges: IMiscItem[] = [];
|
||||||
|
for (const ingredientContribution of request.IngredientContributions) {
|
||||||
|
const componentMiscItem = component.MiscItems.find(x => x.ItemType == ingredientContribution.ItemType);
|
||||||
|
if (componentMiscItem) {
|
||||||
|
const ingredientMeta = componentMeta.ingredients.find(x => x.ItemType == ingredientContribution.ItemType)!;
|
||||||
|
if (
|
||||||
|
componentMiscItem.ItemCount + ingredientContribution.ItemCount >
|
||||||
|
scaleRequiredCount(ingredientMeta.ItemCount)
|
||||||
|
) {
|
||||||
|
ingredientContribution.ItemCount =
|
||||||
|
scaleRequiredCount(ingredientMeta.ItemCount) - componentMiscItem.ItemCount;
|
||||||
|
}
|
||||||
|
componentMiscItem.ItemCount += ingredientContribution.ItemCount;
|
||||||
|
} else {
|
||||||
|
component.MiscItems.push(ingredientContribution);
|
||||||
|
}
|
||||||
|
miscItemChanges.push({
|
||||||
|
ItemType: ingredientContribution.ItemType,
|
||||||
|
ItemCount: ingredientContribution.ItemCount * -1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
addMiscItems(inventory, miscItemChanges);
|
||||||
|
inventoryChanges.MiscItems = miscItemChanges;
|
||||||
|
|
||||||
|
if (component.RegularCredits >= scaleRequiredCount(componentMeta.price)) {
|
||||||
|
let fullyFunded = true;
|
||||||
|
for (const ingredient of componentMeta.ingredients) {
|
||||||
|
const componentMiscItem = component.MiscItems.find(x => x.ItemType == ingredient.ItemType);
|
||||||
|
if (!componentMiscItem || componentMiscItem.ItemCount < scaleRequiredCount(ingredient.ItemCount)) {
|
||||||
|
fullyFunded = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fullyFunded) {
|
||||||
|
component.RegularCredits = undefined;
|
||||||
|
component.MiscItems = undefined;
|
||||||
|
component.CompletionTime = new Date(Date.now() + componentMeta.time * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await guild.save();
|
||||||
|
await inventory.save();
|
||||||
|
res.json({
|
||||||
|
...getDojoClient(guild, 0, component._id),
|
||||||
|
InventoryChanges: inventoryChanges
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface IContributeToDojoComponentRequest {
|
||||||
|
ComponentId: string;
|
||||||
|
IngredientContributions: {
|
||||||
|
ItemType: string;
|
||||||
|
ItemCount: number;
|
||||||
|
}[];
|
||||||
|
RegularCredits: number;
|
||||||
|
VaultIngredientContributions: [];
|
||||||
|
VaultCredits: number;
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
import { getGuildForRequestEx } from "@/src/services/guildService";
|
import { getGuildForRequestEx, scaleRequiredCount } from "@/src/services/guildService";
|
||||||
import { ExportDojoRecipes, IDojoResearch } from "warframe-public-export-plus";
|
import { ExportDojoRecipes, IDojoResearch } from "warframe-public-export-plus";
|
||||||
import { getAccountIdForRequest } from "@/src/services/loginService";
|
import { getAccountIdForRequest } from "@/src/services/loginService";
|
||||||
import { addMiscItems, addRecipes, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
import { addMiscItems, addRecipes, getInventory, updateCurrency } from "@/src/services/inventoryService";
|
||||||
@ -130,8 +130,3 @@ interface IGuildTechContributeFields {
|
|||||||
VaultCredits: number;
|
VaultCredits: number;
|
||||||
VaultMiscItems: IMiscItem[];
|
VaultMiscItems: IMiscItem[];
|
||||||
}
|
}
|
||||||
|
|
||||||
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));
|
|
||||||
};
|
|
||||||
|
@ -12,7 +12,7 @@ export const setDojoComponentMessageController: RequestHandler = async (req, res
|
|||||||
component.Message = payload.Message;
|
component.Message = payload.Message;
|
||||||
}
|
}
|
||||||
await guild.save();
|
await guild.save();
|
||||||
res.json(getDojoClient(guild, 1));
|
res.json(getDojoClient(guild, 0, component._id));
|
||||||
};
|
};
|
||||||
|
|
||||||
type SetDojoComponentMessageRequest = { Name: string } | { Message: string };
|
type SetDojoComponentMessageRequest = { Name: string } | { Message: string };
|
||||||
|
@ -26,8 +26,7 @@ export const startDojoRecipeController: RequestHandler = async (req, res) => {
|
|||||||
ppf: request.PlacedComponent.ppf,
|
ppf: request.PlacedComponent.ppf,
|
||||||
pi: new Types.ObjectId(request.PlacedComponent.pi!.$oid),
|
pi: new Types.ObjectId(request.PlacedComponent.pi!.$oid),
|
||||||
op: request.PlacedComponent.op,
|
op: request.PlacedComponent.op,
|
||||||
pp: request.PlacedComponent.pp,
|
pp: request.PlacedComponent.pp
|
||||||
CompletionTime: new Date(Date.now()) // TOOD: Omit this field & handle the "Collecting Materials" state.
|
|
||||||
});
|
});
|
||||||
await guild.save();
|
await guild.save();
|
||||||
res.json(getDojoClient(guild, 0));
|
res.json(getDojoClient(guild, 0));
|
||||||
|
@ -16,6 +16,8 @@ const dojoComponentSchema = new Schema<IDojoComponentDatabase>({
|
|||||||
pp: String,
|
pp: String,
|
||||||
Name: String,
|
Name: String,
|
||||||
Message: String,
|
Message: String,
|
||||||
|
RegularCredits: Number,
|
||||||
|
MiscItems: { type: [typeCountSchema], default: undefined },
|
||||||
CompletionTime: Date
|
CompletionTime: Date
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import express from "express";
|
import express from "express";
|
||||||
import { abandonLibraryDailyTaskController } from "@/src/controllers/api/abandonLibraryDailyTaskController";
|
import { abandonLibraryDailyTaskController } from "@/src/controllers/api/abandonLibraryDailyTaskController";
|
||||||
|
import { abortDojoComponentController } from "@/src/controllers/api/abortDojoComponentController";
|
||||||
import { activateRandomModController } from "@/src/controllers/api/activateRandomModController";
|
import { activateRandomModController } from "@/src/controllers/api/activateRandomModController";
|
||||||
import { addFriendImageController } from "@/src/controllers/api/addFriendImageController";
|
import { addFriendImageController } from "@/src/controllers/api/addFriendImageController";
|
||||||
import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController";
|
import { arcaneCommonController } from "@/src/controllers/api/arcaneCommonController";
|
||||||
@ -11,6 +12,7 @@ import { claimCompletedRecipeController } from "@/src/controllers/api/claimCompl
|
|||||||
import { claimLibraryDailyTaskRewardController } from "@/src/controllers/api/claimLibraryDailyTaskRewardController";
|
import { claimLibraryDailyTaskRewardController } from "@/src/controllers/api/claimLibraryDailyTaskRewardController";
|
||||||
import { clearDialogueHistoryController } from "@/src/controllers/api/clearDialogueHistoryController";
|
import { clearDialogueHistoryController } from "@/src/controllers/api/clearDialogueHistoryController";
|
||||||
import { completeRandomModChallengeController } from "@/src/controllers/api/completeRandomModChallengeController";
|
import { completeRandomModChallengeController } from "@/src/controllers/api/completeRandomModChallengeController";
|
||||||
|
import { contributeToDojoComponentController } from "@/src/controllers/api/contributeToDojoComponentController";
|
||||||
import { createGuildController } from "@/src/controllers/api/createGuildController";
|
import { createGuildController } from "@/src/controllers/api/createGuildController";
|
||||||
import { creditsController } from "@/src/controllers/api/creditsController";
|
import { creditsController } from "@/src/controllers/api/creditsController";
|
||||||
import { deleteSessionController } from "@/src/controllers/api/deleteSessionController";
|
import { deleteSessionController } from "@/src/controllers/api/deleteSessionController";
|
||||||
@ -135,6 +137,7 @@ apiRouter.get("/surveys.php", surveysController);
|
|||||||
apiRouter.get("/updateSession.php", updateSessionGetController);
|
apiRouter.get("/updateSession.php", updateSessionGetController);
|
||||||
|
|
||||||
// post
|
// post
|
||||||
|
apiRouter.post("/abortDojoComponent.php", abortDojoComponentController);
|
||||||
apiRouter.post("/activateRandomMod.php", activateRandomModController);
|
apiRouter.post("/activateRandomMod.php", activateRandomModController);
|
||||||
apiRouter.post("/addFriendImage.php", addFriendImageController);
|
apiRouter.post("/addFriendImage.php", addFriendImageController);
|
||||||
apiRouter.post("/arcaneCommon.php", arcaneCommonController);
|
apiRouter.post("/arcaneCommon.php", arcaneCommonController);
|
||||||
@ -144,6 +147,7 @@ apiRouter.post("/changeDojoRoot.php", changeDojoRootController);
|
|||||||
apiRouter.post("/claimCompletedRecipe.php", claimCompletedRecipeController);
|
apiRouter.post("/claimCompletedRecipe.php", claimCompletedRecipeController);
|
||||||
apiRouter.post("/clearDialogueHistory.php", clearDialogueHistoryController);
|
apiRouter.post("/clearDialogueHistory.php", clearDialogueHistoryController);
|
||||||
apiRouter.post("/completeRandomModChallenge.php", completeRandomModChallengeController);
|
apiRouter.post("/completeRandomModChallenge.php", completeRandomModChallengeController);
|
||||||
|
apiRouter.post("/contributeToDojoComponent.php", contributeToDojoComponentController);
|
||||||
apiRouter.post("/createGuild.php", createGuildController);
|
apiRouter.post("/createGuild.php", createGuildController);
|
||||||
apiRouter.post("/drones.php", dronesController);
|
apiRouter.post("/drones.php", dronesController);
|
||||||
apiRouter.post("/endlessXp.php", endlessXpController);
|
apiRouter.post("/endlessXp.php", endlessXpController);
|
||||||
|
@ -5,6 +5,7 @@ import { Guild, TGuildDatabaseDocument } from "@/src/models/guildModel";
|
|||||||
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
import { TInventoryDatabaseDocument } from "@/src/models/inventoryModels/inventoryModel";
|
||||||
import { IDojoClient, IDojoComponentClient } from "@/src/types/guildTypes";
|
import { IDojoClient, IDojoComponentClient } from "@/src/types/guildTypes";
|
||||||
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
|
import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
|
||||||
|
import { Types } from "mongoose";
|
||||||
|
|
||||||
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);
|
||||||
@ -27,7 +28,11 @@ export const getGuildForRequestEx = async (
|
|||||||
return guild;
|
return guild;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDojoClient = (guild: TGuildDatabaseDocument, status: number): IDojoClient => {
|
export const getDojoClient = (
|
||||||
|
guild: TGuildDatabaseDocument,
|
||||||
|
status: number,
|
||||||
|
componentId: Types.ObjectId | undefined = undefined
|
||||||
|
): IDojoClient => {
|
||||||
const dojo: IDojoClient = {
|
const dojo: IDojoClient = {
|
||||||
_id: { $oid: guild._id.toString() },
|
_id: { $oid: guild._id.toString() },
|
||||||
Name: guild.Name,
|
Name: guild.Name,
|
||||||
@ -41,23 +46,33 @@ export const getDojoClient = (guild: TGuildDatabaseDocument, status: number): ID
|
|||||||
DojoComponents: []
|
DojoComponents: []
|
||||||
};
|
};
|
||||||
guild.DojoComponents.forEach(dojoComponent => {
|
guild.DojoComponents.forEach(dojoComponent => {
|
||||||
const clientComponent: IDojoComponentClient = {
|
if (!componentId || componentId == dojoComponent._id) {
|
||||||
id: toOid(dojoComponent._id),
|
const clientComponent: IDojoComponentClient = {
|
||||||
pf: dojoComponent.pf,
|
id: toOid(dojoComponent._id),
|
||||||
ppf: dojoComponent.ppf,
|
pf: dojoComponent.pf,
|
||||||
Name: dojoComponent.Name,
|
ppf: dojoComponent.ppf,
|
||||||
Message: dojoComponent.Message,
|
Name: dojoComponent.Name,
|
||||||
DecoCapacity: 600
|
Message: dojoComponent.Message,
|
||||||
};
|
DecoCapacity: 600
|
||||||
if (dojoComponent.pi) {
|
};
|
||||||
clientComponent.pi = toOid(dojoComponent.pi);
|
if (dojoComponent.pi) {
|
||||||
clientComponent.op = dojoComponent.op!;
|
clientComponent.pi = toOid(dojoComponent.pi);
|
||||||
clientComponent.pp = dojoComponent.pp!;
|
clientComponent.op = dojoComponent.op!;
|
||||||
|
clientComponent.pp = dojoComponent.pp!;
|
||||||
|
}
|
||||||
|
if (dojoComponent.CompletionTime) {
|
||||||
|
clientComponent.CompletionTime = toMongoDate(dojoComponent.CompletionTime);
|
||||||
|
} else {
|
||||||
|
clientComponent.RegularCredits = dojoComponent.RegularCredits;
|
||||||
|
clientComponent.MiscItems = dojoComponent.MiscItems;
|
||||||
|
}
|
||||||
|
dojo.DojoComponents.push(clientComponent);
|
||||||
}
|
}
|
||||||
if (dojoComponent.CompletionTime) {
|
|
||||||
clientComponent.CompletionTime = toMongoDate(dojoComponent.CompletionTime);
|
|
||||||
}
|
|
||||||
dojo.DojoComponents.push(clientComponent);
|
|
||||||
});
|
});
|
||||||
return dojo;
|
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));
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user