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

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

	// 可以写一些直接执行的代码
	// 在这里写的代码将会在【资源加载前】被执行，此时图片等资源尚未被加载。
	// 请勿在这里对包括bgm，图片等资源进行操作。


////// “即捡即用类”道具的使用效果 //////
items.prototype.getItemEffect = function (itemId, itemNum) {
    var itemCls = core.material.items[itemId].cls;
    // 消耗品
    if (itemCls === 'items') {
        var ratio = parseInt(core.status.thisMap.item_ratio) || 1;
        var curr_hp = core.status.hero.hp;
        if (itemId in this.itemEffect) {
            try {
                eval(this.itemEffect[itemId]);
            }
            catch (e) {
                main.log(e);
            }
		}
		core.status.hero.hp = Math.floor(core.status.hero.hp);
        core.status.hero.statistics.hp += core.status.hero.hp - curr_hp;
    }
    else {
        core.addItem(itemId, itemNum);
    }
}

control.prototype._updateStatusBar_setToolboxIcon = function () {
    if (core.isReplaying()) {
        core.statusBar.image.book.src = core.status.replay.pausing ? core.statusBar.icons.play.src : core.statusBar.icons.pause.src;
        core.statusBar.image.book.style.opacity = 1;
        core.statusBar.image.fly.src = core.statusBar.icons.stop.src;
        core.statusBar.image.fly.style.opacity = 1;
        core.statusBar.image.toolbox.src = core.statusBar.icons.rewind.src;
        core.statusBar.image.keyboard.src = core.statusBar.icons.book.src;
        core.statusBar.image.shop.src = core.statusBar.icons.floor.src;
        core.statusBar.image.save.src = core.statusBar.icons.speedDown.src;
        core.statusBar.image.load.src = core.statusBar.icons.speedUp.src;
        core.statusBar.image.settings.src = core.statusBar.icons.save.src;
    }
    else {
        core.statusBar.image.book.src = core.statusBar.icons.book.src;
        core.statusBar.image.book.style.opacity = core.hasItem('book') ? 1 : 0.3;
        if (!core.flags.equipboxButton) {
            core.statusBar.image.fly.src = core.statusBar.icons.fly.src;
            core.statusBar.image.fly.style.opacity = core.hasItem('skill1') ? 1 : 0.3;
        }
        else {
            core.statusBar.image.fly.src = core.statusBar.icons.equipbox.src;
            core.statusBar.image.fly.style.opacity = 1;
        }
        core.statusBar.image.toolbox.src = core.statusBar.icons.toolbox.src;
        core.statusBar.image.keyboard.src = core.statusBar.icons.keyboard.src;
        core.statusBar.image.shop.src = core.statusBar.icons.shop.src;
        core.statusBar.image.save.src = core.statusBar.icons.save.src;
        core.statusBar.image.load.src = core.statusBar.icons.load.src;
        core.statusBar.image.settings.src = core.statusBar.icons.settings.src;
    }
}
////// 点击状态栏中的楼层传送器/装备栏时 //////
main.statusBar.image.fly.onclick = function (e) {
    e.stopPropagation();

    // 播放录像时
    if (core.isReplaying()) {
        core.stopReplay();
        return;
    }

    // 绘图模式
    if (main.core.isPlaying() && (core.status.event||{}).id=='paint') {
        core.actions.setPaintMode('erase');
        return;
    }

    if (main.core.isPlaying()) {
		if(core.status && core.status.lockControl){
			return;
		}
		if(core.hasItem("skill1")){
			core.useItem("skill1");
		}
    }
}

	this._afterLoadResources = function () {
		// 本函数将在所有资源加载完毕后，游戏开启前被执行
		// 可以在这个函数里面对资源进行一些操作，比如切分图片等。

		// 这是一个将assets.png拆分成若干个32x32像素的小图片并保存的样例。
		// var arr = core.splitImage("assets.png", 32, 32);
		// for (var i = 0; i < arr.length; i++) {
		//     core.material.images.images["asset"+i+".png"] = arr[i];
		// }

	}

	//// 获取关卡通关人数信息 主要是通过胜利结局确定属于哪个关卡 如果是多结局的话 需要分别判断
	this.getMissionNum = function(name){
		var formData = new FormData();
		var response;
		core.setFlag('missionInfo',{});
		var missionInfo = core.getFlag('missionInfo')
		formData.append('type', 'tower');
		formData.append('name', name);
		core.http("POST", "/games/info.php", formData, function (data) {
			response = JSON.parse(data) || {};
			(response.content||"").split('\n').forEach(
				function(it){
					var d = it.indexOf('：');
					if(d>0){
						missionInfo[it.substr(0,d)]=parseInt(it.substr(d).match(/[1-9][0-9]*/g)[0]);
					}
			});
		}, function (e) {
			//core.drawText("出错啦 错误原因："+e);
		})
	}


	///////////// 对勇士移动的修改 /////////////
	// 挪走战前自动存档
	/*
	core.events.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.drawTip("你打不过此怪物！");
		//	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, callback);
	}
	*/
	// 判断块是否为敌人
	var isBlockEnemy = function(blk){
		if(blk && blk.block.event && blk.block.event.cls == 'enemys'){
			return true;
		}
		return false;
	}
	// 移动前自动存档
	var orginMoveHero = core.control.moveHero;
	core.control.moveHero = function(direction, callback){
		/* 不知道为啥出问题了 索性去掉
		if (core.status.heroMoving){
			if(!direction)
			direction = core.getHeroLoc('direction');
		var x = core.getHeroLoc('x');
		var y = core.getHeroLoc('y');
		var blk = core.getBlock(x + core.utils.scan[direction].x, y + core.utils.scan[direction].y);
			if(isBlockEnemy(blk)){
				if (!core.isset(core.status.event.id) && core.canBattle(blk.block.event.id,x,y)) // 打怪走路之前存档
				{
					core.autosave(false);
				}
			}
		}*/
		orginMoveHero.call(core.control,direction, callback);
	}
	

	// 判断移动
	var orginCanMoveHero = core.maps.canMoveHero
	core.maps.canMoveHero = function(x,y,direction,floorId){
		if (!core.isset(x)) x=core.getHeroLoc('x');
		if (!core.isset(y)) y=core.getHeroLoc('y');
		if (!core.isset(direction)) direction=core.getHeroLoc('direction');
		floorId = floorId || core.status.floorId;
		if (!core.isset(floorId)) return false;

		// 如果存在异种颜色且当前处于颜色状态则不可通行
		var dx = core.utils.scan[direction].x,
			dy = core.utils.scan[direction].y;
		var blk = core.getBlock(x+dx,y+dy,floorId);
		var color = (core.getFlag('floorRoute',{})[floorId] || {})[(dx+x)+','+(y+dy)];
		if(isBlockEnemy(blk) && !core.enemys.canBattle(blk.block.event.id, x+dx, y+dy)){
			return false;
		}

		if(core.getFlag('color',null)!=null && color && core.getFlag('color',null)!=color){
			return false;
		}
		return orginCanMoveHero.call(core.maps,x,y,direction,floorId);
	}

	// 绕过敌人
	core.maps._automaticRoute_deepAdd = function (x, y) {
		// 判定每个可通行点的损耗值，越高越应该绕路
		var deepAdd = 1;
		var block = core.getBlock(x,y);
		if (block != null){
			var id = block.block.event.id;
			var cls  =block.block.event.cls;
			// 绕过亮灯
			if (id == "light") deepAdd += 100;
			// 绕过路障
			if (id.endsWith("Net")) deepAdd += 100;
			if (cls == 'enemys' || cls=='enemy48') deepAdd += 200;
			// 绕过血瓶
			if (!core.flags.potionWhileRouting && id.endsWith("Potion")) deepAdd += 100;
			// 绕过传送点
			// if (block.block.event.trigger == 'changeFloor') deepAdd+=10;
		}
		// 绕过存在伤害的地方
		deepAdd += (core.status.checkBlock.damage[x+","+y]||0) * 100;
		// 绕过捕捉
		if (core.status.checkBlock.ambush[x+","+y]) deepAdd += 1000;
		return deepAdd;
	}
