Greasy Fork

Greasy Fork is available in English.

diepAPI

https://github.com/Cazka/diepAPI

当前为 2022-02-26 提交的版本,查看 最新版本

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/433681/1022511/diepAPI.js

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

var diepAPI;
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	// The require scope
/******/ 	var __webpack_require__ = {};
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "CanvasKit": () => (/* reexport */ CanvasKit),
  "Vector": () => (/* reexport */ Vector),
  "arena": () => (/* reexport */ arena),
  "arenaScaling": () => (/* reexport */ arenaScaling),
  "entityManager": () => (/* reexport */ entityManager),
  "game": () => (/* reexport */ game),
  "gamepad": () => (/* reexport */ gamepad),
  "minimap": () => (/* reexport */ minimap),
  "player": () => (/* reexport */ player)
});

;// CONCATENATED MODULE: ./src/vector.ts
class Vector {
    x;
    y;
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    /**
     * ( u1 ) + ( v1 ) = ( u1 + v1 )
     * ( u2 )   ( v2 )   ( u2 + v2 )
     */
    static add(u, v) {
        return new Vector(u.x + v.x, u.y + v.y);
    }
    /**
     * ( u1 ) - ( v1 ) = ( u1 - v1 )
     * ( u2 )   ( v2 )   ( u2 - v2 )
     */
    static subtract(u, v) {
        return new Vector(u.x - v.x, u.y - v.y);
    }
    /**
     * ( u1 ) * ( v1 ) = ( u1 * v1 )
     * ( u2 )   ( v2 )   ( u2 * v2 )
     */
    static multiply(u, v) {
        return new Vector(u.x * v.x, u.y * v.y);
    }
    /**
     * ( u1 ) / ( v1 ) = ( u1 / v1 )
     * ( u2 )   ( v2 )   ( u2 / v2 )
     */
    static divide(u, v) {
        return new Vector(u.x / v.x, u.y / v.y);
    }
    /**
     * r * ( v1 ) = ( r * v1 )
     *     ( v2 )   ( r * v2 )
     */
    static scale(r, v) {
        return new Vector(r * v.x, r * v.y);
    }
    static round(v) {
        return new Vector(Math.round(v.x), Math.round(v.y));
    }
    static len(v) {
        return Math.sqrt(v.x ** 2 + v.y ** 2);
    }
    static distance(u, v) {
        return Vector.len(Vector.subtract(u, v));
    }
    /**
     * Calculates the [centroid](https://en.wikipedia.org/wiki/Centroid)
     */
    static centroid(...vertices) {
        const sum = vertices.reduce((acc, vec) => Vector.add(acc, vec), new Vector(0, 0));
        const centroid = Vector.scale(1 / vertices.length, sum);
        return centroid;
    }
    /**
     * Calcutes the radius from a set of vertices that are placed on a circle
     */
    static radius(...vertices) {
        const centroid = Vector.centroid(...vertices);
        const distance = vertices.reduce((acc, vec) => acc + Vector.distance(centroid, vec), 0);
        const radius = distance / vertices.length;
        return radius;
    }
}

;// CONCATENATED MODULE: ./src/canvas_kit.ts
class CanvasKit {
    /**
     * The consumer will be called before
     */
    static hook(method, consumer) {
        const target = window.CanvasRenderingContext2D.prototype;
        target[method] = new Proxy(target[method], {
            apply(target, thisArg, args) {
                if (thisArg.canvas.className !== 'CanvasKit-bypass')
                    consumer(target, thisArg, args);
                return Reflect.apply(target, thisArg, args);
            },
        });
    }
    /**
     * replaces the function. Use `return Reflect.apply(target, thisArg, args);` in
     * your function to call the original function.
     */
    static replace(method, func) {
        const target = window.CanvasRenderingContext2D.prototype;
        target[method] = new Proxy(target[method], {
            apply(target, thisArg, args) {
                if (thisArg.canvas.className !== 'CanvasKit-bypass')
                    return func(target, thisArg, args);
                return Reflect.apply(target, thisArg, args);
            },
        });
    }
    /**
     * The consumer will be called before.
     */
    static hookRAF(consumer) {
        window.requestAnimationFrame = new Proxy(window.requestAnimationFrame, {
            apply(target, thisArg, args) {
                consumer();
                return Reflect.apply(target, thisArg, args);
            },
        });
    }
    /**
     * If you want to a canvas then create it with this method.
     */
    static createCanvas() {
        const canvas = document.createElement('canvas');
        canvas.className = 'CanvasKit-bypass';
        canvas.style.pointerEvents = 'none';
        canvas.style.position = 'fixed';
        canvas.style['z-index'] = 1;
        canvas.style.top = '0px';
        canvas.style.left = '0px';
        canvas.style.right = '0px';
        canvas.style.bottom = '0px';
        canvas.style.width = '100%';
        canvas.style.height = '100%';
        return canvas;
    }
}

