feat: dojo room destruction stage (#1089)
Closes #1074 Based on what I could find, apparently only rooms need 2 hours to destroy and decos are removed instantly. Reviewed-on: OpenWF/SpaceNinjaServer#1089
This commit is contained in:
parent
6daa8ab5da
commit
77aa1caa8f
@ -33,6 +33,7 @@
|
|||||||
"noDailyStandingLimits": true,
|
"noDailyStandingLimits": true,
|
||||||
"instantResourceExtractorDrones": false,
|
"instantResourceExtractorDrones": false,
|
||||||
"noDojoRoomBuildStage": true,
|
"noDojoRoomBuildStage": true,
|
||||||
|
"fastDojoRoomDestruction": true,
|
||||||
"noDojoResearchCosts": true,
|
"noDojoResearchCosts": true,
|
||||||
"noDojoResearchTime": true,
|
"noDojoResearchTime": true,
|
||||||
"spoofMasteryRank": -1
|
"spoofMasteryRank": -1
|
||||||
|
@ -9,7 +9,6 @@ export const abortDojoComponentController: RequestHandler = async (req, res) =>
|
|||||||
const guild = await getGuildForRequestEx(req, inventory);
|
const guild = await getGuildForRequestEx(req, inventory);
|
||||||
const request = JSON.parse(String(req.body)) as IAbortDojoComponentRequest;
|
const request = JSON.parse(String(req.body)) as IAbortDojoComponentRequest;
|
||||||
|
|
||||||
// TODO: Move already-contributed credits & items to the clan vault
|
|
||||||
if (request.DecoId) {
|
if (request.DecoId) {
|
||||||
removeDojoDeco(guild, request.ComponentId, request.DecoId);
|
removeDojoDeco(guild, request.ComponentId, request.DecoId);
|
||||||
} else {
|
} else {
|
||||||
@ -17,7 +16,7 @@ export const abortDojoComponentController: RequestHandler = async (req, res) =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
await guild.save();
|
await guild.save();
|
||||||
res.json(getDojoClient(guild, 0, request.ComponentId));
|
res.json(await getDojoClient(guild, 0, request.ComponentId));
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IAbortDojoComponentRequest {
|
interface IAbortDojoComponentRequest {
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
|
||||||
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
|
export const abortDojoComponentDestructionController: RequestHandler = async (req, res) => {
|
||||||
|
const guild = await getGuildForRequest(req);
|
||||||
|
const componentId = req.query.componentId as string;
|
||||||
|
|
||||||
|
guild.DojoComponents.id(componentId)!.DestructionTime = undefined;
|
||||||
|
|
||||||
|
await guild.save();
|
||||||
|
res.json(await getDojoClient(guild, 0, componentId));
|
||||||
|
};
|
@ -58,7 +58,7 @@ export const changeDojoRootController: RequestHandler = async (req, res) => {
|
|||||||
|
|
||||||
await guild.save();
|
await guild.save();
|
||||||
|
|
||||||
res.json(getDojoClient(guild, 0));
|
res.json(await getDojoClient(guild, 0));
|
||||||
};
|
};
|
||||||
|
|
||||||
interface INode {
|
interface INode {
|
||||||
|
@ -50,7 +50,7 @@ export const contributeToDojoComponentController: RequestHandler = async (req, r
|
|||||||
await guild.save();
|
await guild.save();
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
res.json({
|
res.json({
|
||||||
...getDojoClient(guild, 0, component._id),
|
...(await getDojoClient(guild, 0, component._id)),
|
||||||
InventoryChanges: inventoryChanges
|
InventoryChanges: inventoryChanges
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -6,10 +6,9 @@ export const destroyDojoDecoController: RequestHandler = async (req, res) => {
|
|||||||
const request = JSON.parse(String(req.body)) as IDestroyDojoDecoRequest;
|
const request = JSON.parse(String(req.body)) as IDestroyDojoDecoRequest;
|
||||||
|
|
||||||
removeDojoDeco(guild, request.ComponentId, request.DecoId);
|
removeDojoDeco(guild, request.ComponentId, request.DecoId);
|
||||||
// TODO: The client says this is supposed to refund the resources to the clan vault, so we should probably do that.
|
|
||||||
|
|
||||||
await guild.save();
|
await guild.save();
|
||||||
res.json(getDojoClient(guild, 0, request.ComponentId));
|
res.json(await getDojoClient(guild, 0, request.ComponentId));
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IDestroyDojoDecoRequest {
|
interface IDestroyDojoDecoRequest {
|
||||||
|
@ -35,7 +35,7 @@ export const dojoComponentRushController: RequestHandler = async (req, res) => {
|
|||||||
await guild.save();
|
await guild.save();
|
||||||
await inventory.save();
|
await inventory.save();
|
||||||
res.json({
|
res.json({
|
||||||
...getDojoClient(guild, 0, component._id),
|
...(await getDojoClient(guild, 0, component._id)),
|
||||||
InventoryChanges: inventoryChanges
|
InventoryChanges: inventoryChanges
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -24,5 +24,5 @@ export const getGuildDojoController: RequestHandler = async (req, res) => {
|
|||||||
await guild.save();
|
await guild.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json(getDojoClient(guild, 0));
|
res.json(await getDojoClient(guild, 0));
|
||||||
};
|
};
|
||||||
|
@ -30,7 +30,7 @@ export const placeDecoInComponentController: RequestHandler = async (req, res) =
|
|||||||
}
|
}
|
||||||
|
|
||||||
await guild.save();
|
await guild.save();
|
||||||
res.json(getDojoClient(guild, 0, component._id));
|
res.json(await getDojoClient(guild, 0, component._id));
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IPlaceDecoInComponentRequest {
|
interface IPlaceDecoInComponentRequest {
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
import { getDojoClient, getGuildForRequest, removeDojoRoom } from "@/src/services/guildService";
|
import { config } from "@/src/services/configService";
|
||||||
|
import { getDojoClient, getGuildForRequest } from "@/src/services/guildService";
|
||||||
import { RequestHandler } from "express";
|
import { RequestHandler } from "express";
|
||||||
|
|
||||||
export const queueDojoComponentDestructionController: RequestHandler = async (req, res) => {
|
export const queueDojoComponentDestructionController: RequestHandler = async (req, res) => {
|
||||||
const guild = await getGuildForRequest(req);
|
const guild = await getGuildForRequest(req);
|
||||||
const componentId = req.query.componentId as string;
|
const componentId = req.query.componentId as string;
|
||||||
|
|
||||||
removeDojoRoom(guild, componentId);
|
guild.DojoComponents.id(componentId)!.DestructionTime = new Date(
|
||||||
|
Date.now() + (config.fastDojoRoomDestruction ? 5_000 : 2 * 3600_000)
|
||||||
|
);
|
||||||
|
|
||||||
await guild.save();
|
await guild.save();
|
||||||
res.json(getDojoClient(guild, 1));
|
res.json(await getDojoClient(guild, 0, componentId));
|
||||||
};
|
};
|
||||||
|
@ -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, 0, component._id));
|
res.json(await getDojoClient(guild, 0, component._id));
|
||||||
};
|
};
|
||||||
|
|
||||||
type SetDojoComponentMessageRequest = { Name: string } | { Message: string };
|
type SetDojoComponentMessageRequest = { Name: string } | { Message: string };
|
||||||
|
@ -37,5 +37,5 @@ export const startDojoRecipeController: RequestHandler = async (req, res) => {
|
|||||||
component.CompletionTime = new Date(Date.now());
|
component.CompletionTime = new Date(Date.now());
|
||||||
}
|
}
|
||||||
await guild.save();
|
await guild.save();
|
||||||
res.json(getDojoClient(guild, 0));
|
res.json(await getDojoClient(guild, 0));
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
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 { abortDojoComponentController } from "@/src/controllers/api/abortDojoComponentController";
|
||||||
|
import { abortDojoComponentDestructionController } from "@/src/controllers/api/abortDojoComponentDestructionController";
|
||||||
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";
|
||||||
@ -105,6 +106,7 @@ const apiRouter = express.Router();
|
|||||||
|
|
||||||
// get
|
// get
|
||||||
apiRouter.get("/abandonLibraryDailyTask.php", abandonLibraryDailyTaskController);
|
apiRouter.get("/abandonLibraryDailyTask.php", abandonLibraryDailyTaskController);
|
||||||
|
apiRouter.get("/abortDojoComponentDestruction.php", abortDojoComponentDestructionController);
|
||||||
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
|
apiRouter.get("/checkDailyMissionBonus.php", checkDailyMissionBonusController);
|
||||||
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
|
apiRouter.get("/claimLibraryDailyTaskReward.php", claimLibraryDailyTaskRewardController);
|
||||||
apiRouter.get("/credits.php", creditsController);
|
apiRouter.get("/credits.php", creditsController);
|
||||||
|
@ -59,6 +59,7 @@ interface IConfig {
|
|||||||
noDailyStandingLimits?: boolean;
|
noDailyStandingLimits?: boolean;
|
||||||
instantResourceExtractorDrones?: boolean;
|
instantResourceExtractorDrones?: boolean;
|
||||||
noDojoRoomBuildStage?: boolean;
|
noDojoRoomBuildStage?: boolean;
|
||||||
|
fastDojoRoomDestruction?: boolean;
|
||||||
noDojoResearchCosts?: boolean;
|
noDojoResearchCosts?: boolean;
|
||||||
noDojoResearchTime?: boolean;
|
noDojoResearchTime?: boolean;
|
||||||
spoofMasteryRank?: number;
|
spoofMasteryRank?: number;
|
||||||
|
@ -7,6 +7,7 @@ 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";
|
import { Types } from "mongoose";
|
||||||
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
import { ExportDojoRecipes } from "warframe-public-export-plus";
|
||||||
|
import { logger } from "../utils/logger";
|
||||||
|
|
||||||
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);
|
||||||
@ -29,11 +30,11 @@ export const getGuildForRequestEx = async (
|
|||||||
return guild;
|
return guild;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDojoClient = (
|
export const getDojoClient = async (
|
||||||
guild: TGuildDatabaseDocument,
|
guild: TGuildDatabaseDocument,
|
||||||
status: number,
|
status: number,
|
||||||
componentId: Types.ObjectId | string | undefined = undefined
|
componentId: Types.ObjectId | string | undefined = undefined
|
||||||
): IDojoClient => {
|
): Promise<IDojoClient> => {
|
||||||
const dojo: IDojoClient = {
|
const dojo: IDojoClient = {
|
||||||
_id: { $oid: guild._id.toString() },
|
_id: { $oid: guild._id.toString() },
|
||||||
Name: guild.Name,
|
Name: guild.Name,
|
||||||
@ -46,6 +47,7 @@ export const getDojoClient = (
|
|||||||
DojoRequestStatus: status,
|
DojoRequestStatus: status,
|
||||||
DojoComponents: []
|
DojoComponents: []
|
||||||
};
|
};
|
||||||
|
const roomsToRemove: Types.ObjectId[] = [];
|
||||||
guild.DojoComponents.forEach(dojoComponent => {
|
guild.DojoComponents.forEach(dojoComponent => {
|
||||||
if (!componentId || dojoComponent._id.equals(componentId)) {
|
if (!componentId || dojoComponent._id.equals(componentId)) {
|
||||||
const clientComponent: IDojoComponentClient = {
|
const clientComponent: IDojoComponentClient = {
|
||||||
@ -63,6 +65,13 @@ export const getDojoClient = (
|
|||||||
}
|
}
|
||||||
if (dojoComponent.CompletionTime) {
|
if (dojoComponent.CompletionTime) {
|
||||||
clientComponent.CompletionTime = toMongoDate(dojoComponent.CompletionTime);
|
clientComponent.CompletionTime = toMongoDate(dojoComponent.CompletionTime);
|
||||||
|
if (dojoComponent.DestructionTime) {
|
||||||
|
if (Date.now() >= dojoComponent.DestructionTime.getTime()) {
|
||||||
|
roomsToRemove.push(dojoComponent._id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
clientComponent.DestructionTime = toMongoDate(dojoComponent.DestructionTime);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
clientComponent.RegularCredits = dojoComponent.RegularCredits;
|
clientComponent.RegularCredits = dojoComponent.RegularCredits;
|
||||||
clientComponent.MiscItems = dojoComponent.MiscItems;
|
clientComponent.MiscItems = dojoComponent.MiscItems;
|
||||||
@ -84,6 +93,13 @@ export const getDojoClient = (
|
|||||||
dojo.DojoComponents.push(clientComponent);
|
dojo.DojoComponents.push(clientComponent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (roomsToRemove.length) {
|
||||||
|
logger.debug(`removing now-destroyed rooms`, roomsToRemove);
|
||||||
|
for (const id of roomsToRemove) {
|
||||||
|
removeDojoRoom(guild, id);
|
||||||
|
}
|
||||||
|
await guild.save();
|
||||||
|
}
|
||||||
return dojo;
|
return dojo;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,7 +108,7 @@ export const scaleRequiredCount = (count: number): number => {
|
|||||||
return Math.max(1, Math.trunc(count / 100));
|
return Math.max(1, Math.trunc(count / 100));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: string): void => {
|
export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: Types.ObjectId | string): 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
|
||||||
@ -102,9 +118,14 @@ export const removeDojoRoom = (guild: TGuildDatabaseDocument, componentId: strin
|
|||||||
guild.DojoCapacity -= meta.capacity;
|
guild.DojoCapacity -= meta.capacity;
|
||||||
guild.DojoEnergy -= meta.energy;
|
guild.DojoEnergy -= meta.energy;
|
||||||
}
|
}
|
||||||
|
// TODO: Add resources spent to the clan vault
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeDojoDeco = (guild: TGuildDatabaseDocument, componentId: string, decoId: string): void => {
|
export const removeDojoDeco = (
|
||||||
|
guild: TGuildDatabaseDocument,
|
||||||
|
componentId: Types.ObjectId | string,
|
||||||
|
decoId: Types.ObjectId | string
|
||||||
|
): void => {
|
||||||
const component = guild.DojoComponents.id(componentId)!;
|
const component = guild.DojoComponents.id(componentId)!;
|
||||||
const deco = component.Decos!.splice(
|
const deco = component.Decos!.splice(
|
||||||
component.Decos!.findIndex(x => x._id.equals(decoId)),
|
component.Decos!.findIndex(x => x._id.equals(decoId)),
|
||||||
@ -114,4 +135,5 @@ export const removeDojoDeco = (guild: TGuildDatabaseDocument, componentId: strin
|
|||||||
if (meta && meta.capacityCost) {
|
if (meta && meta.capacityCost) {
|
||||||
component.DecoCapacity! += meta.capacityCost;
|
component.DecoCapacity! += meta.capacityCost;
|
||||||
}
|
}
|
||||||
|
// TODO: Add resources spent to the clan vault
|
||||||
};
|
};
|
||||||
|
@ -525,6 +525,10 @@
|
|||||||
<input class="form-check-input" type="checkbox" id="noDojoRoomBuildStage" />
|
<input class="form-check-input" type="checkbox" id="noDojoRoomBuildStage" />
|
||||||
<label class="form-check-label" for="noDojoRoomBuildStage" data-loc="cheats_noDojoRoomBuildStage"></label>
|
<label class="form-check-label" for="noDojoRoomBuildStage" data-loc="cheats_noDojoRoomBuildStage"></label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-check">
|
||||||
|
<input class="form-check-input" type="checkbox" id="fastDojoRoomDestruction" />
|
||||||
|
<label class="form-check-label" for="fastDojoRoomDestruction" data-loc="cheats_fastDojoRoomDestruction"></label>
|
||||||
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="checkbox" id="noDojoResearchCosts" />
|
<input class="form-check-input" type="checkbox" id="noDojoResearchCosts" />
|
||||||
<label class="form-check-label" for="noDojoResearchCosts" data-loc="cheats_noDojoResearchCosts"></label>
|
<label class="form-check-label" for="noDojoResearchCosts" data-loc="cheats_noDojoResearchCosts"></label>
|
||||||
|
@ -111,6 +111,7 @@ dict = {
|
|||||||
cheats_noDailyStandingLimits: `No Daily Standing Limits`,
|
cheats_noDailyStandingLimits: `No Daily Standing Limits`,
|
||||||
cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`,
|
cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`,
|
||||||
cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
|
cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
|
||||||
|
cheats_fastDojoRoomDestruction: `Fast Dojo Room Destruction`,
|
||||||
cheats_noDojoResearchCosts: `No Dojo Research Costs`,
|
cheats_noDojoResearchCosts: `No Dojo Research Costs`,
|
||||||
cheats_noDojoResearchTime: `No Dojo Research Time`,
|
cheats_noDojoResearchTime: `No Dojo Research Time`,
|
||||||
cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`,
|
cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`,
|
||||||
|
@ -112,6 +112,7 @@ dict = {
|
|||||||
cheats_noDailyStandingLimits: `Pas de limite de réputation journalière`,
|
cheats_noDailyStandingLimits: `Pas de limite de réputation journalière`,
|
||||||
cheats_instantResourceExtractorDrones: `Ressources de drone d'extraction instantannées`,
|
cheats_instantResourceExtractorDrones: `Ressources de drone d'extraction instantannées`,
|
||||||
cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
|
cheats_noDojoRoomBuildStage: `No Dojo Room Build Stage`,
|
||||||
|
cheats_fastDojoRoomDestruction: `[UNTRANSLATED] Fast Dojo Room Destruction`,
|
||||||
cheats_noDojoResearchCosts: `Aucun coût de recherche (Dojo)`,
|
cheats_noDojoResearchCosts: `Aucun coût de recherche (Dojo)`,
|
||||||
cheats_noDojoResearchTime: `Aucun temps de recherche (Dojo)`,
|
cheats_noDojoResearchTime: `Aucun temps de recherche (Dojo)`,
|
||||||
cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`,
|
cheats_spoofMasteryRank: `Spoofed Mastery Rank (-1 to disable)`,
|
||||||
|
@ -112,6 +112,7 @@ dict = {
|
|||||||
cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`,
|
cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`,
|
||||||
cheats_instantResourceExtractorDrones: `[UNTRANSLATED] Instant Resource Extractor Drones`,
|
cheats_instantResourceExtractorDrones: `[UNTRANSLATED] Instant Resource Extractor Drones`,
|
||||||
cheats_noDojoRoomBuildStage: `[UNTRANSLATED] No Dojo Room Build Stage`,
|
cheats_noDojoRoomBuildStage: `[UNTRANSLATED] No Dojo Room Build Stage`,
|
||||||
|
cheats_fastDojoRoomDestruction: `[UNTRANSLATED] Fast Dojo Room Destruction`,
|
||||||
cheats_noDojoResearchCosts: `[UNTRANSLATED] No Dojo Research Costs`,
|
cheats_noDojoResearchCosts: `[UNTRANSLATED] No Dojo Research Costs`,
|
||||||
cheats_noDojoResearchTime: `[UNTRANSLATED] No Dojo Research Time`,
|
cheats_noDojoResearchTime: `[UNTRANSLATED] No Dojo Research Time`,
|
||||||
cheats_spoofMasteryRank: `Подделанный ранг мастерства (-1 для отключения)`,
|
cheats_spoofMasteryRank: `Подделанный ранг мастерства (-1 для отключения)`,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user