/*
	core.maps._canMoveHero_checkPoint = function (x, y, direction, floorId, extraData) {
		if(isBlockEnemy(core.getBlock(x,y,floorId))){
			return false;
		}
    // 1. 检查该点 cannotMove
    if (core.inArray((core.floors[floorId].cannotMove || {})[x + "," + y], direction))
        return false;

    var nx = x + core.utils.scan[direction].x, ny = y + core.utils.scan[direction].y;
    if (nx < 0 || ny < 0 || nx >= core.floors[floorId].width || ny >= core.floors[floorId].height)
        return false;

    // 2. 检查该点素材的 cannotOut 和下一个点的 cannotIn
    if (this._canMoveHero_checkCannotInOut([
            extraData.bgArray[y][x], extraData.fgArray[y][x], extraData.eventArray[y][x]
        ], "cannotOut", direction))
        return false;
    if (this._canMoveHero_checkCannotInOut([
            extraData.bgArray[ny][nx], extraData.fgArray[ny][nx], extraData.eventArray[ny][nx]
        ], "cannotIn", direction))
        return false;

    // 3. 检查是否能进将死的领域
    if (floorId == core.status.floorId
        && core.status.hero.hp <= (core.status.checkBlock.damage[nx + "," + ny]||0)
        && !core.flags.canGoDeadZone && extraData.eventArray[ny][nx] == 0)
        return false;

    return true;
}
*/
	// TODO:可以设置敌人不可通行
	maps.prototype._automaticRoute_bfs = function (startX, startY, destX, destY) {
		var route = {}, canMoveArray = this.generateMovableArray();
		// 使用优先队列
		var queue = new PriorityQueue({comparator: function (a,b) { return a.depth - b.depth; }});
		route[startX + "," + startY] = '';
		queue.queue({depth: 0, x: startX, y: startY});
		while (queue.length!=0) {
			var curr = queue.dequeue(), deep = curr.depth, nowX = curr.x, nowY = curr.y;
			for (var direction in core.utils.scan) {
				if (!core.inArray(canMoveArray[nowX][nowY], direction)) continue;
				var nx = nowX + core.utils.scan[direction].x;
				var ny = nowY + core.utils.scan[direction].y;
				if (nx<0 || nx>=core.bigmap.width || ny<0 || ny>=core.bigmap.height || route[nx+","+ny] != null) continue;
				// 重点
				if (nx == destX && ny == destY) {
					route[nx+","+ny] = direction;
					break;
				}
				// 不可通行
				if (core.noPass(nx, ny)) continue;
				route[nx+","+ny] = direction;
				queue.queue({depth: deep + this._automaticRoute_deepAdd(nx, ny), x: nx, y: ny});
			}
			if (route[destX+","+destY] != null) break;
		}
		return route;
	}