;// CONCATENATED MODULE: ./src/diep_gamepad.ts
class DiepGamepad {
    #axes;
    #buttons;
    connected;
    /**
     * Emulates a Gampad
     * when `gamepad.connected` is set to `true` the game will
     * ignore following keyboard inputs:
     * 		W, A, S, D, upArrow, leftArrow, downArrow, rightArray
     *      leftMouse, rightMouse, Spacebar, Shift,
     *      MouseMovement to change tank angle
     * these are also the only keys we emulate with this gamepad
     *
     */
    constructor() {
        this.#axes = [0, 0, 0, 0];
        this.#buttons = [...Array(17)].map((x) => {
            return { pressed: false };
        });
        this.connected = false;
        //window.navigator.getGamepads = () => [this.connected ? this.#toGamepad() : undefined];
        window.navigator.getGamepads = new Proxy(window.navigator.getGamepads, {
            apply: (target, thisArg, args) => {
                if (this.connected)
                    return [this.#toGamepad()];
                return Reflect.apply(target, thisArg, args);
            },
        });
    }
    set x(value) {
        this.#axes[0] = value;
    }
    set y(value) {
        this.#axes[1] = value;
    }
    set mx(value) {
        this.#axes[2] = value;
    }
    set my(value) {
        this.#axes[3] = value;
    }
    set leftMouse(value) {
        this.#buttons[7].pressed = value;
    }
    set rightMouse(value) {
        this.#buttons[6].pressed = value;
    }
    get x() {
        return this.#axes[0];
    }
    get y() {
        return this.#axes[1];
    }
    get mx() {
        return this.#axes[2];
    }
    get my() {
        return this.#axes[3];
    }
    get leftMouse() {
        return this.#buttons[7].pressed;
    }
    get rightMouse() {
        return this.#buttons[6].pressed;
    }
    #toGamepad() {
        return {
            axes: this.#axes,
            buttons: this.#buttons,
            mapping: 'standard',
        };
    }
}
const gamepad = new DiepGamepad();

