var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = 
{
    "init": function () {
	// 在此增加新插件
},
    "drawLight": function () {

	// 绘制灯光/漆黑层效果。调用方式 core.plugin.drawLight(...)
	// 【参数说明】
	// name：必填，要绘制到的画布名；可以是一个系统画布，或者是个自定义画布；如果不存在则创建
	// color：可选，只能是一个0~1之间的数，为不透明度的值。不填则默认为0.9。
	// lights：可选，一个数组，定义了每个独立的灯光。
	//        其中每一项是三元组 [x,y,r] x和y分别为该灯光的横纵坐标，r为该灯光的半径。
	// lightDec：可选，0到1之间，光从多少百分比才开始衰减（在此范围内保持全亮），不设置默认为0。
	//        比如lightDec为0.5代表，每个灯光部分内圈50%的范围全亮，50%以后才开始快速衰减。
	// 【调用样例】
	// core.plugin.drawLight('curtain'); // 在curtain层绘制全图不透明度0.9，等价于更改画面色调为[0,0,0,0.9]。
	// core.plugin.drawLight('ui', 0.95, [[25,11,46]]); // 在ui层绘制全图不透明度0.95，其中在(25,11)点存在一个半径为46的灯光效果。
	// core.plugin.drawLight('test', 0.2, [[25,11,46,0.1]]); // 创建一个test图层，不透明度0.2，其中在(25,11)点存在一个半径为46的灯光效果，灯光中心不透明度0.1。
	// core.plugin.drawLight('test2', 0.9, [[25,11,46],[105,121,88],[301,221,106]]); // 创建test2图层，且存在三个灯光效果，分别是中心(25,11)半径46，中心(105,121)半径88，中心(301,221)半径106。
	// core.plugin.drawLight('xxx', 0.3, [[25,11,46],[105,121,88,0.2]], 0.4); // 存在两个灯光效果，它们在内圈40%范围内保持全亮，40%后才开始衰减。
	this.drawLight = function (name, color, lights, lightDec) {

		// 清空色调层；也可以修改成其它层比如animate/weather层，或者用自己创建的canvas
		var ctx = core.getContextByName(name);
		if (ctx == null) {
			if (typeof name == 'string')
				ctx = core.createCanvas(name, 0, 0, core.__PIXELS__, core.__PIXELS__, 98);
			else return;
		}

		ctx.mozImageSmoothingEnabled = false;
		ctx.webkitImageSmoothingEnabled = false;
		ctx.msImageSmoothingEnabled = false;
		ctx.imageSmoothingEnabled = false;

		core.clearMap(name);
		// 绘制色调层，默认不透明度
		if (color == null) color = 0.9;
		ctx.fillStyle = "rgba(0,0,0," + color + ")";
		ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);

		lightDec = core.clamp(lightDec, 0, 1);

		// 绘制每个灯光效果
		ctx.globalCompositeOperation = 'destination-out';
		lights.forEach(function (light) {
			// 坐标，半径，中心不透明度
			var x = light[0],
				y = light[1],
				r = light[2];
			// 计算衰减距离
			var decDistance = parseInt(r * lightDec);
			// 正方形区域的直径和左上角坐标
			var grd = ctx.createRadialGradient(x, y, decDistance, x, y, r);
			grd.addColorStop(0, "rgba(0,0,0,1)");
			grd.addColorStop(1, "rgba(0,0,0,0)");
			ctx.beginPath();
			ctx.fillStyle = grd;
			ctx.arc(x, y, r, 0, 2 * Math.PI);
			ctx.fill();
		});
		ctx.globalCompositeOperation = 'source-over';
		// 可以在任何地方（如afterXXX或自定义脚本事件）调用函数，方法为  core.plugin.xxx();
	}
},
    "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);
},
    "removeMap": function () {
	// 高层塔砍层插件，删除后不会存入存档，不可浏览地图也不可飞到。
	// 推荐用法：
	// 对于超高层或分区域塔，当在1区时将2区以后的地图删除；1区结束时恢复2区，进二区时删除1区地图，以此类推
	// 这样可以大幅减少存档空间，以及加快存读档速度

	// 删除楼层
	// core.removeMaps("MT1", "MT300") 删除MT1~MT300之间的全部层
	// core.removeMaps("MT10") 只删除MT10层
	this.removeMaps = function (fromId, toId) {
		toId = toId || fromId;
		var fromIndex = core.floorIds.indexOf(fromId),
			toIndex = core.floorIds.indexOf(toId);
		if (toIndex < 0) toIndex = core.floorIds.length - 1;
		flags.__visited__ = flags.__visited__ || {};
		flags.__removed__ = flags.__removed__ || [];
		flags.__disabled__ = flags.__disabled__ || {};
		flags.__leaveLoc__ = flags.__leaveLoc__ || {};
		for (var i = fromIndex; i <= toIndex; ++i) {
			var floorId = core.floorIds[i];
			if (core.status.maps[floorId].deleted) continue;
			delete flags.__visited__[floorId];
			flags.__removed__.push(floorId);
			delete flags.__disabled__[floorId];
			delete flags.__leaveLoc__[floorId];
			(core.status.autoEvents || []).forEach(function (event) {
				if (event.floorId == floorId && event.currentFloor) {
					core.autoEventExecuting(event.symbol, false);
					core.autoEventExecuted(event.symbol, false);
				} 
			});
			core.status.maps[floorId].deleted = true;
			core.status.maps[floorId].canFlyTo = false;
			core.status.maps[floorId].canFlyFrom = false;
			core.status.maps[floorId].cannotViewMap = true;
		}
	}

	// 恢复楼层
	// core.resumeMaps("MT1", "MT300") 恢复MT1~MT300之间的全部层
	// core.resumeMaps("MT10") 只恢复MT10层
	this.resumeMaps = function (fromId, toId) {
		toId = toId || fromId;
		var fromIndex = core.floorIds.indexOf(fromId),
			toIndex = core.floorIds.indexOf(toId);
		if (toIndex < 0) toIndex = core.floorIds.length - 1;
		flags.__removed__ = flags.__removed__ || [];
		for (var i = fromIndex; i <= toIndex; ++i) {
			var floorId = core.floorIds[i];
			if (!core.status.maps[floorId].deleted) continue;
			flags.__removed__ = flags.__removed__.filter(function (f) { return f != floorId; });
			core.status.maps[floorId] = core.loadFloor(floorId);
		}
	}

	// 分区砍层相关
	var inAnyPartition = function (floorId) {
		var inPartition = false;
		(core.floorPartitions || []).forEach(function (floor) {
			var fromIndex = core.floorIds.indexOf(floor[0]);
			var toIndex = core.floorIds.indexOf(floor[1]);
			var index = core.floorIds.indexOf(floorId);
			if (fromIndex < 0 || index < 0) return;
			if (toIndex < 0) toIndex = core.floorIds.length - 1;
			if (index >= fromIndex && index <= toIndex) inPartition = true;
		});
		return inPartition;
	}

	// 分区砍层
	this.autoRemoveMaps = function (floorId) {
		if (main.mode != 'play' || !inAnyPartition(floorId)) return;
		// 根据分区信息自动砍层与恢复
		(core.floorPartitions || []).forEach(function (floor) {
			var fromIndex = core.floorIds.indexOf(floor[0]);
			var toIndex = core.floorIds.indexOf(floor[1]);
			var index = core.floorIds.indexOf(floorId);
			if (fromIndex < 0 || index < 0) return;
			if (toIndex < 0) toIndex = core.floorIds.length - 1;
			if (index >= fromIndex && index <= toIndex) {
				core.resumeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]);
			} else {
				core.removeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]);
			}
		});
	}
},
    "fiveLayers": function () {
	// 是否启用五图层（增加背景2层和前景2层） 将__enable置为true即会启用；启用后请保存后刷新编辑器
	// 背景层2将会覆盖背景层 被事件层覆盖 前景层2将会覆盖前景层
	// 另外 请注意加入两个新图层 会让大地图的性能降低一些
	// 插件作者：ad
	var __enable = false;
	if (!__enable) return;

	// 创建新图层
	function createCanvas(name, zIndex) {
		if (!name) return;
		var canvas = document.createElement('canvas');
		canvas.id = name;
		canvas.className = 'gameCanvas';
		// 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高
		if (main.mode != "editor") canvas.style.zIndex = zIndex || 0;
		// 将图层插入进游戏内容
		document.getElementById('gameDraw').appendChild(canvas);
		var ctx = canvas.getContext('2d');
		core.canvas[name] = ctx;
		canvas.width = core.__PIXELS__;
		canvas.height = core.__PIXELS__;
		return canvas;
	}

	var bg2Canvas = createCanvas('bg2', 20);
	var fg2Canvas = createCanvas('fg2', 63);
	// 大地图适配
	core.bigmap.canvas = ["bg2", "fg2", "bg", "event", "event2", "fg", "damage"];
	core.initStatus.bg2maps = {};
	core.initStatus.fg2maps = {};

	if (main.mode == 'editor') {
		/*插入编辑器的图层 不做此步新增图层无法在编辑器显示*/
		// 编辑器图层覆盖优先级 eui > efg > fg(前景层) > event2(48*32图块的事件层) > event(事件层) > bg(背景层)
		// 背景层2(bg2) 插入事件层(event)之前(即bg与event之间)
		document.getElementById('mapEdit').insertBefore(bg2Canvas, document.getElementById('event'));
		// 前景层2(fg2) 插入编辑器前景(efg)之前(即fg之后)
		document.getElementById('mapEdit').insertBefore(fg2Canvas, document.getElementById('ebm'));
		// 原本有三个图层 从4开始添加
		var num = 4;
		// 新增图层存入editor.dom中
		editor.dom.bg2c = core.canvas.bg2.canvas;
		editor.dom.bg2Ctx = core.canvas.bg2;
		editor.dom.fg2c = core.canvas.fg2.canvas;
		editor.dom.fg2Ctx = core.canvas.fg2;
		editor.dom.maps.push('bg2map', 'fg2map');
		editor.dom.canvas.push('bg2', 'fg2');

		// 创建编辑器上的按钮
		var createCanvasBtn = function (name) {
			// 电脑端创建按钮
			var input = document.createElement('input');
			// layerMod4/layerMod5
			var id = 'layerMod' + num++;
			// bg2map/fg2map
			var value = name + 'map';
			input.type = 'radio';
			input.name = 'layerMod';
			input.id = id;
			input.value = value;
			editor.dom[id] = input;
			input.onchange = function () {
				editor.uifunctions.setLayerMod(value);
			}
			return input;
		};

		var createCanvasBtn_mobile = function (name) {
			// 手机端往选择列表中添加子选项
			var input = document.createElement('option');
			var id = 'layerMod' + num++;
			var value = name + 'map';
			input.name = 'layerMod';
			input.value = value;
			editor.dom[id] = input;
			return input;
		};
		if (!editor.isMobile) {
			var input = createCanvasBtn('bg2');
			var input2 = createCanvasBtn('fg2');
			// 获取事件层及其父节点
			var child = document.getElementById('layerMod'),
				parent = child.parentNode;
			// 背景层2插入事件层前
			parent.insertBefore(input, child);
			// 不能直接更改背景层2的innerText 所以创建文本节点
			var txt = document.createTextNode('bg2');
			// 插入事件层前(即新插入的背景层2前)
			parent.insertBefore(txt, child);
			// 向最后插入前景层2(即插入前景层后)
			parent.appendChild(input2);
			var txt2 = document.createTextNode('fg2');
			parent.appendChild(txt2);
			parent.childNodes[2].replaceWith("bg");
			parent.childNodes[6].replaceWith("事件");
			parent.childNodes[8].replaceWith("fg");
		} else {
			var input = createCanvasBtn_mobile('bg2');
			var input2 = createCanvasBtn_mobile('fg2');
			// 手机端因为是选项 所以可以直接改innerText
			input.innerText = '背景层2';
			input2.innerText = '前景层2';
			var parent = document.getElementById('layerMod');
			parent.insertBefore(input, parent.children[1]);
			parent.appendChild(input2);
		}
	}

	var _loadFloor_doNotCopy = core.maps._loadFloor_doNotCopy;
	core.maps._loadFloor_doNotCopy = function () {
		return ["bg2map", "fg2map"].concat(_loadFloor_doNotCopy());
	}
	////// 绘制背景和前景层 //////
	core.maps._drawBg_draw = function (floorId, toDrawCtx, cacheCtx, config) {
		config.ctx = cacheCtx;
		core.maps._drawBg_drawBackground(floorId, config);
		// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块；后绘制的覆盖先绘制的。
		core.maps._drawFloorImages(floorId, config.ctx, 'bg', null, null, config.onMap);
		core.maps._drawBgFgMap(floorId, 'bg', config);
		if (config.onMap) {
			core.drawImage(toDrawCtx, cacheCtx.canvas, core.bigmap.v2 ? -32 : 0, core.bigmap.v2 ? -32 : 0);
			core.clearMap('bg2');
			core.clearMap(cacheCtx);
		}
		core.maps._drawBgFgMap(floorId, 'bg2', config);
		if (config.onMap) core.drawImage('bg2', cacheCtx.canvas, core.bigmap.v2 ? -32 : 0, core.bigmap.v2 ? -32 : 0);
		config.ctx = toDrawCtx;
	}
	core.maps._drawFg_draw = function (floorId, toDrawCtx, cacheCtx, config) {
		config.ctx = cacheCtx;
		// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制前景图块；后绘制的覆盖先绘制的。
		core.maps._drawFloorImages(floorId, config.ctx, 'fg', null, null, config.onMap);
		core.maps._drawBgFgMap(floorId, 'fg', config);
		if (config.onMap) {
			core.drawImage(toDrawCtx, cacheCtx.canvas, core.bigmap.v2 ? -32 : 0, core.bigmap.v2 ? -32 : 0);
			core.clearMap('fg2');
			core.clearMap(cacheCtx);
		}
		core.maps._drawBgFgMap(floorId, 'fg2', config);
		if (config.onMap) core.drawImage('fg2', cacheCtx.canvas, core.bigmap.v2 ? -32 : 0, core.bigmap.v2 ? -32 : 0);
		config.ctx = toDrawCtx;
	}
	////// 移动判定 //////
	core.maps._generateMovableArray_arrays = function (floorId) {
		return {
			bgArray: this.getBgMapArray(floorId),
			fgArray: this.getFgMapArray(floorId),
			eventArray: this.getMapArray(floorId),
			bg2Array: this._getBgFgMapArray('bg2', floorId),
			fg2Array: this._getBgFgMapArray('fg2', floorId)
		};
	}
},
    "itemShop": function () {
	// 道具商店相关的插件
	// 可在全塔属性-全局商店中使用「道具商店」事件块进行编辑（如果找不到可以在入口方块中找）

	var shopId = null; // 当前商店ID
	var type = 0; // 当前正在选中的类型，0买入1卖出
	var selectItem = 0; // 当前正在选中的道具
	var selectCount = 0; // 当前已经选中的数量
	var page = 0;
	var totalPage = 0;
	var totalMoney = 0;
	var list = [];
	var shopInfo = null; // 商店信息
	var choices = []; // 商店选项
	var use = 'money';
	var useText = '金币';

	var bigFont = core.ui._buildFont(20, false),
		middleFont = core.ui._buildFont(18, false);

	this._drawItemShop = function () {
		// 绘制道具商店

		// Step 1: 背景和固定的几个文字
		core.ui._createUIEvent();
		core.clearMap('uievent');
		core.ui.clearUIEventSelector();
		core.setTextAlign('uievent', 'left');
		core.setTextBaseline('uievent', 'top');
		core.fillRect('uievent', 0, 0, 416, 416, 'black');
		core.drawWindowSkin('winskin.png', 'uievent', 0, 0, 416, 56);
		core.drawWindowSkin('winskin.png', 'uievent', 0, 56, 312, 56);
		core.drawWindowSkin('winskin.png', 'uievent', 0, 112, 312, 304);
		core.drawWindowSkin('winskin.png', 'uievent', 312, 56, 104, 56);
		core.drawWindowSkin('winskin.png', 'uievent', 312, 112, 104, 304);
		core.setFillStyle('uievent', 'white');
		core.setStrokeStyle('uievent', 'white');
		core.fillText("uievent", "购买", 32, 74, 'white', bigFont);
		core.fillText("uievent", "卖出", 132, 74);
		core.fillText("uievent", "离开", 232, 74);
		core.fillText("uievent", "当前" + useText, 324, 66, null, middleFont);
		core.setTextAlign("uievent", "right");
		core.fillText("uievent", core.formatBigNumber(core.status.hero[use]), 405, 89);
		core.setTextAlign("uievent", "left");
		core.ui.drawUIEventSelector(1, "winskin.png", 22 + 100 * type, 66, 60, 33);
		if (selectItem != null) {
			core.setTextAlign('uievent', 'center');
			core.fillText("uievent", type == 0 ? "买入个数" : "卖出个数", 364, 320, null, bigFont);
			core.fillText("uievent", "<   " + selectCount + "   >", 364, 350);
			core.fillText("uievent", "确定", 364, 380);
		}

		// Step 2：获得列表并展示
		list = choices.filter(function (one) {
			if (one.condition != null && one.condition != '') {
				try { if (!core.calValue(one.condition)) return false; } catch (e) {}
			}
			return (type == 0 && one.money != null) || (type == 1 && one.sell != null);
		});
		var per_page = 6;
		totalPage = Math.ceil(list.length / per_page);
		page = Math.floor((selectItem || 0) / per_page) + 1;

		// 绘制分页
		if (totalPage > 1) {
			var half = 156;
			core.setTextAlign('uievent', 'center');
			core.fillText('uievent', page + " / " + totalPage, half, 388, null, middleFont);
			if (page > 1) core.fillText('uievent', '上一页', half - 80, 388);
			if (page < totalPage) core.fillText('uievent', '下一页', half + 80, 388);
		}
		core.setTextAlign('uievent', 'left');

		// 绘制每一项
		var start = (page - 1) * per_page;
		for (var i = 0; i < per_page; ++i) {
			var curr = start + i;
			if (curr >= list.length) break;
			var item = list[curr];
			core.drawIcon('uievent', item.id, 10, 125 + i * 40);
			core.setTextAlign('uievent', 'left');
			core.fillText('uievent', core.material.items[item.id].name, 50, 132 + i * 40, null, bigFont);
			core.setTextAlign('uievent', 'right');
			core.fillText('uievent', (type == 0 ? core.calValue(item.money) : core.calValue(item.sell)) + useText + "/个", 300, 133 + i * 40, null, middleFont);
			core.setTextAlign("uievent", "left");
			if (curr == selectItem) {
				// 绘制描述，文字自动放缩
				var text = core.material.items[item.id].text || "该道具暂无描述";
				try { text = core.replaceText(text); } catch (e) {}
				for (var fontSize = 20; fontSize >= 8; fontSize -= 2) {
					var config = { left: 10, fontSize: fontSize, maxWidth: 403 };
					var height = core.getTextContentHeight(text, config);
					if (height <= 50) {
						config.top = (56 - height) / 2;
						core.drawTextContent("uievent", text, config);
						break;
					}
				}
				core.ui.drawUIEventSelector(2, "winskin.png", 8, 120 + i * 40, 295, 40);
				if (type == 0 && item.number != null) {
					core.fillText("uievent", "存货", 324, 132, null, bigFont);
					core.setTextAlign("uievent", "right");
					core.fillText("uievent", item.number, 406, 132, null, null, 40);
				} else if (type == 1) {
					core.fillText("uievent", "数量", 324, 132, null, bigFont);
					core.setTextAlign("uievent", "right");
					core.fillText("uievent", core.itemCount(item.id), 406, 132, null, null, 40);
				}
				core.setTextAlign("uievent", "left");
				core.fillText("uievent", "预计" + useText, 324, 250);
				core.setTextAlign("uievent", "right");
				totalMoney = selectCount * (type == 0 ? core.calValue(item.money) : core.calValue(item.sell));
				core.fillText("uievent", core.formatBigNumber(totalMoney), 405, 280);

				core.setTextAlign("uievent", "left");
				core.fillText("uievent", type == 0 ? "已购次数" : "已卖次数", 324, 170);
				core.setTextAlign("uievent", "right");
				core.fillText("uievent", (type == 0 ? item.money_count : item.sell_count) || 0, 405, 200);
			}
		}

		core.setTextAlign('uievent', 'left');
		core.setTextBaseline('uievent', 'alphabetic');
	}

	var _add = function (item, delta) {
		if (item == null) return;
		selectCount = core.clamp(
			selectCount + delta, 0,
			Math.min(type == 0 ? Math.floor(core.status.hero[use] / core.calValue(item.money)) : core.itemCount(item.id),
				type == 0 && item.number != null ? item.number : Number.MAX_SAFE_INTEGER)
		);
	}

	var _confirm = function (item) {
		if (item == null || selectCount == 0) return;
		if (type == 0) {
			core.status.hero[use] -= totalMoney;
			core.getItem(item.id, selectCount);
			core.stopSound();
			core.playSound('确定');
			if (item.number != null) item.number -= selectCount;
			item.money_count = (item.money_count || 0) + selectCount;
		} else {
			core.status.hero[use] += totalMoney;
			core.removeItem(item.id, selectCount);
			core.playSound('确定');
			core.drawTip("成功卖出" + selectCount + "个" + core.material.items[item.id].name, item.id);
			if (item.number != null) item.number += selectCount;
			item.sell_count = (item.sell_count || 0) + selectCount;
		}
		selectCount = 0;
	}

	this._performItemShopKeyBoard = function (keycode) {
		var item = list[selectItem] || null;
		// 键盘操作
		switch (keycode) {
		case 38: // up
			if (selectItem == null) break;
			if (selectItem == 0) selectItem = null;
			else selectItem--;
			selectCount = 0;
			break;
		case 37: // left
			if (selectItem == null) {
				if (type > 0) type--;
				break;
			}
			_add(item, -1);
			break;
		case 39: // right
			if (selectItem == null) {
				if (type < 2) type++;
				break;
			}
			_add(item, 1);
			break;
		case 40: // down
			if (selectItem == null) {
				if (list.length > 0) selectItem = 0;
				break;
			}
			if (list.length == 0) break;
			selectItem = Math.min(selectItem + 1, list.length - 1);
			selectCount = 0;
			break;
		case 13:
		case 32: // Enter/Space
			if (selectItem == null) {
				if (type == 2)
					core.insertAction({ "type": "break" });
				else if (list.length > 0)
					selectItem = 0;
				break;
			}
			_confirm(item);
			break;
		case 27: // ESC
			if (selectItem == null) {
				core.insertAction({ "type": "break" });
				break;
			}
			selectItem = null;
			break;
		}
	}

	this._performItemShopClick = function (px, py) {
		var item = list[selectItem] || null;
		// 鼠标操作
		if (px >= 22 && px <= 82 && py >= 71 && py <= 102) {
			// 买
			if (type != 0) {
				type = 0;
				selectItem = null;
				selectCount = 0;
			}
			return;
		}
		if (px >= 122 && px <= 182 && py >= 71 && py <= 102) {
			// 卖
			if (type != 1) {
				type = 1;
				selectItem = null;
				selectCount = 0;
			}
			return;
		}
		if (px >= 222 && px <= 282 && py >= 71 && py <= 102) // 离开
			return core.insertAction({ "type": "break" });
		// < >
		if (px >= 318 && px <= 341 && py >= 348 && py <= 376)
			return _add(item, -1);
		if (px >= 388 && px <= 416 && py >= 348 && py <= 376)
			return _add(item, 1);
		// 确定
		if (px >= 341 && px <= 387 && py >= 380 && py <= 407)
			return _confirm(item);

		// 上一页/下一页
		if (px >= 45 && px <= 105 && py >= 388) {
			if (page > 1) {
				selectItem -= 6;
				selectCount = 0;
			}
			return;
		}
		if (px >= 208 && px <= 268 && py >= 388) {
			if (page < totalPage) {
				selectItem = Math.min(selectItem + 6, list.length - 1);
				selectCount = 0;
			}
			return;
		}

		// 实际区域
		if (px >= 9 && px <= 300 && py >= 120 && py < 360) {
			if (list.length == 0) return;
			var index = parseInt((py - 120) / 40);
			var newItem = 6 * (page - 1) + index;
			if (newItem >= list.length) newItem = list.length - 1;
			if (newItem != selectItem) {
				selectItem = newItem;
				selectCount = 0;
			}
			return;
		}
	}

	this._performItemShopAction = function () {
		if (flags.type == 0) return this._performItemShopKeyBoard(flags.keycode);
		else return this._performItemShopClick(flags.px, flags.py);
	}

	this.openItemShop = function (itemShopId) {
		shopId = itemShopId;
		type = 0;
		page = 0;
		selectItem = null;
		selectCount = 0;
		core.isShopVisited(itemShopId);
		shopInfo = flags.__shops__[shopId];
		if (shopInfo.choices == null) shopInfo.choices = core.clone(core.status.shops[shopId].choices);
		choices = shopInfo.choices;
		use = core.status.shops[shopId].use;
		if (use != 'exp') use = 'money';
		useText = use == 'money' ? '金币' : '经验';

		core.insertAction([{
				"type": "while",
				"condition": "true",
				"data": [
					{ "type": "function", "function": "function () { core.plugin._drawItemShop(); }" },
					{ "type": "wait" },
					{ "type": "function", "function": "function() { core.plugin._performItemShopAction(); }" }
				]
			},
			{
				"type": "function",
				"function": "function () { core.deleteCanvas('uievent'); core.ui.clearUIEventSelector(); }"
			}
		]);
	}

},
    "enemyLevel": function () {
	// 此插件将提供怪物手册中的怪物境界显示
	// 使用此插件需要先给每个怪物定义境界，方法如下：
	// 点击怪物的【配置表格】，找到“【怪物】相关的表格配置”，然后在【名称】仿照增加境界定义：
	/*
	 "level": {
	 	"_leaf": true,
	 	"_type": "textarea",
	 	"_string": true,
	 	"_data": "境界"
	 },
	 */
	// 然后保存刷新，可以看到怪物的属性定义中出现了【境界】。再开启本插件即可。

	// 是否开启本插件，默认禁用；将此改成 true 将启用本插件。
	var __enable = false;
	if (!__enable) return;

	// 这里定义每个境界的显示颜色；可以写'red', '#RRGGBB' 或者[r,g,b,a]四元数组
	var levelToColors = {
		"萌新一阶": "red",
		"萌新二阶": "#FF0000",
		"萌新三阶": [255, 0, 0, 1],
	};

	// 复写 _drawBook_drawName
	var originDrawBook = core.ui._drawBook_drawName;
	core.ui._drawBook_drawName = function (index, enemy, top, left, width) {
		// 如果没有境界，则直接调用原始代码绘制
		if (!enemy.level) return originDrawBook.call(core.ui, index, enemy, top, left, width);
		// 存在境界，则额外进行绘制
		core.setTextAlign('ui', 'center');
		if (enemy.specialText.length == 0) {
			core.fillText('ui', enemy.name, left + width / 2,
				top + 27, '#DDDDDD', this._buildFont(17, true));
			core.fillText('ui', enemy.level, left + width / 2,
				top + 51, core.arrayToRGBA(levelToColors[enemy.level] || '#DDDDDD'), this._buildFont(14, true));
		} else {
			core.fillText('ui', enemy.name, left + width / 2,
				top + 20, '#DDDDDD', this._buildFont(17, true), width);
			switch (enemy.specialText.length) {
			case 1:
				core.fillText('ui', enemy.specialText[0], left + width / 2,
					top + 38, core.arrayToRGBA((enemy.specialColor || [])[0] || '#FF6A6A'),
					this._buildFont(14, true), width);
				break;
			case 2:
				// Step 1: 计算字体
				var text = enemy.specialText[0] + "  " + enemy.specialText[1];
				core.setFontForMaxWidth('ui', text, width, this._buildFont(14, true));
				// Step 2: 计算总宽度
				var totalWidth = core.calWidth('ui', text);
				var leftWidth = core.calWidth('ui', enemy.specialText[0]);
				var rightWidth = core.calWidth('ui', enemy.specialText[1]);
				// Step 3: 绘制
				core.fillText('ui', enemy.specialText[0], left + (width + leftWidth - totalWidth) / 2,
					top + 38, core.arrayToRGBA((enemy.specialColor || [])[0] || '#FF6A6A'));
				core.fillText('ui', enemy.specialText[1], left + (width + totalWidth - rightWidth) / 2,
					top + 38, core.arrayToRGBA((enemy.specialColor || [])[1] || '#FF6A6A'));
				break;
			default:
				core.fillText('ui', '多属性...', left + width / 2,
					top + 38, '#FF6A6A', this._buildFont(14, true), width);
			}
			core.fillText('ui', enemy.level, left + width / 2,
				top + 56, core.arrayToRGBA(levelToColors[enemy.level] || '#DDDDDD'), this._buildFont(14, true));
		}
	}

	// 也可以复写其他的属性颜色如怪物攻防等，具体参见下面的例子的注释部分
	core.ui._drawBook_drawRow1 = 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.hp || 0), col1 + 30, position, /*'red' */ null, b13);
		core.fillText('ui', '攻击', col2, position, null, f13);
		core.fillText('ui', core.formatBigNumber(enemy.atk || 0), col2 + 30, position, /* '#FF0000' */ null, b13);
		core.fillText('ui', '防御', col3, position, null, f13);
		core.fillText('ui', core.formatBigNumber(enemy.def || 0), col3 + 30, position, /* [255, 0, 0, 1] */ null, b13);
	}


},
    "dynamicHp": function () {
	// 此插件允许人物血量动态进行变化
	// 原作：Fux2（老黄鸡）

	// 是否开启本插件，默认禁用；将此改成 true 将启用本插件。
	var __enable = false;
	if (!__enable) return;

	var speed = 0.05; // 动态血量变化速度，越大越快。

	var _currentHp = null;
	var _lastStatus = null;
	var _check = function () {
		if (_lastStatus != core.status.hero) {
			_lastStatus = core.status.hero;
			_currentHp = core.status.hero.hp;
		}
	}

	core.registerAnimationFrame('dynamicHp', true, function () {
		_check();
		if (core.status.hero.hp != _currentHp) {
			var dis = (_currentHp - core.status.hero.hp) * speed;
			if (Math.abs(dis) < 2) {
				_currentHp = core.status.hero.hp;
			} else {
				_currentHp -= dis;
			}
			core.setStatusBarInnerHTML('hp', _currentHp);
		}
	});
},
    "multiHeros": function () {
	// 多角色插件
	// Step 1: 启用本插件
	// Step 2: 定义每个新的角色各项初始数据（参见下方注释）
	// Step 3: 在游戏中的任何地方都可以调用 `core.changeHero()` 进行切换；也可以 `core.changeHero(1)` 来切换到某个具体的角色上

	// 是否开启本插件，默认禁用；将此改成 true 将启用本插件。
	var __enable = false;
	if (!__enable) return;

	// 在这里定义全部的新角色属性
	// 请注意，在这里定义的内容不会多角色共用，在切换时会进行恢复。
	// 你也可以自行新增或删除，比如不共用金币则可以加上"money"的初始化，不共用道具则可以加上"items"的初始化，
	// 多角色共用hp的话则删除hp，等等。总之，不共用的属性都在这里进行定义就好。
	var hero1 = {
		"floorId": "MT0", // 该角色初始楼层ID；如果共用楼层可以注释此项
		"image": "brave.png", // 角色的行走图名称；此项必填不然会报错
		"name": "1号角色",
		"lv": 1,
		"hp": 10000, // 如果HP共用可注释此项
		"atk": 1000,
		"def": 1000,
		"mdef": 0,
		// "money": 0, // 如果要不共用金币则取消此项注释
		// "exp": 0, // 如果要不共用经验则取消此项注释
		"loc": { "x": 0, "y": 0, "direction": "up" }, // 该角色初始位置；如果共用位置可注释此项
		"items": {
			"tools": {}, // 如果共用消耗道具（含钥匙）则可注释此项
			// "constants": {}, // 如果不共用永久道具（如手册）可取消注释此项
			"equips": {}, // 如果共用在背包的装备可注释此项
		},
		"equipment": [], // 如果共用装备可注释此项；此项和上面的「共用在背包的装备」需要拥有相同状态，不然可能出现问题
	};
	// 也可以类似新增其他角色
	// 新增的角色，各项属性共用与不共用的选择必须和上面完全相同，否则可能出现问题。
	// var hero2 = { ...

	var heroCount = 2; // 包含默认角色在内总共多少个角色，该值需手动修改。

	this.initHeros = function () {
		core.setFlag("hero1", core.clone(hero1)); // 将属性值存到变量中
		// core.setFlag("hero2", core.clone(hero2)); // 更多的角色也存入变量中；每个定义的角色都需要新增一行

		// 检测是否存在装备
		if (hero1.equipment) {
			if (!hero1.items || !hero1.items.equips) {
				alert('多角色插件的equipment和道具中的equips必须拥有相同状态！');
			}
			// 存99号套装为全空
			var saveEquips = core.getFlag("saveEquips", []);
			saveEquips[99] = [];
			core.setFlag("saveEquips", saveEquips);
		} else {
			if (hero1.items && hero1.items.equips) {
				alert('多角色插件的equipment和道具中的equips必须拥有相同状态！');
			}
		}
	}

	// 在游戏开始注入initHeros
	var _startGame_setHard = core.events._startGame_setHard;
	core.events._startGame_setHard = function () {
		_startGame_setHard.call(core.events);
		core.initHeros();
	}

	// 切换角色
	// 可以使用 core.changeHero() 来切换到下一个角色
	// 也可以 core.changeHero(1) 来切换到某个角色（默认角色为0）
	this.changeHero = function (toHeroId) {
		var currHeroId = core.getFlag("heroId", 0); // 获得当前角色ID
		if (toHeroId == null) {
			toHeroId = (currHeroId + 1) % heroCount;
		}
		if (currHeroId == toHeroId) return;

		var saveList = Object.keys(hero1);

		// 保存当前内容
		var toSave = {};
		// 暂时干掉 drawTip 和 音效，避免切装时的提示
		var _drawTip = core.ui.drawTip;
		core.ui.drawTip = function () {};
		var _playSound = core.control.playSound;
		core.control.playSound = function () {}
		// 记录当前录像，因为可能存在换装问题
		core.clearRouteFolding();
		var routeLength = core.status.route.length;
		// 优先判定装备
		if (hero1.equipment) {
			core.items.quickSaveEquip(100 + currHeroId);
			core.items.quickLoadEquip(99);
		}

		saveList.forEach(function (name) {
			if (name == 'floorId') toSave[name] = core.status.floorId; // 楼层单独设置
			else if (name == 'items') {
				toSave.items = core.clone(core.status.hero.items);
				Object.keys(toSave.items).forEach(function (one) {
					if (!hero1.items[one]) delete toSave.items[one];
				});
			} else toSave[name] = core.clone(core.status.hero[name]); // 使用core.clone()来创建新对象
		});

		core.setFlag("hero" + currHeroId, toSave); // 将当前角色信息进行保存
		var data = core.getFlag("hero" + toHeroId); // 获得要切换的角色保存内容

		// 设置角色的属性值
		saveList.forEach(function (name) {
			if (name == "floorId");
			else if (name == "items") {
				Object.keys(core.status.hero.items).forEach(function (one) {
					if (data.items[one]) core.status.hero.items[one] = core.clone(data.items[one]);
				});
			} else {
				core.status.hero[name] = core.clone(data[name]);
			}
		});
		// 最后装上装备
		if (hero1.equipment) {
			core.items.quickLoadEquip(100 + toHeroId);
		}

		core.ui.drawTip = _drawTip;
		core.control.playSound = _playSound;
		core.status.route = core.status.route.slice(0, routeLength);
		core.control._bindRoutePush();

		// 插入事件：改变角色行走图并进行楼层切换
		var toFloorId = data.floorId || core.status.floorId;
		var toLoc = data.loc || core.status.hero.loc;
		core.insertAction([
			{ "type": "setHeroIcon", "name": data.image || "hero.png" }, // 改变行走图
			// 同层则用changePos，不同层则用changeFloor；这是为了避免共用楼层造成触发eachArrive
			toFloorId != core.status.floorId ? {
				"type": "changeFloor",
				"floorId": toFloorId,
				"loc": [toLoc.x, toLoc.y],
				"direction": toLoc.direction,
				"time": 0 // 可以在这里设置切换时间
			} : { "type": "changePos", "loc": [toLoc.x, toLoc.y], "direction": toLoc.direction }
			// 你还可以在这里执行其他事件，比如增加或取消跟随效果
		]);
		core.setFlag("heroId", toHeroId); // 保存切换到的角色ID
	}
},
    "itemCategory": function () {
	// 物品分类插件。此插件允许你对消耗道具和永久道具进行分类，比如标记「宝物类」「剧情道具」「药品」等等。
	// 使用方法：
	// 1. 启用本插件
	// 2. 在下方数组中定义全部的物品分类类型
	// 3. 点击道具的【配置表格】，找到“【道具】相关的表格配置”，然后在【道具描述】之后仿照增加道具的分类：
	/*
	 "category": {
	 	"_leaf": true,
	 	"_type": "textarea",
	 	"_string": true,
	 	"_data": "道具分类"
	 },
	 */
	// （你也可以选择使用下拉框的方式定义每个道具的分类，写法参见上面的cls）
	// 然后刷新编辑器，就可以对每个物品进行分类了

	// 是否开启本插件，默认禁用；将此改成 true 将启用本插件。
	var __enable = false;
	if (!__enable) return;

	// 在这里定义所有的道具分类类型，一行一个
	var categories = [
		"宝物类",
		"辅助类",
		"技能类",
		"剧情道具",
		"增益道具",
	];
	// 当前选中的道具类别
	var currentCategory = null;

	// 重写 core.ui._drawToolbox 以绘制分类类别
	var _drawToolbox = core.ui._drawToolbox;
	core.ui._drawToolbox = function (index) {
		_drawToolbox.call(this, index);
		core.setTextAlign('ui', 'left');
		core.fillText('ui', '类别[E]：' + (currentCategory || "全部"), 15, this.PIXEL - 13);
	}

	// 获得所有应该在道具栏显示的某个类型道具
	core.ui.getToolboxItems = function (cls) {
		// 检查类别
		return Object.keys(core.status.hero.items[cls])
			.filter(function (id) {
				return !core.material.items[id].hideInToolbox &&
					(currentCategory == null || core.material.items[id].category == currentCategory);
			}).sort();
	}

	// 注入道具栏的点击事件（点击类别）
	var _clickToolbox = core.actions._clickToolbox;
	core.actions._clickToolbox = function (x, y) {
		if (x >= 0 && x <= this.HSIZE - 4 && y == this.LAST) {
			drawToolboxCategory();
			return;
		}
		return _clickToolbox.call(core.actions, x, y);
	}

	// 注入道具栏的按键事件（E键）
	var _keyUpToolbox = core.actions._keyUpToolbox;
	core.actions._keyUpToolbox = function (keyCode) {
		if (keyCode == 69) {
			// 按E键则打开分类类别选择
			drawToolboxCategory();
			return;
		}
		return _keyUpToolbox.call(core.actions, keyCode);
	}

	// ------ 以下为选择道具分类的相关代码 ------ //

	// 关闭窗口时清除分类选择项
	var _closePanel = core.ui.closePanel;
	core.ui.closePanel = function () {
		currentCategory = null;
		_closePanel.call(core.ui);
	}

	// 弹出菜单以选择具体哪个分类
	// 直接使用 core.drawChoices 进行绘制
	var drawToolboxCategory = function () {
		if (core.status.event.id != 'toolbox') return;
		var selection = categories.indexOf(currentCategory) + 1;
		core.ui.closePanel();
		core.status.event.id = 'toolbox-category';
		core.status.event.selection = selection;
		core.lockControl();
		// 给第一项插入「全部」
		core.drawChoices('请选择道具类别', ["全部"].concat(categories));
	}

	// 选择某一项
	var _selectCategory = function (index) {
		core.ui.closePanel();
		if (index <= 0 || index > categories.length) currentCategory = null;
		else currentCategory = categories[index - 1];
		core.openToolbox();
	}

	var _clickToolBoxCategory = function (x, y) {
		if (!core.status.lockControl || core.status.event.id != 'toolbox-category') return false;

		if (x < core.actions.CHOICES_LEFT || x > core.actions.CHOICES_RIGHT) return false;
		var choices = core.status.event.ui.choices;
		var topIndex = core.actions._getChoicesTopIndex(choices.length);
		if (y >= topIndex && y < topIndex + choices.length) {
			_selectCategory(y - topIndex);
		}
		return true;
	}

	// 注入点击事件
	core.registerAction('onclick', 'toolbox-category', _clickToolBoxCategory, 100);

	// 注入光标跟随事件
	core.registerAction('onmove', 'toolbox-category', function (x, y) {
		if (!core.status.lockControl || core.status.event.id != 'toolbox-category') return false;
		core.actions._onMoveChoices(x, y);
		return true;
	}, 100);

	// 注入键盘光标事件
	core.registerAction('keyDown', 'toolbox-category', function (keyCode) {
		if (!core.status.lockControl || core.status.event.id != 'toolbox-category') return false;
		core.actions._keyDownChoices(keyCode);
		return true;
	}, 100);

	// 注入键盘按键事件
	core.registerAction('keyUp', 'toolbox-category', function (keyCode) {
		if (!core.status.lockControl || core.status.event.id != 'toolbox-category') return false;
		core.actions._selectChoices(core.status.event.ui.choices.length, keyCode, _clickToolBoxCategory);
		return true;
	}, 100);

},
    "heroFourFrames": function () {
	// 样板的勇士/跟随者移动时只使用2、4两帧，观感较差。本插件可以将四帧全用上。

	// 是否启用本插件
	var __enable = false;
	if (!__enable) return;

	["up", "down", "left", "right"].forEach(function (one) {
		// 指定中间帧动画
		core.material.icons.hero[one].midFoot = 2;
	});

	var heroMoving = function (timestamp) {
		if (core.status.heroMoving <= 0) return;
		if (timestamp - core.animateFrame.moveTime > core.values.moveSpeed) {
			core.animateFrame.leftLeg++;
			core.animateFrame.moveTime = timestamp;
		}
		core.drawHero(['stop', 'leftFoot', 'midFoot', 'rightFoot'][core.animateFrame.leftLeg % 4], 4 * core.status.heroMoving);
	}
	core.registerAnimationFrame('heroMoving', true, heroMoving);

	core.events._eventMoveHero_moving = function (step, moveSteps) {
		var curr = moveSteps[0];
		var direction = curr[0], x = core.getHeroLoc('x'), y = core.getHeroLoc('y');
		// ------ 前进/后退
		var o = direction == 'backward' ? -1 : 1;
		if (direction == 'forward' || direction == 'backward') direction = core.getHeroLoc('direction');
		var faceDirection = direction;
		if (direction == 'leftup' || direction == 'leftdown') faceDirection = 'left';
		if (direction == 'rightup' || direction == 'rightdown') faceDirection = 'right';
		core.setHeroLoc('direction', direction);
		if (curr[1] <= 0) {
			core.setHeroLoc('direction', faceDirection);
			moveSteps.shift();
			return true;
		}
		if (step <= 4) core.drawHero('stop', 4 * o * step);
		else if (step <= 8) core.drawHero('leftFoot', 4 * o * step);
		else if (step <= 12) core.drawHero('midFoot', 4 * o * (step - 8));
		else if (step <= 16) core.drawHero('rightFoot', 4 * o * (step - 8)); // if (step == 8) {
		if (step == 8 || step == 16) {
			core.setHeroLoc('x', x + o * core.utils.scan2[direction].x, true);
			core.setHeroLoc('y', y + o * core.utils.scan2[direction].y, true);
			core.updateFollowers();
			curr[1]--;
			if (curr[1] <= 0) moveSteps.shift();
			core.setHeroLoc('direction', faceDirection);
			return step == 16;
		}
		return false;
	}
},
    "startCanvas": function () {
	// 使用本插件可以将自绘的标题界面居中。仅在【标题开启事件化】后才有效。
	// 由于一些技术性的原因，标题界面事件化无法应用到覆盖状态栏的整个界面。
	// 这是一个较为妥协的插件，会在自绘标题界面时隐藏状态栏、工具栏和边框，并将画布进行居中。
	// 本插件仅在全塔属性的 "startCanvas" 生效；进入 "startText" 时将会离开居中状态，回归正常界面。

	// 是否开启本插件，默认禁用；将此改成 true 将启用本插件。
	var __enable = false;
	if (!__enable) return;

	// 检查【标题开启事件化】是否开启
	if (!core.flags.startUsingCanvas || main.mode != 'play') return;

	var _isTitleCanvasEnabled = false;
	var _getClickLoc = core.actions._getClickLoc;
	this._setTitleCanvas = function () {
		if (_isTitleCanvasEnabled) return;
		_isTitleCanvasEnabled = true;

		// 禁用窗口resize
		window.onresize = function () {};
		core.resize = function () {}

		// 隐藏状态栏
		core.dom.statusBar.style.display = 'none';
		core.dom.statusCanvas.style.display = 'none';
		core.dom.toolBar.style.display = 'none';
		// 居中画布
		if (core.domStyle.isVertical) {
			core.dom.gameDraw.style.top =
				(parseInt(core.dom.gameGroup.style.height) - parseInt(core.dom.gameDraw.style.height)) / 2 + "px";
		} else {
			core.dom.gameDraw.style.right =
				(parseInt(core.dom.gameGroup.style.width) - parseInt(core.dom.gameDraw.style.width)) / 2 + "px";
		}
		core.dom.gameDraw.style.border = '3px transparent solid';
		core.actions._getClickLoc = function (x, y) {
			var left = core.dom.gameGroup.offsetLeft + core.dom.gameDraw.offsetLeft + 3;
			var top = core.dom.gameGroup.offsetTop + core.dom.gameDraw.offsetTop + 3;
			var loc = { 'x': Math.max(x - left, 0), 'y': Math.max(y - top, 0), 'size': 32 * core.domStyle.scale };
			return loc;
		}
	}

	this._resetTitleCanvas = function () {
		if (!_isTitleCanvasEnabled) return;
		_isTitleCanvasEnabled = false;
		window.onresize = function () { try { main.core.resize(); } catch (e) { main.log(e); } }
		core.resize = function () { return core.control.resize(); }
		core.resize();
		core.actions._getClickLoc = _getClickLoc;
	}

	// 复写“开始游戏”
	core.events._startGame_start = function (hard, seed, route, callback) {
		console.log('开始游戏');
		core.resetGame(core.firstData.hero, hard, null, core.cloneArray(core.initStatus.maps));
		core.setHeroLoc('x', -1);
		core.setHeroLoc('y', -1);

		if (seed != null) {
			core.setFlag('__seed__', seed);
			core.setFlag('__rand__', seed);
		} else core.utils.__init_seed();

		core.clearStatusBar();
		core.plugin._setTitleCanvas();

		var todo = [];
		core.hideStatusBar();
		core.push(todo, core.firstData.startCanvas);
		core.push(todo, { "type": "function", "function": "function() { core.plugin._resetTitleCanvas(); core.events._startGame_setHard(); }" })
		core.push(todo, core.firstData.startText);
		this.insertAction(todo, null, null, function () {
			core.events._startGame_afterStart(callback);
		});

		if (route != null) core.startReplay(route);
	}

	var _loadData = core.control.loadData;
	core.control.loadData = function (data, callback) {
		core.plugin._resetTitleCanvas();
		_loadData.call(core.control, data, callback);
	}
},
    "rewrite": function () {
	// 在此增加新插件

	control.prototype._moveAction_popAutomaticRoute = function () {
		var automaticRoute = core.status.automaticRoute;
		// 检查自动寻路是否被弹出
		if (automaticRoute.autoHeroMove) {

			core.clearContinueAutomaticRoute();
			core.stopAutomaticRoute();
		}
	}

	actions.prototype._keyUpToolbox = function (keycode) {
		if (keycode == 71) {
			core.playSound('确定');
			core.ui.closePanel();
			if (core.isReplaying())
				core.control._replay_equipbox();
			else
				core.openEquipbox();
			return;
		}
		if (keycode == 84 || keycode == 27 || keycode == 88) {
			core.playSound('取消');
			core.ui.closePanel();
			var last = core.status.route[core.status.route.length - 1];
			if (last.startsWith('equip:') || last.startsWith('unEquip:')) {
				core.status.route.push('no');
			}
			core.checkAutoEvents();
			return;
		}
		if (core.status.event.data == null) return;

		if (keycode == 13 || keycode == 32 || keycode == 67) {
			this._clickToolboxIndex(core.status.event.selection);
			return;
		}
	}

	actions.prototype._keyUpEquipbox = function (keycode, altKey) {
		if (altKey && keycode >= 48 && keycode <= 57) {
			core.items.quickSaveEquip(keycode - 48);
			return;
		}
		if (keycode == 84) {
			core.playSound('确定');
			core.ui.closePanel();
			if (core.isReplaying())
				core.control._replay_toolbox();
			else
				core.openToolbox();
			return;
		}
		if (keycode == 71 || keycode == 27 || keycode == 88) {
			core.playSound('取消');
			core.ui.closePanel();
			var last = core.status.route[core.status.route.length - 1];
			if (last.startsWith('equip:') || last.startsWith('unEquip:')) {
				core.status.route.push('no');
			}
			core.checkAutoEvents();
			return;
		}
		if (!core.status.event.data.selectId) return;

		if (keycode == 13 || keycode == 32 || keycode == 67) {
			this._clickEquipboxIndex(core.status.event.selection);
			return;
		}
	}

	ui.prototype._drawEquipbox_drawStatusChanged = function (info, y, equip, equipType) {
		var compare = this._drawEquipbox_getStatusChanged(info, equip, equipType, y);
		if (compare == null) return;
		var obj = { drawOffset: 10, y: y };

		// --- 变化值...
		core.setFont('ui', this._buildFont(14, true));
		for (var name in core.status.hero) {
			if (typeof core.status.hero[name] != 'number') continue;
			var nowValue = core.getStatus(name);
			// 查询新值
			var newValue = Math.floor((core.getStatus(name) + (compare.value[name] || 0)) *
				(core.getBuff(name) * 100 + (compare.percentage[name] || 0)) / 100 + 0.0000001);
			if (nowValue == newValue) continue;
			var text = core.getStatusLabel(name);
			this._drawEquipbox_drawStatusChanged_draw(text + " ", '#CCCCCC', obj);
			var color = newValue > nowValue ? '#00FF00' : '#FF0000';
			nowValue = core.formatBigNumber(nowValue);
			newValue = core.formatBigNumber(newValue);
			this._drawEquipbox_drawStatusChanged_draw(nowValue + "->", '#CCCCCC', obj);
			this._drawEquipbox_drawStatusChanged_draw(newValue, color, obj);
			obj.drawOffset += 8;
		}
	}

	ui.prototype.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;
		// 清除onDownInterval
		clearInterval(core.interval.onDownInterval);
		core.interval.onDownInterval = 'tmp';

		core.drawMap()
	}

	ui.prototype._drawBook_drawContent = function (index, enemy, top, left) {
		var width = this.PIXEL - left; // 9 : 8 : 8 划分三列
		this._drawBook_drawRow1(index, enemy, top, left, width, top + 20);
		this._drawBook_drawRow2(index, enemy, top, left, width, top + 56);
	}

	ui.prototype._drawBook_drawRow1 = 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', core.getStatusLabel('hp'), col1, position, '#DDDDDD', f13);
		core.fillText('ui', core.formatBigNumber(enemy.hp || 0), col1 + 30, position, null, b13);
		core.fillText('ui', core.getStatusLabel('atk'), col2, position, null, f13);
		core.fillText('ui', core.formatBigNumber(enemy.atk || 0), col2 + 30, position, null, b13);
		core.fillText('ui', core.getStatusLabel('matk'), col3, position, null, f13);
		core.fillText('ui', core.formatBigNumber(enemy.matk || 0), col3 + 30, position, null, b13);
		core.fillText('ui', core.getStatusLabel('speed'), col1, position + 18, null, f13);
		core.fillText('ui', core.formatBigNumber(enemy.speed || 0), col1 + 30, position + 18, null, b13);
		core.fillText('ui', core.getStatusLabel('def'), col2, position + 18, null, f13);
		core.fillText('ui', core.formatBigNumber(enemy.def || 0), col2 + 30, position + 18, null, b13);
		core.fillText('ui', core.getStatusLabel('mdef'), col3, position + 18, null, f13);
		core.fillText('ui', core.formatBigNumber(enemy.mdef || 0), col3 + 30, position + 18, null, b13);
	}

	ui.prototype._drawBook_drawRow2 = 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;
		// 获得第二行绘制的内容
		var second_line = [];
		if (core.flags.statusBarItems.indexOf('enableMoney') >= 0) second_line.push([core.getStatusLabel('money'), core.formatBigNumber(enemy.money || 0)]);
		if (core.flags.enableAddPoint) second_line.push([core.getStatusLabel('point'), core.formatBigNumber(enemy.point || 0)]);
		if (core.flags.statusBarItems.indexOf('enableExp') >= 0) second_line.push([core.getStatusLabel('exp'), core.formatBigNumber(enemy.exp || 0)]);

		var damage_offset = col1 + (this.PIXEL - col1) / 2 - 12;
		// 第一列
		if (second_line.length > 0) {
			var one = second_line.shift();
			core.fillText('ui', one[0], col1, position, '#DDDDDD', f13);
			core.fillText('ui', one[1], col1 + 30, position, null, b13);
			damage_offset = col2 + (this.PIXEL - col2) / 2 - 12;
		}
		// 第二列
		if (second_line.length > 0) {
			var one = second_line.shift();
			core.fillText('ui', one[0], col2, position, '#DDDDDD', f13);
			core.fillText('ui', one[1], col2 + 30, position, null, b13);
			damage_offset = col3 + (this.PIXEL - col3) / 2 - 12;
		}
		// 忽略第三列，直接绘制伤害
		this._drawBook_drawDamage(index, enemy, damage_offset, position);
	}

	ui.prototype._drawBook_drawDamage = function (index, enemy, offset, position) {
		core.setTextAlign('ui', 'center');
		var damage = enemy.damage,
			color = '#FFFF00';
		if (damage == null) {
			damage = '无法战斗';
			color = '#FF2222';
		} 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));
	}

	ui.prototype._drawBookDetail_turnAndCriticals = function (enemy, floorId, texts) {

	}

	enemys.prototype.canBattle = function (enemy, x, y, floorId) {
		return true
	}

	enemys.prototype.getDamageString = function (enemy, x, y, floorId) {
		var hp = core.getEnemyValue(enemy, 'hp', x, y, floorId)
		var maxhp = core.getEnemyValue(enemy, 'hp')

		var color = '#000000';

		if (hp < maxhp / 3) color = '#FFFFFF';
		else if (hp < maxhp * 2 / 3) color = '#FFFF00';
		else color = '#FF9933';

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

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

		// 没有怪物手册
		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);
	}

	control.prototype._updateDamage_damage = function (floorId, onMap) {
		core.status.damage.data = [];
		if (!core.flags.displayEnemyDamage && !core.flags.displayExtraDamage) return;

		core.extractBlocks(floorId);
		core.status.maps[floorId].blocks.forEach(function (block) {
			var x = block.x,
				y = block.y;

			// v2优化，只绘制范围内的部分
			if (onMap && 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;
				}
			}

			if (!block.disable && block.event.cls.indexOf('enemy') == 0 && block.event.displayDamage !== false) {
				if (core.flags.displayEnemyDamage) {
					var damageString = core.enemys.getDamageString(block.event.id, x, y, floorId);
					core.status.damage.data.push({ text: damageString.damage, px: 32 * x + 1, py: 32 * (y + 1) - 1, color: damageString.color });
					var damage = core.getDamage(block.event.id, x, y, floorId)
					core.status.damage.data.push({ text: damage, px: 32 * x + 1, py: 32 * (y + 1) - 11, color: '#FFFFFF' });
					var cd = (((flags.enemy_stat || {})[core.status.floorId] || {})[x + "," + y] || {}).cd || 0
					if (cd) core.status.damage.data.push({ text: cd, px: 32 * x + 1, py: 32 * (y + 1) - 21, color: "#80eed6" });
				}
				/*if (core.flags.displayCritical) {
					var critical = core.enemys.nextCriticals(block.event.id, 1, x, y, floorId);
					critical = core.formatBigNumber((critical[0] || [])[0], true);
					if (critical == '???') critical = '?';
					core.status.damage.data.push({ text: critical, px: 32 * x + 1, py: 32 * (y + 1) - 11, color: '#FFFFFF' });
				}*/
			}
		});
	}

	control.prototype._updateDamage_extraDamage = function (floorId, onMap) {
		core.status.damage.extraData = [];
		if (!core.flags.displayExtraDamage) return;

		var width = core.floors[floorId].width,
			height = core.floors[floorId].height;
		var startX = onMap && core.bigmap.v2 ? Math.max(0, core.bigmap.posX - core.bigmap.extend) : 0;
		var endX = onMap && core.bigmap.v2 ? Math.min(width, core.bigmap.posX + core.__SIZE__ + core.bigmap.extend + 1) : width;
		var startY = onMap && core.bigmap.v2 ? Math.max(0, core.bigmap.posY - core.bigmap.extend) : 0;
		var endY = onMap && core.bigmap.v2 ? Math.min(height, core.bigmap.posY + core.__SIZE__ + core.bigmap.extend + 1) : height;

		for (var x = startX; x < endX; x++) {
			for (var y = startY; y < endY; y++) {
				var alpha = 1;
				if (core.noPass(x, y, floorId)) {
					if (core.flags.extraDamageType == 2) alpha = 0;
					else if (core.flags.extraDamageType == 1) alpha = 0.6;
				}
				var damage = core.status.checkBlock.damage[x + "," + y] || 0;
				if (damage > 0) { // 该点伤害
					damage = core.formatBigNumber(damage, true);
					core.status.damage.extraData.push({ text: damage, px: 32 * x + 16, py: 32 * (y + 1) - 14, color: '#ffaa33', alpha: alpha });
				} else { // 检查捕捉
					if (core.status.checkBlock.ambush[x + "," + y]) {
						core.status.damage.extraData.push({ text: '!', px: 32 * x + 16, py: 32 * (y + 1) - 14, color: '#ffaa33', alpha: alpha });
					}
				}
			}
		}
	}

	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);

		if (!core.flags.enableEnemyPoint ||
			(locEnemyInfo.atk == enemyInfo.atk && locEnemyInfo.def == enemyInfo.def && locEnemyInfo.hp == enemyInfo.hp && locEnemyInfo.speed == enemyInfo.speed && !((flags.enemy_stat || {})[floorId || core.status.floorId] || {})[x + "," + y])) {
			x = null;
			y = null;
		} else {
			// 检查enemys里面是否使用了存在的内容
			for (var i = 0; i < enemys.length; ++i) {
				var one = enemys[i];
				if (id == one.id && one.locs != null &&
					locEnemyInfo.atk == one.atk && locEnemyInfo.def == one.def && locEnemyInfo.hp == one.hp && locEnemyInfo.speed == one.speed && core.sameStat(((flags.enemy_stat || {})[floorId || core.status.floorId] || {})[x + "," + y], ((flags.enemy_stat || {})[floorId || core.status.floorId] || {})[one.locs[0][0] + "," + one.locs[0][1]])) {
					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);
		var specialColor = core.enemys.getSpecialColor(enemy);

		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 = 0;
		e.criticalDamage = 0;
		e.defDamage = 0;
		enemys.push(e);
	}

	////// 重置某个点上的怪物属性 //////
	events.prototype.resetEnemyOnPoint = function (x, y, floorId, norefresh) {
		delete((flags.enemyOnPoint || {})[floorId || core.status.floorId] || {})[x + "," + y];
		delete((flags.enemy_stat || {})[floorId || core.status.floorId] || {})[x + "," + y];
		if (!norefresh) core.updateStatusBar();
	}

	////// 将某个点上已经设置的怪物属性移动到其他点 //////
	events.prototype.moveEnemyOnPoint = function (fromX, fromY, toX, toY, floorId, norefresh) {
		floorId = floorId || core.status.floorId;
		if (((flags.enemyOnPoint || {})[floorId] || {})[fromX + "," + fromY]) {
			flags.enemyOnPoint[floorId][toX + "," + toY] = flags.enemyOnPoint[floorId][fromX + "," + fromY];
			delete flags.enemyOnPoint[floorId][fromX + "," + fromY];
			if (!norefresh) core.updateStatusBar();
		}
		if (((flags.enemy_stat || {})[floorId] || {})[fromX + "," + fromY]) {
			flags.enemy_stat[floorId][toX + "," + toY] = flags.enemy_stat[floorId][fromX + "," + fromY];
			delete flags.enemy_stat[floorId][fromX + "," + fromY];
			if (!norefresh) core.updateStatusBar();
		}
	}

	events.prototype.battle = function (id, x, y, force, callback) {
		core.saveAndStopAutomaticRoute();
		id = id || core.getBlockId(x, y);
		if (!id) return core.clearContinueAutomaticRoute(callback);
		// 非强制战斗
		if (!core.enemys.canBattle(id, x, y) && !force && !core.status.event.id) {
			core.stopSound();
			core.playSound('操作失败');
			core.drawTip("你打不过此怪物！", id);
			return core.clearContinueAutomaticRoute(callback);
		}
		// 自动存档
		// if (!core.status.event.id) core.autosave(true);
		// 战前事件
		if (!this.beforeBattle(id, x, y))
			return core.clearContinueAutomaticRoute(callback);
		// 战后事件
		this.afterBattle(id, x, y);
		if (callback) callback();
	}

	control.prototype.getRealStatusOrDefault = function (status, name) {
		var res = Math.floor(this.getStatusOrDefault(status, name) * this.getBuff(name) + 0.0000001);
		var stat = flags.hero_stat || {}
		if (stat["def+"] && (name == "def" || name == "mdef")) res *= 1.4
		if (stat["atk+"] && (name == "atk" || name == "matk")) res *= 1.2
		if (stat["speed+"] && name == "speed") res *= 1.25
		if (stat["def-"] && (name == "def" || name == "mdef")) res *= 0.6
		if (stat["atk-"] && (name == "atk" || name == "matk")) res *= 0.8
		if (stat["speed-"] && name == "speed") res *= 0.75
		if (flags.skill_level && flags.skill_level["圣盾"] && name == "armor")
			res += Math.ceil((0.01 + 0.01 * flags.skill_level["圣盾"]) * (core.getRealStatus("def") + core.getRealStatus("mdef")) - 0.0000001)
		if (flags.skill_level && flags.skill_level["暗影领域"] && (name == "atk" || name == "matk")) {
			var count = 0
			for (var i = -1; i <= 1; i++)
				for (var j = -1; j <= 1; j++) {
					if (i * i + j * j > 1) continue
					var x = hero.loc.x + i,
						y = hero.loc.y + j
					var block = core.getBlock(x, y)
					if (block && block.event.cls == "enemys") count++
				}
			if (!count) res *= (1 + (0.04 + 0.04 * flags.skill_level["暗影领域"]))
		}
		if (flags.skill_level && flags.skill_level["陷阵"] && (name == "def" || name == "mdef")) {
			var count = 0
			for (var i = -2; i <= 2; i++)
				for (var j = -2; j <= 2; j++) {
					if (i * i + j * j > 4) continue
					var x = hero.loc.x + i,
						y = hero.loc.y + j
					var block = core.getBlock(x, y)
					if (block && block.event.cls == "enemys") count++
				}
			res *= (1 + count * (0.03 + 0.03 * flags.skill_level["陷阵"]))
		}
		if (flags.skill_level && flags.skill_level["背水"] && (name == "attackRec" || name == "speed")) {
			var per = 100 * hero.hp / core.getRealStatus("hpmax")
			var n = Math.ceil((100 + 0.0001 - per) / (25 - 5 * flags.skill_level["背水"]) - 0.0000001)
			if (name == "speed") res *= 1 + 0.06 * n
			else res += 2 * n
		}
		if (core.hasEquip("I388") && name == "rec") res += 0.02 * core.getRealStatus("hpmax")
		return Math.ceil(res - 0.0000001)
	}

},
    "battle": function () {
	// 在此增加新插件

	this.checkEnemyHpMax = function (enemy, x, y) {
		var enemyInfo = core.enemys.getEnemyInfo(enemy, hero, x, y);
		var mon_hp = enemyInfo.hp
		var mon_hpmax = core.material.enemys[enemy].hp
		if (mon_hp > mon_hpmax) core.setEnemyOnPoint(x, y, null, "hp", mon_hpmax, "=")
	}

	this.damageToEnemy = function (enemy, x, y, type, ratio, speedBonus, notMainAttack) {
		//console.log(enemy, x, y, type, ratio, speedBonus, notMainAttack)

		var hero_hp = core.getRealStatusOrDefault(hero, 'hp'),
			hero_atk = core.getRealStatusOrDefault(hero, 'atk'),
			hero_matk = core.getRealStatusOrDefault(hero, 'matk'),
			hero_speed = core.getRealStatusOrDefault(hero, 'speed'),
			hero_def = core.getRealStatusOrDefault(hero, 'def'),
			hero_mdef = core.getRealStatusOrDefault(hero, 'mdef'),
			hero_armor = core.getRealStatusOrDefault(hero, 'armor')

		var hero_attackRec = core.getRealStatusOrDefault(hero, 'attackRec'),
			hero_skillRec = core.getRealStatusOrDefault(hero, 'skillRec'),
			hero_defBreak = core.getRealStatusOrDefault(hero, 'defBreak'),
			hero_mdefBreak = core.getRealStatusOrDefault(hero, 'mdefBreak')

		var enemyInfo = core.enemys.getEnemyInfo(enemy, hero, x, y);
		var mon_hp = enemyInfo.hp,
			mon_atk = enemyInfo.atk,
			mon_def = enemyInfo.def,
			mon_matk = enemyInfo.matk,
			mon_mdef = enemyInfo.mdef,
			mon_speed = enemyInfo.speed,
			mon_special = enemyInfo.special,
			mon_exp = enemyInfo.exp,
			mon_money = enemyInfo.money;
		var mon_hpmax = core.material.enemys[enemy].hp
		var hero_hpmax = core.getRealStatusOrDefault(hero, "hpmax")

		var st = ((flags.enemy_stat || {})[core.status.floorId] || {})[x + "," + y] || {}

		if (flags.skill_level && flags.skill_level["圣痕"]) {
			var a = hero_atk * (0.09 + 0.09 * flags.skill_level["圣痕"])
			var b = hero_matk * (0.09 + 0.09 * flags.skill_level["圣痕"])
			hero_atk += b
			hero_def += b
			hero_matk += a
			hero_mdef += a
		}

		if (!speedBonus && notMainAttack) {
			hero_atk = hero_def
			hero_matk = hero_mdef
		}

		mon_def -= hero_defBreak
		mon_mdef -= hero_mdefBreak

		var damage = ratio
		//物理/魔法
		if (type == "psy") damage *= hero_atk * 100 / (Math.max(mon_def, -50) + 100)
		else if (type == "magic" || type == "magic-rec") damage *= hero_matk * 100 / (Math.max(mon_mdef, -50) + 100)

		//破败
		if (speedBonus && !notMainAttack && core.hasEquip("I384")) damage += mon_hp / (Math.max(mon_def, -50) + 100) / (core.material.enemys[enemy].notBomb ? 3 : 1)

		//日炎
		if (type == "I381") {
			damage = 10 * hero_hpmax / (Math.max(mon_mdef, -50) + 100)
			type = "magic"
		}

		//过滤
		if (core.hasSpecial(mon_special, 31)) damage = Math.max(0, damage - (mon_def + mon_mdef) * 0.1)

		//攻速/淘汰
		if (speedBonus) damage *= hero_speed / 100
		if (!speedBonus && flags.skill_level && flags.skill_level["淘汰"] && mon_hp < mon_hpmax) damage *= 1 + (mon_hpmax - mon_hp) / mon_hpmax * (0.15 + 0.15 * flags.skill_level["淘汰"])

		//真伤
		if (type == "real") damage = ratio

		//虚无
		if (st.void)
			if (type == "psy") damage = 0
		else if (type == "magic" || type == "magic-rec") damage *= 2

		//毒素
		if (speedBonus && Math.abs(x - hero.loc.x) + Math.abs(y - hero.loc.y) == 1 && flags.skill_level && flags.skill_level["神经毒素"]) damage += hero_speed / 100 * (0.05 + 0.05 * flags.skill_level["神经毒素"]) * (core.hasEquip("I385") ? 1.2 * hero_matk : hero_atk)

		//刺杀
		if (flags.skill_level && flags.skill_level["刺杀标记"]) {
			var count = 0
			for (var i = -1; i <= 1; i++)
				for (var j = -1; j <= 1; j++) {
					if (i * i + j * j != 1) continue
					var tx = x + i,
						ty = y + j
					var block = core.getBlock(tx, ty)
					if (block && block.event.cls == "enemys") count++
				}
			if (!count) damage *= 1 + 0.08 + 0.08 * flags.skill_level["刺杀标记"]
		}

		//穿透
		if (flags.skill_level && flags.skill_level["穿透之眼"] && (st.silence || st.stun || st["speed-"]))
			damage *= 1 + 0.08 + 0.08 * flags.skill_level["穿透之眼"]

		//观察者/虚影战刃
		var dis = Math.sqrt((x - hero.loc.x) * (x - hero.loc.x) + (y - hero.loc.y) * (y - hero.loc.y))
		if (core.hasEquip("I389") && type == "psy" && !speedBonus) damage *= 1 + 0.1 * hero_speed / 100
		if (core.hasEquip("I386") && (type == "magic" || type == "magic-rec")) damage *= 1 + 0.05 * dis

		//再生护盾
		if (core.hasSpecial(mon_special, 35) && !st.cd) {
			damage = 0
			core.setEnemyStat(x, y, "cd", 5)
		}

		damage = Math.ceil(damage - 0.0000001)
		damage = Math.min(damage, mon_hp)

		//吸血
		if (type == "magic-rec") core.healHero(damage / 2)
		if (speedBonus && !notMainAttack) core.healHero(damage * hero_attackRec / 100, true)
		if (!speedBonus) core.healHero(damage * hero_skillRec / 100, true)

		core.tiaozi(damage, "red", x * 32 + 16, y * 32 + 16)
		core.setEnemyOnPoint(x, y, null, 'hp', damage, '-=')

		//生死符
		var died = 0
		if (core.hasEquip("I376")) died = Math.floor(0.1 * mon_hpmax + 0.0000001)

		//死了
		if (core.getEnemyValue(enemy, 'hp', x, y) <= died) {
			if (st.KZSR) flags.skill_cd["无我之怒"] = 0
			core.removeBlock(x, y)
			core.resetEnemyOnPoint(x, y)
			core.getExp(mon_exp)
			core.getMoney(mon_money)

			if (flags.skill_level && flags.skill_level["浴血"]) core.healHero((0.03 + 0.03 * flags.skill_level["浴血"]) * core.getRealStatus("hpmax"), true)
			if (flags.skill_level && flags.skill_level["灵魂之核"]) {
				if (flags.skill_level["灵魂之核"] >= 1 && flags.equiped_skill[0]) flags.skill_cd[flags.equiped_skill[0]] = Math.max(0, flags.skill_cd[flags.equiped_skill[0]] - 1)
				if (flags.skill_level["灵魂之核"] >= 2 && flags.equiped_skill[1]) flags.skill_cd[flags.equiped_skill[1]] = Math.max(0, flags.skill_cd[flags.equiped_skill[1]] - 1)
				if (flags.skill_level["灵魂之核"] >= 3 && flags.equiped_skill[2]) flags.skill_cd[flags.equiped_skill[2]] = Math.max(0, flags.skill_cd[flags.equiped_skill[2]] - 1)
				if (flags.equiped_skill[3]) flags.skill_cd[flags.equiped_skill[3]] = Math.max(0, flags.skill_cd[flags.equiped_skill[3]] - flags.skill_level["灵魂之核"])
			}

			core.updateStatusBar()
		}
	}

	this.enemyAction = function (enemy, x, y) {
		var hero_hp = core.getRealStatusOrDefault(hero, 'hp'),
			hero_atk = core.getRealStatusOrDefault(hero, 'atk'),
			hero_matk = core.getRealStatusOrDefault(hero, 'matk'),
			hero_speed = core.getRealStatusOrDefault(hero, 'speed'),
			hero_def = core.getRealStatusOrDefault(hero, 'def'),
			hero_mdef = core.getRealStatusOrDefault(hero, 'mdef'),
			hero_armor = core.getRealStatusOrDefault(hero, 'armor')

		var enemyInfo = core.enemys.getEnemyInfo(enemy, hero, x, y);
		var mon_hp = enemyInfo.hp,
			mon_atk = enemyInfo.atk,
			mon_def = enemyInfo.def,
			mon_matk = enemyInfo.matk,
			mon_mdef = enemyInfo.mdef,
			mon_speed = enemyInfo.speed,
			mon_special = enemyInfo.special,
			mon_exp = enemyInfo.exp,
			mon_money = enemyInfo.money;

		var damage = core.getDamage(enemy, x, y)
		var st = ((flags.enemy_stat || {})[core.status.floorId] || {})[x + "," + y] || {}
		var cd = st.cd || 0

		if (!cd && !st.silence) {
			if (core.hasSpecial(mon_special, 33)) {
				damage += Math.max(0, 2 * mon_matk * 100 / (Math.max(hero_mdef, -50) + 100) - hero_armor)
				core.setEnemyStat(x, y, "cd", 4)
			}
			if (core.hasSpecial(mon_special, 36)) {
				var v = Math.max(0, 2 * mon_atk * 100 / (Math.max(hero_def, -50) + 100) - hero_armor)
				damage += v
				core.setEnemyStat(x, y, "cd", 5)
				core.setEnemyOnPoint(x, y, null, 'hp', Math.ceil(v - 0.0000001), '+=')
				core.checkEnemyHpMax(enemy, x, y)
			}
			if (core.hasSpecial(mon_special, 39)) {
				damage += Math.max(0, 2 * mon_atk * 100 / (Math.max(hero_def, -50) + 100) - hero_armor)
				flags.hero_stat = flags.hero_stat || {}
				core.setHeroStatFromEnemy("stun", 2)
				core.setEnemyStat(x, y, "cd", 8)
			}

			if ((((flags.enemy_stat || {})[core.status.floorId] || {})[x + "," + y] || {}).cd)
				if (flags.skill_level && flags.skill_level["光之棱镜"])
					core.damageToEnemy(enemy, x, y, "magic", 0.8 + 0.8 * flags.skill_level["光之棱镜"], false, true)
		}

		if (Math.abs(x - hero.loc.x) + Math.abs(y - hero.loc.y) == 1 && flags.skill_level && flags.skill_level["幻影之幕"]) damage = damage * (1 - (0.12 + 0.12 * flags.skill_level["幻影之幕"]))
		if (Math.abs(x - hero.loc.x) + Math.abs(y - hero.loc.y) == 1 && flags.skill_level && flags.skill_level["反射护盾"]) core.damageToEnemy(enemy, x, y, "psy", 0.2 + 0.2 * flags.skill_level["反射护盾"], false, true)

		var dis = Math.sqrt((x - hero.loc.x) * (x - hero.loc.x) + (y - hero.loc.y) * (y - hero.loc.y))
		if (core.hasEquip("I387")) damage *= Math.max(0, 1 - 0.1 * dis)

		damage = Math.ceil(damage - 0.0000001)

		if ((flags.hero_stat || {}).miss) damage = 0

		return damage
	}

	this.enemySkill = function (enemy, x, y) {
		var hero_hp = core.getRealStatusOrDefault(hero, 'hp'),
			hero_atk = core.getRealStatusOrDefault(hero, 'atk'),
			hero_matk = core.getRealStatusOrDefault(hero, 'matk'),
			hero_speed = core.getRealStatusOrDefault(hero, 'speed'),
			hero_def = core.getRealStatusOrDefault(hero, 'def'),
			hero_mdef = core.getRealStatusOrDefault(hero, 'mdef'),
			hero_armor = core.getRealStatusOrDefault(hero, 'armor')

		var enemyInfo = core.enemys.getEnemyInfo(enemy, hero, x, y);
		var mon_hp = enemyInfo.hp,
			mon_atk = enemyInfo.atk,
			mon_def = enemyInfo.def,
			mon_matk = enemyInfo.matk,
			mon_mdef = enemyInfo.mdef,
			mon_speed = enemyInfo.speed,
			mon_special = enemyInfo.special,
			mon_exp = enemyInfo.exp,
			mon_money = enemyInfo.money;

		var damage = 0
		var st = ((flags.enemy_stat || {})[core.status.floorId] || {})[x + "," + y] || {}
		var cd = st.cd || 0
		var dis = (x - hero.loc.x) * (x - hero.loc.x) + (y - hero.loc.y) * (y - hero.loc.y)

		if (core.hasSpecial(mon_special, 44)) {
			for (var i = 0; !core.outMap(i, 0); i++)
				for (var j = 0; !core.outMap(i, j); j++) {
					var block = core.getBlock(i, j)
					if (block && block.event.cls == "enemys") {
						var v = core.material.enemys[block.event.id].hp
						core.setEnemyOnPoint(i, j, null, 'hp', Math.ceil(v / 200 - 0.0000001), '+=', null, true)
						core.checkEnemyHpMax(block.event.id, i, j)
					}
				}
			core.updateStatusBar()
		}

		if (!cd && !st.silence) {
			if (core.hasSpecial(mon_special, 37) && dis <= 25) {
				core.setHeroStatFromEnemy("atk-", 3)
				core.setEnemyStat(x, y, "cd", 5)
			}

			if (core.hasSpecial(mon_special, 40) && dis <= 25) {
				core.setHeroStatFromEnemy("def-", 3)
				core.setEnemyStat(x, y, "cd", 5)
			}

			if (core.hasSpecial(mon_special, 41) && dis <= 25) {
				damage += Math.max(0, 2 * mon_matk * 100 / (Math.max(hero_mdef, -50) + 100) - hero_armor)
				core.setEnemyStat(x, y, "cd", 4)
			}

			if (core.hasSpecial(mon_special, 42) && dis <= 25) {
				damage += Math.max(0, 2 * mon_matk * 100 / (Math.max(hero_mdef, -50) + 100) - hero_armor)
				core.setHeroStatFromEnemy("speed-", 3)
				core.setEnemyStat(x, y, "cd", 5)
			}

			if (core.hasSpecial(mon_special, 30)) {
				damage += Math.max(0, 2 * mon_atk * 100 / (Math.max(hero_def, -50) + 100) - hero_armor)
				core.setEnemyStat(x, y, "cd", 4)
			}

			if (core.hasSpecial(mon_special, 43)) {
				core.setHeroStatFromEnemy("silence", 2)
				core.setEnemyStat(x, y, "cd", 5)
			}

			if ((((flags.enemy_stat || {})[core.status.floorId] || {})[x + "," + y] || {}).cd)
				if (flags.skill_level && flags.skill_level["光之棱镜"])
					core.damageToEnemy(enemy, x, y, "magic", 0.8 + 0.8 * flags.skill_level["光之棱镜"], false, true)
		}

		if (Math.abs(x - hero.loc.x) + Math.abs(y - hero.loc.y) == 1 && flags.skill_level && flags.skill_level["幻影之幕"]) damage = damage * (1 - (0.12 + 0.12 * flags.skill_level["幻影之幕"]))

		var dis = Math.sqrt(dis)
		if (core.hasEquip("I387")) damage *= Math.max(0, 1 - 0.1 * dis)

		damage = Math.ceil(damage - 0.0000001)

		if ((flags.hero_stat || {}).miss) damage = 0

		return damage
	}

	this.healHero = function (h, notTip) {
		if (flags.skill_level && flags.skill_level["圣符"]) h *= (1 + 0.05 + 0.05 * flags.skill_level["圣符"])
		h = Math.ceil(h - 0.0000001)
		hero.hp = Math.min(hero.hp + h, core.getRealStatus("hpmax"))
		if (!notTip) core.tiaozi(h, "green", hero.loc.x * 32 + 16, hero.loc.y * 32 + 16)
	}

	this.attackEnemy = function () {
		var x = core.nextX(),
			y = core.nextY()
		var enemy = core.getBlock(x, y)
		if (enemy && enemy.event.cls == "enemys") {
			var ani = ["Axe2", "Axe1", "Sword2", "Hand1"]
			core.drawAnimate(ani[flags.class], x, y)
			if (core.hasEquip("I385")) core.damageToEnemy(enemy.event.id, x, y, "magic", 1.2, true)
			else core.damageToEnemy(enemy.event.id, x, y, "psy", 1, true)
			if (flags.skill_level && flags.skill_level["横扫"]) {
				var dx = [0, 1, 0, -1],
					dy = [-1, 0, 1, 0]
				for (var i = 0; i < 4; i++) {
					var tx = x + dx[i],
						ty = y + dy[i],
						block = core.getBlock(tx, ty)
					if (block && block.event.cls == "enemys")
						if (core.hasEquip("I385")) core.damageToEnemy(block.event.id, tx, ty, "magic", 0.18 + 0.18 * flags.skill_level["横扫"], true, true)
					else core.damageToEnemy(block.event.id, tx, ty, "psy", 0.15 + 0.15 * flags.skill_level["横扫"], true, true)
				}
			}
		} else {
			if (flags.class < 2) return
			var ani = [null, null, "Bow2", "Water2"]
			var d = 1
			var ratio = 0.8,
				notMainAttack = false
			if (flags.skill_level && flags.skill_level["弓弩强化"]) ratio += 0.1 * (flags.skill_level["弓弩强化"] - 1)
			while (1) {
				x = core.nextX(d)
				y = core.nextY(d)
				if (core.outMap(x, y)) return
				enemy = core.getBlock(x, y)
				if (enemy && enemy.event.cls == "enemys") {
					core.drawAnimate(ani[flags.class], x, y)
					if (flags.class == 2) core.damageToEnemy(enemy.event.id, x, y, "psy", ratio, true, notMainAttack)
					if (flags.class == 3) core.damageToEnemy(enemy.event.id, x, y, "magic", ratio, true, notMainAttack)
					ratio *= 0.75
					notMainAttack = true
					if (!(flags.hero_stat || {}).cross) return
				} else if (core.noPass(x, y) && !flags.skill_level["弓弩强化"]) return
				d += 1
			}
		}
	}
},
    "system": function () {
	// 在此增加新插件
	this.tiaozi = function (text, color, x, y) { //跳字
		if (core.status.replay.replaying) {} else {
			var pi = Math.acos(-1)
			var deg = Math.random() * pi / 2 - pi * 5 / 4;
			var dx = Math.sin(deg),
				dy = Math.cos(deg);
			var t = 0,
				tMax = (flags.waitTime || 1000) / 12;
			var name = "tiaozi" + Math.floor(Math.random() * 1000000); //如不需要连续跳字可不加随机数
			core.createCanvas(name, x - 16, y - 16, 96, 64, 255);
			core.fillText(name, text, 0, 16, color, "bold 17px Verdana");
			var fade = setInterval(function () {
				t = t + 1
				core.relocateCanvas(name, x - 16 + dx * t / tMax * 20, y - 16 + dy * t / tMax * 20);
				if (t > tMax) {
					delete core.animateFrame.asyncId[fade];
					clearInterval(fade);
					core.deleteCanvas(name);
				}
			}, 10);
			core.animateFrame.asyncId[fade] = true;
		}
	}

	this.initHero = function () {
		var stat = [{ "atk": 43, "def": 27, "matk": 25, "mdef": 10, "hpmax": 720, "speed": 100, "rec": 5, "armor": 1 },
			{ "atk": 31, "def": 23, "matk": 35, "mdef": 30, "hpmax": 675, "speed": 80, "rec": 4, "armor": 3 },
			{ "atk": 36, "def": 12, "matk": 30, "mdef": 20, "hpmax": 600, "speed": 110, "rec": 2, "armor": 0 },
			{ "atk": 25, "def": 15, "matk": 40, "mdef": 15, "hpmax": 575, "speed": 90, "rec": 4, "armor": 1 },
		]
		var c = flags.class
		for (var i in stat[c]) hero[i] = stat[c][i]
		hero.hp = hero.hpmax
		hero.attackRec = 0
		hero.skillRec = 0
		hero.defBreak = 0
		hero.mdefBreak = 0
		flags.skill_point = 1
		flags.skill_level = {}
		flags.skill_cd = {}
		flags.equiped_skill = []
	}

	this.levelUp = function () {
		var stat = [{ "atk": 7, "def": 6, "matk": 3, "mdef": 2, "hpmax": 55, "speed": 7, "rec": 3, "armor": 0 },
			{ "atk": 5, "def": 5, "matk": 6, "mdef": 6, "hpmax": 50, "speed": 4, "rec": 0, "armor": 1 },
			{ "atk": 6, "def": 2, "matk": 5, "mdef": 4, "hpmax": 40, "speed": 8, "rec": 2, "armor": 0 },
			{ "atk": 4, "def": 4, "matk": 8, "mdef": 5, "hpmax": 45, "speed": 5, "rec": 1, "armor": 0 },
		]
		var c = flags.class
		for (var i in stat[c]) {
			hero[i] += stat[c][i]
			if (i == "hpmax") hero.hp += stat[c][i]
		}
		flags.skill_point += 1
		hero.lv += 1
		core.drawAnimate("Heal4", hero.loc.x, hero.loc.y)
	}

	const LV_MAX = 30

	this.needExp = function () {
		if (hero.lv == LV_MAX) return -1
		return (hero.lv + 1) * (hero.lv + 2) * 5 - 10
	}

	events.prototype.checkLvUp = function () {
		while (hero.lv < LV_MAX && hero.exp >= core.needExp()) {
			core.levelUp()
			core.drawTip("等级提升")
		}
	}

	this.getExp = function (value) {
		hero.exp += value
	}

	this.getMoney = function (value) {
		hero.money += value
	}

	this.putEnemy = function (e) {
		var x = [],
			y = [],
			len = 0
		for (var i = 0; !core.outMap(i, 0); i++)
			for (var j = 0; !core.outMap(i, j); j++)
				if (!i || !j || core.outMap(i, j + 1) || core.outMap(i + 1, j))
					if (!core.getBlock(i, j) && (i != hero.loc.x || j != hero.loc.y)) {
						x.push(i)
						y.push(j)
						len += 1
					}
		if (!len) {
			hero.hp = 0
			return
		}
		var r = core.rand(len)
		core.setBlock(e, x[r], y[r])
		//console.log(e, flags.turn, x[r], y[r])
	}

	this.checkEnemy = function (e, s, t, n, delta) {
		var time = flags.turn,
			a = []
		time -= s
		t -= s
		if (time > t) return
		if (delta > 0) {
			a[1] = n
			for (var i = 2; i <= n; i++) a[i] = a[i - 1] - delta
		} else {
			a[n] = n
			for (var i = n - 1; i >= 1; i--) a[i] = a[i + 1] + delta
		}
		for (var i = 2; i <= n; i++) a[i] += a[i - 1]
		//for (var i = 1; i <= n; i++) console.log(Math.floor(a[i] / a[n] * t))
		for (var i = 1; i <= n; i++)
			if (time == Math.floor(a[i] / a[n] * t)) core.putEnemy(e)
	}

	this.generateEnemy = function () {
		var s, t, e, n

		s = 0
		t = 300
		e = ["greenSlime", "redSlime", "bat", "bluePriest", "skeleton", "skeletonWarrior", "yellowGateKeeper", "skeletonCaptain"]
		n = [15, 11, 6, 4, 5, 3, 2, 1]
		for (var i = 0; i < 8; i++) core.checkEnemy(e[i], s, t, n[i], -0.75 + 0.25 * i)

		s = 360
		t = 660
		e = ["blackSlime", "bigBat", "redPriest", "zombie", "zombieKnight", "rock", "slimeman", "vampire"]
		n = [15, 12, 9, 7, 5, 3, 4, 1]
		for (var i = 0; i < 8; i++) core.checkEnemy(e[i], s, t, n[i], -0.75 + 0.25 * i)

		s = 720
		t = 1020
		e = ["silverSlime", "ghostSoldier", "soldier", "redKnight", "blueGateKeeper", "swordsman", "yellowKnight", "magicMaster"]
		n = [20, 16, 10, 7, 4, 5, 2, 1]
		for (var i = 0; i < 8; i++) core.checkEnemy(e[i], s, t, n[i], -0.75 + 0.25 * i)

		s = 1080
		t = 1380
		e = ["slimelord", "redBat", "brownWizard", "redWizard", "darkKnight", "redGateKeeper", "blueKing", "redKing"]
		n = [21, 16, 12, 9, 7, 3, 5, 1]
		for (var i = 0; i < 8; i++) core.checkEnemy(e[i], s, t, n[i], -0.75 + 0.25 * i)

		s = 1440
		t = 1740
		e = ["watcherSlime", "evilPrincess", "bowman", "grayPriest", "ironRock", "demonPriest", "devilKnight", "blackKing"]
		n = [22, 17, 13, 10, 8, 7, 5, 1]
		for (var i = 0; i < 8; i++) core.checkEnemy(e[i], s, t, n[i], -0.75 + 0.25 * i)
	}

	this.afterMove = function () {
		if (!(flags.hero_stat || {}).stun) core.attackEnemy()
		core.checkLvUp()

		// 刹那
		if (flags.doubleMove) {
			flags.doubleMove -= 1
			return;
		}

		var visited = [],
			canAttack = [],
			que = [
				[hero.loc.x, hero.loc.y]
			],
			len = 1,
			s = 0,
			totDamage = -core.getRealStatus("rec")

		if (flags.skill_level && flags.skill_level["圣符"]) totDamage -= Math.ceil(core.getRealStatus("rec") * (0.05 + 0.05 * flags.skill_level["圣符"]) - 0.0000001)
		if ((flags.hero_stat || {}).rec) totDamage -= Math.ceil(core.getRealStatus("hpmax") * 0.08 - 0.0000001)

		//怪物移动
		visited[hero.loc.x + "," + hero.loc.y] = 1
		canAttack[hero.loc.x + "," + hero.loc.y] = 1
		while (s < len) {
			var x = que[s][0],
				y = que[s][1]
			var dx = [0, 1, 0, -1],
				dy = [1, 0, -1, 0]
			for (var i = 0; i < 4; i++) {
				var tx = x + dx[i],
					ty = y + dy[i]
				if (core.outMap(tx, ty)) continue
				var block = core.getBlock(tx, ty)
				if (core.noPass(tx, ty) && block.event.cls != "enemys") continue
				if (!visited[tx + "," + ty]) {
					len += 1
					que.push([tx, ty])
					visited[tx + "," + ty] = visited[x + "," + y] + 1
				}
				if (s && !core.getBlock(x, y) && block && block.event.cls == "enemys" && visited[tx + "," + ty] > visited[x + "," + y]) {
					core.moveEnemyOnPoint(tx, ty, x, y)
					core.setBlock(block.event.id, x, y)
					core.removeBlock(tx, ty)
				}
			}
			var enemy = core.getBlock(x, y)
			if (canAttack[x + "," + y]) {
				if (!s || enemy)
					for (var i = 0; i < 4; i++) {
						var tx = x + dx[i],
							ty = y + dy[i]
						canAttack[tx + "," + ty] = 1
					}
			}
			s += 1
		}

		//怪物攻击，包括攻击触发的技能
		for (var x = 0; !core.outMap(x, 0); x++) {
			for (var y = 0; !core.outMap(x, y); y++) {
				var block = core.getBlock(x, y)
				if (block && block.event.cls == "enemys" && canAttack[x + "," + y]) {
					var dam = core.enemyAction(block.event.id, x, y)
					if (flags.shield) {
						if (dam < flags.shield) {
							flags.shield -= dam
							dam = 0
						} else {
							dam -= flags.shield
							flags.shield = 0
						}
					}
					totDamage += dam
				}
			}
		}

		//怪物不需要攻击就能释放的技能
		for (var x = 0; !core.outMap(x, 0); x++) {
			for (var y = 0; !core.outMap(x, y); y++) {
				var block = core.getBlock(x, y)
				if (block && block.event.cls == "enemys") {
					var dam = core.enemySkill(block.event.id, x, y)
					if (flags.shield) {
						if (dam < flags.shield) {
							flags.shield -= dam
							dam = 0
						} else {
							dam -= flags.shield
							flags.shield = 0
						}
					}
					totDamage += dam
				}
			}
		}

		//理想之盾爆炸
		if ((flags.hero_stat || {}).shield == 1 && flags.shield > 0) {
			var d = flags.shield
			core.drawAnimate("Heal9", hero.loc.x, hero.loc.y)
			for (var x = 0; !core.outMap(x, 0); x++) {
				for (var y = 0; !core.outMap(x, y); y++) {
					var block = core.getBlock(x, y)
					if (block && block.event.cls == "enemys")
						core.damageToEnemy(block.event.id, x, y, "real", d / Math.sqrt((x - hero.loc.x) * (x - hero.loc.x) + (y - hero.loc.y) * (y - hero.loc.y)), false)
				}
			}
			flags.shield = 0
		}

		//提示损失
		if (totDamage > 0) core.tiaozi(totDamage, "red", hero.loc.x * 32 + 16, hero.loc.y * 32 + 16)
		else core.tiaozi(-totDamage, "green", hero.loc.x * 32 + 16, hero.loc.y * 32 + 16)
		if (flags.shield) core.tiaozi(flags.shield, "white", hero.loc.x * 32 + 16, hero.loc.y * 32 + 16)
		hero.hp -= totDamage

		//新回合开始
		if (hero.hp <= 0) {
			core.lose()
			return
		}
		flags.turn = (flags.turn || 0) + 1

		if (core.hasEquip("I377")) {
			flags.I377 = Math.min((flags.I377 || 0) + 1, 20)
			if (flags.I377 >= 20 && core.itemCount("redPotion") < 3) {
				flags.I377 = 0
				core.getItem("redPotion")
			}
		}
		if (core.hasEquip("I382")) {
			flags.I382 = Math.min((flags.I382 || 0) + 1, 8)
			if (flags.I382 >= 8 && core.itemCount("jumpShoes") < 8) {
				flags.I382 = 0
				core.getItem("jumpShoes")
			}
		}

		// 处理勇士状态
		flags.hero_stat = flags.hero_stat || {}
		core.refStat(flags.hero_stat)
		if (!(flags.hero_stat || {}).silence)
			for (var skill in flags.skill_cd)
				if (flags.skill_cd[skill] > 0) flags.skill_cd[skill] -= 1

		//处理怪物状态
		flags.enemy_stat = flags.enemy_stat || {}
		flags.enemy_stat[core.status.floorId] = flags.enemy_stat[core.status.floorId] || {}
		for (var e in flags.enemy_stat[core.status.floorId]) {
			core.refStat(flags.enemy_stat[core.status.floorId][e])
			var f = 0
			for (var x in flags.enemy_stat[core.status.floorId][e]) f = 1
			if (!f) delete flags.enemy_stat[core.status.floorId][e]
		}

		//生成新怪物
		core.generateEnemy()

		if (hero.hp <= 0) {
			core.lose()
			return
		}

		//结算剑刃风暴
		if ((flags.hero_stat || {}).storm) {
			var tx = hero.loc.x,
				ty = hero.loc.y
			core.drawAnimate("Wind5", tx, ty)
			for (var i = -2; i <= 2; i++)
				for (var j = -2; j <= 2; j++) {
					var x = tx + i,
						y = ty + j
					if (core.outMap(x, y)) continue
					if (i * i + j * j > 4) continue
					var enemy = core.getBlock(x, y)
					if (enemy && enemy.event.cls == "enemys")
						core.damageToEnemy(enemy.event.id, x, y, "psy", 4, false)
				}
		}

		//结算陷阱
		for (var x = 0; !core.outMap(x, 0); x++) {
			for (var y = 0; !core.outMap(x, y); y++) {
				var block = core.getBlock(x, y)
				if (block && block.event.cls == "enemys" && core.getBgNumber(x, y) == 168) {
					core.drawAnimate("Light1", x, y)
					for (var i = -3; i <= 3; i++)
						for (var j = -3; j <= 3; j++) {
							var tx = x + i,
								ty = y + j
							if (core.outMap(tx, ty)) continue
							if (i * i + j * j > 3 * 3) continue
							var enemy = core.getBlock(tx, ty)
							if (enemy && enemy.event.cls == "enemys")
								core.damageToEnemy(enemy.event.id, tx, ty, "magic", 3.6 + 1.8 * flags.skill_level["布置陷阱"], false)
						}
					core.setBgFgBlock("bg", 0, x, y)
				}
			}
		}

		//结算守卫
		for (var x = 0; !core.outMap(x, 0); x++) {
			for (var y = 0; !core.outMap(x, y); y++) {
				if (core.getFgNumber(x, y) == 64) {
					for (var i = -1; i <= 1; i++)
						for (var j = -1; j <= 1; j++) {
							var tx = x + i,
								ty = y + j
							if (core.outMap(tx, ty)) continue
							var enemy = core.getBlock(tx, ty)
							if (enemy && enemy.event.cls == "enemys")
								core.damageToEnemy(enemy.event.id, tx, ty, "psy", 1.2 + 0.6 * flags.skill_level["圣印结界"], false)
						}
					flags.lastTime[x + "," + y] -= 1
					if (!flags.lastTime[x + "," + y]) core.setBgFgBlock("fg", 0, x, y)
				}
			}
		}

		//结算日炎
		if (core.hasEquip("I381"))
			for (var i = -1; i <= 1; i++)
				for (var j = -1; j <= 1; j++) {
					var tx = hero.loc.x + i,
						ty = hero.loc.y + j
					if (core.outMap(tx, ty)) continue
					var enemy = core.getBlock(tx, ty)
					if (enemy && enemy.event.cls == "enemys")
						core.damageToEnemy(enemy.event.id, tx, ty, "I381", 0, false)
				}

		//结算追踪光弹
		if (flags.skill_level && flags.skill_level["追踪光弹"]) {
			var tx, ty, td = -1
			for (var x = 0; !core.outMap(x, 0); x++) {
				for (var y = 0; !core.outMap(x, y); y++) {
					var block = core.getBlock(x, y)
					if (block && block.event.cls == "enemys") {
						var dis = (hero.loc.x - x) * (hero.loc.x - x) + (hero.loc.y - y) * (hero.loc.y - y)
						if (td < 0 || dis < td) td = dis, tx = x, ty = y
					}
				}
			}
			if (td >= 0) {
				var enemy = core.getBlock(tx, ty)
				core.drawAnimate("Water2", tx, ty)
				core.damageToEnemy(enemy.event.id, tx, ty, "magic", 0.2 + 0.2 * flags.skill_level["追踪光弹"], false)
			}
		}

		//处理结束
		core.updateStatusBar()
		core.autosave()

	}

	this.outMap = function (x, y) {
		return x < 0 || y < 0 || x >= 13 || y >= 13
	}

	this.refStat = function (a) {
		if (a.cd && !a.silence) {
			a.cd -= 1
			if (a.cd <= 0) delete a.cd
		}
		for (var i in a)
			if (i != 'cd') {
				a[i] -= 1
				if (a[i] <= 0) delete a[i]
			}
	}

	this.sameStat = function (a, b) {
		if (!a && !b) return true
		if (!a || !b) return false
		for (var i in a)
			if (a[i] != b[i]) return false
		return true
	}

	this.setStat = function (s, x, t) {
		var oppo = { "def-": "def+", "atk-": "atk+", "speed-": "speed+", "def+": "def-", "atk+": "atk-", "speed+": "speed-" }
		if (oppo[x] && s[oppo[x]]) delete s[oppo[x]]
		if (s[x]) s[x] = Math.max(s[x], t)
		else s[x] = t
	}

	//由于施加后会立刻进行回合倒数，所以t+1
	this.setHeroStatFromEnemy = function (x, t) {
		flags.hero_stat = flags.hero_stat || {}

		if (flags.hero_stat.immue || flags.hero_stat.miss) return;

		if (flags.skill_level && flags.skill_level["状态吸收"] >= 3 && (x == "silence" || x == "stun")) return
		var oppo = { "def-": "def+", "atk-": "atk+", "speed-": "speed+" }
		if (flags.skill_level && flags.skill_level["状态吸收"] && oppo[x])
			if (flags.skill_level["状态吸收"] >= 2) x = oppo[x]
		else return

		if (core.hasEquip("I383")) t = 1

		core.setStat(flags.hero_stat, x, t + 1)
	}

	this.setEnemyStat = function (x, y, name, t) {
		var floorId = core.status.floorId
		flags.enemy_stat = flags.enemy_stat || {}
		flags.enemy_stat[floorId] = flags.enemy_stat[floorId] || {}
		flags.enemy_stat[floorId][x + "," + y] = flags.enemy_stat[floorId][x + "," + y] || {}
		core.setStat(flags.enemy_stat[floorId][x + "," + y], name, t)
	}
},
    "skillTree": function () {

	var current

	const skills = [{
			"狂战士": {
				"name": "狂战士",
				"levelMax": 0,
				"pointCost": [0],
				"kind": 0,
				"passive": true,
				"posX": 5,
				"posY": 0,
				"father": {},
				"image": "attack.png",
				"describe": function (lv) { return "你是一个狂战士，你的普通攻击只能攻击面前一格的敌人，造成1.0倍率的物理伤害" },
				"onlearn": function (lv) {},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {},
				"cd": 0
			},
			"猛击": {
				"name": "猛击",
				"levelMax": 3,
				"pointCost": [1, 1, 1],
				"kind": 0,
				"passive": false,
				"posX": 1.5,
				"posY": 1,
				"father": {},
				"image": "KZSQ1.png",
				"describe": function (lv) { return "Q技能，对面前一格的敌人造成" + core.skillTextSelect([3.2, 4.8, 6.4], lv) + "倍率的物理伤害，并击晕其2回合，冷却时间5" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {
					var x = core.nextX(),
						y = core.nextY()
					var enemy = core.getBlock(x, y)
					if (enemy && enemy.event.cls == "enemys") {
						core.drawAnimate("Axe8", x, y)
						core.setEnemyStat(x, y, "stun", 2)
						core.damageToEnemy(enemy.event.id, x, y, "psy", 1.6 + 1.6 * lv, false)
						return true
					}
					return false
				},
				"cd": function (lv) { return 5 }
			},
			"旋风斩": {
				"name": "旋风斩",
				"levelMax": 3,
				"pointCost": [1, 1, 1],
				"kind": 0,
				"passive": false,
				"posX": 3.5,
				"posY": 1,
				"father": {},
				"image": "KZSQ2.png",
				"describe": function (lv) { return "Q技能，对自身九宫格范围内敌人造成" + core.skillTextSelect([3.2, 4.8, 6.4], lv) + "倍率的物理伤害，冷却时间7" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {
					core.drawAnimate("Wind4", hero.loc.x, hero.loc.y)
					for (var i = -1; i <= 1; i++)
						for (var j = -1; j <= 1; j++) {
							var x = hero.loc.x + i,
								y = hero.loc.y + j
							if (core.outMap(x, y)) continue
							var enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys")
								core.damageToEnemy(enemy.event.id, x, y, "psy", 1.6 + 1.6 * lv, false)
						}
					return true
				},
				"cd": function (lv) { return 7 }
			},
			"附魔打击": {
				"name": "附魔打击",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 1,
				"posY": 2,
				"father": {},
				"image": "KZSW1.png",
				"describe": function (lv) { return "W技能，对面前一格的敌人造成" + core.skillTextSelect([6, 7, 8], lv) + "倍率的魔法伤害，并在4回合内造成防御下降效果，冷却时间" + core.skillTextSelect([6, 5, 4], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					var x = core.nextX(),
						y = core.nextY()
					var enemy = core.getBlock(x, y)
					if (enemy && enemy.event.cls == "enemys") {
						core.drawAnimate("Axe7", x, y)
						core.setEnemyStat(x, y, "def-", 4)
						core.damageToEnemy(enemy.event.id, x, y, "magic", 5 + 1 * lv, false)
						return true
					}
					return false
				},
				"cd": function (lv) { return 7 - lv }
			},
			"流星枪": {
				"name": "流星枪",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 2.5,
				"posY": 2,
				"father": {},
				"image": "KZSW2.png",
				"describe": function (lv) { return "W技能，掷出长枪，对前方最近的那名敌人造成" + core.skillTextSelect([4.8, 6, 7.2], lv) + "倍率的物理伤害，并将其击退至发生碰撞，如果撞到其他敌人，对那名敌人也造成相同倍率的伤害，冷却时间" + core.skillTextSelect([8, 7, 6], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					var d = 1,
						enemy, x, y
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) return false
						enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") {
							core.drawAnimate("Axe9", x, y)
							core.damageToEnemy(enemy.event.id, x, y, "psy", 3.6 + 1.2 * lv, false)
							break
						}
						if (core.noPass(x, y)) return false
						d += 1
					}
					d += 1
					var sx = x,
						sy = y,
						senemy = core.getBlock(x, y)
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) break
						enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") {
							core.damageToEnemy(enemy.event.id, x, y, "psy", 3.6 + 1.2 * lv, false)
							break
						}
						if (core.noPass(x, y)) break
						d += 1
					}
					d -= 1
					x = core.nextX(d)
					y = core.nextY(d)
					if (senemy && (sx != x || sy != y)) {
						core.moveEnemyOnPoint(sx, sy, x, y)
						core.setBlock(senemy.event.id, x, y)
						core.removeBlock(sx, sy)
					}
					return true
				},
				"cd": function (lv) { return 9 - lv }
			},
			"固守": {
				"name": "固守",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 4,
				"posY": 2,
				"father": {},
				"image": "KZSW3.png",
				"describe": function (lv) { return "W技能，在接下来的" + core.skillTextSelect([3, 4, 5], lv) + "回合内获得防御提升效果，且每回合回复8%最大生命值，冷却时间" + core.skillTextSelect([12, 11, 10], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					core.drawAnimate("St9", hero.loc.x, hero.loc.y)
					flags.hero_stat = flags.hero_stat || {}
					core.setStat(flags.hero_stat, "def+", lv + 2)
					core.setStat(flags.hero_stat, "rec", lv + 2)
					return true
				},
				"cd": function (lv) { return 13 - lv }
			},
			"战争咆哮": {
				"name": "战争咆哮",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 1,
				"posY": 3,
				"father": {},
				"image": "KZSE1.png",
				"describe": function (lv) { return "E技能，对前方90°角范围中距离3.5格内的敌人造成" + core.skillTextSelect([7.2, 9.6, 12], lv) + "倍率的魔法伤害，并附加5回合的攻击下降效果，冷却时间" + core.skillTextSelect([11, 10, 9], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					var x = hero.loc.x,
						y = hero.loc.y,
						dir = core.utils.scan[hero.loc.direction]
					core.drawAnimate("SPActive", x, y)
					for (var i = -3; i <= 3; i++)
						for (var j = -3; j <= 3; j++) {
							var tx = x + i,
								ty = y + j
							if (core.outMap(tx, ty)) continue
							if (dir.x) {
								if (dir.x * i < 0) continue
								if (Math.abs(j) > Math.abs(i)) continue
							}
							if (dir.y) {
								if (dir.y * j < 0) continue
								if (Math.abs(i) > Math.abs(j)) continue
							}
							if (i * i + j * j > 3.5 * 3.5) continue
							var enemy = core.getBlock(tx, ty)
							if (enemy && enemy.event.cls == "enemys") {
								core.drawAnimate("St4", tx, ty)
								core.setEnemyStat(tx, ty, "atk-", 5)
								core.damageToEnemy(enemy.event.id, tx, ty, "magic", 4.8 + 2.4 * lv, false)
							}
						}
					return true
				},
				"cd": function (lv) { return 12 - lv }
			},
			"无畏冲锋": {
				"name": "无畏冲锋",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 2.5,
				"posY": 3,
				"father": {},
				"image": "KZSE2.png",
				"describe": function (lv) { return "E技能，向前冲锋穿过若干敌人至能停下的最远位置，对途径的敌人造成" + core.skillTextSelect([4.8, 6.4, 8], lv) + "倍率的物理伤害，无法穿过墙体，冷却时间" + core.skillTextSelect([10, 9, 8], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					var d = 1,
						x, y, td = 0
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) break
						if (!core.noPass(x, y) || core.getBlock(x, y).event.cls == "enemys") {
							if (!core.noPass(x, y)) td = d
						} else break
						d += 1
					}
					if (!td) return false
					for (d = 1; d < td; d++) {
						x = core.nextX(d)
						y = core.nextY(d)
						var enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") {
							core.drawAnimate("Hand2", x, y)
							core.damageToEnemy(enemy.event.id, x, y, "psy", 3.2 + 1.6 * lv, false)
						}
					}
					hero.loc.x = core.nextX(td)
					hero.loc.y = core.nextY(td)
					core.drawHero()
					return true
				},
				"cd": function (lv) { return 11 - lv }
			},
			"沸血": {
				"name": "沸血",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 4,
				"posY": 3,
				"father": {},
				"image": "KZSE3.png",
				"describe": function (lv) { return "E技能，在接下来的" + core.skillTextSelect([3, 4, 5], lv) + "回合内获得攻击上升与攻速上升效果，冷却时间" + core.skillTextSelect([9, 8, 7], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					core.drawAnimate("St8", hero.loc.x, hero.loc.y)
					flags.hero_stat = flags.hero_stat || {}
					core.setStat(flags.hero_stat, "atk+", lv + 2)
					core.setStat(flags.hero_stat, "speed+", lv + 2)
					return true
				},
				"cd": function (lv) { return 10 - lv }
			},
			"无我之怒": {
				"name": "无我之怒",
				"levelMax": 1,
				"pointCost": [3],
				"kind": 3,
				"passive": false,
				"posX": 1.5,
				"posY": 4.5,
				"father": {},
				"image": "KZSR1.png",
				"describe": function (lv) { return "R技能，消耗8%最大生命的生命值，对面前一格的敌人造成12倍率的物理伤害，如果目标在这回合死亡，刷新这个技能的冷却时间。冷却时间20。需等级12" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 12 },
				"effect": function (lv) {
					var cost = Math.floor(core.getRealStatus("hpmax") * 0.08 + 0.0000001)
					if (hero.hp <= cost) return false
					var x = core.nextX(),
						y = core.nextY()
					var enemy = core.getBlock(x, y)
					if (enemy && enemy.event.cls == "enemys") {
						core.drawAnimate("Axe10", x, y)
						hero.hp -= cost
						core.setEnemyStat(x, y, "KZSR", 1)
						core.damageToEnemy(enemy.event.id, x, y, "psy", 12, false)
						return true
					}
					return false
				},
				"cd": function (lv) { return 20 }
			},
			"剑刃风暴": {
				"name": "剑刃风暴",
				"levelMax": 1,
				"pointCost": [3],
				"kind": 3,
				"passive": false,
				"posX": 3.5,
				"posY": 4.5,
				"father": {},
				"image": "KZSR2.png",
				"describe": function (lv) { return "R技能，对2格内的敌人造成4倍率物理伤害，并在接下来4回合开始时重复此效果。冷却时间20。需等级12" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 12 },
				"effect": function (lv) {
					flags.hero_stat = flags.hero_stat || {}
					core.setStat(flags.hero_stat, "storm", 5)
					var tx = hero.loc.x,
						ty = hero.loc.y
					core.drawAnimate("Wind5", tx, ty)
					for (var i = -2; i <= 2; i++)
						for (var j = -2; j <= 2; j++) {
							var x = tx + i,
								y = ty + j
							if (core.outMap(x, y)) continue
							if (i * i + j * j > 4) continue
							var enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys")
								core.damageToEnemy(enemy.event.id, x, y, "psy", 4, false)
						}
					return true
				},
				"cd": function (lv) { return 20 }
			},
			"浴血": {
				"name": "浴血",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 4,
				"passive": true,
				"posX": 6.5,
				"posY": 1.5,
				"father": {},
				"image": "KZSD1.png",
				"describe": function (lv) { return "被动技能，每当有一名敌人死亡时，回复" + core.skillTextSelect([6, 9, 12], lv) + "%最大生命。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 9) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 9 },
			},
			"横扫": {
				"name": "横扫",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 4,
				"passive": true,
				"posX": 8.5,
				"posY": 1.5,
				"father": {},
				"image": "KZSD2.png",
				"describe": function (lv) { return "被动技能，你的普通攻击对与目标相邻的敌人也会造成" + core.skillTextSelect([30, 45, 60], lv) + "%倍率的伤害。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 9) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 9 },
			},
			"背水": {
				"name": "背水",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 6,
				"posY": 3.5,
				"father": {},
				"image": "KZSF1.png",
				"describe": function (lv) { return "被动技能，每损失" + core.skillTextSelect([20, 15, 10], lv) + "%生命值就会获得6%攻击速度与2%攻击吸血，满血时也有一层效果。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
			"淘汰": {
				"name": "淘汰",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 7.5,
				"posY": 3.5,
				"father": {},
				"image": "KZSF2.png",
				"describe": function (lv) { return "被动技能，造成技能伤害时，基于目标已损失生命的百分比最多提高" + core.skillTextSelect([30, 45, 60], lv) + "%。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
			"陷阵": {
				"name": "陷阵",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 9,
				"posY": 3.5,
				"father": {},
				"image": "KZSF3.png",
				"describe": function (lv) { return "被动技能，两格内每有一名敌人，防御、魔防提高" + core.skillTextSelect([6, 9, 12], lv) + "%。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},

		},
		{
			"圣骑士": {
				"name": "圣骑士",
				"levelMax": 0,
				"pointCost": [0],
				"kind": 0,
				"passive": true,
				"posX": 5,
				"posY": 0,
				"father": {},
				"image": "attack.png",
				"describe": function (lv) { return "你是一个圣骑士，你的普通攻击只能攻击面前一格的敌人，造成1.0倍率的物理伤害" },
				"onlearn": function (lv) {},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {},
				"cd": 0
			},
			"挑锤": {
				"name": "挑锤",
				"levelMax": 3,
				"pointCost": [1, 1, 1],
				"kind": 0,
				"passive": false,
				"posX": 1.5,
				"posY": 1,
				"father": {},
				"image": "SQSQ1.png",
				"describe": function (lv) { return "Q技能，对面前一格的敌人造成" + core.skillTextSelect([3.6, 5.4, 7.2], lv) + "倍率的物理伤害，并在可能的条件下将其移动到自己身后，如果成功挑走了一名敌人，自身向前移动一格，冷却时间5" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {
					var x = core.nextX(),
						y = core.nextY()
					var enemy = core.getBlock(x, y)
					if (enemy && enemy.event.cls == "enemys") {
						core.drawAnimate("Axe3", x, y)
						core.damageToEnemy(enemy.event.id, x, y, "psy", 1.8 + 1.8 * lv, false)
						var tx = core.nextX(-1),
							ty = core.nextY(-1)
						enemy = core.getBlock(x, y)
						if (enemy && !core.outMap(tx, ty) && !core.getBlock(tx, ty)) {
							core.moveEnemyOnPoint(x, y, tx, ty)
							core.setBlock(enemy.event.id, tx, ty)
							core.removeBlock(x, y)
							hero.loc.x = x
							hero.loc.y = y
							core.drawHero()
						}
						return true
					}
					return false
				},
				"cd": function (lv) { return 5 }
			},
			"圣光": {
				"name": "圣光",
				"levelMax": 3,
				"pointCost": [1, 1, 1],
				"kind": 0,
				"passive": false,
				"posX": 3.5,
				"posY": 1,
				"father": {},
				"image": "SQSQ2.png",
				"describe": function (lv) { return "Q技能，治疗自身" + core.skillTextSelect([12, 18, 24], lv) + "%最大生命值，对九宫格范围内敌人造成" + core.skillTextSelect([2.4, 3.6, 4.8], lv) + "倍率的魔法伤害，冷却时间9" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {
					core.drawAnimate("Heal7", hero.loc.x, hero.loc.y)
					core.healHero(core.getRealStatus("hpmax") * (0.06 + 0.06 * lv))
					for (var i = -1; i <= 1; i++)
						for (var j = -1; j <= 1; j++) {
							var x = hero.loc.x + i,
								y = hero.loc.y + j
							if (core.outMap(x, y)) continue
							var enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys")
								core.damageToEnemy(enemy.event.id, x, y, "magic", 1.2 + 1.2 * lv, false)
						}
					return true
				},
				"cd": function (lv) { return 9 }
			},
			"回旋锤": {
				"name": "回旋锤",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 1,
				"posY": 2,
				"father": {},
				"image": "SQSW1.png",
				"describe": function (lv) { return "W技能，扔出圣锤，对前方最近的那名敌人造成" + core.skillTextSelect([8, 10, 12], lv) + "倍率的物理伤害，并将其拉至身前，冷却时间" + core.skillTextSelect([8, 7, 6], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					var d = 1,
						enemy, x, y
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) return false
						enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") {
							core.drawAnimate("Axe4", x, y)
							core.damageToEnemy(enemy.event.id, x, y, "psy", 6 + 2 * lv, false)
							break
						}
						if (core.noPass(x, y)) return false
						d += 1
					}
					enemy = core.getBlock(x, y)
					if (enemy && (d > 1)) {
						core.moveEnemyOnPoint(x, y, core.nextX(1), core.nextY(1))
						core.setBlock(enemy.event.id, core.nextX(1), core.nextY(1))
						core.removeBlock(x, y)
					}
					return true
				},
				"cd": function (lv) { return 9 - lv }
			},
			"雷霆一击": {
				"name": "雷霆一击",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 2.5,
				"posY": 2,
				"father": {},
				"image": "SQSW2.png",
				"describe": function (lv) { return "W技能，震击地面，对2.5格内的敌人造成" + core.skillTextSelect([5.4, 7.2, 9], lv) + "倍率的物理伤害，并在5回合内造成速度下降效果，冷却时间" + core.skillTextSelect([13, 12, 11], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					core.drawAnimate("Axe6", hero.loc.x, hero.loc.y)
					for (var i = -2; i <= 2; i++)
						for (var j = -2; j <= 2; j++) {
							var x = hero.loc.x + i,
								y = hero.loc.y + j
							if (core.outMap(x, y)) continue
							if (i * i + j * j > 6.25) continue
							var enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys") {
								core.setEnemyStat(x, y, "speed-", 5)
								core.damageToEnemy(enemy.event.id, x, y, "psy", 3.6 + 1.8 * lv, false)
							}
						}
					return true
				},
				"cd": function (lv) { return 14 - lv }
			},
			"圣印结界": {
				"name": "圣印结界",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 4,
				"posY": 2,
				"father": {},
				"image": "SQSW3.png",
				"describe": function (lv) { return "W技能，在前方的墙体上施下一个圣印，圣印会持续灼烧周围的敌人，每回合对九宫格范围敌人造成" + core.skillTextSelect([1.8, 2.4, 3], lv) + "倍率的物理伤害，持续6回合，冷却时间" + core.skillTextSelect([10, 9, 8], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					var x = core.nextX(1),
						y = core.nextY(1)
					if (core.outMap(x, y)) return false
					var block = core.getBlock(x, y)
					if (block && block.event.cls != "enemys" && !core.getFgNumber(x, y)) {
						core.drawAnimate("MPActive", x, y)
						core.setBgFgBlock("fg", 64, x, y)
						flags.lastTime = flags.lastTime || {}
						flags.lastTime[x + "," + y] = 6
						return true
					}
					return false
				},
				"cd": function (lv) { return 11 - lv }
			},
			"惩戒": {
				"name": "惩戒",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 1,
				"posY": 3,
				"father": {},
				"image": "SQSE1.png",
				"describe": function (lv) { return "E技能，对前方最近的那名敌人造成" + core.skillTextSelect([6, 7.5, 9], lv) + "倍率的魔法伤害，并使其处于沉默与攻击下降状态，持续4回合，冷却时间" + core.skillTextSelect([9, 8, 7], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					var d = 1,
						enemy, x, y
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) return false
						enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") {
							core.drawAnimate("Heal10", x, y)
							core.setEnemyStat(x, y, "atk-", 4)
							core.setEnemyStat(x, y, "silence", 4)
							core.damageToEnemy(enemy.event.id, x, y, "magic", 4.5 + 1.5 * lv, false)
							return true
						}
						if (core.noPass(x, y)) return false
						d += 1
					}
					return false
				},
				"cd": function (lv) { return 10 - lv }
			},
			"纯净光束": {
				"name": "纯净光束",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 2.5,
				"posY": 3,
				"father": {},
				"image": "SQSE2.png",
				"describe": function (lv) { return "E技能，向前方发出一道光束，对命中的所有敌人造成" + core.skillTextSelect([3.6, 4.8, 6], lv) + "倍率的魔法伤害，造成伤害的50%治疗自身，不会穿过墙体，冷却时间" + core.skillTextSelect([12, 11, 10], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					var d = 1,
						x, y
					core.drawAnimate("Heal2", hero.loc.x, hero.loc.y)
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) break
						var enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") {
							core.drawAnimate("Light1", x, y)
							core.damageToEnemy(enemy.event.id, x, y, "magic-rec", 2.4 + 1.2 * lv, false)
						} else if (core.noPass(x, y))
							break
						d += 1
					}
					return true
				},
				"cd": function (lv) { return 13 - lv }
			},
			"圣芒十字": {
				"name": "圣芒十字",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 4,
				"posY": 3,
				"father": {},
				"image": "SQSE3.png",
				"describe": function (lv) { return "E技能，生成一道圣十字，对与自身同行或同列的所有敌人造成" + core.skillTextSelect([8, 10, 12], lv) + "倍率的魔法伤害，不会被墙体阻挡，冷却时间" + core.skillTextSelect([16, 14, 12], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					var effect = 0
					for (var x = 0; !core.outMap(x, 0); x++) {
						for (var y = 0; !core.outMap(x, y); y++) {
							if (x != hero.loc.x && y != hero.loc.y) continue
							var enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys") {
								core.drawAnimate("Sword3", x, y)
								core.damageToEnemy(enemy.event.id, x, y, "magic", 6 + 2 * lv, false)
								effect = 1
							}
						}
					}
					return effect
				},
				"cd": function (lv) { return 18 - 2 * lv }
			},
			"真神形态": {
				"name": "真神形态",
				"levelMax": 1,
				"pointCost": [3],
				"kind": 3,
				"passive": false,
				"posX": 1.5,
				"posY": 4.5,
				"father": {},
				"image": "SQSR1.png",
				"describe": function (lv) { return "R技能，在9回合内获得攻击上升和防御上升效果，且免疫敌人造成的任何其他状态。冷却时间20。需等级12" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 12 },
				"effect": function (lv) {
					core.drawAnimate("Heal12", hero.loc.x, hero.loc.y)
					flags.hero_stat = flags.hero_stat || {}
					core.setStat(flags.hero_stat, "atk+", 9)
					core.setStat(flags.hero_stat, "def+", 9)
					core.setStat(flags.hero_stat, "immue", 9)
					return true
				},
				"cd": function (lv) { return 20 }
			},
			"理想之盾": {
				"name": "理想之盾",
				"levelMax": 1,
				"pointCost": [3],
				"kind": 3,
				"passive": false,
				"posX": 3.5,
				"posY": 4.5,
				"father": {},
				"image": "SQSR2.png",
				"describe": function (lv) { return "R技能，获得60%最大生命值的护盾值，五回合后，未被击破的护盾量将转化为对全图敌人的随距离衰减的真实伤害。冷却时间20。需等级12" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 12 },
				"effect": function (lv) {
					core.drawAnimate("Heal9", hero.loc.x, hero.loc.y)
					flags.shield = Math.ceil(0.6 * core.getRealStatus("hpmax") * (flags.skill_level["圣符"] ? (1.05 + 0.05 * flags.skill_level["圣符"]) : 1) - 0.0000001)
					flags.hero_stat = flags.hero_stat || {}
					core.setStat(flags.hero_stat, "shield", 5)
					return true
				},
				"cd": function (lv) { return 20 }
			},
			"反射护盾": {
				"name": "反射护盾",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 4,
				"passive": true,
				"posX": 6.5,
				"posY": 1.5,
				"father": {},
				"image": "SQSD1.png",
				"describe": function (lv) { return "被动技能，受到距离为1的敌人攻击时，对其造成使用自身防御作为攻击进行计算的" + core.skillTextSelect([0.4, 0.6, 0.8], lv) + "倍率的物理伤害，会享受圣痕加成。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 9) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 9 },
			},
			"光之棱镜": {
				"name": "光之棱镜",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 4,
				"passive": true,
				"posX": 8.5,
				"posY": 1.5,
				"father": {},
				"image": "SQSD2.png",
				"describe": function (lv) { return "被动技能，受到敌方主动技能影响时，对效果来源造成使用自身魔防作为魔攻进行计算的" + core.skillTextSelect([1.6, 2.4, 3.2], lv) + "倍率的魔法伤害，会享受圣痕加成。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 9) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 9 },
			},
			"圣痕": {
				"name": "圣痕",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 6,
				"posY": 3.5,
				"father": {},
				"image": "SQSF1.png",
				"describe": function (lv) { return "被动技能，造成物理伤害时，将魔攻的" + core.skillTextSelect([18, 27, 36], lv) + "%加到攻击上进行计算，造成魔法伤害时将相同百分比的攻击加到魔攻上进行计算。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
			"圣符": {
				"name": "圣符",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 7.5,
				"posY": 3.5,
				"father": {},
				"image": "SQSF2.png",
				"describe": function (lv) { return "被动技能，最大生命值及所有受到的回复和护盾效果提高" + core.skillTextSelect([10, 15, 20], lv) + "%。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
					core.setBuff("hpmax", 1 + 0.05 + (0.05 * flags.skill_level[this.name]))
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
			"圣盾": {
				"name": "圣盾",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 9,
				"posY": 3.5,
				"father": {},
				"image": "SQSF3.png",
				"describe": function (lv) { return "被动技能，额外获得" + core.skillTextSelect([2, 3, 4], lv) + "%(防御+魔防)的抵抗。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
		},
		{
			"潜行者": {
				"name": "潜行者",
				"levelMax": 0,
				"pointCost": [0],
				"kind": 0,
				"passive": true,
				"posX": 5,
				"posY": 0,
				"father": {},
				"image": "attack.png",
				"describe": function (lv) { return "你是一个潜行者，普通攻击时，若你面前一格有敌人，用匕首对其造成1.0倍率的物理伤害，否则射出一发弩箭对前方最近的敌人造成0.8倍率的物理伤害" },
				"onlearn": function (lv) {},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {},
				"cd": 0
			},
			"淬毒飞镖": {
				"name": "淬毒飞镖",
				"levelMax": 3,
				"pointCost": [1, 1, 1],
				"kind": 0,
				"passive": false,
				"posX": 1.5,
				"posY": 1,
				"father": {},
				"image": "QXZQ1.png",
				"describe": function (lv) { return "Q技能，扔出带有腐蚀性的飞镖，对前方最近的那名敌人造成" + core.skillTextSelect([2.8, 4.2, 5.6], lv) + "倍率的物理伤害，并在4回合内造成防御下降效果，冷却时间5" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {
					var d = 1,
						enemy, x, y
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) return false
						enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") {
							core.drawAnimate("Bow5", x, y)
							core.setEnemyStat(x, y, "def-", 4)
							core.damageToEnemy(enemy.event.id, x, y, "psy", 1.4 + 1.4 * lv, false)
							return true
						}
						if (core.noPass(x, y)) return false
						d += 1
					}
				},
				"cd": function (lv) { return 5 }
			},
			"谢幕之雾": {
				"name": "谢幕之雾",
				"levelMax": 3,
				"pointCost": [1, 1, 1],
				"kind": 0,
				"passive": false,
				"posX": 3.5,
				"posY": 1,
				"father": {},
				"image": "QXZQ2.png",
				"describe": function (lv) { return "Q技能，向前翻越至前方第一个空地处，之后在原位置爆出一片雾气对九宫格范围敌人造成" + core.skillTextSelect([3.6, 5.4, 7.2], lv) + "倍率的魔法伤害，冷却时间8" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {
					var d = 1,
						x, y
					var sx = hero.loc.x,
						sy = hero.loc.y
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) break
						if (!core.getBlock(x, y)) {
							hero.loc.x = x
							hero.loc.y = y
							core.drawHero()
							break
						}
						d += 1
					}
					core.drawAnimate("Dark1", sx, sy)
					for (var i = -1; i <= 1; i++)
						for (var j = -1; j <= 1; j++) {
							var x = sx + i,
								y = sy + j
							if (core.outMap(x, y)) continue
							var enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys")
								core.damageToEnemy(enemy.event.id, x, y, "magic", 1.8 + 1.8 * lv, false)
						}
					return true
				},
				"cd": function (lv) { return 8 }
			},
			"三连箭": {
				"name": "三连箭",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 1,
				"posY": 2,
				"father": {},
				"image": "QXZW1.png",
				"describe": function (lv) { return "W技能，对前方、左侧一格前方和右侧一格前方连续射出三箭，分别对最近的那名敌人造成" + core.skillTextSelect([6, 7.5, 9], lv) + "倍率的物理伤害，可以穿过墙体，冷却时间" + core.skillTextSelect([9, 8, 7], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					var d, enemy, x, y, effect = 0
					for (var p = -1; p <= 1; p++) {
						d = 1
						while (1) {
							x = core.nextX(d)
							y = core.nextY(d)
							if (x == hero.loc.x) x += p
							else if (y == hero.loc.y) y += p
							if (core.outMap(x, y)) break
							enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys") {
								core.drawAnimate("Bow1", x, y)
								core.damageToEnemy(enemy.event.id, x, y, "psy", 4.5 + 1.5 * lv, false)
								effect = 1
								break
							}
							d += 1
						}
					}
					return effect
				},
				"cd": function (lv) { return 10 - lv }
			},
			"布置陷阱": {
				"name": "布置陷阱",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 2.5,
				"posY": 2,
				"father": {},
				"image": "QXZW2.png",
				"describe": function (lv) { return "W技能，在脚下布置一个陷阱，有敌人踩上陷阱时会触发，对陷阱3格内敌人造成" + core.skillTextSelect([5.4, 7.2, 9], lv) + "倍率的魔法伤害，冷却时间" + core.skillTextSelect([11, 10, 9], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					if (!core.getBgNumber()) {
						core.drawAnimate("EM2", hero.loc.x, hero.loc.y)
						core.setBgFgBlock("bg", 168, hero.loc.x, hero.loc.y)
						return true
					}
					return false
				},
				"cd": function (lv) { return 12 - lv }
			},
			"刹那": {
				"name": "刹那",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 4,
				"posY": 2,
				"father": {},
				"image": "QXZW3.png",
				"describe": function (lv) { return "W技能，当前回合你可以行动三次，冷却时间" + core.skillTextSelect([12, 9, 6], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					core.drawAnimate("St10", hero.loc.x, hero.loc.y)
					flags.doubleMove = 2
					return true
				},
				"cd": function (lv) { return 15 - 3 * lv }
			},
			"爆炸射击": {
				"name": "爆炸射击",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 1,
				"posY": 3,
				"father": {},
				"image": "QXZE1.png",
				"describe": function (lv) { return "E技能，朝前方射出穿透性的箭矢，对穿过的敌人造成" + core.skillTextSelect([4.8, 6.4, 8], lv) + "倍率的物理伤害并在命中墙壁时爆炸，爆炸对九宫格范围敌人造成" + core.skillTextSelect([4.8, 6.4, 8], lv) + "倍率的魔法伤害，冷却时间" + core.skillTextSelect([12, 11, 10], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					var d = 1,
						x, y
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) break
						var enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") {
							core.drawAnimate("Book1", x, y)
							core.damageToEnemy(enemy.event.id, x, y, "psy", 3.2 + 1.6 * lv, false)
						} else if (core.noPass(x, y))
							break
						d += 1
					}
					d -= 1
					core.drawAnimate("Fire1", core.nextX(d), core.nextY(d))
					for (var i = -1; i <= 1; i++)
						for (var j = -1; j <= 1; j++) {
							var x = core.nextX(d) + i,
								y = core.nextY(d) + j
							if (core.outMap(x, y)) continue
							var enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys")
								core.damageToEnemy(enemy.event.id, x, y, "magic", 3.2 + 1.6 * lv, false)
						}
					return true
				},
				"cd": function (lv) { return 13 - lv }
			},
			"狙击姿态": {
				"name": "狙击姿态",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 2.5,
				"posY": 3,
				"father": {},
				"image": "QXZE2.png",
				"describe": function (lv) { return "E技能，在接下来的" + core.skillTextSelect([4, 6, 8], lv) + "回合内，获得攻速提升且你的远程普通攻击带有穿透效果，每穿过一名敌人倍率减少25%，冷却时间15。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					core.drawAnimate("St11", hero.loc.x, hero.loc.y)
					flags.hero_stat = flags.hero_stat || {}
					core.setStat(flags.hero_stat, "speed+", lv * 2 + 2)
					core.setStat(flags.hero_stat, "cross", lv * 2 + 2)
					return true
				},
				"cd": function (lv) { return 15 }
			},
			"遁入阴影": {
				"name": "遁入阴影",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 4,
				"posY": 3,
				"father": {},
				"image": "QXZE3.png",
				"describe": function (lv) { return "E技能，在接下来的" + core.skillTextSelect([3, 4, 5], lv) + "回合内，不会受到来自敌方的任何攻击和技能影响，冷却时间15。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					core.drawAnimate("None1", hero.loc.x, hero.loc.y)
					flags.hero_stat = flags.hero_stat || {}
					core.setStat(flags.hero_stat, "miss", lv + 2)
					return true
				},
				"cd": function (lv) { return 15 }
			},
			"瞬闪": {
				"name": "瞬闪",
				"levelMax": 1,
				"pointCost": [3],
				"kind": 3,
				"passive": false,
				"posX": 1.5,
				"posY": 4.5,
				"father": {},
				"image": "QXZR1.png",
				"describe": function (lv) { return "R技能，瞬间移动到前方一名敌人身后并对其造成6倍率的物理伤害，如果其身后没有空地则改为移动到身前，冷却时间4。需等级12" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 12 },
				"effect": function (lv) {
					var d = 1,
						enemy, x, y
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) return false
						enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys")
							break
						if (core.noPass(x, y)) return false
						d += 1
					}
					var tx = core.nextX(d + 1),
						ty = core.nextY(d + 1)
					if (!core.outMap(tx, ty) && !core.getBlock(tx, ty)) {
						hero.loc.x = tx
						hero.loc.y = ty
						core.drawHero()
					} else if (d > 1) {
						hero.loc.x = core.nextX(d - 1)
						hero.loc.y = core.nextY(d - 1)
						core.drawHero()
					}
					core.drawAnimate("Sword4", x, y)
					core.damageToEnemy(enemy.event.id, x, y, "psy", 6, false)
					return true
				},
				"cd": function (lv) { return 4 }
			},
			"镜花水月": {
				"name": "镜花水月",
				"levelMax": 1,
				"pointCost": [3],
				"kind": 3,
				"passive": false,
				"posX": 3.5,
				"posY": 4.5,
				"father": {},
				"image": "QXZR2.png",
				"describe": function (lv) { return "R技能，初次学习时，在原地留下一个影子。施放：与影子交换位置，之后影子对2格内的敌人造成6倍率的魔法伤害。冷却时间7。需等级12" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.shadow_x = hero.loc.x
						flags.shadow_y = hero.loc.y
						core.setBgFgBlock("fg", 358, hero.loc.x, hero.loc.y)
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 12 },
				"effect": function (lv) {
					var sx = flags.shadow_x,
						sy = flags.shadow_y
					var tx = hero.loc.x,
						ty = hero.loc.y
					hero.loc.x = sx
					hero.loc.y = sy
					core.setBgFgBlock("fg", 0, sx, sy)
					var block = core.getBlock(sx, sy)
					if (block) {
						core.moveEnemyOnPoint(sx, sy, tx, ty)
						core.removeBlock(sx, sy)
						core.setBlock(block.event.id, tx, ty)
					}
					core.drawHero()
					core.setBgFgBlock("fg", 358, tx, ty)
					core.drawMap()
					flags.shadow_x = tx
					flags.shadow_y = ty

					core.drawAnimate("St18", tx, ty)
					for (var i = -2; i <= 2; i++)
						for (var j = -2; j <= 2; j++) {
							var x = tx + i,
								y = ty + j
							if (core.outMap(x, y)) continue
							if (i * i + j * j > 4) continue
							var enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys")
								core.damageToEnemy(enemy.event.id, x, y, "magic", 6, false)
						}
					return true
				},
				"cd": function (lv) { return 7 }
			},
			"弓弩强化": {
				"name": "弓弩强化",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 4,
				"passive": true,
				"posX": 6.5,
				"posY": 1.5,
				"father": {},
				"image": "QXZD1.png",
				"describe": function (lv) { return "被动技能，你的远程普通攻击现在可以穿过墙壁，且倍率提高" + core.skillTextSelect([0, 0.1, 0.2], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 9) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 9 },
			},
			"神经毒素": {
				"name": "神经毒素",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 4,
				"passive": true,
				"posX": 8.5,
				"posY": 1.5,
				"father": {},
				"image": "QXZD2.png",
				"describe": function (lv) { return "被动技能，你的近战普通攻击额外造成" + core.skillTextSelect([10, 15, 20], lv) + "%倍率的真实伤害。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 9) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 9 },
			},
			"暗影领域": {
				"name": "暗影领域",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 6,
				"posY": 3.5,
				"father": {},
				"image": "QXZF1.png",
				"describe": function (lv) { return "被动技能，在没有邻接的敌人时，攻击和魔攻提高" + core.skillTextSelect([8, 12, 16], lv) + "%。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
			"幻影之幕": {
				"name": "幻影之幕",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 7.5,
				"posY": 3.5,
				"father": {},
				"image": "QXZF2.png",
				"describe": function (lv) { return "被动技能，受到来自邻接敌人的伤害减少" + core.skillTextSelect([24, 36, 48], lv) + "%。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
			"刺杀标记": {
				"name": "刺杀标记",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 9,
				"posY": 3.5,
				"father": {},
				"image": "QXZF3.png",
				"describe": function (lv) { return "被动技能，对没有邻接友军的敌人造成的伤害提高" + core.skillTextSelect([16, 24, 32], lv) + "%。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
		},
		{
			"奥术师": {
				"name": "奥术师",
				"levelMax": 0,
				"pointCost": [0],
				"kind": 0,
				"passive": true,
				"posX": 5,
				"posY": 0,
				"father": {},
				"image": "attack.png",
				"describe": function (lv) { return "你是一个奥术师，普通攻击时，若你面前一格有敌人，用杖砸对其造成1.0倍率的物理伤害，否则射出一道能量对前方最近的敌人造成0.8倍率的魔法伤害" },
				"onlearn": function (lv) {},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {},
				"cd": 0
			},
			"雷击": {
				"name": "雷击",
				"levelMax": 3,
				"pointCost": [1, 1, 1],
				"kind": 0,
				"passive": false,
				"posX": 1.5,
				"posY": 1,
				"father": {},
				"image": "ASSQ1.png",
				"describe": function (lv) { return "Q技能，召唤出闪电，对前方最近的那名敌人造成" + core.skillTextSelect([3, 4.5, 6], lv) + "倍率的魔法伤害，可以伤害墙体后的敌人，冷却时间5" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {
					var d = 1,
						enemy, x, y
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) return false
						enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") {
							core.drawAnimate("Wind1", x, y)
							core.damageToEnemy(enemy.event.id, x, y, "magic", 1.5 + 1.5 * lv, false)
							return true
						}
						d += 1
					}
				},
				"cd": function (lv) { return 5 }
			},
			"能量吸收": {
				"name": "能量吸收",
				"levelMax": 3,
				"pointCost": [1, 1, 1],
				"kind": 0,
				"passive": false,
				"posX": 3.5,
				"posY": 1,
				"father": {},
				"image": "ASSQ2.png",
				"describe": function (lv) { return "Q技能，吸收面前一格敌人的生命力，造成" + core.skillTextSelect([3, 4.5, 6], lv) + "倍率的魔法伤害，造成伤害的50%治疗自身，冷却时间6" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return true },
				"effect": function (lv) {
					var x = core.nextX(),
						y = core.nextY()
					var enemy = core.getBlock(x, y)
					if (enemy && enemy.event.cls == "enemys") {
						core.drawAnimate("Dark2", x, y)
						core.damageToEnemy(enemy.event.id, x, y, "magic-rec", 1.5 + 1.5 * lv, false)
						return true
					}
					return false
				},
				"cd": function (lv) { return 6 }
			},
			"冲击波": {
				"name": "冲击波",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 1,
				"posY": 2,
				"father": {},
				"image": "ASSW1.png",
				"describe": function (lv) { return "W技能，对前方三列、每列六格区域内的敌人造成" + core.skillTextSelect([4, 5.2, 6.4], lv) + "倍率的魔法伤害，冷却时间" + core.skillTextSelect([10, 9, 8], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					var d, enemy, x, y, effect = 0
					for (var p = -1; p <= 1; p++) {
						for (d = 1; d <= 6; d++) {
							x = core.nextX(d)
							y = core.nextY(d)
							if (x == hero.loc.x) x += p
							else if (y == hero.loc.y) y += p
							if (core.outMap(x, y)) break
							enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys") {
								core.drawAnimate("Water1", x, y)
								core.damageToEnemy(enemy.event.id, x, y, "magic", 2.8 + 1.2 * lv, false)
								effect = 1
							}
						}
					}
					return effect
				},
				"cd": function (lv) { return 11 - lv }
			},
			"火焰轰击": {
				"name": "火焰轰击",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 2.5,
				"posY": 2,
				"father": {},
				"image": "ASSW2.png",
				"describe": function (lv) { return "W技能，对前方两格处为中心、半径2.5格区域内的敌人造成" + core.skillTextSelect([4, 5.2, 6.4], lv) + "倍率的魔法伤害，并击晕他们2回合，冷却时间" + core.skillTextSelect([11, 10, 9], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					var sx = core.nextX(2),
						sy = core.nextY(2)
					if (core.outMap(sx, sy)) return false
					core.drawAnimate("Fire2", sx, sy)
					for (var i = -2; i <= 2; i++)
						for (var j = -2; j <= 2; j++) {
							var x = sx + i,
								y = sy + j
							if (core.outMap(x, y)) continue
							if (i * i + j * j > 6.25) continue
							var enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys") {
								core.setEnemyStat(x, y, "stun", 2)
								core.damageToEnemy(enemy.event.id, x, y, "magic", 2.8 + 1.2 * lv, false)
							}
						}
					return true
				},
				"cd": function (lv) { return 12 - lv }
			},
			"冰霜新星": {
				"name": "冰霜新星",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 1,
				"passive": false,
				"posX": 4,
				"posY": 2,
				"father": {},
				"image": "ASSW3.png",
				"describe": function (lv) { return "W技能，对前方最近的敌人造成" + core.skillTextSelect([6, 7.5, 9], lv) + "倍率的魔法伤害，其九宫格范围内其他敌人受到75%倍率的伤害，并对所有受影响的敌人施加持续4回合的速度下降，冷却时间" + core.skillTextSelect([9, 8, 7], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 3) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 3 },
				"effect": function (lv) {
					var d = 1,
						enemy, x, y
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) return false
						enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") break
						if (core.noPass(x, y)) return false
						d += 1
					}
					var sx = core.nextX(d),
						sy = core.nextY(d)
					core.drawAnimate("Ice2", sx, sy)
					for (var i = -1; i <= 1; i++)
						for (var j = -1; j <= 1; j++) {
							x = sx + i
							y = sy + j
							if (core.outMap(x, y)) continue
							enemy = core.getBlock(x, y)
							if (enemy && enemy.event.cls == "enemys") {
								core.setEnemyStat(x, y, "speed-", 4)
								core.damageToEnemy(enemy.event.id, x, y, "magic", ((!i && !j) ? 1 : 0.75) * (4.5 + 1.5 * lv), false)
							}
						}
					return true
				},
				"cd": function (lv) { return 10 - lv }
			},
			"虚空放逐": {
				"name": "虚空放逐",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 1,
				"posY": 3,
				"father": {},
				"image": "ASSE1.png",
				"describe": function (lv) { return "E技能，将前方最近的那名敌人放逐至虚空，其受到的物理伤害变为0，受到的魔法伤害提高100%，持续4回合，冷却时间" + core.skillTextSelect([24, 18, 12], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					var d = 1,
						enemy, x, y
					while (1) {
						x = core.nextX(d)
						y = core.nextY(d)
						if (core.outMap(x, y)) return false
						enemy = core.getBlock(x, y)
						if (enemy && enemy.event.cls == "enemys") {
							core.drawAnimate("St13", x, y)
							core.setEnemyStat(x, y, "void", 4)
							return true
						}
						if (core.noPass(x, y)) return false
						d += 1
					}
					return false
				},
				"cd": function (lv) { return 30 - 6 * lv }
			},
			"禁制领域": {
				"name": "禁制领域",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 2.5,
				"posY": 3,
				"father": {},
				"image": "ASSE2.png",
				"describe": function (lv) { return "E技能，沉默地图上所有敌人，持续6回合，冷却时间" + core.skillTextSelect([24, 18, 12], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					var effect = 0
					for (var x = 0; !core.outMap(x, 0); x++) {
						for (var y = 0; !core.outMap(x, y); y++) {
							var block = core.getBlock(x, y)
							if (block && block.event.cls == "enemys") {
								core.drawAnimate("St14", x, y)
								core.setEnemyStat(x, y, "silence", 6)
								effect = 1
							}
						}
					}
					return effect
				},
				"cd": function (lv) { return 30 - 6 * lv }
			},
			"相位转移": {
				"name": "相位转移",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 2,
				"passive": false,
				"posX": 4,
				"posY": 3,
				"father": {},
				"image": "ASSE3.png",
				"describe": function (lv) { return "E技能，传送到当前位置的中心对称位置，可以短暂落在墙体上，冷却时间" + core.skillTextSelect([24, 18, 12], lv) + "。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 6) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 6 },
				"effect": function (lv) {
					core.drawAnimate("Light2", hero.loc.x, hero.loc.y)
					hero.loc.x = 12 - hero.loc.x
					hero.loc.y = 12 - hero.loc.y
					core.drawAnimate("Light2", hero.loc.x, hero.loc.y)
					core.drawHero()
					return true
				},
				"cd": function (lv) { return 30 - 6 * lv }
			},
			"奥能风暴": {
				"name": "奥能风暴",
				"levelMax": 1,
				"pointCost": [3],
				"kind": 3,
				"passive": false,
				"posX": 1.5,
				"posY": 4.5,
				"father": {},
				"image": "ASSR1.png",
				"describe": function (lv) { return "R技能，对地图上的所有敌人造成6倍率的魔法伤害。冷却时间20。需等级12" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 12 },
				"effect": function (lv) {
					core.drawAnimate("None2", 6, 6)
					for (var x = 0; !core.outMap(x, 0); x++) {
						for (var y = 0; !core.outMap(x, y); y++) {
							var block = core.getBlock(x, y)
							if (block && block.event.cls == "enemys")
								core.damageToEnemy(block.event.id, x, y, "magic", 6, false)
						}
					}
					return true
				},
				"cd": function (lv) { return 20 }
			},
			"法术重载": {
				"name": "法术重载",
				"levelMax": 1,
				"pointCost": [3],
				"kind": 3,
				"passive": false,
				"posX": 3.5,
				"posY": 4.5,
				"father": {},
				"image": "ASSR2.png",
				"describe": function (lv) { return "R技能，刷新你的其他技能的冷却时间。冷却时间20。需等级12" },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 12 },
				"effect": function (lv) {
					core.drawAnimate("Heal8", hero.loc.x, hero.loc.y)
					flags.skill_cd = {}
					return true
				},
				"cd": function (lv) { return 20 }
			},
			"追踪光弹": {
				"name": "追踪光弹",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 4,
				"passive": true,
				"posX": 6.5,
				"posY": 1.5,
				"father": {},
				"image": "ASSD1.png",
				"describe": function (lv) { return "被动技能，每回合自动对与你最近的那名敌人造成" + core.skillTextSelect([0.4, 0.6, 0.8], lv) + "倍率的魔法伤害。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 9) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 9 },
			},
			"能量循环": {
				"name": "能量循环",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 4,
				"passive": true,
				"posX": 8.5,
				"posY": 1.5,
				"father": {},
				"image": "ASSD2.png",
				"describe": function (lv) { return "被动技能，每次使用技能时回复" + core.skillTextSelect([2, 3, 4], lv) + "%最大生命。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 9) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 9 },
			},
			"状态吸收": {
				"name": "状态吸收",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 6,
				"posY": 3.5,
				"father": {},
				"image": "ASSF1.png",
				"describe": function (lv) { return "被动技能。  等级1：不会受到敌人造成的能力下降效果。  等级2：改为将受到的能力下降效果变为对应的能力提升效果。  等级3：额外免疫击晕、沉默。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
			"穿透之眼": {
				"name": "穿透之眼",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 7.5,
				"posY": 3.5,
				"father": {},
				"image": "ASSF2.png",
				"describe": function (lv) { return "被动技能，对处于击晕/沉默/速度下降中任意状态的敌人造成额外" + core.skillTextSelect([16, 24, 32], lv) + "%伤害。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
			"灵魂之核": {
				"name": "灵魂之核",
				"levelMax": 3,
				"pointCost": [2, 2, 2],
				"kind": 5,
				"passive": true,
				"posX": 9,
				"posY": 3.5,
				"father": {},
				"image": "ASSF3.png",
				"describe": function (lv) { return "被动技能，每当一名敌人死亡时，你的" + core.skillTextSelect(["Q", "QW", "QWE"], lv) + "技能冷却减少1回合，同时R技能冷却减少" + core.skillTextSelect([1, 2, 3], lv) + "回合。" + (lv < 3 ? (" 需要达到" + (lv * 3 + 15) + "级才可继续学习") : "") },
				"onlearn": function (lv) {
					if (lv == 1) {
						flags.equiped_skill[this.kind] = current;
						core.updateStatusBar()
					}
				},
				"canLearn": function (lv) { return hero.lv >= 3 * lv + 15 },
			},
		}
	]

	/*this.hurtEnemy = function (x, y, dam, type) {
		let block = core.getBlock(x, y)
		dam = Math.floor(dam)
		if (!block || block.event.cls != "enemys") return;
		core.setEnemyOnPoint(x, y, null, "hp", dam, "-=")
		core.drawAnimate("zone", x, y)
		if (core.getEnemyValue(block.event.id, 'hp', x, y) <= 0) {
			flags.kill_by_skill = true
			core.afterBattle(block.event.id, x, y)
			flags.kill_by_skill = false
		}
	}*/

	this.getSkillByName = function (name) {
		return skills[flags.class][name]
	}

	this.skillTextSelect = function (arr, lv) {
		arr.unshift(0)
		let r = ""
		for (let i = 1; i < arr.length; i++) {
			if (i == lv) r = r + "\r[#FFAA00]" + arr[i] + "\r"
			else r = r + arr[i]
			if (i != arr.length - 1) r = r + "/"
		}
		return r
	}

	const defau = ["狂战士", "圣骑士", "潜行者", "奥术师"]

	/*this.resetSkillTimes = function () {
		flags.skill_times = {}
		let s = skills[flags.class]
		for (var name in flags.skill_level) {
			if (!s[name].passive && s[name].type == "times") {
				flags.skill_times[name] = s[name].number(flags.skill_level[name])
			}
		}
	}*/

	this.canLearn = function (s) {
		let x = flags.skill_level,
			p = flags.skill_point,
			l = x[s.name] || 0
		if (flags.equiped_skill[s.kind] && flags.equiped_skill[s.kind] != s.name) return false
		if (l == s.levelMax) return false
		if (s.father)
			for (var i in s.father) {
				let t = x[i] || 0
				if (t < s.father[i]) return false
			}
		if (s.canLearn && !s.canLearn(l)) return false
		return p >= s.pointCost[l]
	}

	this.onlearn = function (s) {
		if (!this.canLearn(s)) return; //此处可添加音效
		let lv = (flags.skill_level[s.name] || 0)
		flags.skill_point -= s.pointCost[lv]
		lv += 1
		flags.skill_level[s.name] = lv
		if (s.onlearn) s.onlearn(lv)
		core.updateStatusBar()
	}

	function setCD(s, lv) {
		if (core.hasEquip("I393")) flags.skill_cd[s.name] = Math.ceil(s.cd(lv) * 0.7 - 0.0000001)
		else flags.skill_cd[s.name] = s.cd(lv)
	}

	this.useSkill = function (id) {
		//if (flags.mapTree_active) return
		if ((flags.hero_stat || {}).silence) return
		let s = core.getSkillByName(flags.equiped_skill[id])
		let lv = flags.skill_level[s.name]
		if (flags.skill_cd[s.name]) return
		setCD(s, lv)
		if (!s.effect(lv)) flags.skill_cd[s.name] = 0
		else {
			if (flags.skill_level && flags.skill_level["能量循环"]) {
				core.healHero((0.01 + 0.01 * flags.skill_level["能量循环"]) * core.getRealStatus("hpmax"), true)
			}
			if (s.name == "法术重载") setCD(s, lv)
		}
		core.updateStatusBar()
	}

	function _calPosX(s) {
		return s.posX * 46 - 39
	}

	const bot = 46 * 5

	function _calPosY(s) {
		return bot - 46 * s.posY + 7
	}

	function getPointText(s) {
		let x = flags.skill_level,
			p = flags.skill_point,
			l = x[s.name] || 0
		if (s.levelMax == 0) return "   攻击方式"
		if (l == s.levelMax) return "   已满级"
		return "   升级需 " + s.pointCost[l] + " 技能点 "
	}

	this.drawSkillTree = function () {
		if (core.isReplaying()) return;
		core.ui._createUIEvent();
		core.clearMap('uievent');
		core.getContextByName('uievent').mozImageSmoothingEnabled = false;
		core.getContextByName('uievent').webkitImageSmoothingEnabled = false;
		core.getContextByName('uievent').msImageSmoothingEnabled = false;
		core.getContextByName('uievent').imageSmoothingEnabled = false;
		core.ui._uievent_drawBackground({ background: [0, 0, 0, 0.85], x: 0, y: 0, width: 416, height: 416 });
		let s = skills[flags.class]
		for (var i in s) {
			let x = _calPosX(s[i]),
				y = _calPosY(s[i])
			core.drawImage("uievent", s[i].image, x, y, 32, 32);
			//core.drawIcon("uievent", s[i].image, x, y);
			if (flags.skill_level[i]) core.ui._uievent_drawTextContent({ text: "" + flags.skill_level[i], left: x + 24, top: y + 22, maxWidth: 10, fontSize: 10 });
			if (i == current) {
				core.drawLine("uievent", x, y, x + 32, y, 'red');
				core.drawLine("uievent", x, y, x, y + 32, 'red');
				core.drawLine("uievent", x + 32, y, x + 32, y + 32, 'red');
				core.drawLine("uievent", x, y + 32, x + 32, y + 32, 'red');
			}
			if (s[i].father)
				for (var f in s[i].father) {
					let fx = _calPosX(s[f]),
						fy = _calPosY(s[f])
					core.drawLine("uievent", fx + 16, fy, x + 16, y + 32, flags.skill_level[i] ? "red" : (s[i].posY > 4 ? "grey" : "white"))
				}
		}
		core.ui._uievent_drawTextContent({ text: "升级", left: 340, top: 395 });
		core.ui._uievent_drawTextContent({ text: "离开", left: 380, top: 395 });
		core.ui._uievent_drawTextContent({ text: "当前技能点：" + flags.skill_point, top: 395, maxWidth: 416, fontSize: 16, align: "center" });
		core.ui._uievent_drawTextContent({ text: "\r[#8A2BE2]" + s[current].name + (s[current].levelMax ? (" Lv:" + (flags.skill_level[current] || 0) + "/" + s[current].levelMax) : "") + getPointText(s[current]) + "：", left: 10, top: 285, fontSize: 16 });
		/*if (!s[current].passive && flags.skill_level[current]) {
			for (let i = 0; i < 3; i++) core.fillCircle("uievent", 352 + i * 27, 294, 8, "green")
			core.ui._uievent_drawTextContent({ text: "\r[#FFAA00]装备：  1   2   3", left: 288, top: 285, fontSize: 16 });
		}*/
		core.ui._uievent_drawTextContent({ text: s[current].describe(flags.skill_level[current] || 0), left: 35, top: 305, maxWidth: 416 - 65, fontSize: 16 });

	};

	// 默认图片大小为32*32。如果不是，请自行修改下面的数据（包括绘图部分）
	this.inRect = function (px, py, rx, ry) {
		return (px >= rx) && (px <= rx + 32) && (py >= ry) && (py <= ry + 32);
	};

	this._clickedSkill = function (px, py) {
		if (px >= 380 && py >= 395) {
			core.insertAction({ "type": "break" });
			return;
		}
		//console.log(px, py)
		let s = skills[flags.class]
		for (var i in s) {
			let x = _calPosX(s[i]),
				y = _calPosY(s[i])
			if (this.inRect(px, py, x, y)) {
				current = i;
			}
		}
		//if (!flags.mapTree_active || flags.mapTree_viewMode) return
		if (py >= 395) {
			this.onlearn(s[current])
		}
		/*if (!s[current].passive && flags.skill_level[current])
			for (let i = 1; i <= 3; i++)
				if (px >= 317 + 27 * i && px <= 331 + 27 * i && py >= 287 && py <= 301) {
					flags.equiped_skill = flags.equiped_skill || []
					for (let j = 1; j <= 3; j++)
						if (flags.equiped_skill[j] == current) flags.equiped_skill[j] = null
					flags.equiped_skill[i] = current
					core.updateStatusBar()
				}*/
	};

	this._keySkill = function (key) {
		switch (key) {
		case 27: //esc
		case 67:
			core.insertAction({ "type": "break" });
			break;
		}
	};

	this.activateSkill = function () {
		if (flags.type == 0)
			this._keySkill(flags.keycode);
		else
			this._clickedSkill(flags.px, flags.py);
	};

	this.openSkillTree = function (arg) {
		if (core.isReplaying()) {
			if (!arg.startsWith("openSkillTree")) return false
		}
		flags.skill_level = flags.skill_level || {}
		flags.skill_point = flags.skill_point || 0
		current = defau[flags.class];
		core.status.route.push("openSkillTree")
		core.insertAction([{
				"type": "while",
				"condition": "true",
				"data": [
					{ "type": "function", "function": "function () { core.drawSkillTree(); }" },
					{ "type": "wait" },
					{ "type": "function", "function": "function() { core.activateSkill(); }" }
				]
			},
			{
				"type": "function",
				"function": "function () { " +
					"core.deleteCanvas('uievent');" +
					"core.clearUI(); " +
					"core.clearMap('uievent');" +
					"core.ui._uievent_drawSelector({ \"code\": 1 }); " +
					"core.ui._uievent_drawSelector({ \"code\": 2 }); " +
					"}"
			},
			{
				"type": "function",
				"function": "function () {if(flags.mapTree_active) core.drawMapTree()}"
			}
		]);
		return true
	};
	core.registerReplayAction("openSkillTree", this.openSkillTree)

},
    "wiki": function () {
	/**
	 * author : alpha
	 * introduce: 介绍物品用页面
	 *
	 * detail:
	 * chage开头函数为数据层，flow开头函数为动画层，其余为register用函数
	 * 动画层原则不作数据判断，flow_left可挪到任意位置，flow_left需挪到一个存在的栏目下
	 * 数据层中在左侧栏目换页、换栏目、初始化时将光标对准对应栏目的第一项，其余情况不参与左侧栏目变动
	 *
	 * use:
	 * 在外部调用
	 * 		core.insertAction({"type": "function", "async": true, "function": "function(){core.showIntroduce()}"})
	 * 		或事件流插入{"type": "function", "async": true, "function": "function(){core.showIntroduce()}"}
	 * 以打开本插件
	 * 
	 * 在外部调用core.setIntroduce(number1, number2, ?true/false)，将introduce[num1][num2]设为可见/不可见
	 * 在本插件中const为自定义config
	 * 请自行修改config及所有用到的图片，以避免报错
	 * 
	 **/

	// [content [x1, y1 x2, y2]]
	const introduce_top = [
		["系统介绍", [20, 65, 105, 85]],
		["战斗计算", [120, 65, 205, 85]],
		["操作说明", [220, 65, 305, 85]],
		["附加信息", [320, 65, 405, 85]],
	];

	// [[title detail show icon_id [icoon_x icon_y]]]
	var introduce_detail = [
		// 一
		[
			["基本介绍", "你每次移动后，会进行一次普通攻击，之后时间(显示在状态栏)会前进。点击状态栏+号左边的攻击图标或按空格可以在不移动的情况下推进时间。随着时间的推移，地图上将出现各种各样的怪物", true],
			["普通攻击", "普通攻击是自动触发的，无论是移动还是原地推进时间后，如果前方有怪物满足你的攻击条件，就会自动进行一次普通攻击，关于你的职业的普通攻击的介绍可以在技能树中查看", true],
			["学习技能", "点击状态栏+号图标或按C键打开技能树，可以在技能树中学习技能，同一行的技能只能学习一个，技能可以点击状态栏释放或使用对应快捷键释放", true],
			["购买物品", "你可以随时点击状态栏金币图标或按V来购买消耗品或装备，所有的非消耗品都可以以80%价格出售，注意前期越贵的装备性价比越低", true],
			["怪物行动", "所有的怪物都会持续尝试靠近你，如果一个怪物与你相邻，或者与另一个能攻击到你的怪物相邻，它就能用普通攻击攻击到你\n怪物的技能可以在怪物手册中查看详细描述，每名怪物最多只会有一个主动技能，如果它的主动技能处于冷却状态，剩余冷却时间会显示在地图上", true],
		],
		// 二
		[
			["属性介绍", "状态栏左上角的三行依次是:\n等级  升级所需经验\n生命  生命上限\n回复  抵抗\n其中每时间单位会自动恢复等同回复的生命值，抵抗则会影响受到的伤害", true],
			["属性介绍", "横屏的接下来三行/竖屏的右侧三行依次是:\n攻击  魔攻\n防御  魔防\n攻速  金币\n其中攻速只影响普通攻击造成的伤害，但同时会增幅所有为攻击附带额外效果的技能/装备", true],
			["伤害计算", "伤害公式以物理伤害为例:\n伤害=((攻击方物攻)*100/(100+防御方防御)*伤害倍率-防御方抵抗)\n魔法伤害使用魔攻和魔防进行计算\n普通攻击的伤害会在最后乘以攻速\n部分技能有独特的计算方式", true],
			["其他属性", "防御穿透会在伤害计算时直接降低目标的防御，并在百分比效果之后计算\n穿透不会使防御/魔防低于-50\n普通攻击和为攻击附带额外效果的技能/装备享受攻击吸血，技能和其他物品的伤害享受技能吸血\n攻击吸血只对主目标生效，穿透/溅射伤害不生效", true],
			["异常状态", "异常状态的效果如下:\n晕眩：不能进行普通攻击\n沉默：不能使用技能且正在冷却的技能不会进行倒数\n攻击上升/下降:攻击和魔攻提高/降低20%\n防御上升/下降:防御和魔防提高/降低40%\n攻速上升/下降:攻速提高/降低25%\n获得一种能力上升/下降效果时，身上相反的效果会消失", true],
		],
		// 三
		[
			["移动端", "电脑上使用方向键移动或鼠标点击地图移动都可以，同时可以用快捷键进行几乎所有操作\n移动端则需要通过持续点击地图或状态栏来操作", true],
			["状态栏", "像+号的图标：打开技能树\n+号左边的攻击图标：原地推进时间\n+号周围的其他图标：对应释放QWER四个技能，学习后才会出现\n金币数值前的金币图标：打开商店", true],
			["快捷键", "QWER：使用对应的技能\nT：打开物品栏\nA：读自动存档(每时间都会自动存档)\nS/D：存档/读档\nF：回放录像\nG：打开装备栏", true],
			["快捷键", "Z：转身(不会推进时间)\nX：打开怪物手册\nC：打开技能树\nV：打开商店\n空格：原地推进时间", true],
			["快捷键", "123：使用对应的消耗道具\n4：原地推进时间(同空格)\n5：读自动存档\n6：取消读取自动存档", true],
		],
		// 四
		[
			["版本信息", "目前版本为1.0公测版，黑衣魔王之后将不会有新怪物，发现bug或想要交流游戏内容可在评论区留言，也可加群121359435讨论", true],
		]
	];
	var imported = 0

	const animate_time = 50;
	const per_page = 8; // 左侧栏目一页数量
	const pixels = core.__PIXELS__;
	/**
	 *
	 * background_image:
	 * 若填入null，则以楼层背景作为页面背景
	 * 填入文件名，则以图片文件作为背景 例："bg.jpg"
	 * 填入其他则以对应图块作为背景 例："star"
	 *
	 * */
	const background_image = "bg2.png";

	// 栏目的显示/隐藏是否跨存档存储
	const useGlobal = false;

	// 初始化栏目可见性，参数为默认可见性值
	function initData(defaultValue) {
		const data = useGlobal ?
			core.getGlobal("introduce_data", []) :
			core.getFlag("introduce_data", []);
		for (let i = 0; i < introduce_detail.length; i++) {
			if (data[i] === void 0) data[i] = [];
			for (let j = 0; j < introduce_detail[i].length; j++) {
				const value =
					defaultValue === void 0 ? introduce_detail[i][j][2] : defaultValue;
				if (data[i][j] === void 0) data[i][j] = value;
				introduce_detail[i][j][2] = data[i][j];
			}
		}
		useGlobal
			?
			core.setGlobal("introduce_data", data) :
			core.setFlag("introduce_data", data);
	}

	// 设置index1栏index2项的可见与否
	this.setIntroduce = function (index1, index2, avilable) {
		if (core.isReplaying()) return;

		const data = useGlobal ?
			core.getGlobal("introduce_data", []) :
			core.getFlag("introduce_data", []);

		if (avilable === void 0) avilable = true;
		if (introduce_detail[index1] && introduce_detail[index1][index2]) {
			introduce_detail[index1][index2][2] = avilable;
			data[index1][index2] = avilable;
			useGlobal
				?
				core.setGlobal("introduce_data", data) :
				core.setFlag("introduce_data", data);
		}
	};

	// 初始化ui页面
	this.showIntroduce = function () {
		if (core.isReplaying()) {
			core.doAction();
			return;
		}

		initData();

		const ui_introduce = core.createCanvas("introduce", 0, 0, pixels, pixels, 141);
		const ui_introduce_flow = core.createCanvas("introduce_flow", 0, 0, pixels, pixels, 143);
		const ui_introduce_button = core.createCanvas("introduce_button", 0, 0, pixels, pixels, 142);

		// 解析背景图片
		core.setAlpha("introduce", 1.0);
		if (background_image) {
			if (background_image.indexOf(".") !== -1)
				core.drawImage("introduce", background_image, 0, 0);
			else {
				for (let i = 0; i < pixels; i += 32)
					for (let j = 0; j < pixels; j += 32)
						core.drawIcon("introduce", background_image, i, j, 32, 32);
			}
		} else {
			core.setFillStyle("introduce", core.material.groundPattern);
		}

		/*core.setAlpha("introduce", 0.6);
		core.setFillStyle("introduce", "#000000");
		core.fillRect("introduce", 0, 0, pixels, pixels);

		core.setAlpha("introduce", 1.0);*/

		// 设置ui中不变部分
		core.drawLine(
			"introduce",
			pixels - 20 - 15,
			20,
			pixels - 20,
			20 + 15,
			"#FFFFFF",
			5
		);
		core.drawLine(
			"introduce",
			pixels - 20,
			20,
			pixels - 20 - 15,
			20 + 15,
			"#FFFFFF",
			5
		);
		core.drawLine("introduce", 0, 60, pixels, 60, "orange", 3);
		core.drawLine("introduce", 0, 100, pixels, 100, "orange", 3);
		core.drawLine("introduce", 100, 100, 100, pixels, "orange", 3);

		// 绘制大标题
		core.fillText("introduce", "资料馆", 150, 40, "white", "30px Verdana");

		core.drawLine("introduce_flow", 10, 60, 10, 100, "orange", 3);
		core.drawLine("introduce_flow", 85, 60, 85, 100, "orange", 3);

		// 裁剪按钮层可见区域
		ui_introduce_button.beginPath();
		ui_introduce_button.moveTo(0, 60);
		ui_introduce_button.lineTo(pixels, 60);
		ui_introduce_button.lineTo(pixels, 100);
		ui_introduce_button.lineTo(100, 100);
		ui_introduce_button.lineTo(100, pixels);
		ui_introduce_button.lineTo(0, pixels);
		ui_introduce_button.lineTo(0, 60);
		ui_introduce.stroke();
		ui_introduce_button.clip();
		core.setAlpha("introduce_button", 1.0);

		for (const top of introduce_top) {
			core.fillText(
				"introduce_button",
				top[0],
				top[1][0],
				top[1][3],
				"#FFFFFF",
				"15px Verdana"
			);
		}

		// 记录上次访问位置或初始化
		core.setFlag(
			"introduce_position",
			core.getFlag("introduce_position", [0, 0])
		);
		core.setFlag("ui_introduce_open", true);

		const position = core.getFlag("introduce_position");
		flow_top(-1, position[0]);
		changeTo(position[0]);
		changeDetail(position[0], position[1]);
	};

	// 转变到顶栏第index项
	function changeTo(_index = 0) {
		core.setAlpha("introduce_flow", 1);
		core.setFillStyle("introduce_flow", "#000000");

		core.setAlpha("introduce_flow", 1);
		core.setFillStyle("introduce_flow", "orange");
		core.clearMap("introduce_flow", 0, 60, pixels, 40);
		core.clearMap("introduce_button", 0, 100, pixels, pixels);

		let start_x = 20 - _index * 100,
			start_y = 100,
			i = 0;
		core.setFlag("introduce_position", [_index, 0]);
		core.drawUIEventSelector(
			1,
			"winskin.png",
			introduce_top[_index][1][0] - 8,
			65,
			72,
			30,
			142
		);
		changeDetail(_index, 0, true);
	}

	// 转变到顶栏index1的侧边栏index2项，默认在右侧显示标题
	function changeDetail(_index1, _index2 = 0, showTitle = true) {
		core.setAlpha("introduce_flow", 1);
		core.setFillStyle("introduce_flow", "#000000");
		core.clearMap("introduce_flow", 100, 100, pixels, pixels);

		core.clearMap("introduce_button", 0, pixels - 30, 100, 30);
		core.fillText(
			"introduce_button",
			"◀ " +
			Math.ceil((_index2 + 1) / per_page) +
			"/" +
			Math.ceil((introduce_detail[_index1] || []).length / per_page) +
			" ▶",
			15,
			pixels - 10,
			"#FFFFFF",
			"15px Verdana"
		);

		if (
			_index2 < 0 ||
			!introduce_detail[_index1] ||
			introduce_detail[_index1].length < 1
		)
			return;
		core.setFlag("introduce_position", [_index1, _index2]);

		// 绘制当前页左侧菜单栏
		const page = Math.ceil((_index2 + 1) / per_page);
		core.clearMap("introduce_button", 0, 100, 100, pixels - 100 - 30);
		for (
			let i = 0; i <
			Math.min(
				per_page,
				introduce_detail[_index1].length - (page - 1) * per_page
			); i++
		) {
			const v = introduce_detail[_index1][i + (page - 1) * per_page];
			if (!v) continue;
			const ttLength = core.calWidth(
				"introduce_button",
				v[2] ? v[0] : "？？？",
				"15px Verdana"
			);
			if (!v[2])
				core.fillText(
					"introduce_button",
					"？？？",
					10,
					100 + i * 35 + 25,
					"gray",
					"15px Verdana",
					80
				);
			else
				core.fillText(
					"introduce_button",
					v[0],
					10,
					100 + i * 35 + 25,
					"#FFFFFF",
					"15px Verdana",
					80
				);
		}

		const detail = introduce_detail[_index1][_index2];
		let start_x = 100 + 10,
			start_y = 100 + 30;
		// 绘制标题
		if (!detail[2]) {
			let x_left =
				start_x + 96;
			core.fillText(
				"introduce_flow",
				"未解锁",
				x_left,
				start_y,
				"gray",
				"25px Verdana"
			);
			return;
		}
		if (showTitle) {
			let x_left =
				start_x + 96;
			core.fillText(
				"introduce_flow",
				detail[0],
				x_left,
				start_y,
				"#FFFFFF",
				"25px Verdana"
			);
			start_y += 30;
		}

		// 绘制详细内容 + 图标
		core.drawTextContent("introduce_flow", detail[1], {
			left: start_x,
			top: start_y,
			color: "#FFFFFF",
			fontSize: 15,
			font: "Verdana",
			maxWidth: pixels - start_x - 10,
		});
		if (detail.length > 3) {
			// 图标框
			// 			core.drawLine("introduce", pixels - 20 - 32, 100 + 30, pixels - 20, 100 + 30, "#FFFFFF", 3)
			// 			core.drawLine("introduce", pixels - 20 - 32, 100 + 30, pixels - 20 - 32, 100 + 30 + 32, "#FFFFFF", 3)
			// 			core.drawLine("introduce", pixels - 20 - 32, 100 + 30 + 32, pixels - 20, 100 + 30 + 32, "#FFFFFF", 3)
			// 			core.drawLine("introduce", pixels - 20, 100 + 30, pixels - 20, 100 + 30 + 32, "#FFFFFF", 3)
			let iconSize = [32, 32];
			if (detail.length > 4) iconSize = detail[4];
			core.drawIcon(
				"introduce_flow",
				detail[3],
				pixels - 20 - iconSize[0],
				100 + 30,
				iconSize[0],
				iconSize[1]
			);
		}
		core.drawUIEventSelector(2, "winskin.png", 5, 100 + (_index2 % per_page) * 35, 90, 35, 142);
	}

	// 顶栏转变所用动画
	function flow_top(now, to = 0) {
		/*if (now > introduce_top.length - 1 || to > introduce_top.length - 1)
			return;

		const temp = now;
		if (now < 0) now = 0;
		const nowTop = introduce_top[now][1],
			toTop = introduce_top[to][1];
		const position = core.getFlag("introduce_position", [0, 0]);

		let i = 0;
		const itv = setInterval(() => {
			core.clearMap("introduce_button", 0, 100, 100, pixels);
			let start_x = 10 - now * 100 - (((to - now) * 100) / animate_time) * i,
				start_y = 100,
				j = 0;

			// 绘制左侧栏小标题内容
			for (let temp = 0; temp < introduce_detail.length; temp++) {
				j = 0;
				if (introduce_detail[temp]) {
					for (
						let ii = 0; ii < introduce_detail[temp].length && ii < per_page; ii++
					) {
						let v = introduce_detail[temp][ii];
						if (temp == position[0]) {
							const page = Math.floor((position[1] + 1) / per_page);
							if (ii + page * per_page > introduce_detail[temp].length - 1)
								break;
							v = introduce_detail[temp][ii + page * per_page];
						}
						const ttLength = core.calWidth(
							"introduce_button",
							v[2] ? v[0] : "？？？",
							"15px Verdana"
						);
						if (!v[2])
							core.fillText(
								"introduce_button",
								"？？？",
								start_x + (80 - ttLength) / 2,
								start_y + j * 40 + 30,
								"gray",
								"15px Verdana"
							);
						else
							core.fillText(
								"introduce_button",
								v[0],
								start_x + (80 - ttLength) / 2,
								start_y + j * 40 + 30,
								"#FFFFFF",
								"15px Verdana"
							);
						j++;
					}
				}
				start_x += 100;
			}
			core.fillText(
				"introduce_button",
				"◀ " +
				Math.ceil((position[1] + 1) / per_page) +
				"/" +
				Math.ceil((introduce_detail[to] || []).length / per_page) +
				" ▶",
				15,
				pixels - 10,
				"#FFFFFF",
				"15px Verdana"
			);

			// 绘制选择框
			core.drawUIEventSelector(
				1,
				"winskin.png",
				nowTop[0] - 8 + ((toTop[0] - nowTop[0]) / animate_time) * i,
				65,
				72,
				30,
				142
			);

			i++;
			if (i > animate_time) {
				clearInterval(itv);
				if (temp < 0) flow_left(0, position[1]);
				else
					flow_left(
						position[1],
						introduce_detail[to] && introduce_detail[to].length > 0 ? 0 : -1
					);
			}
		}, 100 / animate_time);*/
	}

	// 侧边栏转变所用动画
	function flow_left(now, to = 0) {
		// to为-1时则隐藏选择框
		// 		if (now == to) return;
		/*if (!introduce_detail[core.getFlag("introduce_position", [0, 0])[0]])
			to = -1;
		// 对于非首次打开页面的初始化
		if (!core.getFlag("ui_introduce_open", false)) {
			to = now;
			now = 0;
		}
		if (to > per_page - 1) to %= per_page;
		if (now > per_page - 1) now %= per_page;

		const nowLeft = [100 + now * 40, 100 + (now + 1) * 40],
			toLeft = [100 + to * 40, 100 + (to + 1) * 40];
		const position = core.getFlag("introduce_position", [0, 0]);

		let i = 0;
		const itv = setInterval(() => {
			// 绘制左侧选择框
			const _y = Math.max(
				nowLeft[0] + ((toLeft[0] - nowLeft[0]) / animate_time) * i + 5,
				100
			);
			const _h = Math.min(
				nowLeft[1] + ((toLeft[1] - nowLeft[1]) / animate_time) * i - 100,
				40
			);
			core.drawUIEventSelector(2, "winskin.png", 5, _y, 90, _h, 142);

			i++;
			if (_h <= 5) {
				core.clearUIEventSelector(2);
				clearInterval(itv);
			}
			if (i > animate_time) {
				clearInterval(itv);
			}
		}, 50 / animate_time);*/
	}

	function close() {}

	// 无条件拒绝的回调
	function action_reject(...args) {
		if (!core.getFlag("ui_introduce_open", false)) return false;
		return true;
	}

	// 开启界面时按下键盘的回调
	function pressKey(e) {
		if (!core.getFlag("ui_introduce_open", false)) return false;

		let position = core.getFlag("introduce_position", [0, 0]);
		const leftLength = (introduce_detail[position[0]] || []).length;
		const maxLength = Math.min(leftLength, per_page);

		switch (e.keyCode) {
			// 顶栏跳转
		case 37:
			flow_top(
				position[0],
				(position[0] + introduce_top.length - 1) % introduce_top.length
			);
			changeTo(
				(position[0] + introduce_top.length - 1) % introduce_top.length
			);
			break;
		case 39:
			flow_top(position[0], (position[0] + 1) % introduce_top.length);
			changeTo((position[0] + 1) % introduce_top.length);
			break;
			// 侧边栏跳转
		case 38:
			if (maxLength == 0) {
				flow_left(0, -1);
				changeDetail(position[0], -1);
			} else {
				flow_left(
					position[1],
					((position[1] + leftLength - 1) % leftLength) % maxLength
				);
				changeDetail(
					position[0],
					(position[1] + leftLength - 1) % leftLength
				);
			}
			break;
		case 40:
			if (maxLength == 0) {
				flow_left(0, -1);
				changeDetail(position[0], -1);
			} else {
				flow_left(
					position[1],
					((position[1] + 1) % leftLength) % maxLength
				);
				changeDetail(position[0], (position[1] + 1) % leftLength);
			}
			break;
		}
		return true;
	}

	// 开启界面时点击鼠标的回调
	function clickIntroduce(x, y, px, py) {
		if (!core.getFlag("ui_introduce_open", false)) return false;

		// 关闭UI
		if (px > pixels - 20 - 15 && px < pixels && py > 0 && py < 20 + 15) {
			core.deleteCanvas((name) => name.startsWith("introduce"));
			core.clearUIEventSelector([1, 2]);
			core.setFlag("ui_introduce_open", false);
			core.doAction();
			return true;
		}

		// 顶栏跳转
		let position = core.getFlag("introduce_position", [0, 0]);
		for (let i = 0; i < introduce_top.length; i++) {
			if (
				px > introduce_top[i][1][0] &&
				px < introduce_top[i][1][2] &&
				py > introduce_top[i][1][1] &&
				py < introduce_top[i][1][3] + 10
			) {
				flow_top(position[0], i);
				changeTo(i);
				return true;
			}
		}

		// 侧边栏跳转
		if (
			py > 100 &&
			py < pixels - 35 &&
			px > 0 &&
			px < 100 &&
			introduce_detail[position[0]]
		) {
			const page = Math.floor(position[1] / per_page);
			for (
				let i = 0; i < introduce_detail[position[0]].length - page * per_page; i++
			) {
				if (py < 100 + (i + 1) * 35) {
					const page = Math.floor(position[1] / per_page);
					flow_left(position[1], i + page * per_page);
					changeDetail(position[0], i + page * per_page);
					return true;
				}
			}
		}

		// 换页
		if (px > 0 && px < 100 && py > pixels - 30 && py < pixels) {
			const page = Math.floor(position[1] / per_page);
			const pageMax = Math.max(
				Math.ceil((introduce_detail[position[0]] || []).length / per_page),
				1
			);
			if (pageMax < 2) return true;
			if (px < 50) {
				flow_left(position[1], 0);
				changeDetail(
					position[0],
					0 + ((page + pageMax - 1) % pageMax) * per_page
				);
			} else {
				flow_left(position[1], 0);
				changeDetail(position[0], 0 + ((page + 1) % pageMax) * per_page);
			}
		}

		return true;
	}

	// 在actions.js中注册自绘界面行为
	core.registerAction("onkeyUp", "introduce", pressKey, 50);
	core.registerAction("onkeyDown", "introduce", action_reject, 50);
	core.registerAction("ondown", "introduce", clickIntroduce, 50);
}
}