Compare commits
	
		
			No commits in common. "c279aac744e5412cdace91617ddd0f3b03139b41" and "5602b59827c02fadd52ff0ed514af8e5d5d7cba0" have entirely different histories.
		
	
	
		
			c279aac744
			...
			5602b59827
		
	
		
| @ -13215,448 +13215,448 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = | ||||
|     }; | ||||
|   }, | ||||
|     "小地图": function () { | ||||
| 	// 在此增加新插件
 | ||||
| 	// ----- 不可自定义 杂七杂八的变量
 | ||||
| 	/** @type {{[x: string]: BFSResult}} */ | ||||
| 	let mapCache = {}; // 地图缓存
 | ||||
| 	let drawCache = {}; // 绘制信息缓存
 | ||||
| 	let status = "none"; // 当前的绘制状态
 | ||||
| 	/** @type {{[x: string]: Sprite}} */ | ||||
| 	let sprites = {}; // 当前所有的sprite
 | ||||
| 	/** @type {{[x: string]: Sprite}} */ | ||||
| 	let canDrag = {}; // 可以拖拽的sprite
 | ||||
| 	/** @type {{[x: string]: Button}} */ | ||||
| 	let areaSprite = {}; // 区域列表对应的sprite
 | ||||
| 	let clicking = false; // 是否正在点击,用于拖拽判定
 | ||||
| 	let drawingMap = ""; // 正在绘制的中心楼层
 | ||||
| 	let nowScale = 0; // 当前绘制的放缩比例
 | ||||
| 	let lastTouch = {}; // 上一次的单点点击信息
 | ||||
| 	let lastLength = 0; // 手机端缩放时上一次的两指间距离
 | ||||
| 	let nowDepth = 0; // 当前的遍历深度
 | ||||
| 	let drawedThumbnail = {}; // 已经绘制过的缩略图
 | ||||
| 	let moved = false; // 鼠标按下后是否移动了
 | ||||
| 	let noBorder = false; // 是否是无边框拼接模式
 | ||||
| 	let lastScale = 0; // 上一次缩放,用于优化缩略图绘制
 | ||||
| 	let areaPage = 0; // 区域显示的当前页数
 | ||||
| 	let nowArea = 0; // 当前区域index
 | ||||
| 	let selecting = ""; // 选择时当前正在选择的地图
 | ||||
|     // 在此增加新插件
 | ||||
|     // ----- 不可自定义 杂七杂八的变量
 | ||||
|     /** @type {{[x: string]: BFSResult}} */ | ||||
|     let mapCache = {}; // 地图缓存
 | ||||
|     let drawCache = {}; // 绘制信息缓存
 | ||||
|     let status = "none"; // 当前的绘制状态
 | ||||
|     /** @type {{[x: string]: Sprite}} */ | ||||
|     let sprites = {}; // 当前所有的sprite
 | ||||
|     /** @type {{[x: string]: Sprite}} */ | ||||
|     let canDrag = {}; // 可以拖拽的sprite
 | ||||
|     /** @type {{[x: string]: Button}} */ | ||||
|     let areaSprite = {}; // 区域列表对应的sprite
 | ||||
|     let clicking = false; // 是否正在点击,用于拖拽判定
 | ||||
|     let drawingMap = ""; // 正在绘制的中心楼层
 | ||||
|     let nowScale = 0; // 当前绘制的放缩比例
 | ||||
|     let lastTouch = {}; // 上一次的单点点击信息
 | ||||
|     let lastLength = 0; // 手机端缩放时上一次的两指间距离
 | ||||
|     let nowDepth = 0; // 当前的遍历深度
 | ||||
|     let drawedThumbnail = {}; // 已经绘制过的缩略图
 | ||||
|     let moved = false; // 鼠标按下后是否移动了
 | ||||
|     let noBorder = false; // 是否是无边框拼接模式
 | ||||
|     let lastScale = 0; // 上一次缩放,用于优化缩略图绘制
 | ||||
|     let areaPage = 0; // 区域显示的当前页数
 | ||||
|     let nowArea = 0; // 当前区域index
 | ||||
|     let selecting = ""; // 选择时当前正在选择的地图
 | ||||
| 
 | ||||
| 	// ---- 不可自定义,常量
 | ||||
| 	/** @type {Area} */ | ||||
| 	let areas = []; // 区域信息
 | ||||
| 	const perPage = Math.floor((core._PY_ - 60) / 30); // 区域的每页显示数量
 | ||||
|     // ---- 不可自定义,常量
 | ||||
|     /** @type {Area} */ | ||||
|     let areas = []; // 区域信息
 | ||||
|     const perPage = Math.floor((core._PY_ - 60) / 30); // 区域的每页显示数量
 | ||||
| 
 | ||||
| 	// ---- 可自定义,默认的切换地图的图块id
 | ||||
| 	const defaultChange = { | ||||
| 		left: "leftPortal", // 左箭头
 | ||||
| 		up: "upPortal", // 上箭头
 | ||||
| 		right: "rightPortal", // 右箭头
 | ||||
| 		down: "downPortal", // 下箭头
 | ||||
| 		upFloor: "upFloor", // 上楼
 | ||||
| 		downFloor: "downFloor", // 下楼
 | ||||
| 	}; | ||||
| 	// ---- 可自定义,默认数值
 | ||||
| 	const defaultValue = { | ||||
| 		font: "Verdana", // 默认字体
 | ||||
| 		scale: 60, // 默认地图缩放比例
 | ||||
| 		depth: Infinity, // 默认的遍历深度
 | ||||
| 	}; | ||||
|     // ---- 可自定义,默认的切换地图的图块id
 | ||||
|     const defaultChange = { | ||||
|       left: "leftPortal", // 左箭头
 | ||||
|       up: "upPortal", // 上箭头
 | ||||
|       right: "rightPortal", // 右箭头
 | ||||
|       down: "downPortal", // 下箭头
 | ||||
|       upFloor: "upFloor", // 上楼
 | ||||
|       downFloor: "downFloor", // 下楼
 | ||||
|     }; | ||||
|     // ---- 可自定义,默认数值
 | ||||
|     const defaultValue = { | ||||
|       font: "Verdana", // 默认字体
 | ||||
|       scale: 60, // 默认地图缩放比例
 | ||||
|       depth: Infinity, // 默认的遍历深度
 | ||||
|     }; | ||||
| 
 | ||||
| 	// ---- 不可自定义,计算数据
 | ||||
| 	const dirData = { | ||||
| 		up: [1, 0], | ||||
| 		down: [-1, 0], | ||||
| 		left: [0, 1], | ||||
| 		right: [0, -1], | ||||
| 		upFloor: [0, 0], | ||||
| 		downFloor: [0, 0], | ||||
| 	}; | ||||
| 	let ignoreEnemies = (this.ignoreEnemies = []); | ||||
|     // ---- 不可自定义,计算数据
 | ||||
|     const dirData = { | ||||
|       up: [1, 0], | ||||
|       down: [-1, 0], | ||||
|       left: [0, 1], | ||||
|       right: [0, -1], | ||||
|       upFloor: [0, 0], | ||||
|       downFloor: [0, 0], | ||||
|     }; | ||||
|     let ignoreEnemies = (this.ignoreEnemies = []); | ||||
| 
 | ||||
| 	let allChangeEntries = Object.entries(defaultChange); | ||||
|     let allChangeEntries = Object.entries(defaultChange); | ||||
| 
 | ||||
| 	this.setq = function (floorId) { | ||||
| 		core.setFlag("任务地点", floorId); | ||||
| 	}; | ||||
|     this.setq = function (floorId) { | ||||
|       core.setFlag("任务地点", floorId); | ||||
|     }; | ||||
| 
 | ||||
| 	const reset = core.events.resetGame; | ||||
| 	this.bfs = function () { | ||||
| 		areas = []; | ||||
| 		// 获取所有分区,使用异步函数,保证不会卡顿
 | ||||
| 		// 原理是用bfs扫,将所有连在一起的地图合并成一个区域
 | ||||
| 		(async function () { | ||||
| 			let all = core.floorIds.slice(); | ||||
| 			const scanned = { | ||||
| 				[all[0]]: true, | ||||
| 			}; | ||||
| 			while (all.length > 0) { | ||||
| 				let now = all.shift(); | ||||
| 				if (core.status.maps[now].deleted) continue; | ||||
| 				if (!now) return; | ||||
| 				await new Promise((res) => { | ||||
| 					const result = core.plugin.bfsSearch(now, Infinity, true); | ||||
| 					mapCache[`${now}_Infinity_false`] = result; | ||||
| 					areas.push({ name: core.floors[now].areas, maps: result.order }); | ||||
| 					for (const map of result.order) { | ||||
| 						scanned[map] = true; | ||||
| 						all = all.filter((v) => !result.order.includes(v)); | ||||
| 					} | ||||
| 					res("success"); | ||||
| 				}).then(() => { | ||||
| 					core.setFlag("areas", areas); | ||||
| 				}); | ||||
| 			} | ||||
| 		})(); | ||||
| 	}; | ||||
| 	core.events.resetGame = function () { | ||||
| 		reset.apply(core.events, arguments); | ||||
| 		core.plugin.bfs(); | ||||
| 	}; | ||||
| 	/** | ||||
| 	 * 广度优先搜索搜索地图路径 | ||||
| 	 * @param {string} center 中心地图的id | ||||
| 	 * @param {number} depth 搜索深度 | ||||
| 	 * @param {boolean} noCache 是否不使用缓存 | ||||
| 	 * @returns {BFSResult} 格式:floorId_x_y_dir: floorId_x_y | ||||
| 	 */ | ||||
| 	this.bfsSearch = function bfsSearch(center, depth, noCache) { | ||||
| 		// 检查缓存
 | ||||
| 		const id = `${center}_${depth}_${noBorder}`; | ||||
| 		if (mapCache[id] && !noCache) return mapCache[id]; | ||||
| 		const used = { | ||||
| 			[center]: true, | ||||
| 		}; // 搜索过的楼层
 | ||||
| 		let queue = []; | ||||
| 		let stack = [center]; // 当前栈
 | ||||
| 		let nowDepth = -1; | ||||
| 		const mapOrder = [center]; // 遍历顺序,顺便还能记录遍历了哪些楼层
 | ||||
|     const reset = core.events.resetGame; | ||||
|     this.bfs = function () { | ||||
|       areas = []; | ||||
|       // 获取所有分区,使用异步函数,保证不会卡顿
 | ||||
|       // 原理是用bfs扫,将所有连在一起的地图合并成一个区域
 | ||||
|       (async function () { | ||||
|         let all = core.floorIds.slice(); | ||||
|         const scanned = { | ||||
|           [all[0]]: true, | ||||
|         }; | ||||
|         while (all.length > 0) { | ||||
|           let now = all.shift(); | ||||
|           if (core.status.maps[now].deleted) continue; | ||||
|           if (!now) return; | ||||
|           await new Promise((res) => { | ||||
|             const result = core.plugin.bfsSearch(now, Infinity, true); | ||||
|             mapCache[`${now}_Infinity_false`] = result; | ||||
|             areas.push({ name: core.floors[now].areas, maps: result.order }); | ||||
|             for (const map of result.order) { | ||||
|               scanned[map] = true; | ||||
|               all = all.filter((v) => !result.order.includes(v)); | ||||
|             } | ||||
|             res("success"); | ||||
|           }).then(() => { | ||||
|             core.setFlag("areas", areas); | ||||
|           }); | ||||
|         } | ||||
|       })(); | ||||
|     }; | ||||
|     core.events.resetGame = function () { | ||||
|       reset.apply(core.events, arguments); | ||||
|       core.plugin.bfs(); | ||||
|     }; | ||||
|     /** | ||||
|      * 广度优先搜索搜索地图路径 | ||||
|      * @param {string} center 中心地图的id | ||||
|      * @param {number} depth 搜索深度 | ||||
|      * @param {boolean} noCache 是否不使用缓存 | ||||
|      * @returns {BFSResult} 格式:floorId_x_y_dir: floorId_x_y | ||||
|      */ | ||||
|     this.bfsSearch = function bfsSearch(center, depth, noCache) { | ||||
|       // 检查缓存
 | ||||
|       const id = `${center}_${depth}_${noBorder}`; | ||||
|       if (mapCache[id] && !noCache) return mapCache[id]; | ||||
|       const used = { | ||||
|         [center]: true, | ||||
|       }; // 搜索过的楼层
 | ||||
|       let queue = []; | ||||
|       let stack = [center]; // 当前栈
 | ||||
|       let nowDepth = -1; | ||||
|       const mapOrder = [center]; // 遍历顺序,顺便还能记录遍历了哪些楼层
 | ||||
| 
 | ||||
| 		const res = {}; // 输出结果,格式:floorId_x_y_dir: floorId_x_y
 | ||||
| 		const enemies = {}; | ||||
| 		const upOrDown = {}; | ||||
| 		const mapdir = {}; | ||||
| 		// 开始循环搜索
 | ||||
| 		while (nowDepth < depth && stack.length > 0) { | ||||
| 			const now = stack.shift(); // 当前id
 | ||||
| 			if (core.status.maps[now].deleted) continue; | ||||
| 			mapdir[now] = mapdir[now] ?? []; | ||||
| 			const blocks = core.getMapBlocksObj(now); // 获取当前地图的每点的事件
 | ||||
| 			enemies[now] = {}; | ||||
| 			// 遍历,获取可以传送的点,只检测绿点事件,因此可用红点事件进行传送来实现分区功能
 | ||||
| 			for (const i in blocks) { | ||||
| 				const block = blocks[i]; | ||||
| 				// 整合漏怪检测,所以要检测怪物
 | ||||
| 				if (block.event.trigger === "battle") { | ||||
| 					const id = block.event.id; | ||||
| 					if (ignoreEnemies.includes(id)) continue; | ||||
| 					else enemies[now][i] = block.event.id; | ||||
| 					continue; | ||||
| 				} | ||||
| 				// 检测触发器是否为切换楼层,不是则直接跳过
 | ||||
| 				if (block.event.trigger !== "changeFloor") continue; | ||||
| 				const dirEntries = allChangeEntries.find( | ||||
| 					(v) => v[1] === block.event.id | ||||
| 				); | ||||
| 				// 如果不是那六种传送门,直接忽略
 | ||||
| 				if (!dirEntries) continue; | ||||
| 				const data = block.event.data; | ||||
| 				const dir = dirEntries[0]; | ||||
| 				const route = now + "_" + i.replace(",", "_") + "_" + dir; | ||||
| 				const target = data.floorId + "_" + data.loc.join("_"); | ||||
|       const res = {}; // 输出结果,格式:floorId_x_y_dir: floorId_x_y
 | ||||
|       const enemies = {}; | ||||
|       const upOrDown = {}; | ||||
|       const mapdir = {}; | ||||
|       // 开始循环搜索
 | ||||
|       while (nowDepth < depth && stack.length > 0) { | ||||
|         const now = stack.shift(); // 当前id
 | ||||
|         if (core.status.maps[now].deleted) continue; | ||||
|         mapdir[now] = mapdir[now] ?? []; | ||||
|         const blocks = core.getMapBlocksObj(now); // 获取当前地图的每点的事件
 | ||||
|         enemies[now] = {}; | ||||
|         // 遍历,获取可以传送的点,只检测绿点事件,因此可用红点事件进行传送来实现分区功能
 | ||||
|         for (const i in blocks) { | ||||
|           const block = blocks[i]; | ||||
|           // 整合漏怪检测,所以要检测怪物
 | ||||
|           if (block.event.trigger === "battle") { | ||||
|             const id = block.event.id; | ||||
|             if (ignoreEnemies.includes(id)) continue; | ||||
|             else enemies[now][i] = block.event.id; | ||||
|             continue; | ||||
|           } | ||||
|           // 检测触发器是否为切换楼层,不是则直接跳过
 | ||||
|           if (block.event.trigger !== "changeFloor") continue; | ||||
|           const dirEntries = allChangeEntries.find( | ||||
|             (v) => v[1] === block.event.id | ||||
|           ); | ||||
|           // 如果不是那六种传送门,直接忽略
 | ||||
|           if (!dirEntries) continue; | ||||
|           const data = block.event.data; | ||||
|           const dir = dirEntries[0]; | ||||
|           const route = now + "_" + i.replace(",", "_") + "_" + dir; | ||||
|           const target = data.floorId + "_" + data.loc.join("_"); | ||||
| 
 | ||||
| 				mapdir[now].push(dir); | ||||
| 				if (!used[data.floorId]) { | ||||
| 					if (dir === "upFloor" || dir === "downFloor") { | ||||
| 						upOrDown[now] = upOrDown[id] ?? []; | ||||
| 						upOrDown[now].push(dir); | ||||
| 					} | ||||
|           mapdir[now].push(dir); | ||||
|           if (!used[data.floorId]) { | ||||
|             if (dir === "upFloor" || dir === "downFloor") { | ||||
|               upOrDown[now] = upOrDown[id] ?? []; | ||||
|               upOrDown[now].push(dir); | ||||
|             } | ||||
| 
 | ||||
| 					queue.push(data.floorId); // 没有搜索过,则加入栈中
 | ||||
| 					mapOrder.push(data.floorId); | ||||
| 					used[data.floorId] = true; | ||||
| 				} | ||||
| 				res[route] = target; | ||||
| 			} | ||||
| 			if (stack.length === 0) { | ||||
| 				stack = queue; | ||||
| 				queue = []; | ||||
| 				nowDepth++; | ||||
| 			} | ||||
| 			if (stack.length === 0 && queue.length === 0) break; | ||||
| 		} | ||||
| 		return { res, order: mapOrder, enemies, upOrDown, mapdir }; | ||||
| 	}; | ||||
| 	/** | ||||
| 	 * 获取绘制信息 | ||||
| 	 * @param {string?} center 中心地图id | ||||
| 	 * @param {number?} depth 搜索深度 | ||||
| 	 * @param {boolean?} noCache 是否不使用缓存 | ||||
| 	 * @returns {MapDrawInfo} | ||||
| 	 */ | ||||
| 	this.getMapDrawInfo = function ( | ||||
| 		center = core.status.floorId, | ||||
| 		depth = defaultValue.depth, | ||||
| 		noCache = false | ||||
| 	) { | ||||
| 		nowDepth = depth; | ||||
| 		drawingMap = center; | ||||
| 		const id = `${center}_${depth}_${noBorder}`; | ||||
| 		// 检查缓存
 | ||||
| 		if (drawCache[id] && !noCache) return drawCache[id]; | ||||
| 		const map = core.plugin.bfsSearch(center, depth, noCache); | ||||
| 		mapCache[id] = map; | ||||
| 		const res = getDrawInfo(map.res, center, map.order); | ||||
| 		res.upOrDown = map.upOrDown; | ||||
| 		res.mapdir = map.mapdir; | ||||
| 		drawCache[id] = res; | ||||
| 		return res; | ||||
| 	}; | ||||
| 	/** | ||||
| 	 * 提供地图的绘制信息 | ||||
| 	 * @param {{[x: string]: string}} map 要绘制的地图,格式:floorId_x_y_dir: floorId_x_y | ||||
| 	 * @param {string} center 中心地图的id | ||||
| 	 * @param {string[]} order 遍历顺序 | ||||
| 	 * @returns {MapDrawInfo} 地图的绘制信息 | ||||
| 	 */ | ||||
|             queue.push(data.floorId); // 没有搜索过,则加入栈中
 | ||||
|             mapOrder.push(data.floorId); | ||||
|             used[data.floorId] = true; | ||||
|           } | ||||
|           res[route] = target; | ||||
|         } | ||||
|         if (stack.length === 0) { | ||||
|           stack = queue; | ||||
|           queue = []; | ||||
|           nowDepth++; | ||||
|         } | ||||
|         if (stack.length === 0 && queue.length === 0) break; | ||||
|       } | ||||
|       return { res, order: mapOrder, enemies, upOrDown, mapdir }; | ||||
|     }; | ||||
|     /** | ||||
|      * 获取绘制信息 | ||||
|      * @param {string?} center 中心地图id | ||||
|      * @param {number?} depth 搜索深度 | ||||
|      * @param {boolean?} noCache 是否不使用缓存 | ||||
|      * @returns {MapDrawInfo} | ||||
|      */ | ||||
|     this.getMapDrawInfo = function ( | ||||
|       center = core.status.floorId, | ||||
|       depth = defaultValue.depth, | ||||
|       noCache = false | ||||
|     ) { | ||||
|       nowDepth = depth; | ||||
|       drawingMap = center; | ||||
|       const id = `${center}_${depth}_${noBorder}`; | ||||
|       // 检查缓存
 | ||||
|       if (drawCache[id] && !noCache) return drawCache[id]; | ||||
|       const map = core.plugin.bfsSearch(center, depth, noCache); | ||||
|       mapCache[id] = map; | ||||
|       const res = getDrawInfo(map.res, center, map.order); | ||||
|       res.upOrDown = map.upOrDown; | ||||
|       res.mapdir = map.mapdir; | ||||
|       drawCache[id] = res; | ||||
|       return res; | ||||
|     }; | ||||
|     /** | ||||
|      * 提供地图的绘制信息 | ||||
|      * @param {{[x: string]: string}} map 要绘制的地图,格式:floorId_x_y_dir: floorId_x_y | ||||
|      * @param {string} center 中心地图的id | ||||
|      * @param {string[]} order 遍历顺序 | ||||
|      * @returns {MapDrawInfo} 地图的绘制信息 | ||||
|      */ | ||||
| 
 | ||||
| 	function getDrawInfo(map, center, order) { | ||||
| 		// 先根据地图id分类,从而确定每个地图连接哪些地图,同时方便处理
 | ||||
| 		const links = {}; | ||||
| 		for (const i in map) { | ||||
| 			const splitted = i.split("_"); | ||||
| 			const id = splitted[0]; | ||||
| 			if (!links[id]) links[id] = {}; | ||||
| 			links[id][i] = map[i]; | ||||
| 		} | ||||
|     function getDrawInfo(map, center, order) { | ||||
|       // 先根据地图id分类,从而确定每个地图连接哪些地图,同时方便处理
 | ||||
|       const links = {}; | ||||
|       for (const i in map) { | ||||
|         const splitted = i.split("_"); | ||||
|         const id = splitted[0]; | ||||
|         if (!links[id]) links[id] = {}; | ||||
|         links[id][i] = map[i]; | ||||
|       } | ||||
| 
 | ||||
| 		// 分类完毕,然后根据连接点先计算出各个地图的坐标,然后再进行判断
 | ||||
| 		const centerFloor = core.status.maps[center]; | ||||
| 		const visitedCenter = core.hasVisitedFloor(center); | ||||
| 		const locs = { | ||||
| 			// 格式:[中心x, 中心y, 宽, 高, 是否到达过]
 | ||||
| 			[center]: [2, 2, 1, 1, visitedCenter], | ||||
| 		}; | ||||
| 		// 可以上楼下楼的地图
 | ||||
| 		const upOrDown = {}; | ||||
| 		for (const id of order) { | ||||
| 			const now = links[id]; | ||||
| 			// 遍历每一个地图的连接情况
 | ||||
| 			for (const from in now) { | ||||
| 				const to = now[from]; | ||||
| 				// 先根据from to计算物理位置
 | ||||
| 				const fromData = from.split("_"), | ||||
| 					toData = to.split("_"); | ||||
| 				const dir = fromData[3]; | ||||
| 				if (dir === "upFloor" || dir === "downFloor") continue; | ||||
| 				if (!defaultChange[dir]) continue; | ||||
| 				const v = dirData[dir][1], // 竖直数值
 | ||||
| 					h = dirData[dir][0], // 水平数值
 | ||||
| 					ha = Math.abs(h), | ||||
| 					va = Math.abs(v); | ||||
| 				const ff = id, // fromFloorId
 | ||||
| 					tf = toData[0]; // toFloorId
 | ||||
| 				const fromFloor = core.status.maps[ff], | ||||
| 					toFloor = core.status.maps[tf]; | ||||
| 				const fhw = Math.floor(fromFloor.width / 2), // fromFloorHalfWidth
 | ||||
| 					fhh = Math.floor(fromFloor.height / 2), | ||||
| 					thw = Math.floor(toFloor.width / 2), | ||||
| 					thh = Math.floor(toFloor.height / 2); | ||||
| 				const fLoc = locs[id] ?? [0, 0]; | ||||
| 				if (!locs[ff]) continue; | ||||
| 				let x, y; | ||||
| 				if (locs && locs[tf]) { | ||||
| 					x = locs[tf][0]; | ||||
| 					y = locs[tf][1]; | ||||
| 				} else { | ||||
| 					// 计算坐标,公式可以通过画图推断出
 | ||||
| 					x = fLoc[0] - v; | ||||
| 					y = fLoc[1] - h; | ||||
| 				} | ||||
| 				locs[tf] = locs[tf] ?? [x, y, 1, 1, core.hasVisitedFloor(tf)]; | ||||
| 			} | ||||
| 		} | ||||
| 		// 获取地图绘制需要的长宽
 | ||||
| 		let width = 0, | ||||
| 			height = 0; | ||||
| 		let left, right, up, down; | ||||
| 		for (const id in locs) { | ||||
| 			const [x, y, w, h] = locs[id]; | ||||
| 			if (left === void 0) { | ||||
| 				left = right = x; | ||||
| 				up = down = y; | ||||
| 			} | ||||
| 			left = Math.min(x - 1, left); | ||||
| 			right = Math.max(x + 1, right); | ||||
| 			up = Math.min(y - 1, up); | ||||
| 			down = Math.max(y + 1, down); | ||||
| 		} | ||||
| 		width = right - left; | ||||
| 		height = down - up; | ||||
|       // 分类完毕,然后根据连接点先计算出各个地图的坐标,然后再进行判断
 | ||||
|       const centerFloor = core.status.maps[center]; | ||||
|       const visitedCenter = core.hasVisitedFloor(center); | ||||
|       const locs = { | ||||
|         // 格式:[中心x, 中心y, 宽, 高, 是否到达过]
 | ||||
|         [center]: [2, 2, 1, 1, visitedCenter], | ||||
|       }; | ||||
|       // 可以上楼下楼的地图
 | ||||
|       const upOrDown = {}; | ||||
|       for (const id of order) { | ||||
|         const now = links[id]; | ||||
|         // 遍历每一个地图的连接情况
 | ||||
|         for (const from in now) { | ||||
|           const to = now[from]; | ||||
|           // 先根据from to计算物理位置
 | ||||
|           const fromData = from.split("_"), | ||||
|             toData = to.split("_"); | ||||
|           const dir = fromData[3]; | ||||
|           if (dir === "upFloor" || dir === "downFloor") continue; | ||||
|           if (!defaultChange[dir]) continue; | ||||
|           const v = dirData[dir][1], // 竖直数值
 | ||||
|             h = dirData[dir][0], // 水平数值
 | ||||
|             ha = Math.abs(h), | ||||
|             va = Math.abs(v); | ||||
|           const ff = id, // fromFloorId
 | ||||
|             tf = toData[0]; // toFloorId
 | ||||
|           const fromFloor = core.status.maps[ff], | ||||
|             toFloor = core.status.maps[tf]; | ||||
|           const fhw = Math.floor(fromFloor.width / 2), // fromFloorHalfWidth
 | ||||
|             fhh = Math.floor(fromFloor.height / 2), | ||||
|             thw = Math.floor(toFloor.width / 2), | ||||
|             thh = Math.floor(toFloor.height / 2); | ||||
|           const fLoc = locs[id] ?? [0, 0]; | ||||
|           if (!locs[ff]) continue; | ||||
|           let x, y; | ||||
|           if (locs && locs[tf]) { | ||||
|             x = locs[tf][0]; | ||||
|             y = locs[tf][1]; | ||||
|           } else { | ||||
|             // 计算坐标,公式可以通过画图推断出
 | ||||
|             x = fLoc[0] - v; | ||||
|             y = fLoc[1] - h; | ||||
|           } | ||||
|           locs[tf] = locs[tf] ?? [x, y, 1, 1, core.hasVisitedFloor(tf)]; | ||||
|         } | ||||
|       } | ||||
|       // 获取地图绘制需要的长宽
 | ||||
|       let width = 0, | ||||
|         height = 0; | ||||
|       let left, right, up, down; | ||||
|       for (const id in locs) { | ||||
|         const [x, y, w, h] = locs[id]; | ||||
|         if (left === void 0) { | ||||
|           left = right = x; | ||||
|           up = down = y; | ||||
|         } | ||||
|         left = Math.min(x - 1, left); | ||||
|         right = Math.max(x + 1, right); | ||||
|         up = Math.min(y - 1, up); | ||||
|         down = Math.max(y + 1, down); | ||||
|       } | ||||
|       width = right - left; | ||||
|       height = down - up; | ||||
| 
 | ||||
| 		return { locs, width, height, layer: upOrDown }; | ||||
| 	} | ||||
|       return { locs, width, height, layer: upOrDown }; | ||||
|     } | ||||
| 
 | ||||
| 	function mapblock(mapdir) { | ||||
| 		let mb = ""; | ||||
| 		if (mapdir.includes("up")) mb += "u"; | ||||
| 		if (mapdir.includes("down")) mb += "d"; | ||||
| 		if (mapdir.includes("left")) mb += "l"; | ||||
| 		if (mapdir.includes("right")) mb += "r"; | ||||
| 		return mb ? mb + ".webp" : "null.webp"; | ||||
| 	} | ||||
| 	core.animateFrame.globalAlphaFloor = 0; | ||||
| 	core.animateFrame.globalAlphaFloorStatus = 1; | ||||
|     function mapblock(mapdir) { | ||||
|       let mb = ""; | ||||
|       if (mapdir.includes("up")) mb += "u"; | ||||
|       if (mapdir.includes("down")) mb += "d"; | ||||
|       if (mapdir.includes("left")) mb += "l"; | ||||
|       if (mapdir.includes("right")) mb += "r"; | ||||
|       return mb ? mb + ".webp" : "null.webp"; | ||||
|     } | ||||
|     core.animateFrame.globalAlphaFloor = 0; | ||||
|     core.animateFrame.globalAlphaFloorStatus = 1; | ||||
| 
 | ||||
| 	const tesk = document.createElement("canvas"); | ||||
| 	tesk.width = 300; | ||||
| 	tesk.height = 300; | ||||
| 	const teskctx = tesk.getContext("2d"); | ||||
|     const tesk = document.createElement("canvas"); | ||||
|     tesk.width = 300; | ||||
|     tesk.height = 300; | ||||
|     const teskctx = tesk.getContext("2d"); | ||||
| 
 | ||||
| 	let line = 50; | ||||
| 	teskctx.strokeStyle = "green"; | ||||
| 	teskctx.fillStyle = "green"; | ||||
| 	let now = 0; | ||||
| 	core.registerAnimationFrame("tesk", true, function (timestamp) { | ||||
| 		if (timestamp - now > 1000 / 60) { | ||||
| 			now = timestamp; | ||||
| 			core.clearMap(teskctx); | ||||
| 			teskctx.lineWidth = 150 - line; | ||||
|     let line = 50; | ||||
|     teskctx.strokeStyle = "green"; | ||||
|     teskctx.fillStyle = "green"; | ||||
|     let now = 0; | ||||
|     core.registerAnimationFrame("tesk", true, function (timestamp) { | ||||
|       if (timestamp - now > 1000 / 60) { | ||||
|         now = timestamp; | ||||
|         core.clearMap(teskctx); | ||||
|         teskctx.lineWidth = 150 - line; | ||||
| 
 | ||||
| 			if (line <= 150) { | ||||
| 				teskctx.beginPath(); | ||||
| 				teskctx.arc(150, 150, line, 0, Math.PI * 2); | ||||
| 				line += 2; | ||||
| 				teskctx.stroke(); | ||||
| 			} else { | ||||
| 				teskctx.beginPath(); | ||||
| 				teskctx.arc(150, 150, line - 150, 0, Math.PI * 2); | ||||
| 				line += 2; | ||||
| 				teskctx.fill(); | ||||
| 				if (line >= 250) line = 50; | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
|         if (line <= 150) { | ||||
|           teskctx.beginPath(); | ||||
|           teskctx.arc(150, 150, line, 0, Math.PI * 2); | ||||
|           line += 2; | ||||
|           teskctx.stroke(); | ||||
|         } else { | ||||
|           teskctx.beginPath(); | ||||
|           teskctx.arc(150, 150, line - 150, 0, Math.PI * 2); | ||||
|           line += 2; | ||||
|           teskctx.fill(); | ||||
|           if (line >= 250) line = 50; | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
| 
 | ||||
| 	/** | ||||
| 	 * 绘制小地图 | ||||
| 	 * @param {MapDrawInfo} info 地图绘制信息 | ||||
| 	 * @param {number} scale 地图的绘制比例 | ||||
| 	 */ | ||||
| 	this.drawSmallMap = function ( | ||||
| 		ctx, | ||||
| 		info, | ||||
| 		center, | ||||
| 		sx, | ||||
| 		sy, | ||||
| 		sw, | ||||
| 		sh, | ||||
| 		scale = defaultValue.scale | ||||
| 	) { | ||||
| 		core.clearMap(ctx, sx, sy, sw + 40, sh + 60); | ||||
| 		if (core.domStyle.isVertical) { | ||||
| 			sy += 50; | ||||
| 			sx += 15; | ||||
| 		} else { | ||||
| 			sy += 60; | ||||
| 			sx += 30; | ||||
| 		} | ||||
| 		core.fillRect(ctx, sx - 10, sy - 10, sw + 20, sh + 20, "#000"); | ||||
| 		core.strokeRect(ctx, sx - 10, sy - 10, sw + 20, sh + 20, "#fff", 5); | ||||
| 		core.setTextAlign("outerUI", "center"); | ||||
| 		core.fillBoldText1( | ||||
| 			ctx, | ||||
| 			core.status.maps[center].areas, | ||||
| 			sx + sw / 2, | ||||
| 			sy - 20, | ||||
| 			"#FFFFFF", | ||||
| 			"#000000", | ||||
| 			6, | ||||
| 			"bold 42px Verdana" | ||||
| 		); | ||||
| 		const locs = info.locs; | ||||
| 		for (const id in locs) { | ||||
| 			const loc = locs[id]; | ||||
| 			let color = "#000"; | ||||
| 			if (!loc[4]) color = "#f0f"; | ||||
| 			const [x, y, w, h] = loc.map((v) => typeof v === "number" && v * scale); | ||||
| 			const fx = x + sx, | ||||
| 				fy = y + sy; | ||||
| 			const mapdir = info.mapdir[id]; | ||||
| 			const img = mapblock(mapdir); | ||||
| 			if (x < 0 || x > 4 * scale || y < 0 || y > 4 * scale) continue; | ||||
| 			core.drawImage(ctx, img, 0, 0, 60, 60, fx, fy, w, h); | ||||
| 			const layer = info.upOrDown[id]; | ||||
| 			const min = Math.min(w, h); | ||||
|     /** | ||||
|      * 绘制小地图 | ||||
|      * @param {MapDrawInfo} info 地图绘制信息 | ||||
|      * @param {number} scale 地图的绘制比例 | ||||
|      */ | ||||
|     this.drawSmallMap = function ( | ||||
|       ctx, | ||||
|       info, | ||||
|       center, | ||||
|       sx, | ||||
|       sy, | ||||
|       sw, | ||||
|       sh, | ||||
|       scale = defaultValue.scale | ||||
|     ) { | ||||
|       core.clearMap(ctx, sx, sy, sw + 40, sh + 60); | ||||
|       if (core.domStyle.isVertical) { | ||||
|         sy += 50; | ||||
|         sx += 15; | ||||
|       } else { | ||||
|         sy += 60; | ||||
|         sx += 30; | ||||
|       } | ||||
|       core.fillRect(ctx, sx, sy, sw, sh, "#000"); | ||||
|       core.strokeRect(ctx, sx, sy, sw, sh, "#fff", 5); | ||||
|       core.setTextAlign("outerUI", "center"); | ||||
|       core.fillBoldText1( | ||||
|         ctx, | ||||
|         core.status.maps[center].areas, | ||||
|         sx + sw / 2, | ||||
|         sy - 10, | ||||
|         "#FFFFFF", | ||||
|         "#000000", | ||||
|         6, | ||||
|         "bold 42px Verdana" | ||||
|       ); | ||||
|       const locs = info.locs; | ||||
|       for (const id in locs) { | ||||
|         const loc = locs[id]; | ||||
|         let color = "#000"; | ||||
|         if (!loc[4]) color = "#f0f"; | ||||
|         const [x, y, w, h] = loc.map((v) => typeof v === "number" && v * scale); | ||||
|         const fx = x + sx, | ||||
|           fy = y + sy; | ||||
|         const mapdir = info.mapdir[id]; | ||||
|         const img = mapblock(mapdir); | ||||
|         if (x < 0 || x > 4 * scale || y < 0 || y > 4 * scale) continue; | ||||
|         core.drawImage(ctx, img, 0, 0, 60, 60, fx, fy, w, h); | ||||
|         const layer = info.upOrDown[id]; | ||||
|         const min = Math.min(w, h); | ||||
| 
 | ||||
| 			if (layer?.includes("upFloor")) | ||||
| 				core.drawIcon( | ||||
| 					ctx, | ||||
| 					defaultChange.upFloor, | ||||
| 					fx + min / 4, | ||||
| 					fy + min / 4, | ||||
| 					min / 2, | ||||
| 					min / 2 | ||||
| 				); | ||||
| 			if (layer?.includes("downFloor")) | ||||
| 				core.drawIcon( | ||||
| 					ctx, | ||||
| 					defaultChange.downFloor, | ||||
| 					fx + min / 4, | ||||
| 					fy + min / 4, | ||||
| 					min / 2, | ||||
| 					min / 2 | ||||
| 				); | ||||
| 			if (core.getFlag("任务地点") && core.getFlag("任务地点") === id) | ||||
| 				ctx.drawImage(tesk, fx + min / 4, fy + min / 4, min / 2, min / 2); | ||||
| 			if (id === core.status.floorId) | ||||
| 				core.drawImage( | ||||
| 					ctx, | ||||
| 					"hero.webp", | ||||
| 					0, | ||||
| 					0, | ||||
| 					32, | ||||
| 					19, | ||||
| 					fx + min / 4, | ||||
| 					fy + (min * 5) / 16, | ||||
| 					32, | ||||
| 					19 | ||||
| 				); | ||||
| 			// 显示漏怪数量
 | ||||
| 			if (core.getFlag("showEnemy")) { | ||||
| 				ctx.textAlign = "center"; | ||||
| 				ctx.textBaseline = "middle"; | ||||
| 				const c = drawingMap + "_" + nowDepth + "_" + noBorder; | ||||
| 				const n = Object.keys(mapCache[c].enemies[id]).length; | ||||
| 				color = "#fff"; | ||||
| 				if (n > 10) color = "#fc3"; | ||||
| 				if (n > 20) color = "#f22"; | ||||
| 				ctx.shadowBlur = 0.6 * nowScale; | ||||
| 				ctx.shadowColor = "#000"; | ||||
| 				if (n > 0) | ||||
| 					core.fillText( | ||||
| 						ctx, | ||||
| 						n, | ||||
| 						fx + (w * 3) / 10, | ||||
| 						fy + (h * 7) / 10, | ||||
| 						color, | ||||
| 						22 + "px normal" | ||||
| 					); | ||||
| 				ctx.shadowBlur = 0; | ||||
| 			} | ||||
| 			if (!core.hasVisitedFloor(id)) { | ||||
| 				core.fillRect(ctx, fx, fy, w, h, "rgba(0,0,0,0.7)"); | ||||
| 				core.fillText( | ||||
| 					ctx, | ||||
| 					"?", | ||||
| 					fx + min / 2, | ||||
| 					fy + (min * 3) / 4, | ||||
| 					"#FFFFFF", | ||||
| 					"bold 42px Verdana" | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 	}; | ||||
| }, | ||||
|         if (layer?.includes("upFloor")) | ||||
|           core.drawIcon( | ||||
|             ctx, | ||||
|             defaultChange.upFloor, | ||||
|             fx + min / 4, | ||||
|             fy + min / 4, | ||||
|             min / 2, | ||||
|             min / 2 | ||||
|           ); | ||||
|         if (layer?.includes("downFloor")) | ||||
|           core.drawIcon( | ||||
|             ctx, | ||||
|             defaultChange.downFloor, | ||||
|             fx + min / 4, | ||||
|             fy + min / 4, | ||||
|             min / 2, | ||||
|             min / 2 | ||||
|           ); | ||||
|         if (core.getFlag("任务地点") && core.getFlag("任务地点") === id) | ||||
|           ctx.drawImage(tesk, fx + min / 4, fy + min / 4, min / 2, min / 2); | ||||
|         if (id === core.status.floorId) | ||||
|           core.drawImage( | ||||
|             ctx, | ||||
|             "hero.webp", | ||||
|             0, | ||||
|             0, | ||||
|             32, | ||||
|             19, | ||||
|             fx + min / 4, | ||||
|             fy + (min * 5) / 16, | ||||
|             32, | ||||
|             19 | ||||
|           ); | ||||
|         // 显示漏怪数量
 | ||||
|         if (core.getFlag("showEnemy")) { | ||||
|           ctx.textAlign = "center"; | ||||
|           ctx.textBaseline = "middle"; | ||||
|           const c = drawingMap + "_" + nowDepth + "_" + noBorder; | ||||
|           const n = Object.keys(mapCache[c].enemies[id]).length; | ||||
|           color = "#fff"; | ||||
|           if (n > 10) color = "#fc3"; | ||||
|           if (n > 20) color = "#f22"; | ||||
|           ctx.shadowBlur = 0.6 * nowScale; | ||||
|           ctx.shadowColor = "#000"; | ||||
|           if (n > 0) | ||||
|             core.fillText( | ||||
|               ctx, | ||||
|               n, | ||||
|               fx + (w * 3) / 10, | ||||
|               fy + (h * 7) / 10, | ||||
|               color, | ||||
|               22 + "px normal" | ||||
|             ); | ||||
|           ctx.shadowBlur = 0; | ||||
|         } | ||||
|         if (!core.hasVisitedFloor(id)) { | ||||
|           core.fillRect(ctx, fx, fy, w, h, "rgba(0,0,0,0.7)"); | ||||
|           core.fillText( | ||||
|             ctx, | ||||
|             "?", | ||||
|             fx + min / 2, | ||||
|             fy + (min * 3) / 4, | ||||
|             "#FFFFFF", | ||||
|             "bold 42px Verdana" | ||||
|           ); | ||||
|         } | ||||
|       } | ||||
|     }; | ||||
|   }, | ||||
|     "楼传": function () { | ||||
| 	// 在此增加新插件
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user