/*
	// 判断通行性
	core.maps.noPass = function (x, y, floorId) {
		var block = core.getBlock(x,y,floorId);
		// 如果存在异种颜色且当前处于颜色状态则不可通行
		var color = (core.getFlag('floorRoute',{})[floorId] || {})[x+','+y];
		if(core.getFlag('color',null)!=null && color){
			if(core.getHeroLoc('x')==x && core.getHeroLoc('y')==y){}
			else return false;
		}
		if(isBlockEnemy(block)){
			if (!core.enemys.canBattle(block.block.event.id, x, y)) {// && !force && !core.status.event.id
				//core.drawTip("你打不过此怪物！");
				return true;
			}
			return false;
		}
		if (block==null) return false;
		return core.isset(block.block.event.noPass) && block.block.event.noPass;
	}

*/
	////////////// 染色相关 ////////////////
	////  每移动一步 是否添加生成颜色的判定
	this.moveCreateCheck = function(x,y,floorId){
		floorId = floorId || core.status.floorId;
		var routeLog = core.getFlag('floorRoute',{});
		var floorLog = routeLog[floorId] || {};
		var index = x+','+y;
		var color = core.getFlag('color',null);
		if(color!=null){//如果染了颜色 对当前地板进行染色
			floorLog[index] = color;
		}
		routeLog[floorId] = floorLog;
		core.setFlag('floorRoute', routeLog);
		if(color!=null){// !只重绘背景层 可以防止闪烁
			core.maps.drawBg(core.status.floorId, core.getContextByName('bg'));
			drawColorOnMap(core.status.floorId);
		}
	}

	// RGP转HEX颜色
	this.colorRGB2Hex = function(r,g,b) {
		var hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
		return hex;
	 }
	 //
	 this.colorHex2RGB = function(hex){
		return [parseInt("0x" + hex.slice(1, 3)) ,parseInt("0x" + hex.slice(3, 5)),parseInt("0x" + hex.slice(5, 7))]
	 }
	// 获取敌人颜色
	this.getEnemyColor = function(x,y,rgb){
		var w = 32,h=32;
		var ctx = core.getContextByName('event');
		var imgData = ctx.getImageData(x*32,y*32,w,h);
		var r=0,g=0,b=0,ct=0;
		for(var ox=0;ox<w;ox+=1){
			for(var oy=0;oy<h;oy+=1){
				var i = (oy*imgData.width + ox)*4;
				if(imgData.data[i+3] >= 128){
					ct += 1;
					r += imgData.data[i];
					g += imgData.data[i+1];
					b += imgData.data[i+2];
				}
			}
		}
		if(rgb)return [parseInt(r/ct),parseInt(g/ct),parseInt(b/ct)];
		return core.colorRGB2Hex(parseInt(r/ct),parseInt(g/ct),parseInt(b/ct));
	}

	//// 战后染色判定 | 在击败敌人前进行捕捉 以当前敌人的平均色作为颜色
 	this.paintColor = function(enemyId, x,y){
		var curEnemy = core.getFlag('curEnemy',null);
		if(curEnemy){//消除当前颜色 消除前先染色 TODO: 多个同色敌人？——此时只能打同色敌人 消除
			core.moveCreateCheck(x,y);
			core.setFlag('color',null);
			core.setFlag('curEnemy',null);
		}else{ //设置当前颜色 并且对当前块染色
			core.setFlag('color',core.getEnemyColor(x,y));
			core.setFlag('curEnemy',enemyId);
			core.moveCreateCheck(x,y);
		}
	}

	

	// 染色技能
	this.skillColor = function(){
		var colors = core.getFlag('colors');
		if(core.getFlag('color',null)==null){
			var chos = [];
			for(var i in colors){
				var c = colors[i];
				if(c)
				chos.push({"text": "■■■■ "+i+" ■■■■", "color": core.colorHex2RGB(c).concat(1), "action": [
					{"type": "setValue", "name": "flag:color", "value": "\'"+c+"\'"},
				  ]});
			}
			chos.push({"text": "退出", "action": []});
			var todo = [
				{"type": "choices", "text": "选择一种颜色，每种颜色只能绘制对应的数字:", "choices": chos},
			  ];
			  core.insertAction(todo);
		}else{
			core.drawTip("染色关闭！");
			//check
			core.setFlag('color',null);
			var res = core.missionCondition();
			if(res>0){
				colors[res]=null;
				core.insertAction([
					{"type": "insert", "name": "数字", "args": [res]},
				  ]);
			}
			core.drawMap();
		}
	}

	//// 地图颜色绘制
	function drawColorOnMap(floorId, tctx){
		if(!floorId)return ;
		var colors = core.getFlag('floorRoute',{})[floorId] || {};
		var ctx = tctx || core.getContextByName('bg');
		ctx.globalAlpha = 0.5;
		for(var index in colors){
			var pos = index.split(',');
			var x = parseInt(pos[0]), y = parseInt(pos[1]);
			var color = colors[index];
			ctx.fillStyle = color;
			ctx.fillRect(x*32,y*32,32,32);
		}
		ctx.globalAlpha = 1.0;
	}
	// 缩略图重绘
	maps.prototype._drawThumbnail_realDrawTempCanvas = function (floorId, blocks, options, tempCanvas) {
		// 缩略图：背景
		this.drawBg(floorId, tempCanvas);
		drawColorOnMap(floorId, tempCanvas);
		// 缩略图：事件
		this.drawEvents(floorId, blocks, tempCanvas);
		// 缩略图：勇士
		if (options.heroLoc) {
			options.heroIcon = options.heroIcon || core.getFlag("heroIcon", "hero.png");
			options.heroIcon = core.getMappedName(options.heroIcon);
			var icon = core.material.icons.hero[options.heroLoc.direction];
			var height = core.material.images.images[options.heroIcon].height / 4;
			tempCanvas.drawImage(core.material.images.images[options.heroIcon], icon.stop * 32, icon.loc * height, 32, height,
				32 * options.heroLoc.x, 32 * options.heroLoc.y + 32 - height, 32, height);
		}
		// 缩略图：前景
		this.drawFg(floorId, tempCanvas);
		// 缩略图：显伤
		if (options.damage)
			core.control.updateDamage(floorId, tempCanvas);
	}
	// 重写原绘图函数
	var originDrawMap = core.maps.drawMap;
	core.maps.drawMap = function (floorId, callback) {
		floorId = floorId || core.status.floorId;
		originDrawMap.call(core.maps,floorId,null);
		drawColorOnMap(floorId);
		if(callback){
			callback();
		}
	}

	//  开始新关卡
	this.startMission = function (areaName){
	}

	/* 通关条件 : 1 铺满地图 2 杀光敌人 || 重写此函数 改变通关条件 或者使用con1 con2控制通关条件
	this.missionCondition = function(con1,con2){
		var blocks = core.status.thisMap.blocks;
		var colorLog = 	core.getFlag('floorRoute', {})[core.status.floorId] || {};
		blocks = blocks.filter(function(blk){return !colorLog[blk.x+','+blk]});
		var fillNum = blocks.length + Object.keys(colorLog).length;//填充数目
		var enemyNum = core.status.thisMap.blocks.filter(function(blk){return blk.event.cls == 'enemys' || blk.event.cls == 'enemy48'}).length;
		ret = false;
		con1 = con1 ? fillNum==core.__SIZE__*core.__SIZE__ :true;
		con2 = con2 ? enemyNum==0 : true;
		return con1 && con2;
	}
	*/

	//1 对1~9进行指纹记录
	var fingerPrint = {};
	function calPosMD(center, pos){
		return (pos[0]-center[0])*100 + pos[1]-center[1];
	}
	function logFingerPrint(){
		var map = core.floors["color"].map;
		for(var i = 301;i<310;i++){
			var center = null;
			var ct = 0;
			var logs = [];
			for(var y = 0;y<core.__SIZE__;y++){
				for(var x=0;x<core.__SIZE__;x++){
					if(map[y][x]==i){
						if(center){
							logs.push(calPosMD(center, [x,y]));
						}else{
							center = [x,y];
						}
						ct++;
					}
				}
			}
			fingerPrint[i-300] = logs;
		}
	};
	logFingerPrint();
	// 消除条件： 数字1~9
	this.missionCondition = function(){
		var blocks = core.status.thisMap.blocks;
		var colorLog = core.getFlag('floorRoute', {})[core.status.floorId] || {};
		//2 检查当前颜色是否符合某个数字
		var colors = core.getFlag('colors');
		var temp = {};
		for(var idx in colorLog){
			var clr = colorLog[idx];
			if(!temp[clr])temp[clr] = [];
			var pos = idx.split(',');
			pos[0] = parseInt(pos[0]);
			pos[1] = parseInt(pos[1]);
			temp[clr].push(pos);
		}
		var delList = {};
		for(var c in colors){
			var clr = colors[c];
			if(!clr)continue;
			var logprint = fingerPrint[c];
			if(temp[clr]){
				if(temp[clr].length!=logprint.length+1){
					delList[clr]=true;
					continue;
				}
				temp[clr] = temp[clr].sort(function(a,b){return (a[0]-b[0])*100+(a[1]-b[1])});
				var setLog = {};
				for(var i = 1;i<temp[clr].length;i++){
					var v = calPosMD(temp[clr][0],temp[clr][i]);
					var idx = logprint.indexOf(v);
					if(idx>=0){
						setLog[idx]=1;
					}else break;
				}
				if(Object.keys(setLog).length==logprint.length)
					return c;
				else{//删除
					delList[clr]=true;
				}
			}
		}
		console.log(delList);
		for(var l in colorLog){
			if(delList[colorLog[l]]){
				delete colorLog[l];
			}
		}
		core.getFlag('floorRoute', {})[core.status.floorId] = colorLog;
		return -1;
	}

	function getEmptyPos(floorId){
		for(var y =0; y<core.__SIZE__;y++){
			for(var x =0; x<core.__SIZE__;x++){
				if(core.floors[floorId].map[y][x]==0)return[x,y];
			}	
		}
		return [6,6];
	}

	// 在千层连消关卡中 返回一个去下层的战后事件 
	this.changeToNextFloor = function(){
		var ret = [];
		var score = core.getFlag('score3',0);
		var log = core.getFlag('missionlog3',{});
		var lst = core.status.floorId.split('_');
		var curHard = lst[0].substr(2);
		var curFloor = parseInt(lst[1]);
		log[curHard] = log[curHard] || 0;
		if(log[curHard] < curFloor){
			var add = parseInt(curHard);
			add *= add;
			score += add; //首次通关加hard^2分
			ret.push('首次通关，加'+add+'分！');
			log[curHard] = curFloor;
		}
		var next = 'XT'+curHard+'_'+(curFloor+1);
		var pos = [6,6];
		if(core.floorIds.indexOf(next)>=0){
		}else if(parseInt(curHard)<=13){
			next = 'XT'+(parseInt(curHard))+'_1';
			ret.push(curHard+"x"+curHard+"全部通关！");
		}else{
			next = 'XT0';
			ret.push("13x13全部通关！");
		}
		pos = getEmptyPos(next);
		ret.push({
			"type": "changeFloor", 
			"floorId": next, 
			"loc": pos, 
			"time": 500 
		});
		core.setFlag('score3',score);
		core.setFlag('missionlog3',log);
		//core.resetMap(core.status.floorId);//重置当前地图 —— 到changeFloor里做
		return ret;
	}

	// 选择关卡
	this.toLastFloor = function(hard,next){
		var log = core.getFlag('missionlog3',{});
		log[hard] = log[hard]||0;
		next = next || log[hard]+1;
		if(next > log[hard]+1)
			return false;
		var floorId = 'XT'+hard+'_'+next;
		if(core.floorIds.indexOf(floorId)<0){
			floorId = 'XT'+hard+'_1';
		}
		var pos = getEmptyPos(floorId);
		core.changeFloor(floorId,null,{'x':pos[0],'y':pos[1]},null,function(){core.closePanel()});
		return true;
	}



	core.maps._canMoveDirectly_checkGlobal = function () {
		if(core.getFlag('color',null)!=null)return false;
		// 检查全塔是否禁止瞬间移动
		if (!core.flags.enableMoveDirectly) return false;
		// 检查该楼层是否不可瞬间移动
		if (core.status.thisMap.cannotMoveDirectly) return false;
		// flag:cannotMoveDirectly为true：不能
		if (core.hasFlag('cannotMoveDirectly')) return false;
		// 中毒状态：不能
		if (core.hasFlag('poison')) return false;
	
		return true;
	}

