var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 
{
    "init": function () {

	console.log("插件编写测试");

	this._afterLoadResources = function () {
		// 本函数将在所有资源加载完毕后，游戏开启前被执行
		// 可以在这个函数里面对资源进行一些操作。
		// 若需要进行切分图片，可以使用 core.splitImage() 函数，或直接在全塔属性-图片切分中操作
		// 
		core.ui.statusBar.init();
	}

	// 可以在任何地方（如afterXXX或自定义脚本事件）调用函数，方法为 core.plugin.xxx();
	// 从V2.6开始，插件中用this.XXX方式定义的函数也会被转发到core中，详见文档-脚本-函数的转发。
},
    "resizeTo11": function () {
	if (main.mode == 'editor') {
		return;
	}

	// 在不修改libs的情况下将页面适配为11x11
	core.__SIZE__ = 11;
	core.__PIXELS__ = core.__SIZE__ * 32;
	core.__HALF_SIZE__ = 5;
	// core.bigmap.width = core.__SIZE__;
	// core.bigmap.height = core.__SIZE__;
	core.actions.SIZE = core.__SIZE__;
	core.actions.HSIZE = core.__HALF_SIZE__;
	core.actions.LAST = core.__SIZE__ - 1;
	core.actions.CHOICES_LEFT = 3;
	core.actions.CHOICES_RIGHT = core.actions.LAST - core.actions.CHOICES_LEFT;
	core.ui.SIZE = core.__SIZE__;
	core.ui.HSIZE = core.__HALF_SIZE__;
	core.ui.LAST = core.__SIZE__ - 1;
	core.ui.PIXEL = core.__PIXELS__;
	core.ui.HPIXEL = core.__PIXELS__ / 2;
},
    "statusBar": function () {
	main.dom.floorMsgGroup.style.display = 'none';
	main.dom.statusBar.style.display = 'none';
	main.dom.toolBar.style.display = 'none';

	const GAMEVIEW_WIDTH = 640;
	const GAMEVIEW_HEIGHT = 422;

	const GAMEVIEW_WIDTH_VERTICAL = 388;
	const GAMEVIEW_HEIGHT_VERTICAL = 630;

	const BAR_WIDTH = 125;
	const BAR_HEIGHT_VERTICAL = 130;
	const BORDER_WIDTH = 18;
	const BORDER_HEIGHT = 24;
	
	const ITEM_BOX_LEFT = 13;
	const ITEM_BOX_TOP = 190;
	const ITEM_BOX_LEFT_VERTICAL = 219;
	const ITEM_BOX_TOP_VERTICAL = 10;

	const ITEM_ICON_OUTER_SIZE = 33;

	const EQUIP_BLOCK_LEFT = 525;
	const EQUIP_BLOCK_TOP = 40;
	const EQUIP_BLOCK_LEFT_VERTICAL = 108;
	const EQUIP_BLOCK_TOP_VERTICAL = 0;

	const KEY_BLOCK_LEFT = EQUIP_BLOCK_LEFT;
	const KEY_BLOCK_LEFT_VERTICAL = EQUIP_BLOCK_LEFT_VERTICAL;
	const KEY_BLOCK_TOP_VERTICAL = 86;

	const INFO_BLOCK_LEFT = EQUIP_BLOCK_LEFT;
	const INFO_BLOCK_TOP = 220;
	const INFO_BLOCK_LEFT_VERTICAL = 8;
	const INFO_BLOCK_TOP_VERTICAL = 538;

	const TOOL_BOX_LEFT = EQUIP_BLOCK_LEFT;
	const TOOL_BOX_TOP = 318;
	const TOOL_BOX_LEFT_VERTICAL = 278;
	const TOOL_BOX_TOP_VERTICAL = INFO_BLOCK_TOP_VERTICAL;

	const TOOL_ICON_OUTER_SIZE = 34;

	const INFO_BAR_HEIGHT = 22;
	const INFO_BAR_HEIGHT_VERTICAL = 18;
	const INFO_BAR_TOP = GAMEVIEW_HEIGHT - INFO_BAR_HEIGHT;
	const INFO_BAR_TOP_VERTICAL = GAMEVIEW_HEIGHT_VERTICAL - INFO_BAR_HEIGHT_VERTICAL;

	const TEXT_COLOR = "#E1E1E1";

	const FORCE_COUNTABLE_ITEMS = ["centerFly"];

	const outerBackground = document.createElement('canvas');
	outerBackground.style.position = 'absolute';
	outerBackground.style.zIndex = 5;
	outerBackground.id = 'outerBackground';
	main.dom.outerBackground = outerBackground;
	main.dom.startPanel.insertAdjacentElement('afterend', outerBackground);

	const outerUI = document.createElement('canvas');
	outerUI.style.position = 'absolute';
	outerUI.style.zIndex = 165;
	outerUI.id = 'outerUI';
	main.dom.outerUI = outerUI;
	outerBackground.insertAdjacentElement('afterend', outerUI);
	setTimeout(function () {
		// Should be executed immediately after init()
		main.canvas.outerUI = outerUI.getContext('2d');
	});
	outerUI.onclick = function (e) {
		try {
			e.preventDefault();
			if (!core.isPlaying()) return false;
			const left = core.dom.gameGroup.offsetLeft;
			const top = core.dom.gameGroup.offsetTop;
			const px = parseInt((e.clientX - left) / core.domStyle.scale),
				py = parseInt((e.clientY - top) / core.domStyle.scale);
			core.ui.statusBar.onclick(px, py);
		} catch (ee) {
			main.log(ee);
		}
	}

	const _resize_gameGroup = function (obj) {
		const gameGroup = core.dom.gameGroup;
		gameGroup.style.width = obj.totalWidth + "px";
		gameGroup.style.height = obj.totalHeight + "px";
		gameGroup.style.left = (obj.clientWidth - obj.totalWidth) / 2 + "px";
		gameGroup.style.top = (obj.clientHeight - obj.totalHeight) / 2 + "px";

		core.dom.musicBtn.style.right = (obj.clientWidth - obj.totalWidth) / 2 + "px";
		core.dom.musicBtn.style.bottom = (obj.clientHeight - obj.totalHeight) / 2 - 27 + "px";
		core.dom.enlargeBtn.style.right = (obj.clientWidth - obj.totalWidth) / 2 + 31 + "px";
		core.dom.enlargeBtn.style.bottom = (obj.clientHeight - obj.totalHeight) / 2 - 27 + "px";

		main.dom.startBackground.src = main.styles.startBackground;
	}

	const _resize_canvas = function (obj) {
		main.dom.outerBackground.style.width = obj.totalWidth + 'px';
		main.dom.outerBackground.style.height = obj.totalHeight + 'px';
		main.dom.outerUI.style.width = obj.totalWidth + 'px';
		main.dom.outerUI.style.height = obj.totalHeight + 'px';

		const innerSize = (obj.canvasWidth * core.domStyle.scale) + "px";
		for (let i = 0; i < core.dom.gameCanvas.length; ++i)
			core.dom.gameCanvas[i].style.width = core.dom.gameCanvas[i].style.height = innerSize;
		core.dom.gif.style.width = core.dom.gif.style.height = innerSize;
		core.dom.gif2.style.width = core.dom.gif2.style.height = innerSize;
		core.dom.gameDraw.style.width = core.dom.gameDraw.style.height = innerSize;
		core.dom.gameDraw.style.top = obj.gameDrawBox.top * core.domStyle.scale + "px";
		core.dom.gameDraw.style.left = (obj.gameDrawBox.left) * core.domStyle.scale + "px";

		// resize bigmap
		core.bigmap.canvas.forEach(function (cn) {
			const ratio = core.canvas[cn].canvas.hasAttribute('isHD') ? core.domStyle.ratio : 1;
			core.canvas[cn].canvas.style.width = core.canvas[cn].canvas.width / ratio * core.domStyle.scale + "px";
			core.canvas[cn].canvas.style.height = core.canvas[cn].canvas.height / ratio * core.domStyle.scale + "px";
		});
		// resize dynamic canvas
		for (const name in core.dymCanvas) {
			const ctx = core.dymCanvas[name],
				canvas = ctx.canvas;
			const ratio = canvas.hasAttribute('isHD') ? core.domStyle.ratio : 1;
			canvas.style.width = canvas.width / ratio * core.domStyle.scale + "px";
			canvas.style.height = canvas.height / ratio * core.domStyle.scale + "px";
			canvas.style.left = parseFloat(canvas.getAttribute("_left")) * core.domStyle.scale + "px";
			canvas.style.top = parseFloat(canvas.getAttribute("_top")) * core.domStyle.scale + "px";
		}
		// resize next
		main.dom.next.style.width = main.dom.next.style.height = 5 * core.domStyle.scale + "px";
		main.dom.next.style.borderBottomWidth = main.dom.next.style.borderRightWidth = 4 * core.domStyle.scale + "px";

	}

	core.control.resize = function () {
		if (main.mode == 'editor') return;

		const clientWidth = main.dom.body.clientWidth,
			clientHeight = main.dom.body.clientHeight;
		const canvasWidth = core.__PIXELS__;

		const isVertical = clientHeight > clientWidth;
		core.domStyle.isVertical = isVertical;

		const totalWidth = isVertical ? GAMEVIEW_WIDTH_VERTICAL : GAMEVIEW_WIDTH,
			totalHeight = isVertical ? GAMEVIEW_HEIGHT_VERTICAL : GAMEVIEW_HEIGHT;

		const maxRatio = Math.min(clientWidth / totalWidth, clientHeight / totalHeight);

		core.domStyle.availableScale = [];
		[1, 1.25, 1.5, 1.75, 2].forEach(function (v) {
			if (maxRatio >= v) {
				core.domStyle.availableScale.push(v);
			}
		});

		if (core.domStyle.availableScale.indexOf(core.domStyle.scale) < 0) {
			core.domStyle.scale = Math.min(1, maxRatio);
		} else if (core.getLocalStorage('scale') == null && core.domStyle.availableScale.length >= 2) {
			core.domStyle.scale = core.domStyle.availableScale[core.domStyle.availableScale.length - 2];
			core.setLocalStorage('scale', core.domStyle.scale);
		}

		const totalWidthScaled = totalWidth * core.domStyle.scale,
			totalHeightScaled = totalHeight * core.domStyle.scale;

		const gameDrawBox = isVertical ? { left: BORDER_WIDTH, top: BAR_HEIGHT_VERTICAL + BORDER_HEIGHT } : { left: BAR_WIDTH + BORDER_WIDTH, top: BORDER_HEIGHT };

		const obj = {
			clientWidth: clientWidth,
			clientHeight: clientHeight,
			canvasWidth: canvasWidth,
			totalWidth: totalWidthScaled,
			totalHeight: totalHeightScaled,
			gameDrawBox: gameDrawBox,
			globalAttribute: core.status.globalAttribute || core.initStatus.globalAttribute,
		};

		_resize_gameGroup(obj);
		_resize_canvas(obj);

		if (core.status.automaticRoute == null) core.status.automaticRoute = {};
		core.control.setViewport(32, 32);
		core.updateStatusBar();
	}

	class StatusBar {
		constructor() {
			this.itemMx = [
				["book", "wand", "fly"],
				["cross", "superPotion", "pickaxe"],
				["bomb", "centerFly", "upFly"],
				["downFly", "knife", "snow"],
				["bigKey", "earthquake", "coin"],
			];
		}
		init() {
			this.toolbarAction = [
				[main.core.openKeyBoard, main.core.openQuickShop, main.core.doSL],
				[main.core.save, main.core.load, main.core.openSettings]
			];
			this.replayAction = [
				[core.triggerReplay, core.stopReplay, core.rewindReplay],
				[core.speedDownReplay, core.speedUpReplay, core.saveReplay]
			];
		}
		update() {
			this._update_background();
			this._update_props();
			this._update_items();
			this._update_equips();
			this._update_keys();
			this._update_infoWindow();
			this._update_infoBar();
		}
		_update_background(updatedFloorTitle) {
			const bgctx = main.dom.outerBackground.getContext("2d");
			const uictx = main.dom.outerUI.getContext("2d");
			if (core.domStyle.isVertical) {
				bgctx.canvas.width = GAMEVIEW_WIDTH_VERTICAL;
				bgctx.canvas.height = GAMEVIEW_HEIGHT_VERTICAL;
				uictx.canvas.width = GAMEVIEW_WIDTH_VERTICAL;
				uictx.canvas.height = GAMEVIEW_HEIGHT_VERTICAL;
				const bg = core.material.images.images["statusBackground_vertical.png"];
				bgctx.drawImage(bg, 0, 0, GAMEVIEW_WIDTH_VERTICAL, GAMEVIEW_HEIGHT_VERTICAL);
				core.setTextAlign('outerUI', 'center');
			} else {
				bgctx.canvas.width = GAMEVIEW_WIDTH;
				bgctx.canvas.height = GAMEVIEW_HEIGHT;
				uictx.canvas.width = GAMEVIEW_WIDTH;
				uictx.canvas.height = GAMEVIEW_HEIGHT;
				const bg = core.material.images.images["statusBackground.jpg"];
				bgctx.drawImage(bg, 0, 0, GAMEVIEW_WIDTH, GAMEVIEW_HEIGHT - INFO_BAR_HEIGHT);
				bgctx.fillStyle = "#676767";
				bgctx.fillRect(0, INFO_BAR_TOP, GAMEVIEW_WIDTH, INFO_BAR_HEIGHT);
				core.setTextAlign('outerUI', 'center');
			}
		}
		// 更新属性
		_update_props(updatedFloorTitle) {
			if (!updatedFloorTitle && core.status.floorId) {
				updatedFloorTitle = core.status.maps[core.status.floorId].title;
			}
			const statusList = ['hp', 'atk', 'def', 'money'];
			const drawStatusList = (baseX, baseY) => {
				let curh = baseY;
				core.setTextAlign('outerUI', 'right');
				statusList.forEach((item) => {
					// 四舍五入
					core.status.hero[item] = Math.round(core.status.hero[item]);
					// 大数据格式化
					core.fillText("outerUI", core.getRealStatus(item), baseX, curh, TEXT_COLOR);
					curh += 24;
				});
				core.setTextAlign('outerUI', 'center');
			};
			if (core.domStyle.isVertical) {
				core.clearMap("outerUI", 10, 0, 105, 120);
				core.setFont("outerUI", 'bold 14px Verdana');
				if (updatedFloorTitle) {
					core.fillText("outerUI", updatedFloorTitle, 54, 22, TEXT_COLOR);
				}
				drawStatusList(96, 46);
			} else {
				core.clearMap("outerUI", 10, 40, 105, 130);
				core.setFont("outerUI", 'bold 16px Verdana');
				if (updatedFloorTitle) {
					core.fillText("outerUI", updatedFloorTitle, 62, 61, TEXT_COLOR);
				}
				drawStatusList(110, 93);
			}
		}
		_update_items(){
			const drawItemMx = (drawFn) => {
				for (let i = 0; i < this.itemMx.length; i++) {
					for (let j = 0; j < this.itemMx[i].length; j++) {
						var item = this.itemMx[i][j];
						drawFn(i, j, item);
					}
				}
			};
			const drawItem = (item, posx, posy) => {
				const icon = core.material.icons.items[item], image = core.material.images.items;
				core.drawImage('outerUI', image, 0, 32 * icon, 32, 32, posx, posy, 32, 32);
				const cnt = core.itemCount(item);
				if (item == "superPotion") {
					const superPotion_hp = Math.round(10 * core.getRealStatus('atk') + 5 * core.getRealStatus('def'))
					core.fillBoldText('outerUI', superPotion_hp, posx + 15, posy + 15, '#FFFFFF', '#000000', "bold 8px Verdana", 52);
				}
				if ((core.items.items[item].cls === "tools" && cnt > 1) || FORCE_COUNTABLE_ITEMS.includes(item)) {
					core.fillText('outerUI', cnt, posx + 25, posy + 28, '#FFFFFF', "bold 12px Verdana");
				}
				// if (this.selectId == item)
				//     core.strokeRect('outerUI', posx + 17, posy - 4, 40, 40, '#FFD700');
			}
			if (core.domStyle.isVertical) {
				core.clearMap("outerUI", ITEM_BOX_LEFT_VERTICAL, ITEM_BOX_TOP_VERTICAL, 105, 185);
				drawItemMx((i, j, item) => {
					if (core.hasItem(item)) {
						const posx = ITEM_BOX_LEFT_VERTICAL + i * 33, posy = ITEM_BOX_TOP_VERTICAL + j * 32;
						drawItem(item, posx, posy);
					}
				});
			} else {
				core.clearMap("outerUI", ITEM_BOX_LEFT, ITEM_BOX_TOP, 105, 185);
				drawItemMx((i, j, item) => {
					if (core.hasItem(item)) {
						const posx = ITEM_BOX_LEFT + j * 33, posy = ITEM_BOX_TOP + i * 32;
						drawItem(item, posx, posy);
					}
				});
			}
		}
		_update_equips() {
			core.setFont("outerUI", 'bold 16px Verdana');
			const drawEquip = (baseX, baseY, id, color, back) => {
				if (!id) core.fillText("outerUI", back, baseX + 50, baseY + 22, color);
				else {
					core.fillText("outerUI", core.material.items[id].name, baseX + 32, baseY + 22, color);
					var icon = core.material.icons.items[id];
					core.drawImage('outerUI', core.material.images.items, 0, 32 * icon, 32, 32, baseX + 64, baseY, 32, 32);
				}
			};
			if (core.domStyle.isVertical) {
				core.clearMap("outerUI", EQUIP_BLOCK_LEFT_VERTICAL, EQUIP_BLOCK_TOP_VERTICAL, 105, 95);
				drawEquip(EQUIP_BLOCK_LEFT_VERTICAL, EQUIP_BLOCK_TOP_VERTICAL + 9, core.getFlag("nowWeapon"), "#FFCFAE", "无武器");
				drawEquip(EQUIP_BLOCK_LEFT_VERTICAL, EQUIP_BLOCK_TOP_VERTICAL + 49, core.getFlag("nowShield"), "#D1CEFF", "无防具");
			} else {
				core.clearMap("outerUI", EQUIP_BLOCK_LEFT, EQUIP_BLOCK_TOP, 105, 95);
				drawEquip(EQUIP_BLOCK_LEFT, EQUIP_BLOCK_TOP + 8, core.getFlag("nowWeapon"), "#FFCFAE", "无武器");
				drawEquip(EQUIP_BLOCK_LEFT, EQUIP_BLOCK_TOP + 56, core.getFlag("nowShield"), "#D1CEFF", "无防具");
			}
		}
		_update_keys() {
			const drawKeyList = (baseX, baseY, lines, rows) => {
				const todraw = [], keyList = ['yellowKey', 'blueKey', 'redKey'];
				let total = 0;
				keyList.forEach(function (key, i) {
					todraw[i] = core.itemCount(key);
					total += todraw[i];
				});
				if (total > lines * rows) {
					let dn = 2;
					for (let i = 0; i <= dn; i++) {
						let deltaX = i * 32, deltaY = parseInt((lines - 1) / 2 * 14);
						this.drawKey(keyList[i], baseX + deltaX, baseY + deltaY);
						core.setFont("outerUI", 'bold 14px Verdana');
						core.setTextAlign("outerUI", "left");
						core.fillText("outerUI", todraw[i], baseX + deltaX + 10, baseY + deltaY + 20, TEXT_COLOR);
					}
				} else {
					let dn = 2, dc = 0;
					while (dn >= 0 && dc < lines * rows) {
						if (todraw[dn]) {
							this.drawKey(keyList[dn], baseX + (dc % rows) * 14, baseY + parseInt(dc / rows) * 17);
							todraw[dn]--, dc++;
						} else dn--;
					}
				}
			};
			if (core.domStyle.isVertical) {
				core.clearMap("outerUI", KEY_BLOCK_LEFT_VERTICAL, KEY_BLOCK_TOP_VERTICAL, 105, 75);
				drawKeyList(KEY_BLOCK_LEFT_VERTICAL + 3, KEY_BLOCK_TOP_VERTICAL + 2, 2, 7);
			} else {
				core.clearMap("outerUI", KEY_BLOCK_LEFT, 140, 105, 75);
				drawKeyList(KEY_BLOCK_LEFT + 3, 142, 3, 7);
			}
		}
		drawKey(key, x, y) {
			let sx = 3, sy = 0;
			if (key == "blueKey") sx += 16;
			else if (key == "yellowKey") sy += 16;
			core.drawImage("outerUI", core.statusBar.icons.keys, sx, sy, 10, 16, x, y, 10, 16);
		}
		_update_infoWindow() {
			const itemId = this.selectedItem;
			if (core.domStyle.isVertical) {
				core.clearMap("outerUI", INFO_BLOCK_LEFT_VERTICAL, INFO_BLOCK_TOP_VERTICAL, 260, 64);
				if (this.selectedItem) {
					const icon = core.material.icons.items[itemId];
					core.fillText("outerUI", core.material.items[itemId].name, INFO_BLOCK_LEFT_VERTICAL + 32, INFO_BLOCK_TOP_VERTICAL + 35, "#D1CEFF");
					core.drawImage('outerUI', core.material.images.items, 0, 32 * icon, 32, 32, INFO_BLOCK_LEFT_VERTICAL + 64, INFO_BLOCK_TOP_VERTICAL + 15, 32, 32);
					core.ui.drawTextContent("outerUI", core.material.items[itemId].text, {
						left: INFO_BLOCK_LEFT_VERTICAL + 100,
						top: INFO_BLOCK_TOP_VERTICAL + 3,
						maxWidth: 160,
						color: "#D1CEFF"
					});
				}
			} else {
				core.clearMap("outerUI", INFO_BLOCK_LEFT, INFO_BLOCK_TOP, 105, 100);
				if (this.selectedItem) {
					const icon = core.material.icons.items[itemId];
					core.fillText("outerUI", core.material.items[itemId].name, INFO_BLOCK_LEFT + 32, INFO_BLOCK_TOP + 25, "#D1CEFF");
					core.drawImage('outerUI', core.material.images.items, 0, 32 * icon, 32, 32, INFO_BLOCK_LEFT + 64, INFO_BLOCK_TOP + 4, 32, 32);
					core.ui.drawTextContent("outerUI", core.material.items[itemId].text, {
						left: INFO_BLOCK_LEFT + 1,
						top: INFO_BLOCK_TOP + 36,
						maxWidth: 105,
						color: "#D1CEFF"
					});
				}
			}
		}
		showItemInfo(itemId) {
			this.selectedItem = itemId;
			this._update_infoWindow();
		}
		clearItemInfo() {
			this.selectedItem = null;
			this._update_infoWindow();
		}
		_update_toolBox() {
			const tools = core.isReplaying() ?
				[
					[core.status.replay.pausing ? "play" : "pause", "stop", "rewind"],
					["speedDown", "speedUp", "save"],
				] : [
					["keyboard", "shop", "T350"],
					["save", "load", "settings"],
				];
			if (core.domStyle.isVertical) {
				core.clearMap("outerUI", TOOL_BOX_LEFT_VERTICAL, TOOL_BOX_TOP_VERTICAL, 115, 80);
				for (let i = 0; i < tools.length; i++) {
					for (let j = 0; j < tools[i].length; j++) {
						core.drawIcon("outerUI", tools[i][j], TOOL_BOX_LEFT_VERTICAL + j * 34, TOOL_BOX_TOP_VERTICAL + i * 34, 32, 32);
					}
				}
			} else {
				core.clearMap("outerUI", TOOL_BOX_LEFT, TOOL_BOX_TOP, 115, 80);
				for (let i = 0; i < tools.length; i++) {
					for (let j = 0; j < tools[i].length; j++) {
						core.drawIcon("outerUI", tools[i][j], TOOL_BOX_LEFT + j * 34, TOOL_BOX_TOP + i * 34, 32, 32);
					}
				}
			}
		}
		onclick(x, y) {
			const makeBox = ([x, y], [w, h]) => {
				return [[x, y], [x + w, y + h]];
			}
			const gridify = ([x, y], [gw, gh]) => {
				return [parseInt(x / gw), parseInt(y / gh)];
			}
			const useItem = (itemId) => {
				if (!core.hasItem(itemId)) return;
				if (core.material.items[itemId].cls == "constants") {
					switch (itemId) {
						case "book":
							core.openBook(true);
							break;
						case "fly":
							core.useFly(true);
							break;
						case "wand":
							core.useItem("wand");
							break;
						case "snow":
							core.useItem("snow");
							break;
						default:
							this.showItemInfo(itemId);
					}
				} else if (itemId != this.selectedItem) {
					this.showItemInfo(itemId);
				} else {
					switch (itemId) {
						case "centerFly":
							core.ui._drawCenterFly();
							break;
						default:
							core.useItem(itemId);
					}
				}
			}
			const inRect = ([x, y], [[sx, sy], [dx, dy]]) => {
				return sx <= x && x <= dx && sy <= y && y <= dy;
			};
			const relativeTo = ([x, y], [ax, ay]) => {
				return [x - ax, y - ay];
			}
			const pos = [x, y];
			if (core.domStyle.isVertical) {
				const itemBox = makeBox([ITEM_BOX_LEFT_VERTICAL, ITEM_BOX_TOP_VERTICAL], [32 * 5, 33 * 3]);
				if (inRect(pos, itemBox)) {
					if (core.isReplaying() || core.status.lockControl || core.isMoving()) return;
					const [gx, gy] = gridify(relativeTo(pos, itemBox[0]), [32, 33]);
					const itemId = this.itemMx[gx][gy];
					useItem(itemId);
					return;
				}
				const toolBox = makeBox([TOOL_BOX_LEFT_VERTICAL, TOOL_BOX_TOP_VERTICAL], [34 * 3, 34 * 2]);
				if (inRect(pos, toolBox)) {
					const [row, col] = gridify(relativeTo(pos, toolBox[0]), [34, 34]);
					if (core.isReplaying()) {
						this.replayAction[col][row].call(core);
					} else if (core.isPlaying()) {
						if (col === 0 && row === 2) { core.doSL("autoSave", "load") } else { this.toolbarAction[col][row].call(core, true) }
					}
					return;
				}
			} else {
				const itemBox = makeBox([ITEM_BOX_LEFT, ITEM_BOX_TOP], [33 * 3, 32 * 5]);
				if (inRect(pos, itemBox)) {
					if (core.isReplaying() || core.status.lockControl || core.isMoving()) return;
					const [gx, gy] = gridify(relativeTo(pos, itemBox[0]), [33, 32]);
					const itemId = this.itemMx[gy][gx];
					useItem(itemId);
					return;
				}
				const toolBox = makeBox([TOOL_BOX_LEFT, TOOL_BOX_TOP], [34 * 3, 34 * 2]);
				if (inRect(pos, toolBox)) {
					const [row, col] = gridify(relativeTo(pos, toolBox[0]), [34, 34]);
					if (core.isReplaying()) {
						this.replayAction[col][row].call(core);
					} else if (core.isPlaying()) {
						if (col === 0 && row === 2) { core.doSL("autoSave", "load") } else { this.toolbarAction[col][row].call(core, true) }
					}
					return;
				}
			}
		}
		infoText;
		infocnt = 0;
		_update_infoBar() {
			core.setTextAlign('outerUI', 'left');
			const text = this.infoText;
			if (core.domStyle.isVertical) {
				core.clearMap("outerUI", 0, INFO_BAR_TOP_VERTICAL, GAMEVIEW_WIDTH, INFO_BAR_HEIGHT_VERTICAL);
				core.setFont("outerUI", 'bold 14px Verdana');
				if (text) {
					core.fillText("outerUI", text, 10, INFO_BAR_TOP_VERTICAL + 14, TEXT_COLOR);
				}
			} else {
				core.clearMap("outerUI", 0, INFO_BAR_TOP, GAMEVIEW_WIDTH, INFO_BAR_HEIGHT);
				core.setFont("outerUI", 'bold 16px Verdana');
				if (text) {
					core.fillText("outerUI", text, 10, INFO_BAR_TOP + 16, TEXT_COLOR);
				}
			}
			core.setTextAlign('outerUI', 'center');
		}
		print(text, cnt = 1) {
			this.infoText = text;
			this.infocnt = cnt;
			this._update_infoBar();
		}
		static infoRules = [
			{ id: "lava", text: "岩浆好热啊!" },
			{ id: "upFloor", text: "你看到了楼梯" },
			{ id: "downFloor", text: "你看到了楼梯" },
			{ id: "blueShop", text: "你看到了一个祭坛" },
			{ id: "man", text: "你看到了一个老人" },
			{ id: "woman", text: "你看到了一个商人" },
			{ id: "fairy", text: "你看到了一个商人" },
			{ id: "thief", text: "你看到了一个小偷" },
		]
		printEnvironmentInfo() {
			if (!this.infocnt) {
				return;
			}
			const ids = [];
			for (const block of core.status.thisMap.blocks) {
				if (!block.disable && core.nearHero(block.x, block.y)) ids.push(block.event.id);
			}
			for (const infoRule of StatusBar.infoRules) {
				if (ids.indexOf(infoRule.id) >= 0) {
					this.print(infoRule.text);
					return;
				}
			}
		}
		clearInfo(etype) {
			this.clearItemInfo();
			if (this.infocnt == 1) {
				setTimeout(() => {
					if (this.infocnt === 0) {
						this.infoText = void 0;
						this._update_infoBar();
					}
				}, 200);
				this.infocnt = 0;
			} else if (this.infocnt > 1) {
				this.infocnt--;
			}
		}
	}

	core.ui.statusBar = new StatusBar();

	core.control.clearStatusBar = function () {
		core.clearMap("outerUI");
	}
	// init() called in `afterLoadResources`.
},
    "override": function () {

	core.statusBar.icons = {
		'floor': 0,
		'name': null,
		'lv': 1,
		'hpmax': 2,
		'hp': 3,
		'atk': 4,
		'def': 5,
		'mdef': 6,
		'money': 7,
		'experience': 8,
		'up': 9,
		'book': 10,
		'fly': 11,
		'toolbox': 12,
		'keyboard': 13,
		'shop': 14,
		'save': 15,
		'load': 16,
		'settings': 17,
		'play': 18,
		'pause': 19,
		'stop': 20,
		'speedDown': 21,
		'speedUp': 22,
		'rewind': 23,
		'equipbox': 24,
		'mana': 25,
		'skill': 26,
		'paint': 27,
		'erase': 28,
		'empty': 29,
		'exit': 30,
		'btn1': 31,
		'btn2': 32,
		'btn3': 33,
		'btn4': 34,
		'btn5': 35,
		'btn6': 36,
		'btn7': 37,
		'btn8': 38,
		'keys': 39,
		'help': 40,
		'battle': 41
	};

	////// 获得某个物品 //////
	core.events.getItem = function (id, num, x, y, isGentleClick, callback) {
		if (num == null) num = 1;
		var itemCls = core.material.items[id].cls;
		if (core.getBlockCls(x, y) === 'items') {
			var ratio = core.status.maps[core.status.floorId].ratio
			if (ratio >= 4) ratio -= 1;
			num += 1 + ratio;
		}
		console.log(num)
		core.removeBlock(x, y);
		core.items.getItemEffect(id, num);
		var text = '获得 ' + core.material.items[id].name;
		if (num > 1) text += "x" + num;
		if (itemCls === 'items' && num == 1) text += core.items.getItemEffectTip(id);
		core.drawTip(text, id);

		// --- 首次获得道具的提示
		if (!core.hasFlag("__itemHint__")) core.setFlag("__itemHint__", []);
		var itemHint = core.getFlag("__itemHint__");
		if (core.flags.itemFirstText && itemHint.indexOf(id) < 0 && itemCls != 'items') {
			var hint = core.material.items[id].text || "该道具暂无描述";
			try {
				hint = core.replaceText(hint);
			} catch (e) {}
			if (!core.status.event.id || core.status.event.id == 'action') {
				core.insertAction("\t[" + core.material.items[id].name + "," + id + "]" + hint + "\n" +
					(id.endsWith('Key') ? "（钥匙类道具，遇到对应的门时自动打开）" :
						itemCls == 'tools' ? "（消耗类道具，请按T在道具栏使用）" :
						itemCls == 'constants' ? "（永久类道具，请按T在道具栏使用）" :
						itemCls == 'equips' ? "（装备类道具，请按Q在装备栏进行装备）" : ""));
			}
			itemHint.push(id);
		}

		this.afterGetItem(id, x, y, isGentleClick);
		if (callback) callback();
	}

	core.events._openDoor_check = function (block, x, y, needKey) {
		var clearAndReturn = function () {
			core.clearContinueAutomaticRoute();
			return false;
		}

		if (block == null || block.event == null) return clearAndReturn();
		var id = block.event.id;

		// 是否存在门或暗墙
		if (core.material.icons.animates[id] == null && core.material.icons.npc48[id] == null) {
			return clearAndReturn();
		}

		if (id == 'steelDoor' && core.flags.steelDoorWithoutKey)
			needKey = false;
		var doorInfo = block.event.doorInfo;
		if (doorInfo == null) return clearAndReturn();
		// Check all keys
		var keyInfo = doorInfo.keys || {};
		if (needKey) {
			for (var keyName in keyInfo) {
				var ratio = core.status.maps[core.status.floorId].ratio
				if (ratio >= 4) ratio -= 1;
				var keyValue = keyInfo[keyName] + ratio + 1;
				if (keyName.endsWith(':o')) keyName = keyName.substring(0, keyName.length - 2);

				// --- 如果是一个不存在的道具，则直接认为无法开启
				if (!core.material.items[keyName]) {
					core.stopSound();
					core.playSound('操作失败');
					core.drawTip("无法开启此门");
					return clearAndReturn();
				}
				if (core.itemCount(keyName) < keyValue) {
					core.stopSound();
					core.playSound('操作失败');
					core.drawTip("你的" + ((core.material.items[keyName] || {}).name || "钥匙") + "不足！", null, true);
					return false;
				}
			}
			if (!core.status.event.id) core.autosave(true);
			for (var keyName in keyInfo) {
				if (!keyName.endsWith(':o')) core.removeItem(keyName, keyValue);
			}
		}
		core.playSound(doorInfo.openSound);
		return true;
	}








	core.actions._clickCenterFly = function (x, y) {
		var posX = core.status.event.data.posX,
			posY = core.status.event.data.posY;
		core.ui.closePanel();
		if (x == posX && y == posY) {
			if (core.canUseItem('centerFly')) {
				core.useItem('centerFly');
			} else {
				core.drawTip('当前不能使用中心对称飞行器');
			}
		} else core.drawTip('取消使用');
	}

	var _clickSL = core.actions._clickSL;
	core.actions._clickSL = function (x, y) {
		var page = core.status.event.data.page,
			offset = core.status.event.data.offset;
		var index = page * 10 + offset;

		// 上一页
		if ((x == this.HSIZE - 1 || x == this.HSIZE - 2) && y == this.LAST) {
			core.ui._drawSLPanel(10 * (page - 1) + offset);
			return;
		}
		// 下一页
		if ((x == this.HSIZE + 1 || x == this.HSIZE + 2) && y == this.LAST) {
			core.ui._drawSLPanel(10 * (page + 1) + offset);
			return;
		}
		if ((x == this.HSIZE - 3 || x == this.HSIZE + 3) && y == this.LAST) {
			return;
		}
		_clickSL.call(this, x, y);
	}

	var _sys_longClick_lockControl = core.actions._sys_longClick_lockControl;
	core.actions._sys_longClick_lockControl = function (x, y) {
		if (!core.status.lockControl) return false;

		// 长按SL上下页快速翻页
		if (["save", "load", "replayLoad", "replayRemain"].indexOf(core.status.event.id) >= 0) {
			if (y == this.LAST && x <= this.HSIZE + 3 && x >= this.HSIZE - 3) {
				core.actions._clickSL(x, y);
				return true;
			}
		}
		return _sys_longClick_lockControl.call(this, x, y);
	}
	core.registerAction('longClick', '_sys_longClick_lockControl', core.actions._sys_longClick_lockControl, 50);

	core.control._moveHero_moving = function () {
		core.status.heroStop = false;
		core.status.automaticRoute.moveDirectly = false;
		var move = function () {
			if (!core.status.heroStop) {
				if (core.hasFlag('debug') && core.status.ctrlDown) {
					if (core.status.heroMoving != 0) return;
					// 检测是否穿出去
					var nx = core.nextX(),
						ny = core.nextY();
					if (nx < 1 || nx >= core.bigmap.width - 1 || ny < 1 || ny >= core.bigmap.height - 1) return;
					core.eventMoveHero([core.getHeroLoc('direction')], core.values.moveSpeed, move);
				} else {
					core.moveAction();
					setTimeout(move, 50);
				}
			}
		}
		move();
	}

	core.control._drawHero_updateViewport = function (x, y, offset) {}

	var _drawThumbnail_drawTempCanvas = core.maps._drawThumbnail_drawTempCanvas;
	core.maps._drawThumbnail_drawTempCanvas = function (floorId, blocks, options) {
		if (main.mode == 'editor') {
			_drawThumbnail_drawTempCanvas.call(this, floorId, blocks, options);
			return;
		}

		var width = core.floors[floorId].width;
		var height = core.floors[floorId].height;
		// 绘制到tempCanvas上面
		var tempCanvas = core.bigmap.tempCanvas;
		options.v2 = false;
		tempCanvas.canvas.width = width * 32;
		tempCanvas.canvas.height = height * 32;
		options.ctx = tempCanvas;

		var hasHero = core.status.hero != null,
			flags = null;
		if (options.flags) {
			if (!hasHero) core.status.hero = {};
			flags = core.status.hero.flags;
			core.status.hero.flags = options.flags;
		}
		this._drawThumbnail_realDrawTempCanvas(floorId, blocks, options);

		if (!hasHero) delete core.status.hero;
		else if (flags != null) core.status.hero.flags = flags;
		tempCanvas.setTransform(1, 0, 0, 1, 0, 0);
	}

	var _drawThumbnail_drawToTarget = core.maps._drawThumbnail_drawToTarget;
	core.maps._drawThumbnail_drawToTarget = function (floorId, options) {
		if (main.mode == 'editor') {
			_drawThumbnail_drawToTarget.call(this, floorId, options);
			return;
		}

		var ctx = core.getContextByName(options.ctx);
		if (ctx == null) return;
		var x = options.x || 0,
			y = options.y || 0,
			size = options.size || core.__PIXELS__;
		var tempCanvas = core.bigmap.tempCanvas;
		core.drawImage(ctx, tempCanvas.canvas, 32, 32, core.__PIXELS__, core.__PIXELS__, x, y, size, size);
	}

	var _drawWindowSkin = core.ui.drawWindowSkin;
	core.ui.drawWindowSkin = function (background, ctx, x, y, w, h, direction, px, py) {
		_drawWindowSkin.call(this, background, ctx, x, y, w, h, direction, px, py);

		var c = parseInt(w / 2);
		core.drawImage(ctx, background, 160, 90, 16, 6, x + c - 8, y, 16, 6);
	}

	var _drawPagination = ui.prototype.drawPagination;
	core.ui.drawPagination = function (page, totalPage, y) {
		if (["save", "load", "replayLoad", "replayRemain", "replaySince"].indexOf(core.status.event.id) >= 0) {
			if (totalPage <= 1) return;
			if (y == null) y = this.LAST;

			core.setFillStyle('ui', '#DDDDDD');
			var length = core.calWidth('ui', page, this._buildFont(15, true));

			core.setTextAlign('ui', 'left');
			core.fillText('ui', page, parseInt((this.PIXEL - length) / 2), y * 32 + 19);

			core.setTextAlign('ui', 'center');
			if (page > 1)
				core.fillText('ui', '上一页', this.HPIXEL - 48, y * 32 + 19);
			if (page < totalPage)
				core.fillText('ui', '下一页', this.HPIXEL + 48, y * 32 + 19);
			return;
		}
		_drawPagination.call(this, page, totalPage, y);
	}

	core.ui._drawCenterFly = function () {
		core.lockControl();
		core.status.event.id = 'centerFly';
		var fillstyle = 'rgba(255,0,0,0.5)';
		if (core.canUseItem('centerFly')) fillstyle = 'rgba(0,255,0,0.5)';
		var toX = core.bigmap.width - 1 - core.getHeroLoc('x'),
			toY = core.bigmap.height - 1 - core.getHeroLoc('y');
		this.clearUI();
		core.fillRect('ui', 0, 0, this.PIXEL, this.PIXEL, '#000000');
		core.drawThumbnail(null, null, { heroLoc: core.status.hero.loc, heroIcon: core.status.hero.image, ctx: 'ui', centerX: toX, centerY: toY });
		var offsetX = 1,
			offsetY = 1;
		core.fillRect('ui', (toX - offsetX) * 32, (toY - offsetY) * 32, 32, 32, fillstyle);
		core.status.event.data = { "x": toX, "y": toY, "posX": toX - offsetX, "posY": toY - offsetY };
		core.playSound('打开界面');
		core.drawTip("请确认当前" + core.material.items['centerFly'].name + "的位置", 'centerFly');
		return;
	}

	core.ui.drawHelp = function () {
		core.clearUI();
		core.status.event.id = 'help';
		core.lockControl();
		core.setAlpha('ui', 1);
		core.fillRect('ui', 0, 0, this.PIXEL, this.PIXEL, '#FFFFFF');
		core.drawImage('ui', core.material.images.keyboard, 0, 0, 416, 416, 0, 0, 352, 352);
	}

	core.actions._getClickLoc = function (x, y) {
		var size = 32 * core.domStyle.scale;
		var left = main.dom.gameDraw.offsetLeft + main.dom.gameGroup.offsetLeft;
		var top = main.dom.gameDraw.offsetTop + main.dom.gameGroup.offsetTop;
		var loc = { 'x': Math.max(x - left, 0), 'y': Math.max(y - top, 0), 'size': size };
		return loc;
	}

	core.enemys.getDamageString = function (enemy, x, y, floorId) {
		if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
		var damage = this.getDamage(enemy, x, y, floorId);

		var color = '#000000';

		if (damage == null) {
			damage = "???";
			color = '#FF2222';
		} else {
			if (core.hasFlag('addhp')) {
				if (damage < core.status.hero.hp) color = '#11FF11';
				else color = '#FF2222';
			} else if (damage <= 0) color = '#11FF11';
			else if (damage < core.status.hero.hp / 3) color = '#FFFFFF';
			else if (damage < core.status.hero.hp * 2 / 3) color = '#FFFF00';
			else if (damage < core.status.hero.hp) color = '#FF9933';
			else color = '#FF2222';

			damage = core.formatBigNumber(damage, true);
			if (core.enemys.hasSpecial(enemy, 19))
				damage += "+";
			if (core.enemys.hasSpecial(enemy, 21))
				damage += "-";
			if (core.enemys.hasSpecial(enemy, 11))
				damage += "^";
		}

		return {
			"damage": damage,
			"color": color
		};
	}

	core.ui._drawBook_drawDamage = function (index, enemy, offset, position) {
		core.setTextAlign('ui', 'center');
		var damage = enemy.damage,
			color = '#FFFF00';
		if (damage == null) {
			damage = '不可攻击';
			color = '#FF2222';
		}
		if (damage == 0) {
			damage = '无危险';
			color = '#11FF11';
		} else {
			if (damage >= core.status.hero.hp) color = '#FF2222';
			else if (damage >= core.status.hero.hp * 2 / 3) color = '#FF9933';
			else if (damage <= 0) color = '#11FF11';
			damage = core.formatBigNumber(damage);
			if (core.enemys.hasSpecial(enemy, 19)) damage += "+";
			if (core.enemys.hasSpecial(enemy, 21)) damage += "-";
			if (core.enemys.hasSpecial(enemy, 11)) damage += "^";
		}
		if (enemy.notBomb) damage += "[b]";
		core.fillText('ui', damage, offset, position, color, this._buildFont(13, true));
	}

	core.control.checkBlock = function () {
		var x = core.getHeroLoc('x'),
			y = core.getHeroLoc('y'),
			loc = x + "," + y;
		var damage = core.status.checkBlock.damage[loc];
		if (damage) {
			core.status.hero.hp -= damage;
			core.drawTip("你没有神圣盾不能防御，受到 " + damage + " 点魔法伤害");
			core.playSound('zone.mp3');
			this._checkBlock_disableQuickShop();
			core.status.hero.statistics.extraDamage += damage;
			if (core.status.hero.hp <= 0) {
				core.status.hero.hp = 0;
				core.updateStatusBar();
				core.events.lose();
				return;
			} else {
				core.updateStatusBar();
			}
		}
		this._checkBlock_ambush(core.status.checkBlock.ambush[loc]);
		this._checkBlock_repulse(core.status.checkBlock.repulse[loc]);
	}

	core.registerSystemEvent("man", function (data, callback) {
		var a = parseInt(core.status.floorId.substring(2));
		var b = core.nextX();
		var c = core.nextY();
		core.insertAction([
			{ "type": "insert", "name": "对话", "args": [a, b, c, 0] },
		]);
		//console.log(data);
		if (callback) callback();
	});

	core.registerSystemEvent("woman", function (data, callback) {
		var name = core.status.floorId + '@' + core.nextX() + '@' + core.nextY() + '@' + 'A';
		if (core.getFlag(name, 0) == 1) {
			var a = parseInt(core.status.floorId.substring(2));
			var b = core.nextX();
			var c = core.nextY();
			core.insertAction([
				{ "type": "insert", "name": "对话", "args": [a, b, c, 1] },
			]);
		} else {
			core.insertAction([
				{ "type": "insert", "name": "商人", "args": [0] },
			]);
		}
		//console.log(data);
		if (callback) callback();
	});

	core.registerSystemEvent("specialwall", function (data, callback) {
		if (data.event.id == 'whiteWall' || core.getFlag('talking') > 0) {
			core.insertAction({ 'type': 'openDoor', loc: [data.x, data.y] });
			if (data.event.id != 'whiteWall') {
				core.setFlag('end', 1);
			}
			core.setFlag('talking', 0); //穿墙之后不能再次穿墙
		}
		//console.log(data);
		if (callback) callback();
	});

	core.registerSystemEvent("fakeWall", function (data, callback) {
		if (data.event.id == 'blueWall') {
			core.insertAction([
				{ "type": "openDoor", loc: [data.x, data.y] },
			]);
		}
		//console.log(data);
		if (callback) callback();
	});

	core.ui._drawWindowSelector = function (background, x, y, w, h) {
		w = Math.round(w) + 48;
		h = Math.round(h);
		var ctx = core.ui.createCanvas("_selector", x - 24, y, w, h, 165);
		ctx.canvas.id = '';
		this._drawSelector(ctx, background, w, h);
	}

	core.ui._drawSelector = function (ctx, background, w, h, left, top) {
		left = left || 0;
		top = top || 0;
		ctx = this.getContextByName(ctx);
		if (!ctx) return;
		if (typeof background == 'string')
			background = core.material.images.images[background];
		if (!(background instanceof Image)) return;
		// badge
		ctx.drawImage(background, 132, 68, 24, 24, left + 4, top + 4, 24, 24);
		ctx.drawImage(background, 132, 68, 24, 24, w - left - 28, top + 4, 24, 24);
	}

	core.ui.drawTip = function (text, id, clear) {
		core.ui.statusBar.print(text);
	}

	core.ui.clearMap = function (name, x, y, width, height) {
		if (name == 'all') {
			for (var m in core.canvas) {
				core.canvas[m].clearRect(0, 0, core.bigmap.width * 32, core.bigmap.height * 32);
			}
			core.clearMap("outerUI");
			core.dom.gif.innerHTML = "";
			core.removeGlobalAnimate();
		} else {
			var ctx = this.getContextByName(name);
			if (ctx) ctx.clearRect(x || 0, y || 0, width || ctx.canvas.width, height || ctx.canvas.height);
		}
	}

	core.control._updateStatusBar_setToolboxIcon = function () {
		core.ui.statusBar._update_toolBox();
	}

	var _changeFloor_getInfo = core.events._changeFloor_getInfo;
	core.events._changeFloor_getInfo = function (floorId, stair, heroLoc, time) {
		var info = _changeFloor_getInfo.call(this, floorId, stair, heroLoc, time);
		if (info == null) return null;
		info.time = 0;
		info.origin = floorId;
		return info;
	}

	core.events._changeFloor_afterChange = function (info, callback) {
		if (!info.locked) core.unlockControl();
		core.status.replay.animate = false;
		core.events.afterChangeFloor(info.floorId);

		if (info.origin == ':before') core.ui.statusBar.print('走下了楼梯')
		else if (info.origin == ':next') core.ui.statusBar.print('登上了楼梯')
		if (callback) callback();
	}

	if (window.jsinterface && window.jsinterface.requestLandscape) {
		window.jsinterface.requestLandscape();
	}
},
    "shop": function () {
	// 【全局商店】相关的功能
	// 
	// 打开一个全局商店
	// shopId：要打开的商店id；noRoute：是否不计入录像
	this.openShop = function (shopId, noRoute) {
		var shop = core.status.shops[shopId];
		// Step 1: 检查能否打开此商店
		if (!this.canOpenShop(shopId)) {
			core.drawTip("该商店尚未开启");
			return false;
		}

		// Step 2: （如有必要）记录打开商店的脚本事件
		if (!noRoute) {
			core.status.route.push("shop:" + shopId);
		}

		// Step 3: 检查道具商店 or 公共事件
		if (shop.item) {
			if (core.openItemShop) {
				core.openItemShop(shopId);
			} else {
				core.playSound('操作失败');
				core.insertAction("道具商店插件不存在！请检查是否存在该插件！");
			}
			return;
		}
		if (shop.commonEvent) {
			core.insertCommonEvent(shop.commonEvent, shop.args);
			return;
		}

		_shouldProcessKeyUp = true;

		// Step 4: 执行标准公共商店    
		core.insertAction(this._convertShop(shop));
		return true;
	}

	////// 将一个全局商店转变成可预览的公共事件 //////
	this._convertShop = function (shop) {
		return [
			{ "type": "function", "function": "function() {core.addFlag('@temp@shop', 1);}" },
			{
				"type": "while",
				"condition": "true",
				"data": [
					// 检测能否访问该商店
					{
						"type": "if",
						"condition": "core.isShopVisited('" + shop.id + "')",
						"true": [
							// 可以访问，直接插入执行效果
							{ "type": "function", "function": "function() { core.plugin._convertShop_replaceChoices('" + shop.id + "', false) }" },
						],
						"false": [
							// 不能访问的情况下：检测能否预览
							{
								"type": "if",
								"condition": shop.disablePreview,
								"true": [
									// 不可预览，提示并退出
									{ "type": "playSound", "name": "操作失败" },
									"当前无法访问该商店！",
									{ "type": "break" },
								],
								"false": [
									// 可以预览：将商店全部内容进行替换
									{ "type": "tip", "text": "当前处于预览模式，不可购买" },
									{ "type": "function", "function": "function() { core.plugin._convertShop_replaceChoices('" + shop.id + "', true) }" },
								]
							}
						]
					}
				]
			},
			{ "type": "function", "function": "function() {core.addFlag('@temp@shop', -1);}" }
		];
	}

	this._convertShop_replaceChoices = function (shopId, previewMode) {
		var shop = core.status.shops[shopId];
		var choices = (shop.choices || []).filter(function (choice) {
			if (choice.condition == null || choice.condition == '') return true;
			try { return core.calValue(choice.condition); } catch (e) { return true; }
		}).map(function (choice) {
			var ableToBuy = core.calValue(choice.need);
			return {
				"text": choice.text,
				"icon": choice.icon,
				"color": ableToBuy && !previewMode ? choice.color : [153, 153, 153, 1],
				"action": ableToBuy && !previewMode ? [{ "type": "playSound", "name": "商店" }].concat(choice.action) : [
					{ "type": "playSound", "name": "操作失败" },
					{ "type": "tip", "text": previewMode ? "预览模式下不可购买" : "购买条件不足" }
				]
			};
		}).concat({ "text": "离开", "action": [{ "type": "playSound", "name": "取消" }, { "type": "break" }] });
		core.insertAction({ "type": "choices", "text": shop.text, "choices": choices });
	}

	/// 是否访问过某个快捷商店
	this.isShopVisited = function (id) {
		if (!core.hasFlag("__shops__")) core.setFlag("__shops__", {});
		var shops = core.getFlag("__shops__");
		if (!shops[id]) shops[id] = {};
		return shops[id].visited;
	}

	/// 当前应当显示的快捷商店列表
	this.listShopIds = function () {
		return Object.keys(core.status.shops).filter(function (id) {
			return core.isShopVisited(id) || !core.status.shops[id].mustEnable;
		});
	}

	/// 是否能够打开某个商店
	this.canOpenShop = function (id) {
		if (this.isShopVisited(id)) return true;
		var shop = core.status.shops[id];
		if (shop.item || shop.commonEvent || shop.mustEnable) return false;
		return true;
	}

	/// 启用或禁用某个快捷商店
	this.setShopVisited = function (id, visited) {
		if (!core.hasFlag("__shops__")) core.setFlag("__shops__", {});
		var shops = core.getFlag("__shops__");
		if (!shops[id]) shops[id] = {};
		if (visited) shops[id].visited = true;
		else delete shops[id].visited;
	}

	/// 能否使用快捷商店
	this.canUseQuickShop = function (id) {
		// 如果返回一个字符串，表示不能，字符串为不能使用的提示
		// 返回null代表可以使用

		// 检查当前楼层的canUseQuickShop选项是否为false
		if (core.status.thisMap.canUseQuickShop === false)
			return '当前楼层不能使用快捷商店。';
		return null;
	}

	var _shouldProcessKeyUp = true;

	/// 允许商店X键退出
	core.registerAction('keyUp', 'shops', function (keycode) {
		if (!core.status.lockControl || core.status.event.id != 'action') return false;
		if ((keycode == 13 || keycode == 32) && !_shouldProcessKeyUp) {
			_shouldProcessKeyUp = true;
			return true;
		}

		if (!core.hasFlag("@temp@shop") || core.status.event.data.type != 'choices') return false;
		var data = core.status.event.data.current;
		var choices = data.choices;
		var topIndex = core.actions._getChoicesTopIndex(choices.length);
		if (keycode == 88 || keycode == 27) { // X, ESC
			core.actions._clickAction(core.actions.HSIZE, topIndex + choices.length - 1);
			return true;
		}
		return false;
	}, 60);

	/// 允许长按空格或回车连续执行操作
	core.registerAction('keyDown', 'shops', function (keycode) {
		if (!core.status.lockControl || !core.hasFlag("@temp@shop") || core.status.event.id != 'action') return false;
		if (core.status.event.data.type != 'choices') return false;
		var data = core.status.event.data.current;
		var choices = data.choices;
		var topIndex = core.actions._getChoicesTopIndex(choices.length);
		if (keycode == 13 || keycode == 32) { // Space, Enter
			core.actions._clickAction(core.actions.HSIZE, topIndex + core.status.event.selection);
			_shouldProcessKeyUp = false;
			return true;
		}
		return false;
	}, 60);

	// 允许长按屏幕连续执行操作
	core.registerAction('longClick', 'shops', function (x, y, px, py) {
		if (!core.status.lockControl || !core.hasFlag("@temp@shop") || core.status.event.id != 'action') return false;
		if (core.status.event.data.type != 'choices') return false;
		var data = core.status.event.data.current;
		var choices = data.choices;
		var topIndex = core.actions._getChoicesTopIndex(choices.length);
		if (x >= core.actions.CHOICES_LEFT && x <= core.actions.CHOICES_RIGHT && y >= topIndex && y < topIndex + choices.length) {
			core.actions._clickAction(x, y);
			return true;
		}
		return false;
	}, 60);
},
    "宝石血瓶显示属性": function () {
	/* 宝石血瓶左下角显示数值
	 * 需要将 变量：itemDetail改为true才可正常运行
	 * 请尽量减少勇士的属性数量，否则可能会出现严重卡顿（划掉，现在你放一万个属性也不会卡）
	 * 注意：这里的属性必须是core.status.hero里面的，flag无法显示
	 * 如果不想显示，可以core.setFlag("itemDetail", false);
	 * 然后再core.getItemDetail();
	 * 如有bug在大群或造塔群@古祠
	 */

	// 忽略的道具
	const ignore = ['superPotion'];

	// 取消注释下面这句可以减少超大地图的判定。
	// 如果地图宝石过多，可能会略有卡顿，可以尝试取消注释下面这句话来解决。
	// core.bigmap.threshold = 256;
	const origin = core.control.updateStatusBar;
	core.updateStatusBar = core.control.updateStatusBar = function () {
		if (core.getFlag('__statistics__')) return;
		else return origin.apply(core.control, arguments);
	}

	core.control.updateDamage = function (floorId, ctx) {
		floorId = floorId || core.status.floorId;
		if (!floorId || core.status.gameOver || main.mode != 'play') return;
		const onMap = ctx == null;

		// 没有怪物手册
		if (!core.hasItem('book')) return;
		core.status.damage.posX = core.bigmap.posX;
		core.status.damage.posY = core.bigmap.posY;
		if (!onMap) {
			const width = core.floors[floorId].width,
				height = core.floors[floorId].height;
			// 地图过大的缩略图不绘制显伤
			if (width * height > core.bigmap.threshold) return;
		}
		this._updateDamage_damage(floorId, onMap);
		this._updateDamage_extraDamage(floorId, onMap);
		core.getItemDetail(floorId); // 宝石血瓶详细信息
		//core.drawDoorDetail(floorId); // 门详细信息
		this.drawDamage(ctx);
	};
	// 获取宝石信息 并绘制
	this.getItemDetail = function (floorId) {
		if (!core.getFlag('itemDetail')) return;
		floorId = floorId === void 0 || floorId === null ? core.status.thisMap.floorId : floorId;
		let diff = {};
		const before = core.status.hero;
		const hero = core.clone(core.status.hero);
		const handler = {
			set: function (target, key, v) {
				diff[key] = v - (target[key] || 0);
				if (!diff[key]) diff[key] = void 0;
				return true;
			}
		};
		core.status.hero = new Proxy(hero, handler);
		core.status.maps[floorId].blocks.forEach(function (block) {
			if (
				block.event.cls !== 'items' ||
				ignore.includes(block.event.id) ||
				block.disable
			)
				return;
			const x = block.x,
				y = block.y;
			// v2优化，只绘制范围内的部分
			if (core.bigmap.v2) {
				if (
					x < core.bigmap.posX - core.bigmap.extend ||
					x > core.bigmap.posX + core._SIZE_ + core.bigmap.extend ||
					y < core.bigmap.posY - core.bigmap.extend ||
					y > core.bigmap.posY + core._SIZE_ + core.bigmap.extend
				) {
					return;
				}
			}
			diff = {};
			const id = block.event.id;
			const item = core.material.items[id];
			if (item.cls === 'equips') {
				// 装备也显示
				const diff = item.equip.value === void 0 || item.equip.value === null ? {} : item.equip.value;

				const per = item.equip.percentage === void 0 || item.equip.percentage === null ? {} : item.equip.percentage;
				for (const name in per) {
					diff[name + 'per'] = per[name].toString() + '%';
				}
				drawItemDetail(diff, x, y);
				return;
			}
			// 跟数据统计原理一样 执行效果 前后比较
			core.setFlag('__statistics__', true);
			try {
				eval(item.itemEffect);
			} catch (error) {}
			drawItemDetail(diff, x, y);
		});
		core.status.hero = before;
		window.hero = before;
		window.flags = before.flags;
	};


	this.drawDoorDetail = function (floorId) {
		//if (!core.getFlag('doorDetail')) return;
		floorId = floorId === void 0 || floorId === null ? core.status.thisMap.floorId : floorId;
		let diff = {};
		const before = core.status.hero;
		const hero = core.clone(core.status.hero);
		const handler = {
			set: function (target, key, v) {
				diff[key] = v - (target[key] || 0);
				if (!diff[key]) diff[key] = void 0;
				return true;
			}
		};
		core.status.hero = new Proxy(hero, handler);
		core.status.maps[floorId].blocks.forEach(function (block) {
			if ((block.id < 81) || (block.id > 83))
				return;
			const x = block.x,
				y = block.y;
			// v2优化，只绘制范围内的部分
			if (core.bigmap.v2) {
				if (
					x < core.bigmap.posX - core.bigmap.extend ||
					x > core.bigmap.posX + core._SIZE_ + core.bigmap.extend ||
					y < core.bigmap.posY - core.bigmap.extend ||
					y > core.bigmap.posY + core._SIZE_ + core.bigmap.extend
				) {
					return;
				}
			}
			core.setFlag('__statistics__', true);
			core.status.damage.data.push({
				text: block.id,
				px: 32 * x + 2,
				py: 32 * y + 30,
				color: '#FFFFFF'
			});
		});
		core.status.hero = before;
		window.hero = before;
		window.flags = before.flags;
	};

	// 绘制
	function drawItemDetail(diff, x, y) {
		const px = 32 * x + 2,
			py = 32 * y + 30;
		let content = '';
		// 获得数据和颜色
		let i = 0;
		for (const name in diff) {
			if (!diff[name]) continue;
			let color = '#fff';

			if (typeof diff[name] === 'number') {
				var ratio = core.status.maps[core.status.floorId].ratio
				if (ratio >= 4) ratio -= 1;
				content = core.formatBigNumber(diff[name], true);
				content *= 2 + ratio

			} else content = diff[name];
			switch (name) {
			case 'atk':
			case 'atkper':
				color = '#FF7A7A';
				break;
			case 'def':
			case 'defper':
				color = '#9999F1';
				break;
			case 'mdef':
			case 'mdefper':
				color = '#6EFF83';
				break;
			case 'hp':
				color = '#88FFBB';
				break;
			case 'hpmax':
			case 'hpmaxper':
				color = '#F9FF00';
				break;
			case 'mana':
				color = '#c66';
				break;
			}
			// 绘制
			core.status.damage.data.push({
				text: content,
				px: px,
				py: py - 10 * i,
				color: color
			});
			i++;
		}
	}

},
    "全局商店": function () {
	// 【全局商店】相关的功能
	// 
	// 打开一个全局商店
	// shopId：要打开的商店id；noRoute：是否不计入录像
	this.openShop = function (shopId, noRoute) {
		var shop = core.status.shops[shopId];
		// Step 1: 检查能否打开此商店
		if (!this.canOpenShop(shopId)) {
			core.drawTip("该商店尚未开启");
			return false;
		}

		// Step 2: （如有必要）记录打开商店的脚本事件
		if (!noRoute) {
			core.status.route.push("shop:" + shopId);
		}

		// Step 3: 检查道具商店 or 公共事件
		if (shop.item) {
			if (core.openItemShop) {
				core.openItemShop(shopId);
			} else {
				core.playSound('操作失败');
				core.insertAction("道具商店插件不存在！请检查是否存在该插件！");
			}
			return;
		}
		if (shop.commonEvent) {
			core.insertCommonEvent(shop.commonEvent, shop.args);
			return;
		}

		_shouldProcessKeyUp = true;

		// Step 4: 执行标准公共商店    
		core.insertAction(this._convertShop(shop));
		return true;
	}

	////// 将一个全局商店转变成可预览的公共事件 //////
	this._convertShop = function (shop) {
		return [
			{ "type": "function", "function": "function() {core.addFlag('@temp@shop', 1);}" },
			{
				"type": "while",
				"condition": "true",
				"data": [
					// 检测能否访问该商店
					{
						"type": "if",
						"condition": "core.isShopVisited('" + shop.id + "')",
						"true": [
							// 可以访问，直接插入执行效果
							{ "type": "function", "function": "function() { core.plugin._convertShop_replaceChoices('" + shop.id + "', false) }" },
						],
						"false": [
							// 不能访问的情况下：检测能否预览
							{
								"type": "if",
								"condition": shop.disablePreview,
								"true": [
									// 不可预览，提示并退出
									{ "type": "playSound", "name": "操作失败" },
									"当前无法访问该商店！",
									{ "type": "break" },
								],
								"false": [
									// 可以预览：将商店全部内容进行替换
									{ "type": "tip", "text": "当前处于预览模式，不可购买" },
									{ "type": "function", "function": "function() { core.plugin._convertShop_replaceChoices('" + shop.id + "', true) }" },
								]
							}
						]
					}
				]
			},
			{ "type": "function", "function": "function() {core.addFlag('@temp@shop', -1);}" }
		];
	}

	this._convertShop_replaceChoices = function (shopId, previewMode) {
		var shop = core.status.shops[shopId];
		var choices = (shop.choices || []).filter(function (choice) {
			if (choice.condition == null || choice.condition == '') return true;
			try { return core.calValue(choice.condition); } catch (e) { return true; }
		}).map(function (choice) {
			var ableToBuy = core.calValue(choice.need);
			return {
				"text": choice.text,
				"icon": choice.icon,
				"color": ableToBuy && !previewMode ? choice.color : [153, 153, 153, 1],
				"action": ableToBuy && !previewMode ? [{ "type": "playSound", "name": "商店" }].concat(choice.action) : [
					{ "type": "playSound", "name": "操作失败" },
					{ "type": "tip", "text": previewMode ? "预览模式下不可购买" : "购买条件不足" }
				]
			};
		}).concat({ "text": "离开", "action": [{ "type": "playSound", "name": "取消" }, { "type": "break" }] });
		core.insertAction({ "type": "choices", "text": shop.text, "choices": choices });
	}

	/// 是否访问过某个快捷商店
	this.isShopVisited = function (id) {
		if (!core.hasFlag("__shops__")) core.setFlag("__shops__", {});
		var shops = core.getFlag("__shops__");
		if (!shops[id]) shops[id] = {};
		return shops[id].visited;
	}

	/// 当前应当显示的快捷商店列表
	this.listShopIds = function () {
		return Object.keys(core.status.shops).filter(function (id) {
			return core.isShopVisited(id) || !core.status.shops[id].mustEnable;
		});
	}

	/// 是否能够打开某个商店
	this.canOpenShop = function (id) {
		if (this.isShopVisited(id)) return true;
		var shop = core.status.shops[id];
		if (shop.item || shop.commonEvent || shop.mustEnable) return false;
		return true;
	}

	/// 启用或禁用某个快捷商店
	this.setShopVisited = function (id, visited) {
		if (!core.hasFlag("__shops__")) core.setFlag("__shops__", {});
		var shops = core.getFlag("__shops__");
		if (!shops[id]) shops[id] = {};
		if (visited) shops[id].visited = true;
		else delete shops[id].visited;
	}

	/// 能否使用快捷商店
	this.canUseQuickShop = function (id) {
		// 如果返回一个字符串，表示不能，字符串为不能使用的提示
		// 返回null代表可以使用

		// 检查当前楼层的canUseQuickShop选项是否为false
		if (core.status.thisMap.canUseQuickShop === false)
			return '当前楼层不能使用快捷商店。';
		return null;
	}

	var _shouldProcessKeyUp = true;

	/// 允许商店X键退出
	core.registerAction('keyUp', 'shops', function (keycode) {
		if (!core.status.lockControl || core.status.event.id != 'action') return false;
		if ((keycode == 13 || keycode == 32) && !_shouldProcessKeyUp) {
			_shouldProcessKeyUp = true;
			return true;
		}

		if (!core.hasFlag("@temp@shop") || core.status.event.data.type != 'choices') return false;
		var data = core.status.event.data.current;
		var choices = data.choices;
		var topIndex = core.actions._getChoicesTopIndex(choices.length);
		if (keycode == 88 || keycode == 27) { // X, ESC
			core.actions._clickAction(core.actions.HSIZE, topIndex + choices.length - 1);
			return true;
		}
		return false;
	}, 60);

	/// 允许长按空格或回车连续执行操作
	core.registerAction('keyDown', 'shops', function (keycode) {
		if (!core.status.lockControl || !core.hasFlag("@temp@shop") || core.status.event.id != 'action') return false;
		if (core.status.event.data.type != 'choices') return false;
		var data = core.status.event.data.current;
		var choices = data.choices;
		var topIndex = core.actions._getChoicesTopIndex(choices.length);
		if (keycode == 13 || keycode == 32) { // Space, Enter
			core.actions._clickAction(core.actions.HSIZE, topIndex + core.status.event.selection);
			_shouldProcessKeyUp = false;
			return true;
		}
		return false;
	}, 60);

	// 允许长按屏幕连续执行操作
	core.registerAction('longClick', 'shops', function (x, y, px, py) {
		if (!core.status.lockControl || !core.hasFlag("@temp@shop") || core.status.event.id != 'action') return false;
		if (core.status.event.data.type != 'choices') return false;
		var data = core.status.event.data.current;
		var choices = data.choices;
		var topIndex = core.actions._getChoicesTopIndex(choices.length);
		if (x >= core.actions.CHOICES_LEFT && x <= core.actions.CHOICES_RIGHT && y >= topIndex && y < topIndex + choices.length) {
			core.actions._clickAction(x, y);
			return true;
		}
		return false;
	}, 60);
},
    "新装备栏/道具栏": function () {
	// 在此增加新插件
	// 注：///// *** 裹起来的区域： 该区域内参数可以随意更改调整ui绘制 不会影响总体布局
	// 请尽量修改该区域而不是其他区域 修改的时候最好可以对照现有ui修改

	///// *** 道具类型
	// cls对应name
	var itemClsName = {
		"constants": "永久道具",
		"tools": "消耗道具",
	}
	// 一页最大放的道具数量 将把整个道具左栏分成num份 每份是一个道具项
	var itemNum = 12;
	///// ***

	// 背景设置
	this.drawBoxBackground = function (ctx) {
		core.setTextAlign(ctx, "left");
		core.clearMap(ctx);
		core.deleteCanvas("_selector");
		var info = core.status.thisUIEventInfo || {};

		///// *** 背景设置
		var max = core.__PIXELS__;
		var x = 2,
			y = x,
			w = max - x * 2,
			h = w;
		var borderWidth = 2,
			borderRadius = 5, // radius:圆角矩形的圆角半径
			borderStyle = "#fff";
		var backgroundColor = "gray";
		// 设置背景不透明度(0.85)
		var backgroundAlpha = 0.85;
		///// ***

		var start_x = x + borderWidth / 2,
			start_y = y + borderWidth / 2,
			width = max - start_x * 2,
			height = max - start_y * 2;

		// 渐变色背景的一个例子(黑色渐变白色)：
		// 有关渐变色的具体知识请网上搜索canvas createGradient了解
		/*
		   var grd = ctx.createLinearGradient(x, y, x + w, y);
		   grd.addColorStop(0, "black");
		   grd.addColorStop(1, "white");
		   backgroundColor = grd;
		*/
		// 使用图片背景要注释掉下面的strokeRect和fillRoundRect
		// 图片背景的一个例子：
		/*
		   core.drawImage(ctx, "xxx.png", x, y, w, h);
		   core.strokeRect(ctx, x, y, w, h, borderStyle, borderWidth);
		*/
		core.setAlpha(ctx, backgroundAlpha);
		core.strokeRoundRect(ctx, x, y, w, h, borderRadius, borderStyle, borderWidth);
		core.fillRoundRect(ctx, start_x, start_y, width, height, borderRadius, backgroundColor);
		core.setAlpha(ctx, 1);

		///// *** 左栏配置
		var leftbar_height = height;
		// 左边栏宽度(width*0.6) 本身仅为坐标使用 需要与底下的rightbar_width(width*0.4)同时更改
		var leftbar_width = width * 0.6;
		///// ***

		// xxx_right参数 代表最右侧坐标
		var leftbar_right = start_x + leftbar_width - borderWidth / 2;
		var leftbar_bottom = start_y + leftbar_height;
		var leftbar_x = start_x;
		var leftbar_y = start_y;

		///// *** 道具栏配置
		var boxName_color = "#fff";
		var boxName_fontSize = 15;
		var boxName_font = core.ui._buildFont(boxName_fontSize, true);
		var arrow_x = 10 + start_x;
		var arrow_y = 10 + start_y;
		var arrow_width = 20;
		var arrow_style = "white";
		// 暂时只能是1 否则不太行 等待新样板(2.7.3)之后对drawArrow做优化
		var arrow_lineWidth = 1;
		// 右箭头
		var rightArrow_right = leftbar_right - 10;
		// 道具内栏顶部坐标 本质是通过该项 控制(道具栏顶部文字和箭头)与道具内栏顶部的间隔
		var itembar_top = arrow_y + 15;
		///// ***

		var itembar_right = rightArrow_right;
		var boxName = core.status.event.id == "toolbox" ? "\r[yellow]道具栏\r | 装备栏" : "道具栏 | \r[yellow]装备栏\r";
		core.drawArrow(ctx, arrow_x + arrow_width, arrow_y, arrow_x, arrow_y, arrow_style, arrow_lineWidth);
		core.drawArrow(ctx, rightArrow_right - arrow_width, arrow_y, rightArrow_right, arrow_y, arrow_style, arrow_lineWidth);
		core.setTextAlign(ctx, "center");
		core.setTextBaseline(ctx, "middle");
		var changeBox = function () {
			var id = core.status.event.id;
			core.closePanel();
			if (id == "toolbox") core.openEquipbox();
			else core.openToolbox();
		}
		core.fillText(ctx, boxName, (leftbar_right + leftbar_x) / 2, arrow_y + 2, boxName_color, boxName_font);

		///// *** 底栏按钮
		var pageBtn_radius = 8;
		// xxx_left 最左侧坐标
		var pageBtn_left = leftbar_x + 3;
		var pageBtn_right = leftbar_right - 3;
		// xxx_bottom 最底部坐标
		var pageBtn_bottom = leftbar_bottom - 2;
		var pageBtn_borderStyle = "#fff";
		var pageBtn_borderWidth = 2;
		var pageText_color = "#fff";
		// 底部按钮与上面的道具内栏的间隔大小
		var bottomSpace = 8;
		///// ***

		core.drawItemListbox_setPageBtn(ctx, pageBtn_left, pageBtn_right, pageBtn_bottom, pageBtn_radius, pageBtn_borderStyle, pageBtn_borderWidth);
		var page = info.page || 1;
		var pageFontSize = pageBtn_radius * 2 - 4;
		var pageFont = core.ui._buildFont(pageFontSize);
		core.setPageItems(page);
		var num = itemNum;
		if (core.status.event.id == "equipbox") num -= 5;
		var maxPage = info.maxPage;
		var pageText = page + " / " + maxPage;
		core.setTextAlign(ctx, "center");
		core.setTextBaseline(ctx, "bottom");
		core.fillText(ctx, pageText, (leftbar_x + leftbar_right) / 2, pageBtn_bottom, pageText_color, pageFont);
		core.addUIEventListener(start_x, start_y, leftbar_right - start_x, arrow_y - start_y + 13, changeBox);
		var itembar_height = Math.ceil(pageBtn_bottom - pageBtn_radius * 2 - pageBtn_borderWidth / 2 - bottomSpace - itembar_top);
		var oneItemHeight = (itembar_height - 4) / itemNum;
		return {
			x: start_x,
			y: start_y,
			width: width,
			height: height,
			leftbar_right: leftbar_right,
			obj: {
				x: arrow_x,
				y: itembar_top,
				width: itembar_right - arrow_x,
				height: itembar_height,
				oneItemHeight: oneItemHeight
			}
		}
	}

	this.drawItemListbox = function (ctx, obj) {
		ctx = ctx || core.canvas.ui;
		var itembar_x = obj.x,
			itembar_y = obj.y,
			itembar_width = obj.width,
			itembar_height = obj.height,
			itemNum = obj.itemNum,
			oneItemHeight = obj.oneItemHeight;
		var itembar_right = itembar_x + itembar_width;
		var info = core.status.thisUIEventInfo || {};
		var obj = {};
		var page = info.page || 1,
			index = info.index,
			select = info.select || {};

		///// *** 道具栏内栏配置
		var itembar_style = "black";
		var itembar_alpha = 0.7;
		// 一个竖屏下减少道具显示的例子:
		// if (core.domStyle.isVertical) itemNum = 10;
		// 每个道具项的上下空隙占总高度的比例
		var itembar_marginHeightRatio = 0.2;
		// 左右间隔空隙
		var item_marginLeft = 2;
		var item_x = itembar_x + 2,
			item_y = itembar_y + 2,
			item_right = itembar_right - 2,
			itemName_color = "#fff";
		// 修改此项以更换闪烁光标
		var item_selector = "winskin.png";
		///// ***

		core.setAlpha(ctx, itembar_alpha);
		core.fillRect(ctx, itembar_x, itembar_y, itembar_width, itembar_height, itembar_style);
		core.setAlpha(ctx, 1);
		var pageItems = core.setPageItems(page);
		var marginHeight = itembar_marginHeightRatio * oneItemHeight;
		core.setTextBaseline(ctx, "middle");
		var originColor = itemName_color;
		for (var i = 0; i < pageItems.length; i++) {
			itemName_color = originColor;
			var item = pageItems[i];
			// 设置某个的字体颜色的一个例子
			// if (item.id == "xxx") itemName_color = "green";
			core.drawItemListbox_drawItem(ctx, item_x, item_right, item_y, oneItemHeight, item_marginLeft, marginHeight, itemName_color, pageItems[i]);
			if (index == i + 1) core.ui._drawWindowSelector(item_selector, item_x + 1, item_y - 1, item_right - item_x - 2, oneItemHeight - 2);
			item_y += oneItemHeight;
		}
	}

	this.drawToolboxRightbar = function (ctx, obj) {
		ctx = ctx || core.canvas.ui;
		var info = core.status.thisUIEventInfo || {};
		var page = info.page || 1,
			index = info.index || 1,
			select = info.select || {};
		var start_x = obj.x,
			start_y = obj.y,
			width = obj.width,
			height = obj.height;
		var toolboxRight = start_x + width,
			toolboxBottom = start_y + height;


		///// *** 侧边栏(rightbar)背景设置(物品介绍)
		var rightbar_width = width * 0.4;
		var rightbar_height = height;
		var rightbar_lineWidth = 2;
		var rightbar_lineStyle = "#fff";
		///// ***

		var rightbar_x = toolboxRight - rightbar_width - rightbar_lineWidth / 2;
		var rightbar_y = start_y;
		core.drawLine(ctx, rightbar_x, rightbar_y, rightbar_x, rightbar_y + rightbar_height, rightbar_lineStyle, rightbar_lineWidth);

		// 获取道具id(有可能为null)
		var itemId = select.id;
		var item = core.material.items[itemId];

		///// *** 侧边栏物品Icon信息
		var iconRect_y = rightbar_y + 10;
		// space：间距
		// 这里布局设定iconRect与侧边栏左边框 itemName与工具栏右边框 itemRect与itemName的间距均为space
		var space = 15;
		var iconRect_x = rightbar_x + space;
		var iconRect_radius = 2,
			iconRect_width = 32,
			iconRect_height = 32,
			iconRect_style = "#fff",
			iconRect_lineWidth = 2;
		///// ***

		var iconRect_bottom = iconRect_y + iconRect_height,
			iconRect_right = iconRect_x + iconRect_width;

		///// *** 侧边栏各项信息
		var itemTextFontSize = 15,
			itemText_x = iconRect_x - 4,
			itemText_y = Math.floor(start_y + rightbar_height * 0.25), // 坐标取整防止模糊
			itemClsFontSize = 15,
			itemClsFont = core.ui._buildFont(itemClsFontSize),
			itemClsColor = "#fff",
			itemCls_x = itemText_x - itemClsFontSize / 2,
			itemCls_middle = (iconRect_bottom + itemText_y) / 2, //_middle代表文字的中心y坐标
			itemNameFontSize = 18,
			itemNameColor = "#fff",
			itemNameFont = core.ui._buildFont(itemNameFontSize, true);
		var itemName_x = iconRect_right + space;
		var itemName_middle = iconRect_y + iconRect_height / 2 + iconRect_lineWidth;
		// 修改这里可以编辑未选中道具时的默认值
		var defaultItem = {
			cls: "constants",
			name: "未知道具",
			text: "没有道具最永久"
		}
		var defaultEquip = {
			cls: "equips",
			name: "未知装备",
			text: "一无所有，又何尝不是一种装备",
			equip: {
				type: "装备"
			}
		}
		///// ***

		var originItem = item;
		if (core.status.event.id == "equipbox") item = item || defaultEquip;
		item = item || defaultItem;
		var itemCls = item.cls,
			itemName = item.name,
			itemText = item.text;
		itemText = core.replaceText(itemText);
		/* 一个根据道具id修改道具名字(右栏)的例子
		 * if (item.id == "xxx") itemNameColor = "red";
		 */
		var itemClsName = core.getItemClsName(item);
		var itemNameMaxWidth = rightbar_width - iconRect_width - iconRect_lineWidth * 2 - space * 2;
		core.strokeRoundRect(ctx, iconRect_x, iconRect_y, iconRect_width, iconRect_height, iconRect_radius, iconRect_style, iconRect_lineWidth);
		if (item.id)
			core.drawIcon(ctx, item.id, iconRect_x + iconRect_lineWidth / 2, iconRect_y + iconRect_lineWidth / 2, iconRect_width - iconRect_lineWidth, iconRect_height - iconRect_lineWidth);
		core.setTextAlign(ctx, "left");
		core.setTextBaseline(ctx, "middle");
		core.fillText(ctx, itemName, itemName_x, itemName_middle, itemNameColor, itemNameFont, itemNameMaxWidth);
		core.fillText(ctx, "【" + itemClsName + "】", itemCls_x, itemCls_middle, itemClsColor, itemClsFont);
		var statusText = "";
		if (core.status.event.id == "equipbox") {
			var type = item.equip.type;
			if (typeof type == "string") type = core.getEquipTypeByName(type);
			var compare = core.compareEquipment(item.id, core.getEquip(type));
			if (info.select.action == "unload") compare = core.compareEquipment(null, item.id);
			// --- 变化值...
			for (var name in core.status.hero) {
				if (typeof core.status.hero[name] != 'number') continue;
				var nowValue = core.getRealStatus(name);
				// 查询新值
				var newValue = Math.floor((core.getStatus(name) + (compare.value[name] || 0)) *
					(core.getBuff(name) * 100 + (compare.percentage[name] || 0)) / 100);
				if (nowValue == newValue) continue;
				var color = newValue > nowValue ? '#00FF00' : '#FF0000';
				nowValue = core.formatBigNumber(nowValue);
				newValue = core.formatBigNumber(newValue);
				statusText += core.getStatusLabel(name) + " " + nowValue + "->\r[" + color + "]" + newValue + "\r\n";
			}
		}
		itemText = statusText + itemText;
		core.drawTextContent(ctx, itemText, {
			left: itemText_x,
			top: itemText_y,
			bold: false,
			color: "white",
			align: "left",
			fontSize: itemTextFontSize,
			maxWidth: rightbar_width - (itemText_x - rightbar_x) * 2 + itemTextFontSize / 2
		});

		///// *** 退出按钮设置
		var btnRadius = 10;
		var btnBorderWidth = 2;
		var btnRight = toolboxRight - 2;
		var btnBottom = toolboxBottom - 2;
		var btnBorderStyle = "#fff";
		///// ***

		// 获取圆心位置
		var btn_x = btnRight - btnRadius - btnBorderWidth / 2;
		btn_y = btnBottom - btnRadius - btnBorderWidth / 2;
		core.drawToolbox_setExitBtn(ctx, btn_x, btn_y, btnRadius, btnBorderStyle, btnBorderWidth);

		///// *** 使用按钮设置
		var useBtnHeight = btnRadius * 2;
		// 这里不设置useBtnWidth而是根据各项数据自动得出width
		var useBtnRadius = useBtnHeight / 2;
		var useBtn_x = rightbar_x + 4,
			useBtn_y = btnBottom - useBtnHeight;
		var useBtnBorderStyle = "#fff";
		var useBtnBorderWidth = btnBorderWidth;
		///// ***

		core.drawToolbox_setUseBtn(ctx, useBtn_x, useBtn_y, useBtnRadius, useBtnHeight, useBtnBorderStyle, useBtnBorderWidth);
	}

	this.drawEquipbox_drawOthers = function (ctx, obj) {
		var info = core.status.thisUIEventInfo;

		///// *** 装备格设置
		var equipList_lineWidth = 2;
		var equipList_boxSize = 32;
		var equipList_borderWidth = 2;
		var equipList_borderStyle = "#fff";
		var equipList_nameColor = "#fff";
		///// ***

		var equipList_x = obj.x + 4,
			equipList_bottom = obj.obj.y - equipList_lineWidth,
			equipList_y = equipList_bottom - obj.obj.oneItemHeight * reduceItem - 2,
			equipList_height = equipList_bottom - equipList_y;
		var equipList_right = obj.leftbar_right,
			equipList_width = equipList_right - equipList_x;
		core.drawLine(ctx, obj.x, equipList_bottom + equipList_lineWidth / 2, equipList_right, equipList_bottom + equipList_lineWidth / 2, equipList_borderStyle, equipList_lineWidth);
		var toDrawList = core.status.globalAttribute.equipName,
			len = toDrawList.length;

		///// *** 装备格设置
		var maxItem = 4;
		var box_width = 32,
			box_height = 32,
			box_borderStyle = "#fff",
			box_selectBorderStyle = "gold", // 选中的装备格的颜色
			box_borderWidth = 2;
		var boxName_fontSize = 14,
			boxName_space = 2,
			boxName_color = "#fff"; // 装备格名称与上面的装备格框的距离
		var maxLine = Math.ceil(len / maxItem);
		///// ***
		var l = Math.sqrt(len)
		if (Math.pow(l) == len && len != 4) {
			if (l <= maxItem) maxItem = l;
		}
		maxItem = Math.min(toDrawList.length, maxItem);
		info.equips = maxItem;

		var boxName_font = core.ui._buildFont(boxName_fontSize);
		// 总宽高减去所有装备格宽高得到空隙大小
		var oneBoxWidth = box_width + box_borderWidth * 2;
		var oneBoxHeight = box_height + boxName_fontSize + boxName_space + 2 * box_borderWidth;
		var space_y = (equipList_height - maxLine * oneBoxHeight) / (1 + maxLine),
			space_x = (equipList_width - maxItem * oneBoxWidth) / (1 + maxItem);
		var box_x = equipList_x + space_x,
			box_y = equipList_y + space_y;
		for (var i = 0; i < len; i++) {
			var id = core.getEquip(i),
				name = toDrawList[i];
			var selectBorder = false;
			if (core.status.thisUIEventInfo.select.type == i) selectBorder = true;
			var borderStyle = selectBorder ? box_selectBorderStyle : box_borderStyle;
			core.drawEquipbox_drawOne(ctx, name, id, box_x, box_y, box_width, box_height, boxName_space, boxName_font, boxName_color, borderStyle, box_borderWidth);
			var todo = new Function("core.clickOneEquipbox('" + id + "'," + i + ")");
			core.addUIEventListener(box_x - box_borderWidth / 2, box_y - box_borderWidth / 2, oneBoxWidth, oneBoxHeight, todo);
			box_x += space_x + oneBoxWidth;
			if ((i + 1) % maxItem == 0) {
				box_x = equipList_x + space_x;
				box_y += space_y + oneBoxHeight;
			}
		}
	}

	this.drawToolbox = function (ctx) {
		ctx = ctx || core.canvas.ui;
		core.status.thisEventClickArea = [];

		var info = core.drawBoxBackground(ctx);
		info.itemNum = itemNum;
		core.drawItemListbox(ctx, info.obj);
		core.drawToolboxRightbar(ctx, info);
		core.setTextBaseline(ctx, "alphabetic");
		core.setTextAlign("left");
	}

	var reduceItem = 4;
	this.drawEquipbox = function (ctx) {
		ctx = ctx || core.canvas.ui;
		core.status.thisEventClickArea = [];
		var info = core.drawBoxBackground(ctx);
		info.itemNum = itemNum - reduceItem;
		info.obj.y += info.obj.oneItemHeight * reduceItem;
		info.obj.height -= info.obj.oneItemHeight * reduceItem;
		core.drawItemListbox(ctx, info.obj);
		core.drawEquipbox_drawOthers(ctx, info);
		core.drawToolboxRightbar(ctx, info);
		core.setTextBaseline(ctx, "alphabetic");
		core.setTextAlign("left");
	}


	this.drawEquipbox_drawOne = function (ctx, name, id, x, y, width, height, space, font, color, style, lineWidth) {
		if (id) core.drawIcon(ctx, id, x + lineWidth / 2, y + lineWidth / 2, width, height);
		core.strokeRect(ctx, x, y, width + lineWidth, height + lineWidth, style, lineWidth);
		core.setTextAlign(ctx, "center");
		core.setTextBaseline(ctx, "top");
		var tx = (x + x + lineWidth / 2 + width) / 2,
			ty = y + height + lineWidth / 2 * 3 + space;
		core.fillText(ctx, name, tx, ty, color, font);
		core.setTextBaseline(ctx, "alphabetic");
		core.setTextAlign("left");
	}

	this.drawItemListbox_drawItem = function (ctx, left, right, top, height, marginLeft, marginHeight, style, id) {
		var info = core.status.thisUIEventInfo;
		var nowClick = info.index;
		var item = core.material.items[id] || {};
		var name = item.name || "???";
		var num = core.itemCount(id) || 0;
		var fontSize = Math.floor(height - marginHeight * 2);
		core.setTextAlign(ctx, "right");
		var numText = "x" + num;
		core.fillText(ctx, numText, right - marginLeft, top + height / 2, style, core.ui._buildFont(fontSize));
		if (name != "???") core.drawIcon(ctx, id, left + marginLeft, top + marginHeight, fontSize, fontSize);
		var text_x = left + marginLeft + fontSize + 2;
		var maxWidth = right - core.calWidth(ctx, numText) - text_x;
		core.setTextAlign(ctx, "left");
		core.fillText(ctx, name, text_x, top + height / 2, style, core.ui._buildFont(fontSize), maxWidth);
		var todo = new Function("core.clickItemFunc('" + id + "');");
		core.addUIEventListener(left, top, right - left, height, todo);
	}

	this.setPageItems = function (page) {
		var num = itemNum;
		if (core.status.event.id == "equipbox") num -= reduceItem;
		var info = core.status.thisUIEventInfo;
		if (!info) return;
		page = page || info.page;
		var items = core.getToolboxItems(core.status.event.id == "toolbox" ? "all" : "equips");
		info.allItems = items;
		var maxPage = Math.ceil(items.length / num);
		info.maxPage = maxPage;
		var pageItems = items.slice((page - 1) * num, page * num);
		info.pageItems = pageItems;
		info.maxItem = pageItems.length;
		if (items.length == 0 && pageItems.length == 0) info.index = null;
		if (pageItems.length == 0 && info.page > 1) {
			info.page = Math.max(1, info.page - 1);
			return core.setPageItems(info.page);
		}
		return pageItems;
	}

	this.drawToolbox_setExitBtn = function (ctx, x, y, r, style, lineWidth) {
		core.strokeCircle(ctx, x, y, r, style, lineWidth);
		ctx.textAlign = "center";
		ctx.textBaseline = "middle";
		var textSize = Math.sqrt(2) * r;
		core.fillText(ctx, "x", x, y, style, core.ui._buildFont(textSize), textSize);
		core.setTextAlign(ctx, "start");
		core.setTextBaseline(ctx, "top");

		var todo = function () {
			core.closePanel();
		}
		core.addUIEventListener(x - r, y - r, r * 2, r * 2, todo);
	}

	this.drawToolbox_setUseBtn = function (ctx, x, y, r, h, style, lineWidth) {
		core.setTextAlign(ctx, "left");
		core.setTextBaseline(ctx, "top");
		var fontSize = h - 4;
		var font = core.ui._buildFont(fontSize);
		var text = core.status.event.id == "toolbox" ? "使用" : "装备";
		if (core.status.thisUIEventInfo.select.action == "unload") text = "卸下";
		var w = core.calWidth(ctx, text, font) + 2 * r + lineWidth / 2;

		core.strokeRoundRect(ctx, x, y, w, h, r, style, lineWidth);
		core.fillText(ctx, text, x + r, y + lineWidth / 2 + 2, style, font);

		var todo = function () {
			core.useSelectItemInBox();
		}
		core.addUIEventListener(x, y, w, h, todo);
	}

	this.drawItemListbox_setPageBtn = function (ctx, left, right, bottom, r, style, lineWidth) {
		var offset = lineWidth / 2 + r;

		var x = left + offset;
		var y = bottom - offset;
		var pos = Math.sqrt(2) / 2 * (r - lineWidth / 2);
		core.fillPolygon(ctx, [
			[x - pos, y],
			[x + pos - 2, y - pos],
			[x + pos - 2, y + pos]
		], style);
		core.strokeCircle(ctx, x, y, r, style, lineWidth);
		var todo = function () {
			core.addItemListboxPage(-1);
		}
		core.addUIEventListener(x - r - 2, y - r - 2, r * 2 + 4, r * 2 + 4, todo);

		x = right - offset;
		core.fillPolygon(ctx, [
			[x + pos, y],
			[x - pos + 2, y - pos],
			[x - pos + 2, y + pos]
		], style);
		core.strokeCircle(ctx, x, y, r, style, lineWidth);
		var todo = function () {
			core.addItemListboxPage(1);
		}
		core.addUIEventListener(x - r - 2, y - r - 2, r * 2 + 4, r * 2 + 4, todo);
	}

	this.clickItemFunc = function (id) {
		var info = core.status.thisUIEventInfo;
		if (!info) return;
		if (info.select.id == id) return core.useSelectItemInBox();
		info.select = {};
		info.select.id = id;
		core.setIndexAndSelect('index');
		core.refreshBox();
	}

	this.clickOneEquipbox = function (id, type) {
		var info = core.status.thisUIEventInfo;
		if (!info) return;
		if (info.select.id == id && info.select.type == type) core.useSelectItemInBox();
		else core.status.thisUIEventInfo.select = {
			id: id,
			type: type,
			action: "unload"
		}
		return core.refreshBox();
	}

	core.ui.getToolboxItems = function (cls) {
		var list = Object.keys(core.status.hero.items[cls] || {});
		if (cls == "all") {
			for (var name in core.status.hero.items) {
				if (name == "equips") continue;
				list = list.concat(Object.keys(core.status.hero.items[name]));
			}
			return list.filter(function (id) {
				return !core.material.items[id].hideInToolbox;
			}).sort();
		}

		if (this.uidata.getToolboxItems) {
			return this.uidata.getToolboxItems(cls);
		}
		return list.filter(function (id) {
			return !core.material.items[id].hideInToolbox;
		}).sort();
	}

	this.useSelectItemInBox = function () {
		var info = core.status.thisUIEventInfo;
		if (!info) return;
		if (!info.select.id) return;
		var id = info.select.id;
		if (core.status.event.id == "toolbox") {
			core.events.tryUseItem(id);
			// core.closePanel();
		} else if (core.status.event.id == "equipbox") {
			var action = info.select.action || "load";
			info.index = 1;
			if (action == "load") {
				var type = core.getEquipTypeById(id);
				core.loadEquip(id, function () {
					core.status.route.push("equip:" + id);
					info.select.type = type;
					core.setIndexAndSelect("select");
					core.drawEquipbox();
				});
			} else {
				var type = info.select.type;
				core.unloadEquip(type, function () {
					core.status.route.push("unEquip:" + type);
					info.select.type = type;
					//info.select.action = 'load'
					core.setIndexAndSelect("select");
					core.drawEquipbox();
				});
			}
		}
	}

	this.setIndexAndSelect = function (toChange) {
		var info = core.status.thisUIEventInfo;
		if (!info) return;
		core.setPageItems(info.page);
		var index = info.index || 1;
		var items = info.pageItems;
		if (info.select.type != null) {
			var type = info.select.type;
			id = core.getEquip(type);
			info.index = null;
			info.select = {
				id: id,
				action: "unload",
				type: type
			};
			return;
		} else {
			info.select.action = null;
			info.select.type = null;
			if (toChange == "index") info.index = items.indexOf(info.select.id) + 1;
			info.select.id = items[info.index - 1];
		}

	}

	this.addItemListboxPage = function (num) {
		var info = core.status.thisUIEventInfo;
		if (!info) return;
		var maxPage = info.maxPage || 1;
		info.page = info.page || 1;
		info.page += num;
		if (info.page <= 0) info.page = maxPage;
		if (info.page > maxPage) info.page = 1;
		info.index = 1;
		core.setPageItems(info.page);
		core.setIndexAndSelect("select");
		core.refreshBox();
	}

	this.addItemListboxIndex = function (num) {
		var info = core.status.thisUIEventInfo;
		if (!info) return;
		var maxItem = info.maxItem || 0;
		info.index = info.index || 0;
		info.index += num;
		if (info.index <= 0) info.index = 1;
		if (info.index > maxItem) info.index = maxItem;
		core.setIndexAndSelect("select");
		core.refreshBox();
	}

	this.addEquipboxType = function (num) {
		var info = core.status.thisUIEventInfo;
		var type = info.select.type;
		if (type == null && num > 0) info.select.type = 0;
		else info.select.type = type + num;
		var max = core.status.globalAttribute.equipName.length;
		if (info.select.type >= max) {
			info.select = {};
			core.setIndexAndSelect("select")
			return core.addItemListboxPage(0);
		} else {
			var m = Math.abs(info.select.type);
			if (info.select.type < 0) info.select.type = max - m;
			core.setIndexAndSelect("select")
			core.refreshBox();
			return;
		}
	}

	core.actions._keyDownToolbox = function (keycode) {
		if (!core.status.thisEventClickArea) return;
		if (keycode == 37) { // left
			core.addItemListboxPage(-1);
			return;
		}
		if (keycode == 38) { // up
			core.addItemListboxIndex(-1);
			return;
		}
		if (keycode == 39) { // right
			core.addItemListboxPage(1);
			return;
		}
		if (keycode == 40) { // down
			core.addItemListboxIndex(1);
			return;
		}
	}

	////// 工具栏界面时，放开某个键的操作 //////
	core.actions._keyUpToolbox = function (keycode) {
		if (keycode == 81) {
			core.ui.closePanel();
			if (core.isReplaying())
				core.control._replay_equipbox();
			else
				core.openEquipbox();
			return;
		}
		if (keycode == 84 || keycode == 27 || keycode == 88) {
			core.closePanel();
			return;
		}
		if (keycode == 13 || keycode == 32 || keycode == 67) {
			var info = core.status.thisUIEventInfo;
			if (info.select) {
				core.useSelectItemInBox();
			}
			return;
		}
	}

	core.actions._keyDownEquipbox = function (keycode) {
		if (!core.status.thisEventClickArea) return;
		if (keycode == 37) { // left
			var info = core.status.thisUIEventInfo;
			if (info.index != null) return core.addItemListboxPage(-1);
			return core.addEquipboxType(-1);
		}
		if (keycode == 38) { // up
			var info = core.status.thisUIEventInfo;
			if (info.index == 1) {
				info.select.type = core.status.globalAttribute.equipName.length - 1;
				core.setIndexAndSelect();
				return core.refreshBox();
			}
			if (info.index) return core.addItemListboxIndex(-1);
			return core.addEquipboxType(-1 * info.equips);
		}
		if (keycode == 39) { // right
			var info = core.status.thisUIEventInfo;
			if (info.index != null) return core.addItemListboxPage(1);
			return core.addEquipboxType(1);
		}
		if (keycode == 40) { // down
			var info = core.status.thisUIEventInfo;
			if (info.index) return core.addItemListboxIndex(1);
			return core.addEquipboxType(info.equips);
		}
	}

	core.actions._keyUpEquipbox = function (keycode, altKey) {
		if (altKey && keycode >= 48 && keycode <= 57) {
			core.items.quickSaveEquip(keycode - 48);
			return;
		}
		if (keycode == 84) {
			core.ui.closePanel();
			if (core.isReplaying())
				core.control._replay_toolbox();
			else
				core.openToolbox();
			return;
		}
		if (keycode == 81 || keycode == 27 || keycode == 88) {
			core.closePanel();
			return;
		}
		if (keycode == 13 || keycode == 32 || keycode == 67) {
			var info = core.status.thisUIEventInfo;
			if (info.select) core.useSelectItemInBox();
			return;
		}
	}

	core.registerAction("ondown", "inEventClickAction", function (x, y, px, py) {
		if (!core.status.thisEventClickArea) return false;
		// console.log(px + "," + py);
		var info = core.status.thisEventClickArea;
		for (var i = 0; i < info.length; i++) {
			var obj = info[i];
			if (px >= obj.x && px <= obj.x + obj.width && py > obj.y && py < obj.y + obj.height) {
				if (obj.todo) obj.todo();
				break;
			}
		}
		return true;
	}, 51);
	core.registerAction("onclick", "stopClick", function () {
		if (core.status.thisEventClickArea) return true;
	}, 51);

	this.addUIEventListener = function (x, y, width, height, todo) {
		if (!core.status.thisEventClickArea) return;
		var obj = {
			x: x,
			y: y,
			width: width,
			height: height,
			todo: todo
		}
		core.status.thisEventClickArea.push(obj);
	}

	this.initThisEventInfo = function () {
		core.status.thisUIEventInfo = {
			page: 1,
			select: {}
		};
		core.status.thisEventClickArea = [];
	}

	this.refreshBox = function () {
		if (!core.status.event.id) return;
		if (core.status.event.id == "toolbox") core.drawToolbox();
		else core.drawEquipbox();
	}

	core.ui.closePanel = function () {
		if (core.status.hero && core.status.hero.flags) {
			// 清除全部临时变量
			Object.keys(core.status.hero.flags).forEach(function (name) {
				if (name.startsWith("@temp@") || /^arg\d+$/.test(name)) {
					delete core.status.hero.flags[name];
				}
			});
		}
		this.clearUI();
		core.maps.generateGroundPattern();
		core.updateStatusBar(true);
		core.unlockControl();
		core.status.event.data = null;
		core.status.event.id = null;
		core.status.event.selection = null;
		core.status.event.ui = null;
		core.status.event.interval = null;
		core.status.thisUIEventInfo = null;
		core.status.thisEventClickArea = null
	}

	this.getItemClsName = function (item) {
		if (item == null) return itemClsName;
		if (item.cls == "equips") {
			if (typeof item.equip.type == "string") return item.equip.type;
			var type = core.getEquipTypeById(item.id);
			return core.status.globalAttribute.equipName[type];
		} else return itemClsName[item.cls] || item.cls;
	}

	core.events.openToolbox = function (fromUserAction) {
		if (core.isReplaying()) return;
		if (!this._checkStatus('toolbox', fromUserAction)) return;
		core.initThisEventInfo();
		let info = core.status.thisUIEventInfo
		info.index = 1
		core.setIndexAndSelect('select')
		core.drawToolbox();
	}

	core.events.openEquipbox = function (fromUserAction) {
		if (core.isReplaying()) return;
		if (!this._checkStatus('equipbox', fromUserAction)) return;
		core.initThisEventInfo();
		let info = core.status.thisUIEventInfo
		info.select.type = 0
		core.setIndexAndSelect('select')
		core.drawEquipbox();
	}

	core.control._replay_toolbox = function () {
		if (!core.isPlaying() || !core.isReplaying()) return;
		if (!core.status.replay.pausing) return core.drawTip("请先暂停录像");
		if (core.isMoving() || core.status.replay.animate || core.status.event.id)
			return core.drawTip("请等待当前事件的处理结束");

		core.lockControl();
		core.status.event.id = 'toolbox';
		core.drawToolbox();
	}

	core.control._replay_equipbox = function () {
		if (!core.isPlaying() || !core.isReplaying()) return;
		if (!core.status.replay.pausing) return core.drawTip("请先暂停录像");
		if (core.isMoving() || core.status.replay.animate || core.status.event.id)
			return core.drawTip("请等待当前事件的处理结束");

		core.lockControl();
		core.status.event.id = 'equipbox';
		core.drawEquipbox();
	}

	core.control._replayAction_item = function (action) {
		if (action.indexOf("item:") != 0) return false;
		var itemId = action.substring(5);
		if (!core.canUseItem(itemId)) return false;
		if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) {
			core.useItem(itemId, false, core.replay);
			return true;
		}
		core.status.event.id = "toolbox";
		core.initThisEventInfo();
		var info = core.status.thisUIEventInfo;
		var items = core.getToolboxItems("all");
		core.setPageItems(1);
		var index = items.indexOf(itemId) + 1;
		info.page = Math.ceil(index / info.maxItem);
		info.index = index % info.maxItem || info.maxItem;
		core.setIndexAndSelect("select");
		core.setPageItems(info.page);
		core.drawToolbox();
		setTimeout(function () {
			core.ui.closePanel();
			core.useItem(itemId, false, core.replay);
		}, core.control.__replay_getTimeout());
		return true;
	}

	core.control._replayAction_equip = function (action) {
		if (action.indexOf("equip:") != 0) return false;
		var itemId = action.substring(6);
		var items = core.getToolboxItems('equips');
		var index = items.indexOf(itemId) + 1;
		if (index < 1) return false;
		core.status.route.push(action);
		if (core.material.items[itemId].hideInReplay || core.status.replay.speed == 24) {
			core.loadEquip(itemId, core.replay);
			return true;
		}
		core.status.event.id = "equipbox";
		core.initThisEventInfo();
		var info = core.status.thisUIEventInfo;
		core.setPageItems(1);
		info.page = Math.ceil(index / info.maxItem);
		info.index = index % info.maxItem || info.maxItem;
		core.setIndexAndSelect("select");
		core.setPageItems(info.page);
		core.drawEquipbox();
		setTimeout(function () {
			core.ui.closePanel();
			core.loadEquip(itemId, core.replay);
		}, core.control.__replay_getTimeout());
		return true;
	}

	core.control._replayAction_unEquip = function (action) {
		if (action.indexOf("unEquip:") != 0) return false;
		var equipType = parseInt(action.substring(8));
		if (!core.isset(equipType)) return false;
		core.status.route.push(action);
		if (core.status.replay.speed == 24) {
			core.unloadEquip(equipType, core.replay);
			return true;
		}
		core.status.event.id = "equipbox";
		core.initThisEventInfo();
		var info = core.status.thisUIEventInfo;
		core.setPageItems(1);
		info.select.type = equipType;
		core.setIndexAndSelect();
		core.drawEquipbox();
		setTimeout(function () {
			core.ui.closePanel();
			core.unloadEquip(equipType, core.replay);
		}, core.control.__replay_getTimeout());
		return true;
	}
	core.registerReplayAction("item", core.control._replayAction_item);
	core.registerReplayAction("equip", core.control._replayAction_equip);
	core.registerReplayAction("unEquip", core.control._replayAction_unEquip);
},
    "一防减伤计算": function () {
	// 在此增加新插件
	ui.prototype._drawBook_drawRow3 = function (index, enemy, top, left, width, position) {
		// 绘制第三行
		core.setTextAlign('ui', 'left');
		var b13 = this._buildFont(13, true),
			f13 = this._buildFont(13, false);
		var col1 = left,
			col2 = left + width * 9 / 25,
			col3 = left + width * 17 / 25;
		core.fillText('ui', '临界', col1, position, '#DDDDDD', f13);
		core.fillText('ui', core.formatBigNumber(enemy.critical || 0), col1 + 30, position, null, b13);
		core.fillText('ui', '减伤', col2, position, null, f13);
		core.fillText('ui', core.formatBigNumber(enemy.criticalDamage || 0), col2 + 30, position, null, b13);
		//core.fillText('ui', '加防', col3, position, null, f13);
		core.fillText('ui', '1防', col3, position, null, f13);
		core.fillText('ui', core.formatBigNumber(enemy.defDamage || 0), col3 + 30, position, null, b13);
	}
	////// 1防减伤计算 //////
	enemys.prototype.getDefDamage = function (enemy, k, x, y, floorId) {
		if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
		k = k || 1;
		var nowDamage = this._getDamage(enemy, null, x, y, floorId);
		var nextDamage = this._getDamage(enemy, { "def": core.status.hero.def + k }, x, y, floorId);
		if (nowDamage == null || nextDamage == null) return "???";
		return nowDamage - nextDamage;
	}
	//防御倍数
	enemys.prototype._getCurrentEnemys_addEnemy_defDamage = function (enemy, x, y, floorId) {
		var ratio = core.status.maps[floorId || core.status.floorId].ratio || 1;
		//第一行为按照ratio值计算减防，第二行为1防减伤
		//return this.getDefDamage(enemy, ratio, x, y, floorId);
		return this.getDefDamage(enemy, null, x, y, floorId);
	}

},
    "越过楼梯": function () {
	// 在此增加新插件
	core.maps._canMoveDirectly_checkStartPoint = function (sx, sy) {
		if (core.status.checkBlock.damage[sx + "," + sy]) return false;
		var block = core.getBlock(sx, sy);
		if (block != null) {
			if ((block.event.id == "upFloor") || (block.event.id == "downFloor")) return true;
			// 只有起点是传送点才是能无视
			return block.event.trigger == 'changeFloor';
		}
		return true;
	}

	core.maps._canMoveDirectly_bfs = function (sx, sy, locs, number, ans, canMoveArray) {
		canMoveArray = canMoveArray || core.maps.generateMovableArray();
		var blocksObj = core.maps.getMapBlocksObj();
		// 滑冰
		var bgMap = core.maps.getBgMapArray();

		var visited = [],
			queue = [];
		visited[sx + "," + sy] = 0;
		queue.push(sx + "," + sy);

		while (queue.length > 0) {
			var now = queue.shift().split(","),
				x = parseInt(now[0]),
				y = parseInt(now[1]);
			for (var direction in core.utils.scan) {
				if (!core.inArray(canMoveArray[x][y], direction)) continue;
				var nx = x + core.utils.scan[direction].x,
					ny = y + core.utils.scan[direction].y,
					nindex = nx + "," + ny;
				if (visited[nindex]) continue;
				if (core.onSki(bgMap[ny][nx])) continue;
				if (!core.maps._canMoveDirectly_checkNextPoint(blocksObj, nx, ny)) continue;
				visited[nindex] = visited[now] + 1;
				// if (nx == ex && ny == ey) return visited[nindex];
				for (var i in ans) {
					if (locs[i][0] == nx && locs[i][1] == ny && ans[i] == null) {
						// 不可以绿点为终点
						var block = blocksObj[nx + "," + ny];
						if (block && !block.disable && block.event.trigger) {
							ans[i] = -1;
						} else {
							if (block && !block.disable && ((block.event.id == "upFloor") || (block.event.id == "downFloor"))) {
								ans[i] = -1;
							} else {
								ans[i] = visited[nindex];
							}
						}
						number--;
						if (number == 0) return ans;
					}
				}
				queue.push(nindex);
			}
		}

		for (var i in ans) {
			if (ans[i] == null) ans[i] = -1;
		}
		return ans;
	}

	core.maps._canMoveDirectly_checkNextPoint = function (blocksObj, x, y) {
		var index = x + "," + y;
		var block = blocksObj[index];
		// 该点是否不可通行或有脚本
		if (block && !block.disable && (block.event.noPass || block.event.script || block.event.event)) {
			if ((block.event.id != "upFloor") && (block.event.id != "downFloor")) {
				return false;
			} else {
				var ignore = core.flags.ignoreChangeFloor;
				if (block.event.data && block.event.data.ignoreChangeFloor != null)
					ignore = block.event.data.ignoreChangeFloor;
				if (!ignore) return false;
			}
		}
		// 该点是否是绿点可触发
		if (block && !block.disable && block.event.trigger) {
			if (block.event.trigger != 'changeFloor') return false;
			var ignore = core.flags.ignoreChangeFloor;
			if (block.event.data && block.event.data.ignoreChangeFloor != null)
				ignore = block.event.data.ignoreChangeFloor;
			if (!ignore) return false;
		}
		// 是否存在阻激夹域伤害
		if (core.status.checkBlock.damage[index]) return false;
		if (core.status.checkBlock.repulse[index]) return false;
		// 是否存在捕捉
		if (core.status.checkBlock.ambush[index]) return false;

		return true;
	}




	core.events.trigger = function (x, y, callback) {
		var _executeCallback = function () {
			// 因为trigger之后还有可能触发其他同步脚本（比如阻激夹域检测）
			// 所以这里强制callback被异步触发
			if (callback) {
				setTimeout(callback, 1); // +1是为了录像检测系统 
			}
			return;
		}
		if (core.status.gameOver) return _executeCallback();
		if (core.status.event.id == 'action') {
			core.insertAction({ "type": "function", "function": "function () { core.events._trigger_inAction(" + x + "," + y + "); }", "async": true },
				null, null, null, true);
			return _executeCallback();
		}
		if (core.status.event.id) return _executeCallback();

		var block = core.getBlock(x, y);
		if (block == null) return _executeCallback();

		// 执行该点的脚本
		if (block.event.script) {
			var noPass = block.event.noPass;
			if (((block.event.id == "upFloor") || (block.event.id == "downFloor")) && !noPass && core.events._trigger_ignoreChangeFloor(block)) return _executeCallback();
			core.clearRouteFolding();
			try {
				eval(block.event.script);
			} catch (e) { main.log(e); }
		}

		// 碰触事件
		if (block.event.event) {
			core.clearRouteFolding();
			core.insertAction(block.event.event, block.x, block.y);
			// 不再执行该点的系统事件
			return _executeCallback();
		}

		if (block.event.trigger && block.event.trigger != 'null') {
			var noPass = block.event.noPass,
				trigger = block.event.trigger;
			if (noPass) core.clearAutomaticRouteNode(x, y);

			// 转换楼层能否穿透
			if (trigger == 'changeFloor' && !noPass && this._trigger_ignoreChangeFloor(block))
				return _executeCallback();
			core.status.automaticRoute.moveDirectly = false;
			this.doSystemEvent(trigger, block);
		}
		return _executeCallback();
	}

},
    "NPC悬停": function () {
	//怪物显示复写而成
	//使用方法：启用useNPCDisplay为true，并且在想要显示信息的npc处，events事件最开头添加注释，内容为想要显示的片段，多行用多个注释，每个注释一行
	this.startNPCDisplay = function (enemy_x, enemy_y) {
		var blk = core.getBlock(enemy_x, enemy_y);
		if (!blk || !blk.event || !blk.event.data) return;
		var dt = core.getBlock(enemy_x, enemy_y).event.data;
		if (!dt || !dt[0] || !dt[0].type || dt[0].type != 'comment') return;
		var cls = core.getBlockCls(enemy_x, enemy_y)
		if (cls != 'npcs' && cls != 'npc48' && cls != 'enemys' && cls != 'enemy48') return;
		var id = core.getBlockId(enemy_x, enemy_y)
		if (id === 'fairy') return;
		var text = [dt[0].text];
		var lines = 1;
		while (lines < dt.length && dt[lines].type == 'comment') {
			text.push(dt[lines].text);
			lines++;
		}
		//在下面设置你的字体和字体大小
		var font = "beeB"; //这里"......"填写你的字体。
		var fontSize = 14;
		core.setFont('NPC', "14px beeB");
		var width = core.ui.calWidth('NPC', text, font) - 220;
		var height = 68 + 40 * lines;
		var cell_x = (enemy_x + 0.5) * 32 - core.bigmap.offsetX;
		var cell_y = (enemy_y + 0.5) * 32 - core.bigmap.offsetY;
		//绘制窗口
		core.plugin.addNPC(width, height, cell_x, cell_y, fontSize, core.getBlockId(enemy_x, enemy_y), font, text);
	}

	//这个子程序用来绘制怪物的基本信息
	this.addNPC = function (width, height, cell_x, cell_y, fontSize, mon_id, font, text) {
		//绘制窗口外观
		width = 0;
		for (let i = 0; i < text.length; i++) {
			let tmp = core.drawTextContent('NPC', core.replaceValue(text[i]), { left: cell_x + 10, top: cell_y + 60 + i * 40, align: 'mid', font: font, fontSize: fontSize });
			let tt = tmp.blocks[tmp.blocks.length - 1];
			width = Math.max(width, tt.left + tt.width + 20);
		}
		core.clearMap('NPC');
		if (cell_x > 32 * core.__SIZE__ - width) cell_x -= width;
		if (cell_y > 32 * core.__SIZE__ - height) cell_y -= height;
		if (cell_x < 0) cell_x = 0;
		if (cell_y < 0) cell_y = 0;

		core.fillRoundRect("NPC", cell_x, cell_y, width, height, 5, [0, 0, 0, 0.85]);
		core.strokeRoundRect("NPC", cell_x, cell_y, width, height, 5, [255, 255, 255, 1], 2);
		//绘制抬头、怪物图标和怪物名称
		core.drawIcon('NPC', mon_id, cell_x + width / 2 - 16, cell_y + 10);
		// 		core.fillText("enemyInfo", info[mon_id].name, cell_x + width / 2 - info[mon_id].name.length * fontSize / 8 -
		// 			info[mon_id].name.replace(/[()]/g, '').length * fontSize / 8 - info[mon_id].name.replace(/[-_ ()0-9a-zA-Z]/g, '').length *
		// 			fontSize / 4, cell_y + 78 + bigEnemy, [255, 255, 255, 1], fontSize + "px " + font);
		for (let i = 0; i < text.length; i++) {
			core.drawTextContent('NPC', core.replaceValue(text[i]), { left: cell_x + 10, top: cell_y + 60 + i * 40, align: 'mid', font: font, fontSize: fontSize });
		}
	}

	//如果鼠标移动，则Register Action
	core.registerAction('onmove', 'NPCDisplay', function (mouse_x, mouse_y) {
		core.plugin.NPCDisplay(mouse_x, mouse_y);
		return false;
	}, 100);


	//主程序，当鼠标移动时进行判断
	this.NPCDisplay = function (mouse_x, mouse_y) {
		//使用需要3个条件：打开开关、拥有怪物手册和玩家在电脑端上游戏
		if (core.getFlag("useEnemyInfoDisplay") == true && core.hasItem("book") && core.platform.isPC == true) {
			core.createCanvas("NPC", 0, 0, 422, 422, 81);
			//这里处理大地图带来的影响
			offsetX = core.bigmap.offsetX;
			offsetY = core.bigmap.offsetY;
			//获得鼠标对应的图块坐标位置
			var enemy_x = core.clamp(Math.floor((mouse_x + offsetX / (32 * core.domStyle.scale))), core.bigmap.offsetX /
				(32 * core.domStyle.scale) - 1, core.__SIZE__ - 1 + core.bigmap.offsetX / (32 * core.domStyle.scale)) + 1;
			var enemy_y = core.clamp(Math.floor((mouse_y + offsetY / (32 * core.domStyle.scale))), core.bigmap.offsetY /
				(32 * core.domStyle.scale) - 1, core.__SIZE__ - 1 + core.bigmap.offsetY / (32 * core.domStyle.scale)) + 1;
			//如果该图块有怪物，则绘制窗口
			core.plugin.startNPCDisplay(enemy_x, enemy_y);
		}
	}




},
    "编辑器显示伤害": function () {
	// 在此增加新插件
	/////// 用户设置 ///////
	// 将__enable置为false将关闭插件
	var __enable = true;
	// 魔防攻速之类的属性可以在这里加 ['atk', 'def', 'mdef']
	var heroStatus = ['atk', 'def', 'mdef', 'hp'];
	// saveHero为true 将会把每次造塔测试时的角色数据存下来 否则会读取初始属性
	// 用不着可以关了 节约缓存空间 (虽然根本没多少 还没一个存档大
	// 也可以手动清理 控制台输入core.removeLocalStorage('editorHero')即可
	var saveHero = true;

	// 下为具体实现 懒得写注释了 大概就是写HTML然后注册交互
	if (!__enable || main.mode != 'editor') return;
	core.plugin.initEditorDamage = false;
	if (heroStatus.length >= 4 && !editor.isMobile) editor.dom.mid2.style.top = 650 + 30 * (heroStatus.length - 3) + 'px';
	editor.statusRatio = core.getLocalStorage('statusRatio', 1);
	editor.saveHero = saveHero;
	editor._heroStatus = heroStatus;
	editor.dom.mapEdit.appendChild(core.canvas.damage.canvas)
	var HTML = "<input type='button' value='←'/><input type='button' value='↑'/><input type='button' value='↓'/><input type='button' value='→'/><input type='button' id='bigmapBtn' value='大地图'' style='margin-left: '5px'/>";

	//if (heroStatus.length >= 4 && !editor.isMobile) editor.dom.mid2.style.top = 650 + 30 * (heroStatus.length - 3) + 'px';
	heroStatus.forEach(function (status) {
		var id = status + 'set',
			id2 = status + 'add',
			id3 = status + 'rec',
			id4 = status + 'help';
		HTML += "<br/><input type='text' size='15' id='" + id + "'><input type='button' id='" + id2 + "' value = '+'><input type='button' id='" + id3 + "' value = '-'><input type='button' value='?' id = '" + id4 + "'>"
	});
	document.getElementById('viewportButtons').innerHTML = HTML;
	['set', 'add', 'rec', 'help'].forEach(function (e) {
		heroStatus.forEach(function (status) {
			editor.dom[status + e] = document.getElementById(status + e);
		});
	});
	var _hasItem = core.items.hasItem;
	core.items.hasItem = function (itemId) {
		if (itemId == 'book' && main.mode == 'editor') return true;
		return _hasItem.call(core.items, itemId);
	}
	if (main.mode == "editor") {
		var applyList = ["getDamageString", "nextCriticals", "getEnemyInfo", "getEnemyValue"];
		applyList.forEach(function (name) {
			var func = core.enemys[name];
			core.enemys[name] = function () {
				var args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));
				if (typeof args[0] == "string") args[0] = core.enemys.enemys[args[0]];
				return func.apply(core.enemys, args);
			}
		});
	}

	////// 获得勇士属性 //////
	core.control.getStatus = function (name) {
		if (!core.status.hero) return null;
		if (name == 'x' || name == 'y' || name == 'direction')
			return this.getHeroLoc(name);
		/*if ( main.mode == 'editor' && !core.hasFlag('__statistics__')) {
			return data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.firstData.hero[name];
		}*/
		return core.status.hero[name];
	}

	core.control.updateDamage = function (floorId, ctx) {
		floorId = floorId || core.status.floorId;
		if (!floorId || core.status.gameOver) return;
		var onMap = ctx == null;
		if (main.mode == 'editor') {
			ctx = core.canvas.damage;
			core.updateCheckBlock();
			core.clearMap(ctx);
			if (editor.uivalues.bigmap) return;
		}

		// 没有怪物手册
		if (!core.hasItem('book')) return;
		core.status.damage.posX = core.bigmap.posX;
		core.status.damage.posY = core.bigmap.posY;
		if (!onMap) {
			var width = core.floors[floorId].width,
				height = core.floors[floorId].height;
			// 地图过大的缩略图不绘制显伤
			if (width * height > core.bigmap.threshold) return;
		}
		this._updateDamage_damage(floorId, onMap);
		this._updateDamage_extraDamage(floorId, onMap);
		this.drawDamage(ctx);
	}

	core.control.drawDamage = function (ctx) {
		if (core.status.gameOver || !core.status.damage /* || main.mode != 'play'*/ ) return;
		var onMap = false;
		if (ctx == null) {
			ctx = core.canvas.damage;
			core.clearMap('damage');
			onMap = true;
		}

		if (onMap && core.bigmap.v2) {
			// 检查是否需要重算...
			if (Math.abs(core.bigmap.posX - core.status.damage.posX) >= core.bigmap.extend - 1 ||
				Math.abs(core.bigmap.posY - core.status.damage.posY) >= core.bigmap.extend - 1) {
				return this.updateDamage();
			}
		}
		return this._drawDamage_draw(ctx, onMap);
	}

	////// 以x,y的形式返回每个点的事件 //////
	core.maps.getMapBlocksObj = function (floorId, noCache) {
		floorId = floorId || core.status.floorId;
		if (core.status.mapBlockObjs[floorId] && !noCache && main.mode != 'editor')
			return core.status.mapBlockObjs[floorId];

		var obj = {};
		core.extractBlocks(floorId);
		core.status.maps[floorId].blocks.forEach(function (block) {
			obj[block.x + "," + block.y] = block;
		});
		core.status.mapBlockObjs[floorId] = obj
		return obj;
	}

	this.bignum = function (num, defaultValue) {
		if (num == null || num == "") return defaultValue;
		num = num + "";
		var list = {
			'w': 1e4,
			'e': 1e8,
			'z': 1e12,
			'j': 1e16,
			'g': 1e20
		};
		// 浮点数问题
		function checkFloat(num) {
			if (!core.isset(num)) return 0;
			num = num + "";
			var index = num.indexOf(".");
			if (index < 0) return 0;
			else return num.slice(index + 1).length;
		}
		var index = num.search(/w|e|z|j|g/);
		if (index <= 0) {
			num = parseInt(num);
			if (core.isset(num)) return num;
			else {
				alert('不正确的输入');
				return defaultValue;
			}
		}
		for (; index > 0; index = num.search(/w|e|z|j|g/)) {
			var p = num[index],
				q = list[p],
				n = num.slice(0, index),
				m = Math.pow(10, checkFloat(n));
			num = n * m * q / m + num.slice(index + 1);
		}
		return parseInt(num);
	}

	this.updateEditorDamage = function (noSave) {
		core.updateDamage();
		heroStatus.forEach(function (status) {
			editor.dom[status + 'set'].value = core.status.hero[status];
		});
		if (!noSave && editor.saveHero) core.setLocalStorage('editorHero', core.status.hero);
	}

	var _resizeMap = core.maps.resizeMap;
	core.maps.resizeMap = function (floorId) {
		_resizeMap.call(core.maps, floorId);
		if (!core.plugin.initEditorDamage && main.mode == 'editor') {
			core.plugin.initEditorDamage = true;
			var editorHero = core.getLocalStorage('editorHero');
			if (editorHero && saveHero) core.status.hero = editorHero;
			else core.removeLocalStorage('editorHero');
			editor._heroStatus.forEach(function (e) {
				editor.dom[e + 'set'].onchange = function () {
					var status = this.id.slice(0, -3);
					core.status.hero[status] = core.bignum(this.value, core.status.hero[status]);
					core.updateEditorDamage();
				}
				editor.dom[e + 'add'].onclick = function () {
					var status = this.id.slice(0, -3);
					core.status.hero[status] += editor.statusRatio;
					core.updateEditorDamage();
				}
				editor.dom[e + 'rec'].onclick = function () {
					var status = this.id.slice(0, -3);
					core.status.hero[status] -= editor.statusRatio;
					core.updateEditorDamage();
				}
				editor.dom[e + 'help'].onclick = function () {
					var status = this.id.slice(0, -4),
						name = core.getStatusLabel(status);
					var ratio = parseInt(prompt("当前属性:" + name + "\n现在的点击按钮变化值:" + editor.statusRatio + ",请输入按下一次+/-按钮的属性变化量,可以写4w 10.2e这种字母缩写"));
					if (!core.isset(ratio)) {
						printe('不合法的输入');
						return;
					}
					editor.statusRatio = ratio;
					core.setLocalStorage('statusRatio', ratio);
				}
			});
			var _updateMap = editor.updateMap;
			editor.updateMap = function () {
				_updateMap.call(editor);
				core.updateEditorDamage(true);
			}
			editor.mode.onmode = function (mode, callback) {
				if (editor_mode.mode != mode) {
					if (mode === 'save') {
						editor_mode.doActionList(editor_mode.mode, editor_mode.actionList, function () {
							if (callback) callback();
							core.updateEditorDamage();
						});
					}
					if (editor_mode.mode === 'nextChange' && mode) editor_mode.showMode(mode);
					if (mode !== 'save') editor_mode.mode = mode;
					editor_mode.actionList = [];
				}
			}
		}
	}
},
    "手册区分特殊属性怪物": function () {
	// 在此增加新插件
	enemys.prototype.getCurrentEnemys = function (floorId) {
		floorId = floorId || core.status.floorId;
		var enemys = [],
			used = {};
		core.extractBlocks(floorId);
		core.status.maps[floorId].blocks.forEach(function (block) {
			if (!block.disable && block.event.cls.indexOf('enemy') == 0) {
				this._getCurrentEnemys_addEnemy(block.event.id, enemys, used, block.x, block.y, floorId);
			}
		}, this);
		return this._getCurrentEnemys_sort(enemys);
	}

	enemys.prototype._getCurrentEnemys_getEnemy = function (enemyId) {
		var enemy = core.material.enemys[enemyId];
		if (!enemy) return null;

		// 检查朝向；displayIdInBook
		return core.material.enemys[enemy.displayIdInBook] || core.material.enemys[(enemy.faceIds || {}).down] || enemy;
	}

	enemys.prototype._getCurrentEnemys_addEnemy = function (enemyId, enemys, used, x, y, floorId) {
		var enemy = this._getCurrentEnemys_getEnemy(enemyId);
		if (enemy == null) return;

		var id = enemy.id;

		var enemyInfo = this.getEnemyInfo(enemy, null, null, null, floorId);
		var locEnemyInfo = this.getEnemyInfo(enemy, null, x, y, floorId);

		var locEnemySpecial = -1,
			enemySpecial = -1;
		if (locEnemyInfo.special && typeof (locEnemyInfo.special) == "object") {
			locEnemyInfo.special.forEach(t => {
				locEnemySpecial += Math.pow(2, t)
			})
		}
		if (enemyInfo.special && typeof (enemyInfo.special) == "object") {
			enemyInfo.special.forEach(t => {
				enemySpecial += Math.pow(2, t)
			})
		}
		if (!core.flags.enableEnemyPoint ||
			(locEnemyInfo.atk == enemyInfo.atk && locEnemyInfo.def == enemyInfo.def && locEnemyInfo.hp == enemyInfo.hp && locEnemySpecial == enemySpecial)) {
			x = null;
			y = null;
		} else {
			// 检查enemys里面是否使用了存在的内容
			for (var i = 0; i < enemys.length; ++i) {
				var one = enemys[i];
				var oneSpecial = -1;
				if (one.special && typeof (one.special) == "object") {
					one.special.forEach(t => {
						oneSpecial += Math.pow(2, t)
					})
				}
				if (id == one.id && one.locs != null &&
					locEnemyInfo.atk == one.atk && locEnemyInfo.def == one.def && locEnemyInfo.hp == one.hp && locEnemySpecial == oneSpecial) {
					one.locs.push([x, y]);
					return;
				}
			}
			enemyInfo = locEnemyInfo;
		}
		var id = enemy.id + ":" + x + ":" + y;
		if (used[id]) return;
		used[id] = true;

		var specialText = core.enemys.getSpecialText(enemy, x, y, floorId);
		var specialColor = core.enemys.getSpecialColor(enemy, x, y, floorId);

		var critical = this.nextCriticals(enemy, 1, x, y, floorId);
		if (critical.length > 0) critical = critical[0];

		var e = core.clone(enemy);
		for (var v in enemyInfo) {
			e[v] = enemyInfo[v];
		}
		if (x != null && y != null) {
			e.locs = [
				[x, y]
			];
		}
		e.name = core.getEnemyValue(enemy, 'name', x, y, floorId);
		e.specialText = specialText;
		e.specialColor = specialColor;
		e.damage = this.getDamage(enemy, x, y, floorId);
		e.critical = critical[0];
		e.criticalDamage = critical[1];
		e.defDamage = this._getCurrentEnemys_addEnemy_defDamage(enemy, x, y, floorId);
		enemys.push(e);
	}

	enemys.prototype._getCurrentEnemys_addEnemy_defDamage = function (enemy, x, y, floorId) {
		var ratio = core.status.maps[floorId || core.status.floorId].ratio || 1;
		return this.getDefDamage(enemy, ratio, x, y, floorId);
	}

	enemys.prototype._getCurrentEnemys_sort = function (enemys) {
		return enemys.sort(function (a, b) {
			if (a.damage == b.damage) {
				return a.money - b.money;
			}
			if (a.damage == null) {
				return 1;
			}
			if (b.damage == null) {
				return -1;
			}
			return a.damage - b.damage;
		});
	}

	////// 获得所有特殊属性的名称 //////
	enemys.prototype.getSpecialText = function (enemy, x, y, floorId) {
		if (typeof enemy == 'string') enemy = this.getEnemyInfo(enemy, null, x, y, floorId);
		if (!enemy) return [];
		var special = enemy.special;
		var text = [];

		var specials = this.getSpecials();
		if (specials) {
			for (var i = 0; i < specials.length; i++) {
				if (this.hasSpecial(special, specials[i][0]))
					text.push(this._calSpecialContent(enemy, specials[i][1]));
			}
		}
		return text;
	}

	////// 获得所有特殊属性的颜色 //////
	enemys.prototype.getSpecialColor = function (enemy, x, y, floorId) {
		if (typeof enemy == 'string') enemy = this.getEnemyInfo(enemy, null, x, y, floorId);
		if (!enemy) return [];
		var special = enemy.special;
		var colors = [];

		var specials = this.getSpecials();
		if (specials) {
			for (var i = 0; i < specials.length; i++) {
				if (this.hasSpecial(special, specials[i][0]))
					colors.push(specials[i][3] || null);
			}
		}
		return colors;

	}

	////// 获得所有特殊属性的额外标记 //////
	enemys.prototype.getSpecialFlag = function (enemy, x, y, floorId) {
		if (typeof enemy == 'string') enemy = getEnemyInfo(enemy, null, x, y, floorId);
		if (!enemy) return [];
		var special = enemy.special;
		var flag = 0;

		var specials = this.getSpecials();
		if (specials) {
			for (var i = 0; i < specials.length; i++) {
				if (this.hasSpecial(special, specials[i][0]))
					flag |= (specials[i][4] || 0);
			}
		}
		return flag;
	}

	////// 获得每个特殊属性的说明 //////
	enemys.prototype.getSpecialHint = function (enemy, special) {
		var specials = this.getSpecials();

		if (special == null) {
			if (specials == null) return [];
			var hints = [];
			for (var i = 0; i < specials.length; i++) {
				if (this.hasSpecial(enemy, specials[i][0]))
					hints.push("\r[" + core.arrayToRGBA(specials[i][3] || "#FF6A6A") + "]\\d" + this._calSpecialContent(enemy, specials[i][1]) +
						"：\\d\r[]" + this._calSpecialContent(enemy, specials[i][2]));
			}
			return hints;
		}

		if (specials == null) return "";
		for (var i = 0; i < specials.length; i++) {
			if (special == specials[i][0])
				return "\r[#FF6A6A]\\d" + this._calSpecialContent(enemy, specials[i][1]) + "：\\d\r[]" + this._calSpecialContent(enemy, specials[i][2]);
		}
		return "";
	}
	ui.prototype._drawBook_drawName = function (index, enemy, top, left, width) {
		// 绘制第零列（名称和特殊属性）
		// 如果需要添加自己的比如怪物的称号等，也可以在这里绘制
		core.setTextAlign('ui', 'center');
		if (core.enemys.getSpecialText(enemy).length == 0) {
			core.fillText('ui', enemy.name, left + width / 2,
				top + 35, '#DDDDDD', this._buildFont(17, true), width);
		} else {
			core.fillText('ui', enemy.name, left + width / 2,
				top + 28, '#DDDDDD', this._buildFont(17, true), width);
			switch (core.enemys.getSpecialText(enemy).length) {
			case 1:
				core.fillText('ui', core.enemys.getSpecialText(enemy)[0], left + width / 2,
					top + 50, core.arrayToRGBA((core.enemys.getSpecialColor(enemy) || [])[0] || '#FF6A6A'),
					this._buildFont(15, true), width);
				break;
			case 2:
				// Step 1: 计算字体
				var text = core.enemys.getSpecialText(enemy)[0] + "  " + core.enemys.getSpecialText(enemy)[1];
				core.setFontForMaxWidth('ui', text, width, this._buildFont(15, true));
				// Step 2: 计算总宽度
				var totalWidth = core.calWidth('ui', text);
				var leftWidth = core.calWidth('ui', core.enemys.getSpecialText(enemy)[0]);
				var rightWidth = core.calWidth('ui', core.enemys.getSpecialText(enemy)[1]);
				// Step 3: 绘制
				core.fillText('ui', core.enemys.getSpecialText(enemy)[0], left + (width + leftWidth - totalWidth) / 2,
					top + 50, core.arrayToRGBA((core.enemys.getSpecialColor(enemy) || [])[0] || '#FF6A6A'));
				core.fillText('ui', core.enemys.getSpecialText(enemy)[1], left + (width + totalWidth - rightWidth) / 2,
					top + 50, core.arrayToRGBA((core.enemys.getSpecialColor(enemy) || [])[1] || '#FF6A6A'));
				break;
			default:
				core.fillText('ui', '多属性...', left + width / 2,
					top + 50, '#FF6A6A', this._buildFont(15, true), width);
			}
		}
	}
	ui.prototype._drawBookDetail_getInfo = function (index) {
		var floorId = core.floorIds[(core.status.event.ui || {}).index] || core.status.floorId;
		// 清除浏览地图时的光环缓存
		if (floorId != core.status.floorId && core.status.checkBlock) {
			core.status.checkBlock.cache = {};
		}
		var enemys = core.enemys.getCurrentEnemys(floorId);
		if (enemys.length == 0) return [];
		index = core.clamp(index, 0, enemys.length - 1);
		var enemy = enemys[index];
		var texts = core.enemys.getSpecialHint(enemy);
		if (texts.length == 0) texts.push("该怪物无特殊属性。");
		if (enemy.description) texts.push(enemy.description + "\r");
		this._drawBookDetail_getTexts(enemy, floorId, texts);
		texts.push("");
		return [enemy, texts];
	}
}
}