forked from OpenWF/SpaceNinjaServer
		
	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