;// CONCATENATED MODULE: ./src/event_emitter.ts
class EventEmitter extends EventTarget {
    /**
     *
     * @param {string} eventName The name of the event
     * @param  {...any} args The arguments that will be passed to the listener
     */
    emit(eventName, ...args) {
        this.dispatchEvent(new CustomEvent(eventName, { detail: args }));
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    on(eventName, listener) {
        this.addEventListener(eventName, (e) => Reflect.apply(listener, this, e.detail));
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    once(eventName, listener) {
        this.addEventListener(eventName, (e) => Reflect.apply(listener, this, e.detail), { once: true });
    }
    /**
     *
     * @param {string} eventName The name of the event
     * @param {EventCallback} listener The callback function
     */
    off(eventName, listener) {
        this.removeEventListener(eventName, listener);
    }
}

;// CONCATENATED MODULE: ./src/game.ts


class Game extends EventEmitter {
    #ready = false;
    constructor() {
        super();
        CanvasKit.hookRAF(() => this.#onframe());
    }
    #onframe() {
        if (!this.#ready && window.input !== undefined) {
            this.#ready = true;
            this.#onready();
        }
        super.emit('frame');
    }
    #onready() {
        setTimeout(() => super.emit('ready'), 100);
    }
}
const game = new Game();

;// CONCATENATED MODULE: ./src/minimap.ts



class Minimap {
    #minimapDim = new Vector(1, 1);
    #minimapPos = new Vector(0, 0);
    #viewportDim = new Vector(1, 1);
    #viewportPos = new Vector(0, 0);
    /**
     * @description The position of the arrow normalized to the range [0,1]
     */
    #arrowPos = new Vector(0.5, 0.5);
    #drawViewport = false;
    constructor() {
        game.once('ready', () => {
            window.input.set_convar('ren_minimap_viewport', 'true');
            window.input.set_convar = new Proxy(window.input.set_convar, {
                apply: (target, thisArg, args) => {
                    if (args[0] === 'ren_minimap_viewport')
                        this.#drawViewport = args[1];
                    else
                        Reflect.apply(target, thisArg, args);
                },
            });
        });
        this._minimapHook();
        this._viewportHook();
        this._arrowHook();
    }
    get minimapDim() {
        return this.#minimapDim;
    }
    get minimapPos() {
        return this.#minimapPos;
    }
    get viewportDim() {
        return this.#viewportDim;
    }
    get viewportPos() {
        return this.#viewportPos;
    }
    get arrowPos() {
        return this.#arrowPos;
    }
    drawViewport(value) {
        this.#drawViewport = value;
    }
    _minimapHook() {
        CanvasKit.hook('strokeRect', (target, thisArg, args) => {
            const transform = thisArg.getTransform();
            this.#minimapDim = new Vector(transform.a, transform.d);
            this.#minimapPos = new Vector(transform.e, transform.f);
        });
    }
    _viewportHook() {
        CanvasKit.replace('fillRect', (target, thisArg, args) => {
            const transform = thisArg.getTransform();
            if (Math.round((transform.a / transform.d) * 10_000) !==
                Math.round((window.innerWidth / window.innerHeight) * 10_000)) {
                return Reflect.apply(target, thisArg, args);
            }
            if (transform.a >= window.innerWidth && transform.d >= window.innerHeight) {
                return Reflect.apply(target, thisArg, args);
            }
            this.#viewportDim = new Vector(transform.a, transform.d);
            this.#viewportPos = new Vector(transform.e, transform.f);
            if (this.#drawViewport)
                return Reflect.apply(target, thisArg, args);
        });
    }
    _arrowHook() {
        let index = 0;
        let pointA;
        let pointB;
        let pointC;
        const calculatePos = () => {
            const side1 = Math.round(Vector.distance(pointA, pointB));
            const side2 = Math.round(Vector.distance(pointA, pointC));
            const side3 = Math.round(Vector.distance(pointB, pointC));
            if (side1 === side2 && side2 === side3)
                return;
            const centroid = Vector.centroid(pointA, pointB, pointC);
            const arrowPos = Vector.subtract(centroid, this.#minimapPos);
            const position = Vector.divide(arrowPos, this.#minimapDim);
            this.#arrowPos = position;
        };
        CanvasKit.hook('beginPath', (target, thisArg, args) => {
            index = 1;
        });
        CanvasKit.hook('moveTo', (target, thisArg, args) => {
            if (index === 1) {
                index++;
                pointA = new Vector(args[0], args[1]);
                return;
            }
            index = 0;
        });
        CanvasKit.hook('lineTo', (target, thisArg, args) => {
            if (index === 2) {
                index++;
                pointB = new Vector(args[0], args[1]);
                return;
            }
            if (index === 3) {
                index++;
                pointC = new Vector(args[0], args[1]);
                return;
            }
            index = 0;
        });
        CanvasKit.hook('fill', (target, thisArg, args) => {
            if (index === 4) {
                index++;
                calculatePos();
                return;
            }
            index = 0;
        });
    }
}
const minimap = new Minimap();

;// CONCATENATED MODULE: ./src/camera.ts



class Camera {
    get position() {
        const center = Vector.add(minimap.viewportPos, Vector.scale(0.5, minimap.viewportDim));
        const cameraPos = Vector.subtract(center, minimap.minimapPos);
        const normalized = Vector.divide(cameraPos, minimap.minimapDim);
        return arena.scale(normalized);
    }
}
const camera = new Camera();

;// CONCATENATED MODULE: ./src/arena_scaling.ts



class ArenaScaling {
    #scalingFactor = 1;
    constructor() {
        CanvasKit.hook('stroke', (target, thisArg, args) => {
            if (thisArg.fillStyle === '#cdcdcd' && thisArg.globalAlpha !== 0) {
                this.#scalingFactor = thisArg.globalAlpha * 10;
            }
        });
    }
    get scalingFactor() {
        return this.#scalingFactor;
    }
    get windowRatio() {
        return Math.max(window.innerWidth / 1920, window.innerHeight / 1080);
    }
    get fov() {
        return this.#scalingFactor / this.windowRatio;
    }
    /**
     *
     * @param {Vector} v The vector in canvas units
     * @returns {Vector} The vector in arena units
     */
    toArenaUnits(v) {
        return Vector.scale(1 / this.#scalingFactor, v);
    }
    /**
     *
     * @param {Vector} v The vector in arena units
     * @returns {Vector} The vector in canvas units
     */
    toCanvasUnits(v) {
        return Vector.scale(this.#scalingFactor, v);
    }
    /**
     * Will translate coordinates from canvas to arena
     * @param {Vector} canvasPos The canvas coordinates
     * @returns {Vector} The `canvasPos` translated to arena coordinates
     */
    toArenaPos(canvasPos) {
        const direction = Vector.subtract(canvasPos, this.screenToCanvas(new Vector(window.innerWidth / 2, window.innerHeight / 2)));
        const scaled = this.toArenaUnits(direction);
        const arenaPos = Vector.add(scaled, camera.position);
        return arenaPos;
    }
    /**
     * Will translate coordinates from arena to canvas
     * @param {Vector} arenaPos The arena coordinates
     * @returns {Vector} The `arenaPos` translated to canvas coordinates
     */
    toCanvasPos(arenaPos) {
        const direction = Vector.subtract(arenaPos, camera.position);
        const scaled = this.toCanvasUnits(direction);
        const canvasPos = Vector.add(scaled, this.screenToCanvas(new Vector(window.innerWidth / 2, window.innerHeight / 2)));
        return canvasPos;
    }
    screenToCanvasUnits(n) {
        return n * window.devicePixelRatio;
    }
    canvasToScreenUnits(n) {
        return n / window.devicePixelRatio;
    }
    /**
     * Will translate coordinates from screen to canvas
     * @param v The screen coordinates
     * @returns The canvas coordinates
     */
    screenToCanvas(v) {
        return Vector.scale(window.devicePixelRatio, v);
    }
    /**
     * Will translate coordinates from canvas to screen
     * @param v The canvas coordinates
     * @returns the screen coordinates
     */
    canvasToScreen(v) {
        return Vector.scale(1 / window.devicePixelRatio, v);
    }
}
const arenaScaling = new ArenaScaling();

;// CONCATENATED MODULE: ./src/arena.ts




class Arena {
    #size = 1;
    constructor() {
        game.on('frame', () => {
            const ratio = Vector.divide(minimap.minimapDim, minimap.viewportDim);
            const arenaDim = Vector.multiply(ratio, arenaScaling.screenToCanvas(new Vector(window.innerWidth, window.innerHeight)));
            const arenaSize = Vector.round(arenaScaling.toArenaUnits(arenaDim));
            this.#size = arenaSize.x;
        });
    }
    /**
     * @returns {number} The Arena size in arena units
     */
    get size() {
        return this.#size;
    }
    //These methods are not much used. can be moved to playerMovement.mjs where its currently only used.
    /**
     *
     * @param {Vector} vector The vector in [0, 1] coordinates
     * @returns {Vector} The scaled vector in [-Arena.size/2, Arena.size/2] coordinates
     */
    scale(vector) {
        const scale = (value) => Math.round(this.#size * (value - 0.5));
        return new Vector(scale(vector.x), scale(vector.y));
    }
    /**
     *
     * @param {Vector} vector - The scaled vector in [-Arena.size/2, Arena.size/2] coordinates
     * @returns {Vector} The unscaled vector in [0, 1] coordinates
     */
    unscale(vector) {
        const unscale = (value) => value / this.#size + 0.5;
        return new Vector(unscale(vector.x), unscale(vector.y));
    }
}
const arena = new Arena();

;// CONCATENATED MODULE: ./src/movement.ts

class Movement {
    #position = new Vector(0, 0);
    #velocity = new Vector(0, 0);
    /*
     * used for average velocity calculation
     */
    #velocitySamplesSize = 10;
    #velocitySamples = [];
    #velocitySamplesIndex = 0;
    #velocityLastNow = performance.now();
    get position() {
        return this.#position;
    }
    /**
     * Velocity in [diep_]units / second
     */
    get velocity() {
        return this.#velocity;
    }
    /**
     * Predict where this object will be after `time`
     * @param time The time in ms.
     */
    predictPos(time) {
        const duration = (time + performance.now() - this.#velocityLastNow) / 1000;
        return Vector.add(this.#position, Vector.scale(duration, this.#velocity));
    }
    updatePos(newPos) {
        this.#updateVelocity(newPos);
        this.#position = newPos;
    }
    #updateVelocity(newPos) {
        const now = performance.now();
        const time = (now - this.#velocityLastNow) / 1000;
        if (time === 0)
            return;
        this.#velocityLastNow = now;
        const velocity = Vector.scale(1 / time, Vector.subtract(newPos, this.#position));
        // add current velocity to our samples array
        this.#velocitySamples[this.#velocitySamplesIndex++] = velocity;
        this.#velocitySamplesIndex %= this.#velocitySamplesSize;
        // calculate the average velocity
        this.#velocity = Vector.scale(1 / this.#velocitySamples.length, this.#velocitySamples.reduce((acc, x) => Vector.add(acc, x)));
    }
}

;// CONCATENATED MODULE: ./src/player_movement.ts




class PlayerMovement extends Movement {
    /**
     * Using the minimap arrow to get the player position and velocity
     */
    constructor() {
        super();
        game.on('frame', () => super.updatePos(arena.scale(minimap.arrowPos)));
    }
}
const playerMovement = new PlayerMovement();

;// CONCATENATED MODULE: ./src/player.ts







const sleep = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms));
class Player extends EventEmitter {
    #isDead = true;
    #mouseLock = false;
    #mouseCanvasPos = new Vector(0, 0);
    #mousePos = new Vector(0, 0);
    #gamemode = window.localStorage.gamemode;
    #level = 1;
    #tank = 'Tank';
    constructor() {
        super();
        game.once('ready', () => {
            //Check dead or alive
            game.on('frame', () => {
                const isDead = !window.input.should_prevent_unload();
                if (this.#isDead == isDead)
                    return;
                this.#isDead = isDead;
                if (this.#isDead)
                    this.#ondead();
                else
                    this.#onspawn();
            });
            //update mouse position
            game.on('frame', () => {
                this.#mousePos = arenaScaling.toArenaPos(this.#mouseCanvasPos);
            });
            //Mouse events
            const canvas = document.getElementById('canvas');
            canvas.onmousemove = new Proxy(canvas.onmousemove, {
                apply: (target, thisArg, args) => {
                    if (this.#mouseLock)
                        return;
                    this.#onmousemove(args[0]);
                    return Reflect.apply(target, thisArg, args);
                },
            });
            canvas.onmousedown = new Proxy(canvas.onmousedown, {
                apply: (target, thisArg, args) => {
                    if (this.#mouseLock)
                        return;
                    this.#onmousedown(args[0]);
                    return Reflect.apply(target, thisArg, args);
                },
            });
            canvas.onmouseup = new Proxy(canvas.onmouseup, {
                apply: (target, thisArg, args) => {
                    if (this.#mouseLock)
                        return;
                    this.#onmouseup(args[0]);
                    return Reflect.apply(target, thisArg, args);
                },
            });
            //Key events
            window.onkeydown = new Proxy(window.onkeydown, {
                apply: (target, thisArg, args) => {
                    this.#onkeydown(args[0]);
                    return Reflect.apply(target, thisArg, args);
                },
            });
            window.onkeyup = new Proxy(window.onkeyup, {
                apply: (target, thisArg, args) => {
                    this.#onkeyup(args[0]);
                    return Reflect.apply(target, thisArg, args);
                },
            });
            // tank and level event listener
            CanvasKit.hook('fillText', (target, thisArg, args) => {
                const text = args[0];
                const match = text.match(/^Lvl (\d+) (\w*)$/);
                if (match == null) {
                    return;
                }
                const newLevel = Number(match[1]);
                const newTank = match[2];
                // make sure to trigger events for all levels in between.
                while (newLevel > this.#level + 1) {
                    super.emit('level', ++this.#level);
                }
                if (newLevel !== this.#level)
                    super.emit('level', newLevel);
                if (newTank !== this.#tank)
                    super.emit('tank', newTank);
                this.#level = newLevel;
                this.#tank = match[2];
            });
        });
    }
    get position() {
        return playerMovement.position;
    }
    get velocity() {
        return playerMovement.velocity;
    }
    get mouse() {
        return this.#mousePos;
    }
    get isDead() {
        return this.#isDead;
    }
    get gamemode() {
        return this.#gamemode;
    }
    get level() {
        return this.#level;
    }
    get tank() {
        return this.#tank;
    }
    /**
     * Predict where this object will be after `time`
     * @param time The time in ms
     */
    predictPos(time) {
        return playerMovement.predictPos(time);
    }
    /**
     * Fun function to upgrade to octo
     * @async
     */
    async octoBuild() {
        this.keyDown('k');
        await this.upgrade_stat(4, 7);
        await this.upgrade_stat(5, 7);
        await this.upgrade_stat(6, 7);
        await this.upgrade_stat(7, 7);
        await this.upgrade_stat(8, 5);
        await this.upgrade_tank(1);
        await this.upgrade_tank(2);
        await this.upgrade_tank(1);
        this.keyUp('k');
    }
    async #ondead() {
        await sleep(50);
        super.emit('dead');
    }
    async #onspawn() {
        this.#gamemode = window.localStorage.gamemode;
        await sleep(50);
        super.emit('spawn');
    }
    useGamepad(value) {
        gamepad.connected = value;
    }
    keyDown(key) {
        if (typeof key == 'string') {
            if (key.length != 1)
                throw new Error(`diepAPI: Unsupported key: ${key}`);
            key = key.toUpperCase().charCodeAt(0);
        }
        window.input.keyDown(key);
        this.#onkeydown({ keyCode: key });
    }
    keyUp(key) {
        if (typeof key == 'string') {
            if (key.length != 1)
                throw new Error(`diepAPI: Unsupported key: ${key}`);
            key = key.toUpperCase().charCodeAt(0);
        }
        window.input.keyUp(key);
        this.#onkeyup({ keyCode: key });
    }
    async keyPress(key) {
        this.keyDown(key);
        await sleep(200);
        this.keyUp(key);
        await sleep(10);
    }
    async spawn(name, attempts = 0) {
        if (!this.#isDead)
            return;
        if (name !== undefined)
            document.getElementById('textInput').value = name;
        await this.keyPress(13);
        await sleep(250);
        await this.spawn(name, attempts + 1);
    }
    async upgrade_stat(id, level) {
        if (id < 1 || id > 8)
            throw `diepAPI: ${id} is not a supported stat`;
        this.keyDown(85);
        for (let i = 0; i < level; i++) {
            await this.keyPress(48 + id);
        }
        this.keyUp(85);
        await sleep(250);
    }
    async upgrade_tank(index) {
        index -= 1;
        const x_index = index % 2;
        const y_index = Math.floor(index / 2);
        const x = arenaScaling.screenToCanvasUnits(arenaScaling.windowRatio * (x_index * 115 + 97.5));
        const y = arenaScaling.screenToCanvasUnits(arenaScaling.windowRatio * (y_index * 110 + 120));
        this.#mouseLock = true;
        window.input.mouse(x, y);
        await this.keyPress(1);
        // wait 200 ms before disabling mouselock
        await sleep(200);
        this.#mouseLock = false;
        // wait 1500 ms for the animation to finish
        await sleep(1500);
    }
    moveTo(arenaPos) {
        if (gamepad.connected) {
            const direction = Vector.subtract(arenaPos, this.position);
            const distance = Vector.len(direction);
            if (distance === 0) {
                gamepad.x = 0;
                gamepad.y = 0;
                return;
            }
            //max speed
            const velocity = Vector.scale(1 / distance, direction);
            gamepad.x = velocity.x;
            gamepad.y = velocity.y;
        }
        else {
            const direction = Vector.subtract(arenaPos, this.position);
            if (direction.x > 0) {
                this.keyUp('a');
                this.keyDown('d');
            }
            else if (direction.x < 0) {
                this.keyUp('d');
                this.keyDown('a');
            }
            else {
                this.keyUp('a');
                this.keyUp('d');
            }
            if (direction.y > 0) {
                this.keyUp('w');
                this.keyDown('s');
            }
            else if (direction.y < 0) {
                this.keyUp('s');
                this.keyDown('w');
            }
            else {
                this.keyUp('w');
                this.keyUp('s');
            }
        }
    }
    lookAt(arenaPos) {
        const position = arenaScaling.toCanvasPos(arenaPos);
        window.input.mouse(position.x, position.y);
        this.#onmousemove({ clientX: position.x, clientY: position.y });
    }
    #onmousemove(e) {
        this.#mouseCanvasPos = arenaScaling.screenToCanvas(new Vector(e.clientX, e.clientY));
        if (gamepad.connected) {
            const arenaPos = arenaScaling.toArenaPos(this.#mouseCanvasPos);
            const direction = Vector.subtract(arenaPos, this.position);
            let axes = Vector.scale(arenaScaling.fov / 1200 / 1.1, direction);
            const length = Vector.len(axes);
            if (length !== 0 && length < 0.15) {
                axes = Vector.scale(0.15 / length, axes);
            }
            gamepad.mx = axes.x;
            gamepad.my = axes.y;
        }
    }
    #onmousedown(e) {
        if (gamepad.connected)
            this.#onkeydown({ keyCode: e.which });
    }
    #onmouseup(e) {
        if (gamepad.connected)
            this.#onkeyup({ keyCode: e.which });
    }
    #onkeydown(e) {
        super.emit('keydown', e.keyCode);
        if (gamepad.connected) {
            switch (e.keyCode) {
                case 37:
                case 65:
                    gamepad.x = -1;
                    break;
                case 40:
                case 83:
                    gamepad.y = 1;
                    break;
                case 38:
                case 87:
                    gamepad.y = -1;
                    break;
                case 39:
                case 68:
                    gamepad.x = 1;
                    break;
                case 1:
                case 32:
                    gamepad.leftMouse = true;
                    break;
                case 3:
                case 16:
                    gamepad.rightMouse = true;
                    break;
            }
        }
    }
    #onkeyup(e) {
        super.emit('keyup', e.keyCode);
        if (gamepad.connected) {
            switch (e.keyCode) {
                case 37:
                case 65:
                    gamepad.x = 0;
                    break;
                case 40:
                case 83:
                    gamepad.y = 0;
                    break;
                case 38:
                case 87:
                    gamepad.y = 0;
                    break;
                case 39:
                case 68:
                    gamepad.x = 0;
                    break;
                case 1:
                case 32:
                    gamepad.leftMouse = false;
                    break;
                case 3:
                case 16:
                    gamepad.rightMouse = false;
                    break;
            }
        }
    }
}
const player = new Player();

;// CONCATENATED MODULE: ./src/entity.ts

var EntityType;
(function (EntityType) {
    EntityType[EntityType["Player"] = 0] = "Player";
    EntityType[EntityType["Bullet"] = 1] = "Bullet";
    EntityType[EntityType["Drone"] = 2] = "Drone";
    EntityType[EntityType["Trap"] = 3] = "Trap";
    EntityType[EntityType["Square"] = 4] = "Square";
    EntityType[EntityType["Triangle"] = 5] = "Triangle";
    EntityType[EntityType["Pentagon"] = 6] = "Pentagon";
    EntityType[EntityType["AlphaPentagon"] = 7] = "AlphaPentagon";
    EntityType[EntityType["Crasher"] = 8] = "Crasher";
    EntityType[EntityType["UNKNOWN"] = 9] = "UNKNOWN";
})(EntityType || (EntityType = {}));
var EntityColor;
(function (EntityColor) {
    EntityColor["TeamBlue"] = "#00b2e1";
    EntityColor["TeamRed"] = "#f14e54";
    EntityColor["TeamPurple"] = "#bf7ff5";
    EntityColor["TeamGreen"] = "#00e16e";
    EntityColor["Square"] = "#ffe869";
    EntityColor["Triangle"] = "#fc7677";
    EntityColor["Pentagon"] = "#768dfc";
    EntityColor["AlphaPentagon"] = "#768dfc";
    EntityColor["Crasher"] = "#f177dd";
    EntityColor["NecromancerDrone"] = "#fcc376";
})(EntityColor || (EntityColor = {}));
const TeamColors = [EntityColor.TeamBlue, EntityColor.TeamRed, EntityColor.TeamPurple, EntityColor.TeamGreen];
/**
 * Represents an ingame Entity.
 *
 * Holds minimal information currently.
 */
class Entity extends Movement {
    type;
    extras;
    constructor(type, extras = {}) {
        super();
        this.type = type;
        this.extras = extras;
    }
    updatePos(newPos) {
        super.updatePos(newPos);
    }
}

;// CONCATENATED MODULE: ./src/entity_manager.ts





/**
 * Entity Manager is used to access the information about the entities, that are currently drawn on the screen.
 * To access the entities the EntityManager exposes the EntityManager.entities field.
 */
class EntityManager {
    #entities = [];
    #entitiesUpdated = [];
    constructor() {
        this.#triangleHook();
        this.#squareHook();
        this.#pentagonHook();
        //when is a bullet being drawn?
        //when is a player being drawn?
        this.#playerHook();
        game.on('frame', () => {
            this.#entities = this.#entitiesUpdated;
            this.#entitiesUpdated = [];
        });
    }
    get entities() {
        return this.#entities;
    }
    /**
     * Adds the entity to `#entitiesUpdated`.
     *
     * Will either find the entity in `#entities` or create a new `Entity`.
     */
    #add(type, position, extras = {}) {
        const entityIndex = this.#findEntity(type, position);
        let entity;
        if (entityIndex === -1) {
            entity = new Entity(type, {
                id: Math.random().toString(36).slice(2, 5),
                timestamp: performance.now(),
                ...extras,
            });
        }
        else {
            entity = this.#entities[entityIndex];
        }
        entity.updatePos(position);
        this.#entitiesUpdated.push(entity);
    }
    /**
     * Searches `#entities` for the entity that is closest to `position` and
     * returns the __index__ of that entity or __-1__ if there is no match.
     */
    #findEntity(type, position) {
        let result = -1;
        let shortestDistance = Number.MAX_SAFE_INTEGER;
        this.#entities.forEach((x, i) => {
            const distance = Vector.distance(x.predictPos(0), position);
            if (distance < shortestDistance) {
                shortestDistance = distance;
                result = i;
            }
        });
        //if distance is too high
        if (shortestDistance > 28 /* accuracy */) {
            return -1;
        }
        //sanity check
        if (EntityType.UNKNOWN !== type && this.#entities[result].type !== type) {
            return -1;
        }
        return result;
    }
    /**
     * Will call the cb method, when a polygon with `numVertices` vertices is drawn.
     */
    #createPolygonHook(numVertices, cb) {
        let index = 0;
        let vertices = [];
        const onFillPolygon = (ctx) => {
            cb(vertices, ctx);
        };
        CanvasKit.hook('beginPath', (target, thisArg, args) => {
            index = 1;
            vertices = [];
        });
        CanvasKit.hook('moveTo', (target, thisArg, args) => {
            if (index === 1) {
                index++;
                vertices.push(new Vector(args[0], args[1]));
                return;
            }
            index = 0;
        });
        CanvasKit.hook('lineTo', (target, thisArg, args) => {
            if (index >= 2 && index <= numVertices) {
                index++;
                vertices.push(new Vector(args[0], args[1]));
                return;
            }
            index = 0;
        });
        CanvasKit.hook('fill', (target, thisArg, args) => {
            if (index === numVertices + 1) {
                index++;
                onFillPolygon(thisArg);
                return;
            }
            index = 0;
        });
    }
    #triangleHook() {
        this.#createPolygonHook(3, (vertices, ctx) => {
            const side1 = Math.round(Vector.distance(vertices[0], vertices[1]));
            const side2 = Math.round(Vector.distance(vertices[0], vertices[2]));
            const side3 = Math.round(Vector.distance(vertices[1], vertices[2]));
            //ignore Minimap Arrow
            if (side1 !== side2 || side2 !== side3)
                return;
            //ignore Leader Arrow
            if ('#000000' === ctx.fillStyle)
                return;
            vertices = vertices.map((x) => arenaScaling.toArenaPos(x));
            const position = Vector.centroid(...vertices);
            const radius = Math.round(Vector.radius(...vertices));
            const color = ctx.fillStyle;
            let type;
            switch (radius) {
                case 23:
                    //battleship drone
                    if (TeamColors.includes(color))
                        type = EntityType.Drone;
                    break;
                case 30:
                    //base drone
                    if (TeamColors.includes(color))
                        type = EntityType.Drone;
                    break;
                case 35:
                    //small crasher
                    if (EntityColor.Crasher === color)
                        type = EntityType.Crasher;
                    break;
                case 40:
                case 41:
                case 42:
                case 43:
                case 44:
                case 45:
                case 46:
                    //overseer/overlord drone
                    if (TeamColors.includes(color))
                        type = EntityType.Drone;
                    break;
                case 55:
                    //big crasher
                    if (EntityColor.Crasher === color)
                        type = EntityType.Crasher;
                    //triangle
                    if (EntityColor.Triangle === color)
                        type = EntityType.Triangle;
                    break;
            }
            if (type === undefined)
                type = EntityType.UNKNOWN;
            this.#add(type, position, { color, radius });
        });
    }
    #squareHook() {
        this.#createPolygonHook(4, (vertices, ctx) => {
            vertices = vertices.map((x) => arenaScaling.toArenaPos(x));
            const position = Vector.centroid(...vertices);
            const radius = Math.round(Vector.radius(...vertices));
            const color = ctx.fillStyle;
            let type;
            switch (radius) {
                case 55:
                    //square
                    if (EntityColor.Square === color)
                        type = EntityType.Square;
                    //necromancer drone
                    if (TeamColors.includes(color) || EntityColor.NecromancerDrone === color)
                        type = EntityType.Drone;
                    break;
            }
            if (type === undefined)
                type = EntityType.UNKNOWN;
            this.#add(type, position, { color, radius });
        });
    }
    #pentagonHook() {
        this.#createPolygonHook(5, (vertices, ctx) => {
            vertices = vertices.map((x) => arenaScaling.toArenaPos(x));
            const position = Vector.centroid(...vertices);
            const radius = Math.round(Vector.radius(...vertices));
            const color = ctx.fillStyle;
            let type;
            switch (radius) {
                case 75:
                    if (EntityColor.Pentagon === color)
                        type = EntityType.Pentagon;
                    break;
                case 200:
                    if (EntityColor.AlphaPentagon === color)
                        type = EntityType.AlphaPentagon;
                    break;
            }
            if (type === undefined)
                type = EntityType.UNKNOWN;
            this.#add(type, position, { color, radius });
        });
    }
    #playerHook() {
        let index = 0;
        let position;
        let color;
        let radius;
        const onCircle = () => {
            position = arenaScaling.toArenaPos(position);
            radius = arenaScaling.toArenaUnits(new Vector(radius, radius)).x;
            let type = EntityType.UNKNOWN;
            if (radius > 53) {
                type = EntityType.Player;
            }
            else {
                type = EntityType.Bullet;
            }
            this.#add(type, position, {
                color,
                radius,
            });
        };
        //Sequence: beginPath -> arc -> fill -> beginPath -> arc -> fill -> arc
        CanvasKit.hook('beginPath', (target, thisArg, args) => {
            //start
            if (index !== 3) {
                index = 1;
                return;
            }
            if (index === 3) {
                index++;
                return;
            }
            index = 0;
        });
        //check when a circle is drawn.
        CanvasKit.hook('arc', (target, thisArg, args) => {
            //outline
            if (index === 1) {
                index++;
                const transform = thisArg.getTransform();
                position = new Vector(transform.e, transform.f);
                radius = transform.a;
                return;
            }
            if (index === 4) {
                index++;
                color = thisArg.fillStyle;
                return;
            }
            //last arc call
            if (index === 6) {
                index++;
                onCircle();
                return;
            }
            index = 0;
        });
        CanvasKit.hook('fill', (target, thisArg, args) => {
            if (index === 2) {
                index++;
                return;
            }
            if (index === 5) {
                index++;
                return;
            }
            index = 0;
        });
    }
}
const entityManager = new EntityManager();

;// CONCATENATED MODULE: ./src/index.ts










diepAPI = __webpack_exports__;
/******/ })()
;