/*	
// 修改1： 存档只存当前地图 其他地图保持不变
core.maps.saveMap = function (floorId) {
    var maps = core.status.maps;
    if (!floorId) {
		var map = {};
		var id = core.status.floorId;
		map[id] = this.saveMap(id);
        return map;
    }
    var map = maps[floorId], floor = core.floors[floorId];
    var blocks = this._getMapArrayFromBlocks(map.blocks, floor.width, floor.height, true);
    if (main.mode == 'editor') return blocks;

    var thisFloor = this._compressFloorData(map, floor);
    var mapArr = this.compressMap(blocks, floorId);
    if (mapArr != null) thisFloor.map = mapArr;
    return thisFloor;
}
// 修改2： 读档时只读一张地图
	core.maps.loadMap = function (data, floorId) {
		if (!floorId) {
			var map = {};
			var floorIds = Object.keys(data);//[core.status.floorId];
			floorIds.forEach(function (id) {
				map[id] = core.maps.loadFloor(id, data[id]);
			})
			return map;
		}
		return this.loadFloor(floorId, data[floorId]);
	}
	
// 修改3： 每次切楼重置地图 
	var orginGetInfo = core.events._changeFloor_getInfo;
	core.events._changeFloor_getInfo = function(floorId, stair, heroLoc, time){
		if (!core.status.maps[floorId]) {
			if(!core.floors[floorId]){
				main.log("不存在的楼层：" + floorId);
				return null;
			}else{
			}
		}
		return orginGetInfo.call(core.events,floorId, stair, heroLoc, time);
	}

	//  验证能否通关？ =========== TODO ========
	this.validate = function(blks){
	}

	////重写
	var originUpdateDamage = core.control._updateDamage_damage;
	core.control._updateDamage_damage = function(floorId, ctx){
		originUpdateDamage.call(core.control, floorId, ctx);
		if(floorId=='ST'){
			core.fillBoldText(ctx, '连消史莱姆', 32*3-16, 32*3,"#FFFFDD");//绘制关卡信息
			core.fillBoldText(ctx, '破阻飞夹', 32*9, 32*3,"#FFFFDD");//绘制关卡信息
			core.fillBoldText(ctx, '疯狂千层消', 32*1, 32*6,"#FF1111");//绘制关卡信息
		}
	}
	var originHasSpecial = core.enemys.hasSpecial;
	core.enemys.hasSpecial = function(special, test){
		if(core.status.floorId.indexOf('XT')==0){
			return false;
		}
		return originHasSpecial.call(core.enemys, special, test);
	}

	core.maps._canMoveDirectly_checkGlobal = function () {
		if(core.getFlag('color',null)!=null)return false;
		// 检查全塔是否禁止瞬间移动
		if (!core.flags.enableMoveDirectly) return false;
		// 检查该楼层是否不可瞬间移动
		if (core.status.thisMap.cannotMoveDirectly) return false;
		// flag:cannotMoveDirectly为true：不能
		if (core.hasFlag('cannotMoveDirectly')) return false;
		// 中毒状态：不能
		if (core.hasFlag('poison')) return false;
	
		return true;
	}

	// 对称飞 飞到对称的位置
	core.registerSystemEvent('custom', function(data, callback){
		var x = core.__SIZE__-data.x-1;
		var y = core.__SIZE__-data.y-1;
		core.insertAction([
			{"type": "changePos", "loc": [x,y]},
		  ]);
		if(callback)callback();
	});
*/


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

