feat: resource extractor drones (#1068)
Closes #793 Reviewed-on: OpenWF/SpaceNinjaServer#1068
This commit is contained in:
		
							parent
							
								
									36d12e08c7
								
							
						
					
					
						commit
						b3003b9fb3
					
				@ -31,6 +31,7 @@
 | 
				
			|||||||
  "unlockExilusEverywhere": true,
 | 
					  "unlockExilusEverywhere": true,
 | 
				
			||||||
  "unlockArcanesEverywhere": true,
 | 
					  "unlockArcanesEverywhere": true,
 | 
				
			||||||
  "noDailyStandingLimits": true,
 | 
					  "noDailyStandingLimits": true,
 | 
				
			||||||
 | 
					  "instantResourceExtractorDrones": false,
 | 
				
			||||||
  "noDojoResearchCosts": true,
 | 
					  "noDojoResearchCosts": true,
 | 
				
			||||||
  "noDojoResearchTime": true,
 | 
					  "noDojoResearchTime": true,
 | 
				
			||||||
  "spoofMasteryRank": -1
 | 
					  "spoofMasteryRank": -1
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										8
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@ -12,7 +12,7 @@
 | 
				
			|||||||
        "copyfiles": "^2.4.1",
 | 
					        "copyfiles": "^2.4.1",
 | 
				
			||||||
        "express": "^5",
 | 
					        "express": "^5",
 | 
				
			||||||
        "mongoose": "^8.11.0",
 | 
					        "mongoose": "^8.11.0",
 | 
				
			||||||
        "warframe-public-export-plus": "^0.5.38",
 | 
					        "warframe-public-export-plus": "^0.5.39",
 | 
				
			||||||
        "warframe-riven-info": "^0.1.2",
 | 
					        "warframe-riven-info": "^0.1.2",
 | 
				
			||||||
        "winston": "^3.17.0",
 | 
					        "winston": "^3.17.0",
 | 
				
			||||||
        "winston-daily-rotate-file": "^5.0.0"
 | 
					        "winston-daily-rotate-file": "^5.0.0"
 | 
				
			||||||
@ -4083,9 +4083,9 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/warframe-public-export-plus": {
 | 
					    "node_modules/warframe-public-export-plus": {
 | 
				
			||||||
      "version": "0.5.38",
 | 
					      "version": "0.5.39",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.38.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/warframe-public-export-plus/-/warframe-public-export-plus-0.5.39.tgz",
 | 
				
			||||||
      "integrity": "sha512-yvc86eOmYPSnnU8LzLBhg/lR1AS1RHID24TqFHVcZuOzMYc934NL8Cv7rtllyefWAMyl7iA5x9tyXSuJWbi6CA=="
 | 
					      "integrity": "sha512-sEGZedtW4I/M2ceoDs6MQ5eHD7sJgv1KRNLt8BWByXLuDa7qTR3Y9px5TGxqt/rBHKGUyPO1LUxu4bDGZi6yXw=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/warframe-riven-info": {
 | 
					    "node_modules/warframe-riven-info": {
 | 
				
			||||||
      "version": "0.1.2",
 | 
					      "version": "0.1.2",
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
    "copyfiles": "^2.4.1",
 | 
					    "copyfiles": "^2.4.1",
 | 
				
			||||||
    "express": "^5",
 | 
					    "express": "^5",
 | 
				
			||||||
    "mongoose": "^8.11.0",
 | 
					    "mongoose": "^8.11.0",
 | 
				
			||||||
    "warframe-public-export-plus": "^0.5.38",
 | 
					    "warframe-public-export-plus": "^0.5.39",
 | 
				
			||||||
    "warframe-riven-info": "^0.1.2",
 | 
					    "warframe-riven-info": "^0.1.2",
 | 
				
			||||||
    "winston": "^3.17.0",
 | 
					    "winston": "^3.17.0",
 | 
				
			||||||
    "winston-daily-rotate-file": "^5.0.0"
 | 
					    "winston-daily-rotate-file": "^5.0.0"
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,140 @@
 | 
				
			|||||||
 | 
					import { toMongoDate, toOid } from "@/src/helpers/inventoryHelpers";
 | 
				
			||||||
 | 
					import { config } from "@/src/services/configService";
 | 
				
			||||||
 | 
					import { addMiscItems, getInventory } from "@/src/services/inventoryService";
 | 
				
			||||||
 | 
					import { getAccountIdForRequest } from "@/src/services/loginService";
 | 
				
			||||||
 | 
					import { getRandomInt, getRandomWeightedReward3 } from "@/src/services/rngService";
 | 
				
			||||||
 | 
					import { IMongoDate, IOid } from "@/src/types/commonTypes";
 | 
				
			||||||
 | 
					import { IDroneClient } from "@/src/types/inventoryTypes/inventoryTypes";
 | 
				
			||||||
 | 
					import { IInventoryChanges } from "@/src/types/purchaseTypes";
 | 
				
			||||||
import { RequestHandler } from "express";
 | 
					import { RequestHandler } from "express";
 | 
				
			||||||
 | 
					import { ExportDrones, ExportResources, ExportSystems } from "warframe-public-export-plus";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const dronesController: RequestHandler = (_req, res) => {
 | 
					export const dronesController: RequestHandler = async (req, res) => {
 | 
				
			||||||
 | 
					    const accountId = await getAccountIdForRequest(req);
 | 
				
			||||||
 | 
					    const inventory = await getInventory(accountId);
 | 
				
			||||||
 | 
					    if ("GetActive" in req.query) {
 | 
				
			||||||
 | 
					        const activeDrones: IActiveDrone[] = [];
 | 
				
			||||||
 | 
					        for (const drone of inventory.Drones) {
 | 
				
			||||||
 | 
					            if (drone.DeployTime) {
 | 
				
			||||||
 | 
					                activeDrones.push({
 | 
				
			||||||
 | 
					                    DeployTime: toMongoDate(drone.DeployTime),
 | 
				
			||||||
 | 
					                    System: drone.System!,
 | 
				
			||||||
 | 
					                    ItemId: toOid(drone._id),
 | 
				
			||||||
 | 
					                    ItemType: drone.ItemType,
 | 
				
			||||||
 | 
					                    CurrentHP: drone.CurrentHP,
 | 
				
			||||||
 | 
					                    DamageTime: toMongoDate(drone.DamageTime!),
 | 
				
			||||||
 | 
					                    PendingDamage: drone.PendingDamage!,
 | 
				
			||||||
 | 
					                    Resources: [
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            ItemType: drone.ResourceType!,
 | 
				
			||||||
 | 
					                            BinTotal: drone.ResourceCount!,
 | 
				
			||||||
 | 
					                            StartTime: toMongoDate(drone.DeployTime)
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    ]
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        res.json({
 | 
				
			||||||
 | 
					            ActiveDrones: activeDrones
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    } else if ("droneId" in req.query && "systemIndex" in req.query) {
 | 
				
			||||||
 | 
					        const drone = inventory.Drones.id(req.query.droneId as string)!;
 | 
				
			||||||
 | 
					        const droneMeta = ExportDrones[drone.ItemType];
 | 
				
			||||||
 | 
					        drone.DeployTime = config.instantResourceExtractorDrones ? new Date(0) : new Date();
 | 
				
			||||||
 | 
					        if (drone.RepairStart) {
 | 
				
			||||||
 | 
					            const repairMinutes = (Date.now() - drone.RepairStart.getTime()) / 60_000;
 | 
				
			||||||
 | 
					            const hpPerMinute = droneMeta.repairRate / 60;
 | 
				
			||||||
 | 
					            drone.CurrentHP = Math.min(drone.CurrentHP + Math.round(repairMinutes * hpPerMinute), droneMeta.durability);
 | 
				
			||||||
 | 
					            drone.RepairStart = undefined;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        drone.System = parseInt(req.query.systemIndex as string);
 | 
				
			||||||
 | 
					        const system = ExportSystems[drone.System - 1];
 | 
				
			||||||
 | 
					        drone.DamageTime = config.instantResourceExtractorDrones
 | 
				
			||||||
 | 
					            ? new Date()
 | 
				
			||||||
 | 
					            : new Date(Date.now() + getRandomInt(3 * 3600 * 1000, 4 * 3600 * 1000));
 | 
				
			||||||
 | 
					        drone.PendingDamage =
 | 
				
			||||||
 | 
					            Math.random() < system.damageChance
 | 
				
			||||||
 | 
					                ? getRandomInt(system.droneDamage.minValue, system.droneDamage.maxValue)
 | 
				
			||||||
 | 
					                : 0;
 | 
				
			||||||
 | 
					        const resource = getRandomWeightedReward3(system.resources, droneMeta.probabilities)!;
 | 
				
			||||||
 | 
					        //logger.debug(`drone rolled`, resource);
 | 
				
			||||||
 | 
					        drone.ResourceType = "/Lotus/" + resource.StoreItem.substring(18);
 | 
				
			||||||
 | 
					        const resourceMeta = ExportResources[drone.ResourceType];
 | 
				
			||||||
 | 
					        if (resourceMeta.pickupQuantity) {
 | 
				
			||||||
 | 
					            const pickupsToCollect = droneMeta.binCapacity * droneMeta.capacityMultipliers[resource.Rarity];
 | 
				
			||||||
 | 
					            drone.ResourceCount = 0;
 | 
				
			||||||
 | 
					            for (let i = 0; i != pickupsToCollect; ++i) {
 | 
				
			||||||
 | 
					                drone.ResourceCount += getRandomInt(
 | 
				
			||||||
 | 
					                    resourceMeta.pickupQuantity.minValue,
 | 
				
			||||||
 | 
					                    resourceMeta.pickupQuantity.maxValue
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            drone.ResourceCount = 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        await inventory.save();
 | 
				
			||||||
        res.json({});
 | 
					        res.json({});
 | 
				
			||||||
 | 
					    } else if ("collectDroneId" in req.query) {
 | 
				
			||||||
 | 
					        const drone = inventory.Drones.id(req.query.collectDroneId as string)!;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (new Date() >= drone.DamageTime!) {
 | 
				
			||||||
 | 
					            drone.CurrentHP -= drone.PendingDamage!;
 | 
				
			||||||
 | 
					            drone.RepairStart = new Date();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const inventoryChanges: IInventoryChanges = {};
 | 
				
			||||||
 | 
					        if (drone.CurrentHP <= 0) {
 | 
				
			||||||
 | 
					            inventory.RegularCredits += 100;
 | 
				
			||||||
 | 
					            inventoryChanges.RegularCredits = 100;
 | 
				
			||||||
 | 
					            inventory.Drones.pull({ _id: req.query.collectDroneId as string });
 | 
				
			||||||
 | 
					            inventoryChanges.RemovedIdItems = [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ItemId: { $oid: req.query.collectDroneId }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            const completionTime = drone.DeployTime!.getTime() + ExportDrones[drone.ItemType].fillRate * 3600_000;
 | 
				
			||||||
 | 
					            if (Date.now() >= completionTime) {
 | 
				
			||||||
 | 
					                const miscItemChanges = [
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        ItemType: drone.ResourceType!,
 | 
				
			||||||
 | 
					                        ItemCount: drone.ResourceCount!
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                ];
 | 
				
			||||||
 | 
					                addMiscItems(inventory, miscItemChanges);
 | 
				
			||||||
 | 
					                inventoryChanges.MiscItems = miscItemChanges;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            drone.DeployTime = undefined;
 | 
				
			||||||
 | 
					            drone.System = undefined;
 | 
				
			||||||
 | 
					            drone.DamageTime = undefined;
 | 
				
			||||||
 | 
					            drone.PendingDamage = undefined;
 | 
				
			||||||
 | 
					            drone.ResourceType = undefined;
 | 
				
			||||||
 | 
					            drone.ResourceCount = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            inventoryChanges.Drones = [drone.toJSON<IDroneClient>()];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await inventory.save();
 | 
				
			||||||
 | 
					        res.json({
 | 
				
			||||||
 | 
					            InventoryChanges: inventoryChanges
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        throw new Error(`drones.php query not handled`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export { dronesController };
 | 
					interface IActiveDrone {
 | 
				
			||||||
 | 
					    DeployTime: IMongoDate;
 | 
				
			||||||
 | 
					    System: number;
 | 
				
			||||||
 | 
					    ItemId: IOid;
 | 
				
			||||||
 | 
					    ItemType: string;
 | 
				
			||||||
 | 
					    CurrentHP: number;
 | 
				
			||||||
 | 
					    DamageTime: IMongoDate;
 | 
				
			||||||
 | 
					    PendingDamage: number;
 | 
				
			||||||
 | 
					    Resources: {
 | 
				
			||||||
 | 
					        ItemType: string;
 | 
				
			||||||
 | 
					        BinTotal: number;
 | 
				
			||||||
 | 
					        StartTime: IMongoDate;
 | 
				
			||||||
 | 
					    }[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -86,6 +86,11 @@ export const sellController: RequestHandler = async (req, res) => {
 | 
				
			|||||||
            inventory.Hoverboards.pull({ _id: sellItem.String });
 | 
					            inventory.Hoverboards.pull({ _id: sellItem.String });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (payload.Items.Drones) {
 | 
				
			||||||
 | 
					        payload.Items.Drones.forEach(sellItem => {
 | 
				
			||||||
 | 
					            inventory.Drones.pull({ _id: sellItem.String });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (payload.Items.Consumables) {
 | 
					    if (payload.Items.Consumables) {
 | 
				
			||||||
        const consumablesChanges = [];
 | 
					        const consumablesChanges = [];
 | 
				
			||||||
        for (const sellItem of payload.Items.Consumables) {
 | 
					        for (const sellItem of payload.Items.Consumables) {
 | 
				
			||||||
@ -152,6 +157,7 @@ interface ISellRequest {
 | 
				
			|||||||
        SentinelWeapons?: ISellItem[];
 | 
					        SentinelWeapons?: ISellItem[];
 | 
				
			||||||
        OperatorAmps?: ISellItem[];
 | 
					        OperatorAmps?: ISellItem[];
 | 
				
			||||||
        Hoverboards?: ISellItem[];
 | 
					        Hoverboards?: ISellItem[];
 | 
				
			||||||
 | 
					        Drones?: ISellItem[];
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    SellPrice: number;
 | 
					    SellPrice: number;
 | 
				
			||||||
    SellCurrency:
 | 
					    SellCurrency:
 | 
				
			||||||
 | 
				
			|||||||
@ -336,7 +336,14 @@ const droneSchema = new Schema<IDroneDatabase>(
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
        ItemType: String,
 | 
					        ItemType: String,
 | 
				
			||||||
        CurrentHP: Number,
 | 
					        CurrentHP: Number,
 | 
				
			||||||
        RepairStart: { type: Date, default: undefined }
 | 
					        RepairStart: { type: Date, default: undefined },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        DeployTime: { type: Date, default: undefined },
 | 
				
			||||||
 | 
					        System: Number,
 | 
				
			||||||
 | 
					        DamageTime: { type: Date, default: undefined },
 | 
				
			||||||
 | 
					        PendingDamage: Number,
 | 
				
			||||||
 | 
					        ResourceType: String,
 | 
				
			||||||
 | 
					        ResourceCount: Number
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    { id: false }
 | 
					    { id: false }
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
@ -347,6 +354,16 @@ droneSchema.set("toJSON", {
 | 
				
			|||||||
        const db = obj as IDroneDatabase;
 | 
					        const db = obj as IDroneDatabase;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        client.ItemId = toOid(db._id);
 | 
					        client.ItemId = toOid(db._id);
 | 
				
			||||||
 | 
					        if (db.RepairStart) {
 | 
				
			||||||
 | 
					            client.RepairStart = toMongoDate(db.RepairStart);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        delete db.DeployTime;
 | 
				
			||||||
 | 
					        delete db.System;
 | 
				
			||||||
 | 
					        delete db.DamageTime;
 | 
				
			||||||
 | 
					        delete db.PendingDamage;
 | 
				
			||||||
 | 
					        delete db.ResourceType;
 | 
				
			||||||
 | 
					        delete db.ResourceCount;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        delete obj._id;
 | 
					        delete obj._id;
 | 
				
			||||||
        delete obj.__v;
 | 
					        delete obj.__v;
 | 
				
			||||||
 | 
				
			|||||||
@ -145,6 +145,7 @@ 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("/createGuild.php", createGuildController);
 | 
					apiRouter.post("/createGuild.php", createGuildController);
 | 
				
			||||||
 | 
					apiRouter.post("/drones.php", dronesController);
 | 
				
			||||||
apiRouter.post("/endlessXp.php", endlessXpController);
 | 
					apiRouter.post("/endlessXp.php", endlessXpController);
 | 
				
			||||||
apiRouter.post("/evolveWeapon.php", evolveWeaponController);
 | 
					apiRouter.post("/evolveWeapon.php", evolveWeaponController);
 | 
				
			||||||
apiRouter.post("/findSessions.php", findSessionsController);
 | 
					apiRouter.post("/findSessions.php", findSessionsController);
 | 
				
			||||||
 | 
				
			|||||||
@ -57,6 +57,7 @@ interface IConfig {
 | 
				
			|||||||
    unlockExilusEverywhere?: boolean;
 | 
					    unlockExilusEverywhere?: boolean;
 | 
				
			||||||
    unlockArcanesEverywhere?: boolean;
 | 
					    unlockArcanesEverywhere?: boolean;
 | 
				
			||||||
    noDailyStandingLimits?: boolean;
 | 
					    noDailyStandingLimits?: boolean;
 | 
				
			||||||
 | 
					    instantResourceExtractorDrones?: boolean;
 | 
				
			||||||
    noDojoResearchCosts?: boolean;
 | 
					    noDojoResearchCosts?: boolean;
 | 
				
			||||||
    noDojoResearchTime?: boolean;
 | 
					    noDojoResearchTime?: boolean;
 | 
				
			||||||
    spoofMasteryRank?: number;
 | 
					    spoofMasteryRank?: number;
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ export const getRandomInt = (min: number, max: number): number => {
 | 
				
			|||||||
    return Math.floor(Math.random() * (max - min + 1)) + min;
 | 
					    return Math.floor(Math.random() * (max - min + 1)) + min;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const getRandomReward = (pool: IRngResult[]): IRngResult | undefined => {
 | 
					export const getRandomReward = <T extends { probability: number }>(pool: T[]): T | undefined => {
 | 
				
			||||||
    if (pool.length == 0) return;
 | 
					    if (pool.length == 0) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const totalChance = pool.reduce((accum, item) => accum + item.probability, 0);
 | 
					    const totalChance = pool.reduce((accum, item) => accum + item.probability, 0);
 | 
				
			||||||
@ -71,3 +71,21 @@ export const getRandomWeightedReward2 = (
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return getRandomReward(resultPool);
 | 
					    return getRandomReward(resultPool);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const getRandomWeightedReward3 = <T extends { Rarity: TRarity }>(
 | 
				
			||||||
 | 
					    pool: T[],
 | 
				
			||||||
 | 
					    weights: Record<TRarity, number>
 | 
				
			||||||
 | 
					): (T & { probability: number }) | undefined => {
 | 
				
			||||||
 | 
					    const resultPool: (T & { probability: number })[] = [];
 | 
				
			||||||
 | 
					    const rarityCounts: Record<TRarity, number> = { COMMON: 0, UNCOMMON: 0, RARE: 0, LEGENDARY: 0 };
 | 
				
			||||||
 | 
					    for (const entry of pool) {
 | 
				
			||||||
 | 
					        ++rarityCounts[entry.Rarity];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    for (const entry of pool) {
 | 
				
			||||||
 | 
					        resultPool.push({
 | 
				
			||||||
 | 
					            ...entry,
 | 
				
			||||||
 | 
					            probability: weights[entry.Rarity] / rarityCounts[entry.Rarity]
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return getRandomReward(resultPool);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -520,6 +520,13 @@ export interface IDroneDatabase {
 | 
				
			|||||||
    CurrentHP: number;
 | 
					    CurrentHP: number;
 | 
				
			||||||
    _id: Types.ObjectId;
 | 
					    _id: Types.ObjectId;
 | 
				
			||||||
    RepairStart?: Date;
 | 
					    RepairStart?: Date;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    DeployTime?: Date;
 | 
				
			||||||
 | 
					    System?: number;
 | 
				
			||||||
 | 
					    DamageTime?: Date;
 | 
				
			||||||
 | 
					    PendingDamage?: number;
 | 
				
			||||||
 | 
					    ResourceType?: string;
 | 
				
			||||||
 | 
					    ResourceCount?: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ITypeXPItem {
 | 
					export interface ITypeXPItem {
 | 
				
			||||||
 | 
				
			|||||||
@ -517,6 +517,10 @@
 | 
				
			|||||||
                                        <input class="form-check-input" type="checkbox" id="noDailyStandingLimits" />
 | 
					                                        <input class="form-check-input" type="checkbox" id="noDailyStandingLimits" />
 | 
				
			||||||
                                        <label class="form-check-label" for="noDailyStandingLimits" data-loc="cheats_noDailyStandingLimits"></label>
 | 
					                                        <label class="form-check-label" for="noDailyStandingLimits" data-loc="cheats_noDailyStandingLimits"></label>
 | 
				
			||||||
                                    </div>
 | 
					                                    </div>
 | 
				
			||||||
 | 
					                                    <div class="form-check">
 | 
				
			||||||
 | 
					                                        <input class="form-check-input" type="checkbox" id="instantResourceExtractorDrones" />
 | 
				
			||||||
 | 
					                                        <label class="form-check-label" for="instantResourceExtractorDrones" data-loc="cheats_instantResourceExtractorDrones"></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_unlockExilusEverywhere: `Exilus Adapters Everywhere`,
 | 
					    cheats_unlockExilusEverywhere: `Exilus Adapters Everywhere`,
 | 
				
			||||||
    cheats_unlockArcanesEverywhere: `Arcane Adapters Everywhere`,
 | 
					    cheats_unlockArcanesEverywhere: `Arcane Adapters Everywhere`,
 | 
				
			||||||
    cheats_noDailyStandingLimits: `No Daily Standing Limits`,
 | 
					    cheats_noDailyStandingLimits: `No Daily Standing Limits`,
 | 
				
			||||||
 | 
					    cheats_instantResourceExtractorDrones: `Instant Resource Extractor Drones`,
 | 
				
			||||||
    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_unlockExilusEverywhere: `Адаптеры Эксилус везде`,
 | 
					    cheats_unlockExilusEverywhere: `Адаптеры Эксилус везде`,
 | 
				
			||||||
    cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`,
 | 
					    cheats_unlockArcanesEverywhere: `Адаптеры для мистификаторов везде`,
 | 
				
			||||||
    cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`,
 | 
					    cheats_noDailyStandingLimits: `Без ежедневных ограничений репутации`,
 | 
				
			||||||
 | 
					    cheats_instantResourceExtractorDrones: `[UNTRANSLATED] Instant Resource Extractor Drones`,
 | 
				
			||||||
    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