"directionPannel":function(){

	///////////////////// 方向盘
	window.dljgs1 = {};

		// canvas Sprite:>>><<<<<
		// ======  UI组件？ ===========
		// 绑定显示和控制的画布 显示时绘制在UI上(不进存档)
		// 目前存在的几个问题 ：
		// 1. 非lockControl下与系统的操作冲突如何解决？比如点地图应该是点UI 但却变成了行走——必须能够自己定义操作的层级，而不是仅限于UI上，要高于默认操作的层级才能使之有效
		// 2. 组件的绘制速度优化
		// 3. 组件操作与画布的自动绑定（通过指针），而非仅仅判断操作范围
		// 4. 组件对象化（组件是一个基类 可继承）
		// 5. action命名空间污染问题
		// 6.
		window.dljgs1.componentList = [];
		// /////////////////////////////////////////////////////////////////
		/*
		 * name : 组件名称/ID，如果没有传入画布就会用这个名字建立canvas用来绘制组件
		 * rect ： 所占区域的位置：可以是rect表达 也可以是某个画布名（xy坐标将会归零需要重新制定） 或者ctx
		 * draw : 绘制方法，需要处理callback（因为绘制是有可能读数据再绘制的，组件并不知道读了什么数据）
		 * actions : 交互行为，字典格式{'ondown':[], 'XX':[]}
		 * options : 其他选项： 优先级prior 父画布的名称 rootCanvas
		 * ***/

		var componentCanvas = function (name, opt) { //opt就是数据
			this.name = name;
			opt = opt || {};
			opt.hwnd = this; //重要的控制指针
			opt.rect = opt.rect || name;
			opt.draw = opt.draw || function (name, callback) {
				callback();
			}; //默认空组件的绘制行为
			opt.actions = opt.actions || {};
			opt.prior = opt.prior || 0;
			opt.x = opt.x || 0;
			opt.y = opt.y || 0;
			opt.w = opt.w || 0;
			opt.h = opt.h || 0;
			opt.rootCanvas = opt.rootCanvas || 'dljgs1_component';
			//父画布在确定之后能否通过数据修改？理论上可以 但不推荐 因为重定位麻烦
			var ctx = null;
			var canvasName = name;
			var isEnable = false;
			var actions = opt.actions;
			var rect = opt.rect;
			var hwnd = this;

			//console.log(rect)
			if (typeof rect === "object") { //放弃rect表示法吧 ？
				opt.x = rect[0];
				opt.y = rect[1];
				opt.w = rect[2];
				opt.h = rect[3];
			} else if (typeof rect === "string") {
				canvasName = rect;
			} else {
				ctx = rect;
			}

			this.canvasName = canvasName;
			this.children = [];
			// init
			dljgs1.componentList.push(this); //每次new自动注册 不需要注册函数了

			/////////// 画布相关
			var drawOnFather = function () { //快速绘制
				var rootCtx = core.getContextByName(opt.rootCanvas);
				//rootCtx.clearRect(opt.x,opt.y,opt.w,opt.h);//是否必要？？父画布本来就会自己清空一次？
				rootCtx.drawImage(ctx.canvas, opt.x, opt.y, opt.w, opt.h);
			};
			// 刷新
			this.flush = function (callback) {
				var ctx = core.getContextByName(canvasName);
				var ct = this.children.length;
				var children = this.children;
				if (!isEnable) {
					return;
				}
				var afterDraw = function () {
					drawOnFather();
					if (callback) callback();
				};
				core.clearMap(canvasName);
				opt.draw(canvasName, function () {
					//console.log('绘制完毕');
					if (ct === 0) afterDraw();
					children.forEach(function (it) {
						it.flush(function () {
							ct -= 1;
							if (0 === ct) afterDraw(); //所有子画布画完之后再执行本画布往父画布的绘制 保证堆叠有效
						});
					});
				});
			};

		// 重建画布
		this.reConstruct = function(_x,_y,_w,_h){
			_x = _x || opt.x;
			_y = _y || opt.y;
			_w = _w || opt.w;
			_h = _h || opt.h;
			var tmp = core.getContextByName(opt.rootCanvas).canvas;
			if(_w>1.0){
				opt.w = _w;opt.h = _h;
			}else{
				opt.w = parseInt(tmp.width*_w);
				opt.h = parseInt(tmp.height*_h);
			}
			if(_x<1.0 && _x>0 && _y<1.0 && _y>0){
				//根据指定的xy比例自适应调控位置 _x_y指定画布中心相对于整个父画布的偏移 xy最终还是左上角
				var ox = tmp.width*_x, oy = tmp.height*_y;
				opt.x = parseInt(ox - opt.w/2);
				opt.y = parseInt(oy - opt.h/2);
			}else{
				opt.x = _x; opt.y = _y;
			}
			ctx = core.createCanvas(canvasName,opt.x,opt.y,opt.w,opt.h);
			this.flush();
		};

			// 重建所有画布
			this.reMapAll = function () {
				this.reConstruct();
				this.children.forEach(function (it) {
					it.reMapAll()
				});
			};

			////// 显示控制相关：

			// 局部控制：
			// 使用隐藏可以支持快速绘制（canvas处于被保存的状态 如果数据不改变可以不刷新画布直接画上去）
			this.hide = function (keepAction) {
				if (!keepAction) {
					this.disable();
				}
				core.clearMap(opt.rootCanvas);
			};
			this.show = function (noFlush) { //显示并使能 适用于隐藏后恢复
				this.enable();
				if (noFlush) {
					drawOnFather();
				} else {
					this.flush();
				}
			};
			// 整体控制：
			this.enable = function () { //使能会检查画布是否存在 但不会显示 适用于失能后的恢复
				isEnable = true;
				if (!core.getContextByName(canvasName)) {
					//console.log(canvasName+'重建画布');
					this.reMapAll();
				}
				if (opt.construct) { //如果存在构造函数 每次使能的时候调用
					opt.construct();
				}
				this.children.forEach(function (it) {
					it.enable()
				});
			};
			this.disable = function () { //disable不会隐藏只是不能按了
				isEnable = false;
				if (opt.denstruct) { //如果存在析构函数 每次失能的时候调用
					opt.denstruct();
				}
				this.children.forEach(function (it) {
					it.disable()
				});
			};

			////// 数据控制相关
			this.init = function () { //初始化 注册交互行为、画布 根据初始的相对坐标重建
				if (!core.getContextByName(canvasName)) ;
				this.reConstruct();
				//console.log('init '+canvasName);
				for (var a in actions) {
					this.procRegister(a, actions[a]);
				}
				this.children.forEach(function (it) {
					it.init()
				});
			};

			// 移除组件 ： 在很长一段时间都不会使用的情况下用 再使用需要重新注册 会将其子组件也一起移除
			this.remove = function () {
				for (var a in actions) {
					this.procRegister(a, actions[a], true);
				}
				dljgs1.componentList = dljgs1.componentList.filter(function (it) {
					return it.name !== name;
				});
			};

			this.addParent = function (comp) {
				opt.rootCanvas = comp.canvasName;
				this.parent = comp;
			};
			this.appendComponent = function (comp) { //将另一个组件放到当前组件上（可能需要重定位）
				//comp.rootCanvas = name;//光这里改是不行的
				comp.addParent(this);
				this.children.push(comp);
			};
			this.getLocBias = function () {
				var x = opt.x,
					y = opt.y;
				if (this.parent) {
					bias = this.parent.getLocBias();
					x += bias.x;
					y += bias.y;
				}
				return {
					'x': x,
					'y': y
				};
			};
			var controlCon = function () {
				if (isEnable) core.lockControl();
				else core.unLockControl();
			};

			// action交互注册相关： 存在一个问题，即判断action时无法对组件本身进行控制，只能控制“数据”
			// 这样的话需要组件和数据分离 尤其是如果数据需要存储 所以组件的控制应当交由控制接口
			// 比如要实现一个能够拖动的控制盘 就需要控制盘的位置由数据控制，而这个数据被action所改变
			// 数据存在哪里？必须是action和component都能访问的地方，可以存到一个集中管理区
			// 数据如何定义？其实就是每次初始化组件需要传入的所有参数 : opt
			// 注册的函数能否在使用过程中修改行为？暂时不支持，使用者自己控制
			this.procRegister = function (type, dofun, unReg) { //注册与撤销
				var packFun = function () { //对行为函数的基本包装：只有处于enable下才会执行
					if (isEnable) return dofun.apply(this, arguments)
				};
				var parent = this.parent; //向父类获取绝对物理坐标
				var fun = packFun;
				if (!unReg) {
					//console.log('regist : ' + type);
					if (type === 'ondown' || type === 'onclick') { //对存在像素判断的类型进行包装 默认包装ondown与onclick onmove不算在内
						fun = function (_x, _y, px, py) {
							var bias = {
								'x': 0,
								'y': 0
							};
							if (parent) {
								bias = parent.getLocBias(name)
							};
							var lx = bias.x + opt.x,
								ly = bias.y + opt.y;
							var rx = lx + opt.w,
								ry = ly + opt.h;
							if (px < rx && px > lx && py < ry && py > ly) {
								return packFun(_x, _y, px, py);
							}
						}
					}
					core.registerAction(type, name, fun, opt.prior);
				} else { //注销
					//console.log('un reg : ' + unReg + type);
					core.unregisterAction(type, name);
				}
			}
		};

		window.dljgs1.getComponent = function (name) {
			for (var i in this.componentList) {
				if (this.componentList[i].name === name) return this.componentList[i];
			}
		};
		// 初始化组件必备canvas
		window.dljgs1.initComponent = function () {
			if(main.mode=="editor")return;
			core.createCanvas('dljgs1_component', 0, 0, core.__PIXELS__, core.__PIXELS__, 145);
			dljgs1.pannel = dljgs1.pannel || new directionPannel();
			dljgs1.pannel.init();
			if(dljgs1.pannel.isOpen()){
				dljgs1.pannel.open();
			}
		};
		core.ui.deleteAllCanvas = function(){
			Object.keys(core.dymCanvas).forEach(function (name) {
					if(name.indexOf('dljgs1')==-1){
							core.dom.gameDraw.removeChild(core.dymCanvas[name].canvas);
							delete core.dymCanvas[name];
					}
			});
	}

		// 控制盘 —— 可以被拖动的一个矩形区域
		var pannel = function (rect) {
			var isdown = false;
			var down_px, down_py;
			var backHwnd;
			rect = rect || [1 / 2, 1 / 2, 1 / 4, 1 / 4];
			var backData = {
				'hwnd': null,
				'rect': rect, //画布相对位置与大小
				'prior': 101,
				'actions': {
					'ondown': function (x, y, px, py) {
						isdown = true;
						down_px = px;
						down_py = py;
						return true;
					},
					'onup': function () {
						isdown = false;
					},
					'onmove': function (x, y, px, py) { //拖动控制盘？只有不是按钮的位置才能拖动 按钮优先级更高
						if (isdown) {
							//console.log('onmove'+px+','+'');
							backHwnd.hide();
							backData.x += px - down_px;
							backData.y += py - down_py; //正常情况需要计算相对位移 直接赋值会导致位置偏差 这里是第一层无所谓
							down_px = px;
							down_py = py;
							backHwnd.show();
							return true;
						}
						return false;
					}
				},
				'draw': function (name, callback) {
					core.setAlpha(name, 0.7);
					core.fillRect(name, 0, 0, 200, 200, "#555555");
					callback();
				}
			};
			backHwnd = new componentCanvas('back', backData);
			this.init = function () {
				backHwnd.init();
			};
			this.open = function () {
				backHwnd.show();
			};
			this.close = function () {
				backHwnd.hide();
			};
			this.hwnd = backHwnd;
		};

		// 简易方向盘
		var directionPannel = function () {
			var back = new pannel([1 / 2, 1 / 2, 1 / 4 * 1.45, 1 / 6 * 1.45]);
			var action = function (dir) {
				if (dir === 'hide') {
					return {
						'ondown': function () {
							back.close();
							return true;
						}
					}
				}
				var mesh = {
					'left': 37,
					'up': 38,
					'right': 39,
					'down': 40
				};
				return {
					'ondown': function () {
						//console.log('ondown '+dir);
						core.actions._sys_onkeyDown({
							'keyCode': mesh[dir],
							'preventDefault':function(){;}
						});
						return true;
					},
					'onup': function () {
						core.status.holdingKeys = core.status.holdingKeys || [];
						core.actions._sys_onkeyUp({
							'keyCode': mesh[dir],
							'preventDefault':function(){;}
						});
						return false;
					}
				};
			};
			var rects = {
				up: [1 / 2, 1 / 4, 1 / 3, 1 / 2],
				left: [1 / 6, 3 / 4, 1 / 3, 1 / 2],
				down: [1 / 2, 3 / 4, 1 / 3, 1 / 2],
				right: [5 / 6, 3 / 4, 1 / 3, 1 / 2],
				//hide:[5/6,1/4,1/3,1/2]
			};
			var data = {};
			var draws = function (dir) {
				return function (name, callback) {
					var w = data[dir].w,
						h = data[dir].h;
					var chrText = {
						'up': '↑',
						'down': '↓',
						'left': '←',
						'right': '→',
						'hide': '[x]'
					};
					core.setAlpha(name, 0.9);
					core.fillRect(name, 1, 1, w - 2, h - 2, "#111444");
					core.setTextBaseline(name, 'middle');
					core.setTextAlign(name, 'center');
					core.setFont(name, core.ui._buildFont(20, true));
					core.fillText(name, chrText[dir], data[dir].w / 2, data[dir].h / 2, "#FFFFFF");
					callback();
				}
			};
			for (var dir in rects) {
				data[dir] = {
					'rect': rects[dir],
					'prior': 102,
					'actions': action(dir),
					'draw': draws(dir)
				};
				back.hwnd.appendComponent(new componentCanvas(dir, data[dir]));
			}
			var is_open = false;
			this.isOpen = function(){
				return is_open;
			}
			this.open = function () {
				is_open = true;
				back.open();
			};
			this.close = function () {
				is_open = false;
				back.close();
			};
			this.init = function () {
				back.init();
			};
			this.switchOff = function () {
				is_open === false ? this.open() : this.close();
				return is_open;
			};
		};

		/////////////////////重写/////////////////
		//var origin_resetGame = core.events.resetGame;
		//core.events.prototype.resetGame = function(hero, hard, floorId, maps, values){
		//	origin_resetGame.bind(core.events)(hero, hard, floorId, maps, values);

		//};
		var originAfterStart = core.events._startGame_afterStart;
		core.events._startGame_afterStart = function (nowLoc, callback) {
			originAfterStart.bind(core.events)(nowLoc, callback);
			dljgs1.initComponent();
		}
		main.statusBar.image.keyboard.onclick = function (e) {
			e.stopPropagation();
			if (core.isReplaying()) {
				core.bookReplay();
				return;
			}
			if (main.core.isPlaying())
				dljgs1.pannel.switchOff();
		};
		////////////////////////////////////////////////////////	
},

    "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();
	}
}
}