diff --git a/public/libs/actions.js b/public/libs/actions.js
index 9e88113..0fbf59b 100644
--- a/public/libs/actions.js
+++ b/public/libs/actions.js
@@ -1,3 +1,5 @@
+///
+
/*
actions.js:用户交互的事件的处理
键盘、鼠标、触摸屏事件相关
diff --git a/public/libs/control.js b/public/libs/control.js
index 68a7ab3..b33bf7d 100644
--- a/public/libs/control.js
+++ b/public/libs/control.js
@@ -1,3 +1,5 @@
+///
+
/*
control.js:游戏主要逻辑控制
主要负责status相关内容,以及各种变量获取/存储
diff --git a/public/libs/core.js b/public/libs/core.js
index 55d0bd2..60b00e6 100644
--- a/public/libs/core.js
+++ b/public/libs/core.js
@@ -1,16 +1,17 @@
+///
/**
* 初始化 start
*/
-"use strict";
+'use strict';
// /**
// * @type {CoreMixin}
// */
// const core = (() => {
-function core () {
+function core() {
this._WIDTH_ = 15;
this._HEIGHT_ = 15;
this._PX_ = this._WIDTH_ * 32;
@@ -22,99 +23,99 @@ function core () {
this.__PIXELS__ = this.__SIZE__ * 32;
this.__HALF_SIZE__ = Math.floor(this.__SIZE__ / 2);
this.material = {
- 'animates': {},
- 'images': {},
- 'bgms': {},
- 'sounds': {},
- 'items': {},
- 'enemys': {},
- 'icons': {},
- 'ground': null,
- 'grundCanvas': null,
- 'groundPattern': null,
- 'autotileEdges': {},
- }
+ animates: {},
+ images: {},
+ bgms: {},
+ sounds: {},
+ items: {},
+ enemys: {},
+ icons: {},
+ ground: null,
+ grundCanvas: null,
+ groundPattern: null,
+ autotileEdges: {}
+ };
this.timeout = {
- 'turnHeroTimeout': null,
- 'onDownTimeout': null,
- 'sleepTimeout': null,
- }
+ turnHeroTimeout: null,
+ onDownTimeout: null,
+ sleepTimeout: null
+ };
this.interval = {
- 'heroMoveInterval': null,
- 'onDownInterval': null,
- }
+ heroMoveInterval: null,
+ onDownInterval: null
+ };
this.animateFrame = {
- 'totalTime': 0,
- 'totalTimeStart': 0,
- 'globalAnimate': false,
- 'globalTime': 0,
- 'selectorTime': 0,
- 'selectorUp': true,
- 'animateTime': 0,
- 'moveTime': 0,
- 'lastLegTime': 0,
- 'leftLeg': true,
- 'weather': {
- 'time': 0,
- 'type': null,
- 'level': 1,
- 'nodes': [],
- 'data': null,
- 'fog': null,
- 'cloud': null,
- 'sun': null
+ totalTime: 0,
+ totalTimeStart: 0,
+ globalAnimate: false,
+ globalTime: 0,
+ selectorTime: 0,
+ selectorUp: true,
+ animateTime: 0,
+ moveTime: 0,
+ lastLegTime: 0,
+ leftLeg: true,
+ weather: {
+ time: 0,
+ type: null,
+ level: 1,
+ nodes: [],
+ data: null,
+ fog: null,
+ cloud: null,
+ sun: null
},
- "tip": null,
- "asyncId": {},
- "lastAsyncId": null
- }
+ tip: null,
+ asyncId: {},
+ lastAsyncId: null
+ };
this.musicStatus = {
- 'audioContext': null, // WebAudioContext
- 'bgmStatus': false, // 是否播放BGM
- 'soundStatus': true, // 是否播放SE
- 'playingBgm': null, // 正在播放的BGM
- 'pauseTime': 0, // 上次暂停的时间
- 'lastBgm': null, // 上次播放的bgm
- 'gainNode': null,
- 'playingSounds': {}, // 正在播放的SE
- 'userVolume': 1.0, // 用户音量
- 'designVolume': 1.0, //设计音量
- 'bgmSpeed': 100, // 背景音乐速度
- 'bgmUsePitch': null, // 是否同时修改音调
- 'cachedBgms': [], // 缓存BGM内容
- 'cachedBgmCount': 8, // 缓存的bgm数量
- }
+ audioContext: null, // WebAudioContext
+ bgmStatus: false, // 是否播放BGM
+ soundStatus: true, // 是否播放SE
+ playingBgm: null, // 正在播放的BGM
+ pauseTime: 0, // 上次暂停的时间
+ lastBgm: null, // 上次播放的bgm
+ gainNode: null,
+ playingSounds: {}, // 正在播放的SE
+ userVolume: 1.0, // 用户音量
+ designVolume: 1.0, //设计音量
+ bgmSpeed: 100, // 背景音乐速度
+ bgmUsePitch: null, // 是否同时修改音调
+ cachedBgms: [], // 缓存BGM内容
+ cachedBgmCount: 8 // 缓存的bgm数量
+ };
this.platform = {
- 'isOnline': true, // 是否http
- 'isPC': true, // 是否是PC
- 'isAndroid': false, // 是否是Android
- 'isIOS': false, // 是否是iOS
- 'string': 'PC',
- 'isWeChat': false, // 是否是微信
- 'isQQ': false, // 是否是QQ
- 'isChrome': false, // 是否是Chrome
- 'supportCopy': false, // 是否支持复制到剪切板
+ isOnline: true, // 是否http
+ isPC: true, // 是否是PC
+ isAndroid: false, // 是否是Android
+ isIOS: false, // 是否是iOS
+ string: 'PC',
+ isWeChat: false, // 是否是微信
+ isQQ: false, // 是否是QQ
+ isChrome: false, // 是否是Chrome
+ supportCopy: false, // 是否支持复制到剪切板
- 'fileInput': null, // FileInput
- 'fileReader': null, // 是否支持FileReader
- 'successCallback': null, // 读取成功
- 'errorCallback': null, // 读取失败
- }
+ fileInput: null, // FileInput
+ fileReader: null, // 是否支持FileReader
+ successCallback: null, // 读取成功
+ errorCallback: null // 读取失败
+ };
// 样式
this.domStyle = {
scale: 1.0,
ratio: 1.0,
- hdCanvas: ["damage", "ui", "data"],
+ hdCanvas: ['damage', 'ui', 'data'],
availableScale: [],
isVertical: false,
showStatusBar: true,
- toolbarBtn: false,
- }
+ toolbarBtn: false
+ };
this.bigmap = {
- canvas: ["bg", "event", "event2", "fg", "damage"],
+ canvas: ['bg', 'event', 'event2', 'fg', 'damage'],
offsetX: 0, // in pixel
offsetY: 0,
- posX: 0, //
+ posX: 0, //
posY: 0,
width: main.mode == 'editor' ? this.__SIZE__ : this._WIDTH_, // map width and height
height: main.mode == 'editor' ? this.__SIZE__ : this._HEIGHT_,
@@ -123,140 +124,149 @@ function core () {
extend: 10,
scale: 1.0,
tempCanvas: null, // A temp canvas for drawing
- cacheCanvas: null, // A cache canvas
- }
+ cacheCanvas: null // A cache canvas
+ };
this.saves = {
- "saveIndex": null,
- "ids": {},
- "autosave": {
- "data": null,
- "time": 0,
- "updated": false,
- "storage": true, // 是否把自动存档写入文件a
- "max": 20, // 自动存档最大回退数
- "now": 0,
+ saveIndex: null,
+ ids: {},
+ autosave: {
+ data: null,
+ time: 0,
+ updated: false,
+ storage: true, // 是否把自动存档写入文件a
+ max: 20, // 自动存档最大回退数
+ now: 0
},
- "favorite": [],
- "favoriteName": {},
- "cache": {}
- }
+ favorite: [],
+ favoriteName: {},
+ cache: {}
+ };
this.initStatus = {
- 'played': false,
- 'gameOver': false,
+ played: false,
+ gameOver: false,
// 勇士属性
- 'hero': {},
- 'heroCenter': { 'px': null, 'py': null },
+ hero: {},
+ heroCenter: { px: null, py: null },
// 当前地图
- 'floorId': null,
- 'thisMap': null,
- 'maps': null,
- 'bgmaps': {},
- 'fgmaps': {},
- 'mapBlockObjs': {},
- 'checkBlock': {}, // 每个点的阻激夹域信息
- 'damage': { // 每个点的显伤绘制
- 'posX': 0,
- 'posY': 0,
- 'data': [],
- 'extraData': [],
+ floorId: null,
+ thisMap: null,
+ maps: null,
+ bgmaps: {},
+ fgmaps: {},
+ mapBlockObjs: {},
+ checkBlock: {}, // 每个点的阻激夹域信息
+ damage: {
+ // 每个点的显伤绘制
+ posX: 0,
+ posY: 0,
+ data: [],
+ extraData: []
},
- 'lockControl': false,
+ lockControl: false,
// 勇士移动状态
- 'heroMoving': 0,
- 'heroStop': true,
+ heroMoving: 0,
+ heroStop: true,
// 自动寻路相关
- 'automaticRoute': {
- 'autoHeroMove': false,
- 'autoStep': 0,
- 'movedStep': 0,
- 'destStep': 0,
- 'destX': null,
- 'destY': null,
- 'offsetX': null,
- 'offsetY': null,
- 'autoStepRoutes': [],
- 'moveStepBeforeStop': [],
- 'lastDirection': null,
- 'cursorX': 0,
- 'cursorY': 0,
- "moveDirectly": false,
+ automaticRoute: {
+ autoHeroMove: false,
+ autoStep: 0,
+ movedStep: 0,
+ destStep: 0,
+ destX: null,
+ destY: null,
+ offsetX: null,
+ offsetY: null,
+ autoStepRoutes: [],
+ moveStepBeforeStop: [],
+ lastDirection: null,
+ cursorX: 0,
+ cursorY: 0,
+ moveDirectly: false
},
// 按下键的时间:为了判定双击
- 'downTime': null,
- 'ctrlDown': false,
- 'preview': {
- 'enabled': false,
- 'prepareDragging': false,
- 'dragging': false,
- 'px': 0,
- 'py': 0,
+ downTime: null,
+ ctrlDown: false,
+ preview: {
+ enabled: false,
+ prepareDragging: false,
+ dragging: false,
+ px: 0,
+ py: 0
},
// 路线&回放
- 'route': [],
- 'replay': {
- 'replaying': false,
- 'pausing': false,
- 'animate': false, // 正在某段动画中
- 'failed': false,
- 'toReplay': [],
- 'totalList': [],
- 'speed': 1.0,
- 'steps': 0,
- 'save': [],
+ route: [],
+ replay: {
+ replaying: false,
+ pausing: false,
+ animate: false, // 正在某段动画中
+ failed: false,
+ toReplay: [],
+ totalList: [],
+ speed: 1.0,
+ steps: 0,
+ save: []
},
// 录像折叠
- 'routeFolding': {},
+ routeFolding: {},
// event事件
- 'shops': {},
- 'event': {
- 'id': null,
- 'data': null,
- 'selection': null,
- 'ui': null,
- 'interval': null,
+ shops: {},
+ event: {
+ id: null,
+ data: null,
+ selection: null,
+ ui: null,
+ interval: null
},
- 'autoEvents': [],
- 'textAttribute': {
- 'position': "center",
- "offset": 0,
- "title": [255, 215, 0, 1],
- "background": [0, 0, 0, 0.85],
- "text": [255, 255, 255, 1],
- "titlefont": 22,
- "textfont": 16,
- "bold": false,
- "time": 0,
- "letterSpacing": 0,
- "animateTime": 0,
+ autoEvents: [],
+ textAttribute: {
+ position: 'center',
+ offset: 0,
+ title: [255, 215, 0, 1],
+ background: [0, 0, 0, 0.85],
+ text: [255, 255, 255, 1],
+ titlefont: 22,
+ textfont: 16,
+ bold: false,
+ time: 0,
+ letterSpacing: 0,
+ animateTime: 0
},
- "globalAttribute": {
- 'equipName': main.equipName || [],
- "statusLeftBackground": main.styles.statusLeftBackground || "url(project/materials/ground.png) repeat",
- "statusTopBackground": main.styles.statusTopBackground || "url(project/materials/ground.png) repeat",
- "toolsBackground": main.styles.toolsBackground || "url(project/materials/ground.png) repeat",
- "borderColor": main.styles.borderColor || [204, 204, 204, 1],
- "statusBarColor": main.styles.statusBarColor || [255, 255, 255, 1],
- "floorChangingStyle": main.styles.floorChangingStyle || "background-color: black; color: white",
- "selectColor": main.styles.selectColor || [255, 215, 0, 1],
- "font": main.styles.font || "Verdana"
+ globalAttribute: {
+ equipName: main.equipName || [],
+ statusLeftBackground:
+ main.styles.statusLeftBackground ||
+ 'url(project/materials/ground.png) repeat',
+ statusTopBackground:
+ main.styles.statusTopBackground ||
+ 'url(project/materials/ground.png) repeat',
+ toolsBackground:
+ main.styles.toolsBackground ||
+ 'url(project/materials/ground.png) repeat',
+ borderColor: main.styles.borderColor || [204, 204, 204, 1],
+ statusBarColor: main.styles.statusBarColor || [255, 255, 255, 1],
+ floorChangingStyle:
+ main.styles.floorChangingStyle ||
+ 'background-color: black; color: white',
+ selectColor: main.styles.selectColor || [255, 215, 0, 1],
+ font: main.styles.font || 'Verdana'
},
- 'curtainColor': null,
+ curtainColor: null,
// 动画
- 'globalAnimateObjs': [],
- 'floorAnimateObjs': [],
- 'boxAnimateObjs': [],
- 'autotileAnimateObjs': [],
- "globalAnimateStatus": 0,
- 'animateObjs': [],
+ globalAnimateObjs: [],
+ floorAnimateObjs: [],
+ boxAnimateObjs: [],
+ autotileAnimateObjs: [],
+ globalAnimateStatus: 0,
+ animateObjs: []
};
// 标记的楼层列表,用于数据统计
this.markedFloorIds = {};
@@ -265,7 +275,10 @@ function core () {
if (main.mode == 'editor') {
document.documentElement.style.setProperty('--size', this.__SIZE__);
- document.documentElement.style.setProperty('--pixel', this.__PIXELS__ + 'px');
+ document.documentElement.style.setProperty(
+ '--pixel',
+ this.__PIXELS__ + 'px'
+ );
}
}
@@ -274,8 +287,7 @@ function core () {
////// 初始化 //////
core.prototype.init = function (coreData, callback) {
this._forwardFuncs();
- for (var key in coreData)
- core[key] = coreData[key];
+ for (var key in coreData) core[key] = coreData[key];
this._init_flags();
this._init_platform();
this._init_others();
@@ -284,10 +296,14 @@ core.prototype.init = function (coreData, callback) {
// 初始化画布
for (var name in core.canvas) {
if (core.domStyle.hdCanvas.indexOf(name) >= 0)
- core.maps._setHDCanvasSize(core.canvas[name], b ? core.__PIXELS__ : core._PX_, b ? core.__PIXELS__ : core._PY_);
+ core.maps._setHDCanvasSize(
+ core.canvas[name],
+ b ? core.__PIXELS__ : core._PX_,
+ b ? core.__PIXELS__ : core._PY_
+ );
else {
- core.canvas[name].canvas.width = (b ? core.__PIXELS__ : core._PX_);
- core.canvas[name].canvas.height = (b ? core.__PIXELS__ : core._PY_);
+ core.canvas[name].canvas.width = b ? core.__PIXELS__ : core._PX_;
+ core.canvas[name].canvas.height = b ? core.__PIXELS__ : core._PY_;
}
}
@@ -298,7 +314,7 @@ core.prototype.init = function (coreData, callback) {
});
core.dom.musicBtn.style.display = 'block';
core.setMusicBtn();
-}
+};
core.prototype._init_flags = function () {
core.flags = core.clone(core.data.flags);
@@ -314,9 +330,11 @@ core.prototype._init_flags = function () {
core.dom.versionLabel.innerText = core.firstData.version;
core.dom.logoLabel.innerText = core.firstData.title;
- document.title = core.firstData.title + " - HTML5魔塔";
- document.getElementById("startLogo").innerText = core.firstData.title;
- (core.firstData.shops || []).forEach(function (t) { core.initStatus.shops[t.id] = t; });
+ document.title = core.firstData.title + ' - HTML5魔塔';
+ document.getElementById('startLogo').innerText = core.firstData.title;
+ (core.firstData.shops || []).forEach(function (t) {
+ core.initStatus.shops[t.id] = t;
+ });
core.maps._initFloors();
// 初始化怪物、道具等
@@ -328,7 +346,9 @@ core.prototype._init_flags = function () {
for (var floorId in core.floors) {
var autoEvents = core.floors[floorId].autoEvent || {};
for (var loc in autoEvents) {
- var locs = loc.split(","), x = parseInt(locs[0]), y = parseInt(locs[1]);
+ var locs = loc.split(','),
+ x = parseInt(locs[0]),
+ y = parseInt(locs[1]);
for (var index in autoEvents[loc]) {
var autoEvent = core.clone(autoEvents[loc][index]);
if (autoEvent && autoEvent.condition && autoEvent.data) {
@@ -336,8 +356,11 @@ core.prototype._init_flags = function () {
autoEvent.x = x;
autoEvent.y = y;
autoEvent.index = index;
- autoEvent.symbol = floorId + "@" + x + "@" + y + "@" + index;
- autoEvent.condition = core.replaceValue(autoEvent.condition);
+ autoEvent.symbol =
+ floorId + '@' + x + '@' + y + '@' + index;
+ autoEvent.condition = core.replaceValue(
+ autoEvent.condition
+ );
autoEvent.data = core.precompile(autoEvent.data);
core.initStatus.autoEvents.push(autoEvent);
}
@@ -351,18 +374,44 @@ core.prototype._init_flags = function () {
if (!equip.equip.equipEvent && !equip.equip.unequipEvent) continue;
var equipFlag = '_equipEvent_' + equipId;
var autoEvent1 = {
- symbol: "_equipEvent_" + equipId,
+ symbol: '_equipEvent_' + equipId,
currentFloor: false,
multiExecute: true,
- condition: "core.hasEquip('" + equipId + "') && !core.hasFlag('" + equipFlag + "')",
- data: core.precompile([{ "type": "setValue", "name": "flag:" + equipFlag, "value": "true" }].concat(equip.equip.equipEvent || [])),
+ condition:
+ "core.hasEquip('" +
+ equipId +
+ "') && !core.hasFlag('" +
+ equipFlag +
+ "')",
+ data: core.precompile(
+ [
+ {
+ type: 'setValue',
+ name: 'flag:' + equipFlag,
+ value: 'true'
+ }
+ ].concat(equip.equip.equipEvent || [])
+ )
};
var autoEvent2 = {
- symbol: "_unequipEvent_" + equipId,
+ symbol: '_unequipEvent_' + equipId,
currentFloor: false,
multiExecute: true,
- condition: "!core.hasEquip('" + equipId + "') && core.hasFlag('" + equipFlag + "')",
- data: core.precompile([{ "type": "setValue", "name": "flag:" + equipFlag, "value": "null" }].concat(equip.equip.unequipEvent || [])),
+ condition:
+ "!core.hasEquip('" +
+ equipId +
+ "') && core.hasFlag('" +
+ equipFlag +
+ "')",
+ data: core.precompile(
+ [
+ {
+ type: 'setValue',
+ name: 'flag:' + equipFlag,
+ value: 'null'
+ }
+ ].concat(equip.equip.unequipEvent || [])
+ )
};
core.initStatus.autoEvents.push(autoEvent1);
core.initStatus.autoEvents.push(autoEvent2);
@@ -372,33 +421,53 @@ core.prototype._init_flags = function () {
if (e1.floorId == null) return 1;
if (e2.floorId == null) return -1;
if (e1.priority != e2.priority) return e2.priority - e1.priority;
- if (e1.floorId != e2.floorId) return core.floorIds.indexOf(e1.floorId) - core.floorIds.indexOf(e2.floorId);
+ if (e1.floorId != e2.floorId)
+ return (
+ core.floorIds.indexOf(e1.floorId) -
+ core.floorIds.indexOf(e2.floorId)
+ );
if (e1.x != e2.x) return e1.x - e2.x;
if (e1.y != e2.y) return e1.y - e2.y;
return e1.index - e2.index;
- })
-
-}
+ });
+};
core.prototype._init_sys_flags = function () {
if (core.flags.equipboxButton) core.flags.equipment = true;
core.flags.displayEnemyDamage = core.getLocalStorage('enemyDamage', true);
core.flags.displayCritical = core.getLocalStorage('critical', true);
core.flags.displayExtraDamage = core.getLocalStorage('extraDamage', true);
- core.flags.enableEnemyPoint = core.getLocalStorage('enableEnemyPoint', core.flags.enableEnemyPoint);
+ core.flags.enableEnemyPoint = core.getLocalStorage(
+ 'enableEnemyPoint',
+ core.flags.enableEnemyPoint
+ );
core.flags.leftHandPrefer = core.getLocalStorage('leftHandPrefer', false);
core.flags.extraDamageType = core.getLocalStorage('extraDamageType', 2);
// 行走速度
- core.values.moveSpeed = core.getLocalStorage('moveSpeed', core.values.moveSpeed || 100);
- core.values.floorChangeTime = core.getLocalStorage('floorChangeTime', core.values.floorChangeTime);
+ core.values.moveSpeed = core.getLocalStorage(
+ 'moveSpeed',
+ core.values.moveSpeed || 100
+ );
+ core.values.floorChangeTime = core.getLocalStorage(
+ 'floorChangeTime',
+ core.values.floorChangeTime
+ );
if (core.values.floorChangeTime == null) core.values.floorChangeTime = 500;
- core.flags.enableHDCanvas = core.getLocalStorage('enableHDCanvas', !core.platform.isIOS);
-}
+ core.flags.enableHDCanvas = core.getLocalStorage(
+ 'enableHDCanvas',
+ !core.platform.isIOS
+ );
+};
core.prototype._init_platform = function () {
- core.platform.isOnline = location.protocol.indexOf("http") == 0;
- if (!core.platform.isOnline) alert("请勿直接打开html文件!使用启动服务或者APP进行离线游戏。");
- window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
+ core.platform.isOnline = location.protocol.indexOf('http') == 0;
+ if (!core.platform.isOnline)
+ alert('请勿直接打开html文件!使用启动服务或者APP进行离线游戏。');
+ window.AudioContext =
+ window.AudioContext ||
+ window.webkitAudioContext ||
+ window.mozAudioContext ||
+ window.msAudioContext;
core.musicStatus.bgmStatus = core.getLocalStorage('bgmStatus', true);
core.musicStatus.soundStatus = core.getLocalStorage('soundStatus', true);
//新增 userVolume 默认值0.7
@@ -407,23 +476,38 @@ core.prototype._init_platform = function () {
core.musicStatus.audioContext = new window.AudioContext();
core.musicStatus.gainNode = core.musicStatus.audioContext.createGain();
core.musicStatus.gainNode.gain.value = core.musicStatus.userVolume;
- core.musicStatus.gainNode.connect(core.musicStatus.audioContext.destination);
+ core.musicStatus.gainNode.connect(
+ core.musicStatus.audioContext.destination
+ );
} catch (e) {
- console.log("该浏览器不支持AudioContext");
+ console.log('该浏览器不支持AudioContext');
core.musicStatus.audioContext = null;
}
- ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"].forEach(function (t) {
- if (navigator.userAgent.indexOf(t) >= 0) {
- if (t == 'iPhone' || t == 'iPad' || t == 'iPod') core.platform.isIOS = true;
- if (t == 'Android') core.platform.isAndroid = true;
- core.platform.isPC = false;
+ ['Android', 'iPhone', 'SymbianOS', 'Windows Phone', 'iPad', 'iPod'].forEach(
+ function (t) {
+ if (navigator.userAgent.indexOf(t) >= 0) {
+ if (t == 'iPhone' || t == 'iPad' || t == 'iPod')
+ core.platform.isIOS = true;
+ if (t == 'Android') core.platform.isAndroid = true;
+ core.platform.isPC = false;
+ }
}
- });
- core.platform.string = core.platform.isPC ? "PC" : core.platform.isAndroid ? "Android" : core.platform.isIOS ? "iOS" : "";
- core.platform.supportCopy = document.queryCommandSupported && document.queryCommandSupported("copy");
+ );
+ core.platform.string = core.platform.isPC
+ ? 'PC'
+ : core.platform.isAndroid
+ ? 'Android'
+ : core.platform.isIOS
+ ? 'iOS'
+ : '';
+ core.platform.supportCopy =
+ document.queryCommandSupported &&
+ document.queryCommandSupported('copy');
var chrome = /Chrome\/(\d+)\./i.exec(navigator.userAgent);
if (chrome && parseInt(chrome[1]) >= 50) core.platform.isChrome = true;
- core.platform.isSafari = /Safari/i.test(navigator.userAgent) && !/Chrome/i.test(navigator.userAgent);
+ core.platform.isSafari =
+ /Safari/i.test(navigator.userAgent) &&
+ !/Chrome/i.test(navigator.userAgent);
core.platform.isQQ = /QQ/i.test(navigator.userAgent);
core.platform.isWeChat = /MicroMessenger/i.test(navigator.userAgent);
if (window.FileReader) {
@@ -432,33 +516,55 @@ core.prototype._init_platform = function () {
core.readFileContent(core.platform.fileReader.result);
};
core.platform.fileReader.onerror = function () {
- if (core.platform.errorCallback)
- core.platform.errorCallback();
- }
+ if (core.platform.errorCallback) core.platform.errorCallback();
+ };
}
- core.flags.enableHDCanvas = core.getLocalStorage('enableHDCanvas', !core.platform.isIOS);
+ core.flags.enableHDCanvas = core.getLocalStorage(
+ 'enableHDCanvas',
+ !core.platform.isIOS
+ );
if (main.mode != 'editor') {
core.domStyle.scale = core.getLocalStorage('scale', 1);
- if (core.flags.enableHDCanvas) core.domStyle.ratio = Math.max(window.devicePixelRatio || 1, core.domStyle.scale);
+ if (core.flags.enableHDCanvas)
+ core.domStyle.ratio = Math.max(
+ window.devicePixelRatio || 1,
+ core.domStyle.scale
+ );
}
-}
+};
core.prototype._init_others = function () {
// 一些额外的东西
- core.material.groundCanvas = document.createElement('canvas').getContext('2d');
- core.material.groundCanvas.canvas.width = core.material.groundCanvas.canvas.height = 32;
- core.material.groundPattern = core.material.groundCanvas.createPattern(core.material.groundCanvas.canvas, 'repeat');
+ core.material.groundCanvas = document
+ .createElement('canvas')
+ .getContext('2d');
+ core.material.groundCanvas.canvas.width =
+ core.material.groundCanvas.canvas.height = 32;
+ core.material.groundPattern = core.material.groundCanvas.createPattern(
+ core.material.groundCanvas.canvas,
+ 'repeat'
+ );
core.bigmap.tempCanvas = document.createElement('canvas').getContext('2d');
core.bigmap.cacheCanvas = document.createElement('canvas').getContext('2d');
- core.loadImage("materials", 'fog', function (name, img) { core.animateFrame.weather.fog = img; });
- core.loadImage("materials", "cloud", function (name, img) { core.animateFrame.weather.cloud = img; })
- core.loadImage("materials", "sun", function (name, img) { core.animateFrame.weather.sun = img; })
- core.loadImage("materials", 'keyboard', function (name, img) { core.material.images.keyboard = img; });
+ core.loadImage('materials', 'fog', function (name, img) {
+ core.animateFrame.weather.fog = img;
+ });
+ core.loadImage('materials', 'cloud', function (name, img) {
+ core.animateFrame.weather.cloud = img;
+ });
+ core.loadImage('materials', 'sun', function (name, img) {
+ core.animateFrame.weather.sun = img;
+ });
+ core.loadImage('materials', 'keyboard', function (name, img) {
+ core.material.images.keyboard = img;
+ });
// 记录存档编号
core.saves.saveIndex = core.getLocalStorage('saveIndex', 1);
- core.control.getSaveIndexes(function (indexes) { core.saves.ids = indexes; });
-}
+ core.control.getSaveIndexes(function (indexes) {
+ core.saves.ids = indexes;
+ });
+};
core.prototype._afterLoadResources = function (callback) {
// 初始化地图
@@ -475,35 +581,43 @@ core.prototype._afterLoadResources = function (callback) {
console.warn('无法裁剪非png格式图片:' + name);
return;
}
- var arr = core.splitImage(core.material.images.images[name], one.width, one.height);
+ var arr = core.splitImage(
+ core.material.images.images[name],
+ one.width,
+ one.height
+ );
for (var i = 0; i < arr.length; ++i) {
- core.material.images.images[(one.prefix || "") + i + '.png'] = arr[i];
+ core.material.images.images[(one.prefix || '') + i + '.png'] =
+ arr[i];
}
});
- if (core.plugin._afterLoadResources)
- core.plugin._afterLoadResources();
+ if (core.plugin._afterLoadResources) core.plugin._afterLoadResources();
core.showStartAnimate();
if (callback) callback();
-}
+};
core.prototype._init_plugins = function () {
- core.plugin = new function () { };
+ core.plugin = new (function () {})();
for (var name in plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1) {
- if (plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1[name] instanceof Function) {
+ if (
+ plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1[name] instanceof
+ Function
+ ) {
try {
- plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1[name].apply(core.plugin);
- }
- catch (e) {
+ plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1[name].apply(
+ core.plugin
+ );
+ } catch (e) {
console.error(e);
- console.error("无法初始化插件" + name);
+ console.error('无法初始化插件' + name);
}
}
}
- core._forwardFunc("plugin");
-}
+ core._forwardFunc('plugin');
+};
core.prototype._forwardFuncs = function () {
for (var i = 0; i < main.loadList.length; ++i) {
@@ -511,12 +625,15 @@ core.prototype._forwardFuncs = function () {
if (name == 'core') continue;
this._forwardFunc(name);
}
-}
+};
core.prototype._forwardFunc = function (name, funcname) {
if (funcname == null) {
for (funcname in core[name]) {
- if (funcname.charAt(0) != "_" && core[name][funcname] instanceof Function) {
+ if (
+ funcname.charAt(0) != '_' &&
+ core[name][funcname] instanceof Function
+ ) {
this._forwardFunc(name, funcname);
}
}
@@ -524,14 +641,36 @@ core.prototype._forwardFunc = function (name, funcname) {
}
if (core[funcname]) {
- console.error("ERROR: 无法转发 " + name + " 中的函数 " + funcname + " 到 core 中!同名函数已存在。");
+ console.error(
+ 'ERROR: 无法转发 ' +
+ name +
+ ' 中的函数 ' +
+ funcname +
+ ' 到 core 中!同名函数已存在。'
+ );
return;
}
- var parameterInfo = /^\s*function\s*[\w_$]*\(([\w_,$\s]*)\)\s*\{/.exec(core[name][funcname].toString());
- var parameters = (parameterInfo == null ? "" : parameterInfo[1]).replace(/\s*/g, '').replace(/,/g, ', ');
+ var parameterInfo = /^\s*function\s*[\w_$]*\(([\w_,$\s]*)\)\s*\{/.exec(
+ core[name][funcname].toString()
+ );
+ var parameters = (parameterInfo == null ? '' : parameterInfo[1])
+ .replace(/\s*/g, '')
+ .replace(/,/g, ', ');
// core[funcname] = new Function(parameters, "return core."+name+"."+funcname+"("+parameters+");");
- eval("core." + funcname + " = function (" + parameters + ") {\n\treturn core." + name + "." + funcname + ".apply(core." + name + ", arguments);\n}");
-}
+ eval(
+ 'core.' +
+ funcname +
+ ' = function (' +
+ parameters +
+ ') {\n\treturn core.' +
+ name +
+ '.' +
+ funcname +
+ '.apply(core.' +
+ name +
+ ', arguments);\n}'
+ );
+};
core.prototype.doFunc = function (func, _this) {
if (typeof func == 'string') {
@@ -539,7 +678,7 @@ core.prototype.doFunc = function (func, _this) {
_this = core.plugin;
}
return func.apply(_this, Array.prototype.slice.call(arguments, 2));
-}
+};
// return new Core();
diff --git a/public/libs/data.js b/public/libs/data.js
index 8fbc63f..6df0a4c 100644
--- a/public/libs/data.js
+++ b/public/libs/data.js
@@ -1,7 +1,8 @@
+///
-"use strict";
+'use strict';
-function data () {
+function data() {
this._init();
}
@@ -10,4 +11,4 @@ data.prototype._init = function () {
this.values = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.values;
this.flags = data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d.flags;
//delete(data_a1e2fb4a_e986_4524_b0da_9b7ba7c0874d);
-}
\ No newline at end of file
+};
diff --git a/public/libs/enemys.js b/public/libs/enemys.js
index 122657a..ba40d73 100644
--- a/public/libs/enemys.js
+++ b/public/libs/enemys.js
@@ -1,7 +1,8 @@
+///
-"use strict";
+'use strict';
-function enemys () {
+function enemys() {
this._init();
}
@@ -14,10 +15,10 @@ enemys.prototype._init = function () {
}
if (main.mode == 'play') {
this.enemydata.hasSpecial = function (a, b) {
- return core.enemys.hasSpecial(a, b)
+ return core.enemys.hasSpecial(a, b);
};
}
-}
+};
enemys.prototype.getEnemys = function () {
var enemys = core.clone(this.enemys);
@@ -36,13 +37,20 @@ enemys.prototype.getEnemys = function () {
if (downId != null && downId != id && enemys[downId]) {
enemys[id] = { id: id };
for (var property in enemys[downId]) {
- if (property != 'id' && enemys[downId].hasOwnProperty(property)) {
+ if (
+ property != 'id' &&
+ enemys[downId].hasOwnProperty(property)
+ ) {
(function (id, downId, property) {
Object.defineProperty(enemys[id], property, {
- get: function () { return enemys[downId][property] },
- set: function (v) { enemys[downId][property] = v },
+ get: function () {
+ return enemys[downId][property];
+ },
+ set: function (v) {
+ enemys[downId][property] = v;
+ },
enumerable: true
- })
+ });
})(id, downId, property);
}
}
@@ -50,7 +58,7 @@ enemys.prototype.getEnemys = function () {
}
}
return enemys;
-}
+};
////// 判断是否含有某特殊属性 //////
enemys.prototype.hasSpecial = function (special, test) {
@@ -73,11 +81,11 @@ enemys.prototype.hasSpecial = function (special, test) {
}
return false;
-}
+};
enemys.prototype.getSpecials = function () {
return this.enemydata.getSpecials();
-}
+};
////// 获得所有特殊属性的名称 //////
enemys.prototype.getSpecialText = function (enemy) {
@@ -94,7 +102,7 @@ enemys.prototype.getSpecialText = function (enemy) {
}
}
return text;
-}
+};
////// 获得所有特殊属性的颜色 //////
enemys.prototype.getSpecialColor = function (enemy) {
@@ -111,8 +119,7 @@ enemys.prototype.getSpecialColor = function (enemy) {
}
}
return colors;
-
-}
+};
////// 获得所有特殊属性的额外标记 //////
enemys.prototype.getSpecialFlag = function (enemy) {
@@ -125,11 +132,11 @@ enemys.prototype.getSpecialFlag = function (enemy) {
if (specials) {
for (var i = 0; i < specials.length; i++) {
if (this.hasSpecial(special, specials[i][0]))
- flag |= (specials[i][4] || 0);
+ flag |= specials[i][4] || 0;
}
}
return flag;
-}
+};
////// 获得每个特殊属性的说明 //////
enemys.prototype.getSpecialHint = function (enemy, special) {
@@ -140,19 +147,30 @@ enemys.prototype.getSpecialHint = function (enemy, special) {
var hints = [];
for (var i = 0; i < specials.length; i++) {
if (this.hasSpecial(enemy, specials[i][0]))
- hints.push("\r[" + core.arrayToRGBA(specials[i][3] || "#FF6A6A") + "]\\d" + this._calSpecialContent(enemy, specials[i][1]) +
- ":\\d\r[]" + this._calSpecialContent(enemy, specials[i][2]));
+ hints.push(
+ '\r[' +
+ core.arrayToRGBA(specials[i][3] || '#FF6A6A') +
+ ']\\d' +
+ this._calSpecialContent(enemy, specials[i][1]) +
+ ':\\d\r[]' +
+ this._calSpecialContent(enemy, specials[i][2])
+ );
}
return hints;
}
- if (specials == null) return "";
+ if (specials == null) return '';
for (var i = 0; i < specials.length; i++) {
if (special == specials[i][0])
- return "\r[#FF6A6A]\\d" + this._calSpecialContent(enemy, specials[i][1]) + ":\\d\r[]" + this._calSpecialContent(enemy, specials[i][2]);
+ return (
+ '\r[#FF6A6A]\\d' +
+ this._calSpecialContent(enemy, specials[i][1]) +
+ ':\\d\r[]' +
+ this._calSpecialContent(enemy, specials[i][2])
+ );
}
- return "";
-}
+ return '';
+};
enemys.prototype._calSpecialContent = function (enemy, content) {
if (typeof content == 'string') return content;
@@ -160,14 +178,18 @@ enemys.prototype._calSpecialContent = function (enemy, content) {
if (content instanceof Function) {
return content(enemy);
}
- return "";
-}
+ return '';
+};
////// 获得某个点上某个怪物的某项属性 //////
enemys.prototype.getEnemyValue = function (enemy, name, x, y, floorId) {
floorId = floorId || core.status.floorId;
- if ((((flags.enemyOnPoint || {})[floorId] || {})[x + "," + y] || {})[name] != null) {
- return flags.enemyOnPoint[floorId][x + "," + y][name];
+ if (
+ (((flags.enemyOnPoint || {})[floorId] || {})[x + ',' + y] || {})[
+ name
+ ] != null
+ ) {
+ return flags.enemyOnPoint[floorId][x + ',' + y][name];
}
if (enemy == null) {
var block = core.getBlock(x, y, floorId);
@@ -177,14 +199,14 @@ enemys.prototype.getEnemyValue = function (enemy, name, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
if (enemy == null) return null;
return enemy[name];
-}
+};
////// 能否获胜 //////
enemys.prototype.canBattle = function (enemy, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
var damage = this.getDamage(enemy, x, y, floorId);
return damage != null && damage < core.status.hero.hp;
-}
+};
enemys.prototype.getDamageString = function (enemy, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
@@ -193,40 +215,43 @@ enemys.prototype.getDamageString = function (enemy, x, y, floorId) {
var color = '#000000';
if (damage == null) {
- damage = "???";
+ damage = '???';
color = '#FF2222';
- }
- else {
+ } else {
if (damage <= 0) color = '#11FF11';
else if (damage < core.status.hero.hp / 3) color = '#FFFFFF';
- else if (damage < core.status.hero.hp * 2 / 3) color = '#FFFF00';
+ else if (damage < (core.status.hero.hp * 2) / 3) color = '#FFFF00';
else if (damage < core.status.hero.hp) color = '#FF9933';
else color = '#FF2222';
damage = core.formatBigNumber(damage, true);
- if (core.enemys.hasSpecial(enemy, 19))
- damage += "+";
- if (core.enemys.hasSpecial(enemy, 21))
- damage += "-";
- if (core.enemys.hasSpecial(enemy, 11))
- damage += "^";
+ if (core.enemys.hasSpecial(enemy, 19)) damage += '+';
+ if (core.enemys.hasSpecial(enemy, 21)) damage += '-';
+ if (core.enemys.hasSpecial(enemy, 11)) damage += '^';
}
return {
- "damage": damage,
- "color": color
+ damage: damage,
+ color: color
};
-}
+};
////// 接下来N个临界值和临界减伤计算 //////
enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
number = number || 1;
- var specialCriticals = this._nextCriticals_special(enemy, number, x, y, floorId);
+ var specialCriticals = this._nextCriticals_special(
+ enemy,
+ number,
+ x,
+ y,
+ floorId
+ );
if (specialCriticals != null) return specialCriticals;
var info = this.getDamageInfo(enemy, null, x, y, floorId);
- if (info == null) { // 如果未破防...
+ if (info == null) {
+ // 如果未破防...
var overAtk = this._nextCriticals_overAtk(enemy, x, y, floorId);
if (overAtk == null) return [];
if (typeof overAtk[1] == 'number') return [[overAtk[0], -overAtk[1]]];
@@ -242,45 +267,91 @@ enemys.prototype.nextCriticals = function (enemy, number, x, y, floorId) {
if (core.flags.useLoop) {
if (core.status.hero.atk <= (main.criticalUseLoop || 1)) {
- return this._nextCriticals_useLoop(enemy, info, number, x, y, floorId);
+ return this._nextCriticals_useLoop(
+ enemy,
+ info,
+ number,
+ x,
+ y,
+ floorId
+ );
+ } else {
+ return this._nextCriticals_useBinarySearch(
+ enemy,
+ info,
+ number,
+ x,
+ y,
+ floorId
+ );
}
- else {
- return this._nextCriticals_useBinarySearch(enemy, info, number, x, y, floorId);
- }
- }
- else {
+ } else {
return this._nextCriticals_useTurn(enemy, info, number, x, y, floorId);
}
-}
+};
/// 未破防临界采用二分计算
enemys.prototype._nextCriticals_overAtk = function (enemy, x, y, floorId) {
var calNext = function (currAtk, maxAtk) {
- var start = currAtk, end = maxAtk;
+ var start = currAtk,
+ end = maxAtk;
if (start > end) return null;
while (start < end) {
var mid = Math.floor((start + end) / 2);
if (mid - start > end - mid) mid--;
- var nextInfo = core.enemys.getDamageInfo(enemy, { "atk": mid }, x, y, floorId);
+ var nextInfo = core.enemys.getDamageInfo(
+ enemy,
+ { atk: mid },
+ x,
+ y,
+ floorId
+ );
if (nextInfo != null) end = mid;
else start = mid + 1;
}
- var nextInfo = core.enemys.getDamageInfo(enemy, { "atk": start }, x, y, floorId);
- return nextInfo == null ? null : [start - core.status.hero.atk, nextInfo];
- }
- return calNext(core.status.hero.atk + 1,
- core.getEnemyValue(enemy, 'hp', x, y, floorId) + core.getEnemyValue(enemy, 'def', x, y, floorId));
-}
+ var nextInfo = core.enemys.getDamageInfo(
+ enemy,
+ { atk: start },
+ x,
+ y,
+ floorId
+ );
+ return nextInfo == null
+ ? null
+ : [start - core.status.hero.atk, nextInfo];
+ };
+ return calNext(
+ core.status.hero.atk + 1,
+ core.getEnemyValue(enemy, 'hp', x, y, floorId) +
+ core.getEnemyValue(enemy, 'def', x, y, floorId)
+ );
+};
-enemys.prototype._nextCriticals_special = function (enemy, number, x, y, floorId) {
+enemys.prototype._nextCriticals_special = function (
+ enemy,
+ number,
+ x,
+ y,
+ floorId
+) {
if (this.hasSpecial(enemy.special, 10) || this.hasSpecial(enemy.special, 3))
return []; // 模仿or坚固临界
return null;
-}
+};
-enemys.prototype._nextCriticals_useLoop = function (enemy, info, number, x, y, floorId) {
- var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, pre = info.damage;
+enemys.prototype._nextCriticals_useLoop = function (
+ enemy,
+ info,
+ number,
+ x,
+ y,
+ floorId
+) {
+ var mon_hp = info.mon_hp,
+ hero_atk = core.status.hero.atk,
+ mon_def = info.mon_def,
+ pre = info.damage;
var list = [];
var start_atk = hero_atk;
if (info.__over__) {
@@ -288,8 +359,8 @@ enemys.prototype._nextCriticals_useLoop = function (enemy, info, number, x, y, f
list.push([info.__overAtk__, -info.damage]);
}
for (var atk = start_atk + 1; atk <= mon_hp + mon_def; atk++) {
- var nextInfo = this.getDamageInfo(enemy, { "atk": atk }, x, y, floorId);
- if (nextInfo == null || (typeof nextInfo == 'number')) break;
+ var nextInfo = this.getDamageInfo(enemy, { atk: atk }, x, y, floorId);
+ if (nextInfo == null || typeof nextInfo == 'number') break;
if (pre > nextInfo.damage) {
pre = nextInfo.damage;
list.push([atk - hero_atk, info.damage - nextInfo.damage]);
@@ -299,10 +370,20 @@ enemys.prototype._nextCriticals_useLoop = function (enemy, info, number, x, y, f
}
if (list.length == 0) list.push([0, 0]);
return list;
-}
+};
-enemys.prototype._nextCriticals_useBinarySearch = function (enemy, info, number, x, y, floorId) {
- var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, pre = info.damage;
+enemys.prototype._nextCriticals_useBinarySearch = function (
+ enemy,
+ info,
+ number,
+ x,
+ y,
+ floorId
+) {
+ var mon_hp = info.mon_hp,
+ hero_atk = core.status.hero.atk,
+ mon_def = info.mon_def,
+ pre = info.damage;
var list = [];
var start_atk = hero_atk;
if (info.__over__) {
@@ -310,20 +391,37 @@ enemys.prototype._nextCriticals_useBinarySearch = function (enemy, info, number,
list.push([info.__overAtk__, -info.damage]);
}
var calNext = function (currAtk, maxAtk) {
- var start = Math.floor(currAtk), end = Math.floor(maxAtk);
+ var start = Math.floor(currAtk),
+ end = Math.floor(maxAtk);
if (start > end) return null;
while (start < end) {
var mid = Math.floor((start + end) / 2);
if (mid - start > end - mid) mid--;
- var nextInfo = core.enemys.getDamageInfo(enemy, { "atk": mid }, x, y, floorId);
- if (nextInfo == null || (typeof nextInfo == 'number')) return null;
+ var nextInfo = core.enemys.getDamageInfo(
+ enemy,
+ { atk: mid },
+ x,
+ y,
+ floorId
+ );
+ if (nextInfo == null || typeof nextInfo == 'number') return null;
if (pre > nextInfo.damage) end = mid;
else start = mid + 1;
}
- var nextInfo = core.enemys.getDamageInfo(enemy, { "atk": start }, x, y, floorId);
- return nextInfo == null || (typeof nextInfo == 'number') || nextInfo.damage >= pre ? null : [start, nextInfo.damage];
- }
+ var nextInfo = core.enemys.getDamageInfo(
+ enemy,
+ { atk: start },
+ x,
+ y,
+ floorId
+ );
+ return nextInfo == null ||
+ typeof nextInfo == 'number' ||
+ nextInfo.damage >= pre
+ ? null
+ : [start, nextInfo.damage];
+ };
var currAtk = start_atk;
while (true) {
var next = calNext(currAtk + 1, mon_hp + mon_def, pre);
@@ -336,16 +434,35 @@ enemys.prototype._nextCriticals_useBinarySearch = function (enemy, info, number,
}
if (list.length == 0) list.push([0, 0]);
return list;
-}
+};
-enemys.prototype._nextCriticals_useTurn = function (enemy, info, number, x, y, floorId) {
- var mon_hp = info.mon_hp, hero_atk = core.status.hero.atk, mon_def = info.mon_def, turn = info.turn;
+enemys.prototype._nextCriticals_useTurn = function (
+ enemy,
+ info,
+ number,
+ x,
+ y,
+ floorId
+) {
+ var mon_hp = info.mon_hp,
+ hero_atk = core.status.hero.atk,
+ mon_def = info.mon_def,
+ turn = info.turn;
// ------ 超大回合数强制使用二分算临界
// 以避免1攻10e回合,2攻5e回合导致下述循环卡死问题
- if (turn >= 1e6) { // 100w回合以上强制二分计算临界
- return this._nextCriticals_useBinarySearch(enemy, info, number, x, y, floorId);
+ if (turn >= 1e6) {
+ // 100w回合以上强制二分计算临界
+ return this._nextCriticals_useBinarySearch(
+ enemy,
+ info,
+ number,
+ x,
+ y,
+ floorId
+ );
}
- var list = [], pre = null;
+ var list = [],
+ pre = null;
var start_atk = hero_atk;
if (info.__over__) {
start_atk += info.__overAtk__;
@@ -357,34 +474,48 @@ enemys.prototype._nextCriticals_useTurn = function (enemy, info, number, x, y, f
nextAtk = Math.ceil(nextAtk / core.getBuff('atk'));
if (nextAtk <= start_atk) break;
if (nextAtk != pre) {
- var nextInfo = this.getDamageInfo(enemy, { "atk": nextAtk }, x, y, floorId);
- if (nextInfo == null || (typeof nextInfo == 'number')) break;
- list.push([nextAtk - hero_atk, Math.floor(info.damage - nextInfo.damage)]);
+ var nextInfo = this.getDamageInfo(
+ enemy,
+ { atk: nextAtk },
+ x,
+ y,
+ floorId
+ );
+ if (nextInfo == null || typeof nextInfo == 'number') break;
+ list.push([
+ nextAtk - hero_atk,
+ Math.floor(info.damage - nextInfo.damage)
+ ]);
if (nextInfo.damage <= 0 && !core.flags.enableNegativeDamage) break;
pre = nextAtk;
}
- if (list.length >= number)
- break;
+ if (list.length >= number) break;
}
if (list.length == 0) list.push([0, 0]);
return list;
-}
+};
////// N防减伤计算 //////
enemys.prototype.getDefDamage = function (enemy, k, x, y, floorId) {
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
k = k || 1;
var nowDamage = this._getDamage(enemy, null, x, y, floorId);
- var nextDamage = this._getDamage(enemy, { "def": core.status.hero.def + k }, x, y, floorId);
- if (nowDamage == null || nextDamage == null) return "???";
+ var nextDamage = this._getDamage(
+ enemy,
+ { def: core.status.hero.def + k },
+ x,
+ y,
+ floorId
+ );
+ if (nowDamage == null || nextDamage == null) return '???';
return nowDamage - nextDamage;
-}
+};
enemys.prototype.getEnemyInfo = function (enemy, hero, x, y, floorId) {
if (enemy == null) return null;
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
- return this.enemydata.getEnemyInfo(enemy, hero, x, y, floorId)
-}
+ return this.enemydata.getEnemyInfo(enemy, hero, x, y, floorId);
+};
////// 获得战斗伤害信息(实际伤害计算函数) //////
enemys.prototype.getDamageInfo = function (enemy, hero, x, y, floorId) {
@@ -392,12 +523,12 @@ enemys.prototype.getDamageInfo = function (enemy, hero, x, y, floorId) {
// 移动到了脚本编辑 - getDamageInfo中
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
return this.enemydata.getDamageInfo(enemy, hero, x, y, floorId);
-}
+};
////// 获得在某个勇士属性下怪物伤害 //////
enemys.prototype.getDamage = function (enemy, x, y, floorId) {
return this._getDamage(enemy, null, x, y, floorId);
-}
+};
enemys.prototype._getDamage = function (enemy, hero, x, y, floorId) {
if (enemy == null) enemy = core.getBlockId(x, y, floorId);
@@ -408,30 +539,49 @@ enemys.prototype._getDamage = function (enemy, hero, x, y, floorId) {
if (info == null) return null;
if (typeof info == 'number') return info;
return info.damage;
-}
+};
////// 获得当前楼层的怪物列表 //////
enemys.prototype.getCurrentEnemys = function (floorId) {
floorId = floorId || core.status.floorId;
- var enemys = [], used = {};
+ var enemys = [],
+ used = {};
core.extractBlocks(floorId);
core.status.maps[floorId].blocks.forEach(function (block) {
if (!block.disable && block.event.cls.indexOf('enemy') == 0) {
- this._getCurrentEnemys_addEnemy(block.event.id, enemys, used, block.x, block.y, floorId);
+ this._getCurrentEnemys_addEnemy(
+ block.event.id,
+ enemys,
+ used,
+ block.x,
+ block.y,
+ floorId
+ );
}
}, this);
return this._getCurrentEnemys_sort(enemys);
-}
+};
enemys.prototype._getCurrentEnemys_getEnemy = function (enemyId) {
var enemy = core.material.enemys[enemyId];
if (!enemy) return null;
// 检查朝向;displayIdInBook
- return core.material.enemys[enemy.displayIdInBook] || core.material.enemys[(enemy.faceIds || {}).down] || enemy;
-}
+ return (
+ core.material.enemys[enemy.displayIdInBook] ||
+ core.material.enemys[(enemy.faceIds || {}).down] ||
+ enemy
+ );
+};
-enemys.prototype._getCurrentEnemys_addEnemy = function (enemyId, enemys, used, x, y, floorId) {
+enemys.prototype._getCurrentEnemys_addEnemy = function (
+ enemyId,
+ enemys,
+ used,
+ x,
+ y,
+ floorId
+) {
var enemy = this._getCurrentEnemys_getEnemy(enemyId);
if (enemy == null) return;
@@ -440,23 +590,32 @@ enemys.prototype._getCurrentEnemys_addEnemy = function (enemyId, enemys, used, x
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)) {
+ if (
+ !core.flags.enableEnemyPoint ||
+ (locEnemyInfo.atk == enemyInfo.atk &&
+ locEnemyInfo.def == enemyInfo.def &&
+ locEnemyInfo.hp == enemyInfo.hp)
+ ) {
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) {
+ if (
+ id == one.id &&
+ one.locs != null &&
+ locEnemyInfo.atk == one.atk &&
+ locEnemyInfo.def == one.def &&
+ locEnemyInfo.hp == one.hp
+ ) {
one.locs.push([x, y]);
return;
}
}
enemyInfo = locEnemyInfo;
}
- var id = enemy.id + ":" + x + ":" + y;
+ var id = enemy.id + ':' + x + ':' + y;
if (used[id]) return;
used[id] = true;
@@ -479,14 +638,24 @@ enemys.prototype._getCurrentEnemys_addEnemy = function (enemyId, enemys, used, x
e.damage = this.getDamage(enemy, x, y, floorId);
e.critical = critical[0];
e.criticalDamage = critical[1];
- e.defDamage = this._getCurrentEnemys_addEnemy_defDamage(enemy, x, y, floorId);
+ e.defDamage = this._getCurrentEnemys_addEnemy_defDamage(
+ enemy,
+ x,
+ y,
+ floorId
+ );
enemys.push(e);
-}
+};
-enemys.prototype._getCurrentEnemys_addEnemy_defDamage = function (enemy, x, y, floorId) {
+enemys.prototype._getCurrentEnemys_addEnemy_defDamage = function (
+ enemy,
+ x,
+ y,
+ floorId
+) {
var ratio = core.status.maps[floorId || core.status.floorId].ratio || 1;
return this.getDefDamage(enemy, ratio, x, y, floorId);
-}
+};
enemys.prototype._getCurrentEnemys_sort = function (enemys) {
return enemys.sort(function (a, b) {
@@ -501,23 +670,33 @@ enemys.prototype._getCurrentEnemys_sort = function (enemys) {
}
return a.damage - b.damage;
});
-}
+};
enemys.prototype.hasEnemyLeft = function (enemyId, floorId) {
if (floorId == null) floorId = core.status.floorId;
if (!(floorId instanceof Array)) floorId = [floorId];
var enemyMap = {};
- if (enemyId instanceof Array) enemyId.forEach(function (v) { enemyMap[v] = true; });
+ if (enemyId instanceof Array)
+ enemyId.forEach(function (v) {
+ enemyMap[v] = true;
+ });
else if (enemyId) enemyMap[enemyId] = true;
else enemyMap = null;
for (var i = 0; i < floorId.length; i++) {
core.extractBlocks(floorId[i]);
var mapBlocks = core.status.maps[floorId[i]].blocks;
for (var b = 0; b < mapBlocks.length; b++) {
- if (!mapBlocks[b].disable && mapBlocks[b].event.cls.indexOf('enemy') === 0) {
- if (enemyMap === null || enemyMap[core.getFaceDownId(mapBlocks[b])]) return true;
+ if (
+ !mapBlocks[b].disable &&
+ mapBlocks[b].event.cls.indexOf('enemy') === 0
+ ) {
+ if (
+ enemyMap === null ||
+ enemyMap[core.getFaceDownId(mapBlocks[b])]
+ )
+ return true;
}
}
}
return false;
-}
+};
diff --git a/public/libs/events.js b/public/libs/events.js
index 3d367fe..d18ec8a 100644
--- a/public/libs/events.js
+++ b/public/libs/events.js
@@ -1,3 +1,5 @@
+///
+
'use strict';
function events() {
diff --git a/public/libs/extensions.js b/public/libs/extensions.js
index 873e70d..a6b2eec 100644
--- a/public/libs/extensions.js
+++ b/public/libs/extensions.js
@@ -1,22 +1,25 @@
+///
/*
extensions.js:负责拓展插件
*/
-"use strict";
+'use strict';
-function extensions () {
-
-}
+function extensions() {}
extensions.prototype._load = function (callback) {
if (main.replayChecking) return callback();
if (!window.fs) {
- this._loadJs('_server/fs.js', function () {
- core.extensions._listExtensions(callback);
- }, callback);
+ this._loadJs(
+ '_server/fs.js',
+ function () {
+ core.extensions._listExtensions(callback);
+ },
+ callback
+ );
} else this._listExtensions(callback);
-}
+};
extensions.prototype._loadJs = function (file, callback, onerror) {
var script = document.createElement('script');
@@ -24,7 +27,7 @@ extensions.prototype._loadJs = function (file, callback, onerror) {
script.onload = callback;
script.onerror = onerror;
main.dom.body.appendChild(script);
-}
+};
extensions.prototype._listExtensions = function (callback) {
if (!window.fs) return callback();
@@ -39,13 +42,13 @@ extensions.prototype._listExtensions = function (callback) {
list.sort();
core.extensions._loadExtensions(list, callback);
});
-}
+};
extensions.prototype._loadExtensions = function (list, callback) {
var i = 0;
var load = function () {
if (i == list.length) return callback();
core.extensions._loadJs('extensions/' + list[i++], load, load);
- }
+ };
load();
-}
+};
diff --git a/public/libs/icons.js b/public/libs/icons.js
index a764e30..d385aed 100644
--- a/public/libs/icons.js
+++ b/public/libs/icons.js
@@ -1,3 +1,5 @@
+///
+
'use strict';
function icons() {
diff --git a/public/libs/items.js b/public/libs/items.js
index 6cf36f7..28bc362 100644
--- a/public/libs/items.js
+++ b/public/libs/items.js
@@ -1,3 +1,5 @@
+///
+
'use strict';
function items() {
diff --git a/public/libs/loader.js b/public/libs/loader.js
index a2bad38..5081c43 100644
--- a/public/libs/loader.js
+++ b/public/libs/loader.js
@@ -1,3 +1,5 @@
+///
+
/*
loader.js:负责对资源的加载
diff --git a/public/libs/maps.js b/public/libs/maps.js
index caf0b86..6e34b7d 100644
--- a/public/libs/maps.js
+++ b/public/libs/maps.js
@@ -1,3 +1,5 @@
+///
+
'use strict';
function maps() {
diff --git a/public/libs/ui.js b/public/libs/ui.js
index 3ee4947..10bc7c9 100644
--- a/public/libs/ui.js
+++ b/public/libs/ui.js
@@ -1,3 +1,5 @@
+///
+
/**
* ui.js:负责所有和UI界面相关的绘制
* 包括:
diff --git a/public/libs/utils.js b/public/libs/utils.js
index 32d444a..c36e80a 100644
--- a/public/libs/utils.js
+++ b/public/libs/utils.js
@@ -1,3 +1,5 @@
+///
+
/*
utils.js 工具类
diff --git a/public/project/plugins.js b/public/project/plugins.js
index 96f6aa8..309d1c7 100644
--- a/public/project/plugins.js
+++ b/public/project/plugins.js
@@ -3,7 +3,9 @@
var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
init: function () {
this._afterLoadResources = function () {
- core.resetSettings();
+ if (!main.replayChecking) {
+ core.resetSettings();
+ }
};
},
sprite: function () {
@@ -1373,1995 +1375,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
return false;
};
},
- minimap: function () {
- // 该插件可自定义空间很大,自定义内容请看注释
-
- // ------------------------- 安装说明 ------------------------- //
- // 先安装基于canvas的sprite化插件(2.10.0以上自带)
- // 确保自己的编辑器已安装造塔群内的编辑器升级压缩包(在HTML5魔塔样板文件夹内,2.10.1以上样板自带)
- // 再将以下代码复制进插件中
- // 提供的api请看以this.xxx = function开头的函数,函数前会有函数说明及参数说明,调用时只需core.plugin.xxx(参数)即可
-
- // ------------------------- 使用说明 ------------------------- //
- /*
- * 直接复制进插件中,然后添加一个快捷键或道具效果为core.plugin.drawFlyMap()即可使用,不需额外设置
- * 楼层id中不要出现下划线
- * 该插件具体功能有:
- * 1.绘制区域内的地图
- * 2.可以拖动地图
- * 3.点击地图可直接传送至目标地图,同时降低背景的不透明度,方便观察
- * 4.滚轮或双指可以放缩绘制内容
- * 5.放缩较大时,绘制地图的缩略图,可能会比较卡,但移动不会卡
- * 6.整合漏怪检测,如果想忽略怪物,请在下方改动或用脚本修改core.plugin.ignoreEnemies,类型为数组
- * 7.整合区域显示,所有单独或连在一起的地图会被视为一个区域
- * 8.键盘操作,上下左右移动
- */
-
- // ------------------------- 插件说明 ------------------------- //
- /*
- * 该插件注释极其详细,可以帮助那些想要提升代码力,但实力有不足的作者
- * 注意!!!该插件难度极大,没有代码底力的不建议研究
- * 该插件涉及部分较为高级的算法,如bfs
- */
-
- // 录像验证直接干掉这个插件
- if (main.replayChecking || main.mode === 'editor') return;
-
- // ----- 不可自定义 杂七杂八的变量
- /** @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 showEnemy = false; // 是否显示漏怪
- let areaPage = 0; // 区域显示的当前页数
- let nowArea = 0; // 当前区域index
- let selecting = ''; // 选择时当前正在选择的地图
-
- // ---- 不可自定义,常量
- /** @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: 3, // 默认地图缩放比例
- 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 = []);
-
- let allChangeEntries = Object.entries(defaultChange);
-
- const reset = core.events.resetGame;
- core.events.resetGame = function () {
- reset.apply(core.events, arguments);
- 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 = bfsSearch(now, Infinity, true);
- mapCache[`${now}_Infinity_false`] = result;
- areas.push({
- name: core.floors[now].title,
- maps: result.order
- });
- for (const map of result.order) {
- scanned[map] = true;
- all = all.filter(v => !result.order.includes(v));
- }
- res('success');
- });
- }
- })();
- };
-
- /** 工具按钮 */
- class Button extends Sprite {
- constructor(
- name,
- x,
- y,
- w,
- h,
- text,
- fontSize = '20px',
- transition = true
- ) {
- const btn = super(x, y, w, h, 1050, 'game', name);
- this.css(transition);
- setTimeout(() => btn.setCss(`opacity: 1;`), 50);
- const ctx = btn.context;
- ctx.textAlign = 'center';
- ctx.textBaseline = 'middle';
- core.fillText(
- ctx,
- text,
- w / 2,
- h / 2,
- '#fff',
- `${fontSize} normal`,
- w - 10
- );
- sprites[name] = btn;
- }
-
- css(transition) {
- this.setCss(
- 'transition: opacity 0.6s linear, transform 0.2s linear;' +
- 'background-color: #aaa;' +
- 'box-shadow: 0px 0px 0px black;' +
- (transition ? 'opacity: 0;' : '') +
- 'filter: drop-shadow(1px 1px 2px black);' +
- 'box-shadow: 0px 0px 4px black;' +
- 'cursor: pointer;'
- );
- }
- }
-
- /** 背景 */
- class Back extends Sprite {
- constructor(name, x, y, w, h, z, color) {
- const sprite = super(x, y, w, h, z, 'game', name);
- sprites[name] = sprite;
- this.setCss(`transition: all 0.6s linear;`);
- setTimeout(() => {
- this.setCss(`background-color: ${color};`);
- }, 50);
- }
- }
-
- /**
- * 获取绘制信息
- * @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 = bfsSearch(center, depth, noCache);
- mapCache[id] = map;
- const res = getDrawInfo(map.res, center, map.order);
- res.upOrDown = map.upOrDown;
- drawCache[id] = res;
- return res;
- };
-
- /**
- * 绘制大地图,可拖动、滚轮缩放、点击对应位置可以楼传等
- * @param {string} floorId 中心地图的id
- * @param {number} depth 遍历深度
- * @param {boolean} noCache 是否不使用缓存
- * @param {number} scale 绘制的缩放比例
- */
- this.drawFlyMap = function (
- floorId = core.status.floorId,
- depth = defaultValue.depth,
- noCache = false,
- scale = defaultValue.scale
- ) {
- if (core.isReplaying()) return;
-
- // 把区域页码归零
- nowArea = areas.findIndex(v =>
- v.maps.includes(core.status.floorId)
- );
- areaPage = 0;
- nowScale = scale;
- selecting = floorId;
- const info = this.getMapDrawInfo(floorId, depth, noCache);
- if (status !== 'scale' && status !== 'border') {
- drawBack();
- drawTools();
- }
- drawMap(info, scale);
- status = 'flyMap';
- core.lockControl();
- core.canvas.data.canvas.style.zIndex = '990';
- };
-
- /**
- * 获得某个区域的剩余怪物
- * @param {string} floorId 区域包含的地图或要扫描的地图
- * @param {boolean} area 是否扫描整个区域
- * @returns {RemainEnemy} 怪物总数、所在地图、位置
- * 返回值格式:{
- * rough: 每种怪物的数量及所有怪物的总数,为字符串,每个怪物独占一行
- * detail: 每个怪物的所在位置,每个怪物独占一行,以每20个整合成字符串,为字符串数组形式
- * data: 怪物数量的原始信息,格式为{ 楼层id: { 'x,y': 怪物id } }
- * }
- */
- this.getRemainEnemy = function (
- floorId = core.status.floorId,
- area = false
- ) {
- const res = bfsSearch(floorId, Infinity, true);
- // 整合怪物总数
- /** @type {{[x: string]: number}} */
- const category = {};
- const toShow = area ? res.order : [floorId];
- const strArr = [];
- const add = (...num) => num.reduce((pre, cur) => pre + cur, 0);
- const name = id => core.material.enemys[id].name;
- const title = id => core.status.maps[id].title;
- for (const id of toShow) {
- const enemies = res.enemies[id];
- Object.values(enemies).forEach(v => {
- // 编辑器不支持 ??=,悲
- category[v] = category[v] ?? 0;
- category[v]++;
- });
- // 每个怪物的信息
- strArr.push(
- ...Object.entries(enemies).map(
- v =>
- `${name(v[1])} 楼层:${title(
- id
- )},楼层id:${id},坐标:${v[0]}`
- )
- );
- }
- // 输出字符串
- const all = `当前${area ? '区域' : '地图'}中剩余怪物数量:${add(
- ...Object.values(category)
- )}`;
- const classified = Object.entries(category).map(
- v => `${name(v[0])} × ${v[1]}`
- ).join`\n`;
- const detail = [];
- while (strArr.length > 0) {
- detail.push(strArr.splice(0, 20).join`\n`);
- }
- return {
- rough: `${all}\n${classified}`,
- detail,
- data: res.enemies
- };
- };
-
- /**
- * 广度优先搜索搜索地图路径
- * @param {string} center 中心地图的id
- * @param {number} depth 搜索深度
- * @param {boolean} noCache 是否不使用缓存
- * @returns {BFSResult} 格式:floorId_x_y_dir: floorId_x_y
- */
- 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 = {};
-
- // 开始循环搜索
- while (nowDepth < depth && stack.length > 0) {
- const now = stack.shift(); // 当前id
- if (core.status.maps[now].deleted) continue;
- 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('_')}`;
- 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 };
- }
-
- /**
- * 提供地图的绘制信息
- * @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];
- }
- // 分类完毕,然后根据连接点先计算出各个地图的坐标,然后再进行判断
- const centerFloor = core.status.maps[center];
- const visitedCenter = core.hasVisitedFloor(center);
- const locs = {
- // 格式:[中心x, 中心y, 宽, 高, 是否到达过]
- [center]: [
- 0,
- 0,
- centerFloor.width,
- centerFloor.height,
- visitedCenter
- ]
- };
- const lines = {}; // 地图间的连线
- // 可以上楼下楼的地图
- 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 fx = parseInt(fromData[1]), // fromX
- fy = parseInt(fromData[2]), // fromY
- tx = parseInt(toData[1]), // toX
- ty = parseInt(toData[2]), // toY
- 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;
- const dis = noBorder ? 1 : 5;
- if (locs && locs[tf]) {
- x = locs[tf][0];
- y = locs[tf][1];
- } else {
- // 计算坐标,公式可以通过画图推断出
- x =
- fLoc[0] -
- ha * (fhw - fx + tx - thw) -
- v * (fhw + thw + dis);
- y =
- fLoc[1] -
- va * (fhh - fy + ty - thh) -
- h * (fhh + thh + dis);
- }
- locs[tf] = locs[tf] ?? [
- x,
- y,
- toFloor.width,
- toFloor.height,
- core.hasVisitedFloor(tf)
- ];
- // 添加连线
- lines[`${from}_${to}`] = [
- [
- fx - fhw + locs[ff][0],
- fy - fhh + locs[ff][1],
- x + tx - thw,
- y + ty - thh
- ]
- ];
- }
- }
- // 获取地图绘制需要的长宽
- 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 - w / 2 - 1, left);
- right = Math.max(x + w / 2 + 1, right);
- up = Math.min(y - h / 2 - 1, up);
- down = Math.max(y + h / 2 + 1, down);
- }
- width = right - left;
- height = down - up;
- // 所有地图和连线向右下移动,避免绘制出现问题
- for (const id in locs) {
- const loc = locs[id];
- loc[0] -= left; // 这时候left和up是负值,所以要减
- loc[1] -= up;
- }
- for (const route in lines) {
- const line = lines[route];
- for (const node of line) {
- node[0] -= left;
- node[1] -= up;
- node[2] -= left;
- node[3] -= up;
- }
- }
-
- return { locs, lines, width, height, layer: upOrDown };
- }
-
- /** 绘制背景 */
- function drawBack() {
- if (status !== 'none') return;
- new Back(
- '__map_back__',
- 0,
- 0,
- core._PX_,
- core._PY_,
- 175,
- 'rgba(0, 0, 0, 0.9)'
- );
- const listen = new Sprite(
- 0,
- 0,
- core._PX_,
- core._PY_,
- 1000,
- 'game',
- '__map_listen__'
- );
- addDrag(listen);
- const exit = new Button(
- '__map_exit__',
- core._PX_ - 64,
- core._PY_ - 26,
- 60,
- 22,
- '退出'
- );
- exit.addEventListener('click', close);
- sprites.listen = listen;
- }
-
- /** 绘制工具栏 */
- function drawTools() {
- new Back(
- '__map_toolback__',
- 0,
- core._PY_ - 30,
- core._PX_,
- 30,
- 600,
- 'rgba(200, 200, 200, 0.9)'
- );
- // 无边框
- const border = new Button(
- '__map_border__',
- core._PX_ - 150,
- core._PY_ - 26,
- 60,
- 22,
- '边框'
- );
- border.addEventListener('click', changeBorder);
- // 怪物数量
- const enemy = new Button(
- '__map_enemy__',
- core._PX_ - 240,
- core._PY_ - 26,
- 60,
- 22,
- '怪物'
- );
- enemy.addEventListener('click', triggerEnemy);
- // 区域显示
- const area = new Back(
- '__map_areasback__',
- core._PX_ - 80,
- 0,
- 80,
- core._PY_ - 30,
- 550,
- 'rgba(200, 200, 200, 0.9)'
- );
- drawAreaList();
- core.drawLine(
- area.context,
- 0,
- core._PY_ - 30,
- 80,
- core._PY_ - 30,
- '#222',
- 2
- );
- }
-
- /** 绘制区域列表 */
- function drawAreaList(transition = true) {
- const start = perPage * areaPage;
- Object.values(areaSprite).forEach(v => v.destroy());
- areaSprite = {};
- for (let i = start; i < start + perPage && areas[i]; i++) {
- const n = i % perPage;
- const { name, maps } = areas[i];
- const btn = new Button(
- `_area_${maps[0]}`,
- core._PX_ - 75,
- 4 + 30 * n,
- 70,
- 22,
- name,
- '16px',
- transition
- );
- areaSprite[maps[0]] = btn;
- if (i === nowArea) btn.setCss(`border: 2px solid gold;`);
- btn.addEventListener('click', e => {
- if (i === nowArea) return;
- changeArea(i);
- });
- }
- // 上一页下一页
- if (areaPage > 0) {
- const last = new Button(
- '_area_last_',
- core._PX_ - 75,
- core._PY_ - 50,
- 30,
- 16,
- '上一页',
- '14px',
- transition
- );
- areaSprite._area_last_ = last;
- last.addEventListener('click', e => {
- areaPage--;
- drawAreaList(false);
- });
- }
- if (areaPage < Math.floor(areas.length / perPage)) {
- const next = new Button(
- '_area_next_',
- core._PX_ - 35,
- core._PY_ - 50,
- 30,
- 16,
- '下一页',
- '14px',
- transition
- );
- areaSprite._area_next_ = next;
- next.addEventListener('click', e => {
- areaPage++;
- drawAreaList(false);
- });
- }
- }
-
- /**
- * 绘制大地图
- * @param {MapDrawInfo} info 地图绘制信息
- * @param {number} scale 地图的绘制比例
- */
- function drawMap(info, scale = defaultValue.scale) {
- if (status === 'flyMap') return;
- const PX = core._PX_,
- PY = core._PY_;
- const w = info.width * scale,
- h = info.height * scale;
- const id = `__flyMap__`;
- const cx = PX / 2 - w / 2,
- cy = PY / 2 - h / 2;
- const map = new Sprite(cx, cy, w, h, 500, 'game', id);
- sprites[id] = map;
- canDrag[id] = map;
- map.canvas.className = 'fly-map';
- const ctx = map.context;
- core.clearMap(ctx);
- if (!noBorder) {
- const drawed = {}; // 绘制过的线
- // 先绘制连线
- const lines = info.lines;
- for (const route in lines) {
- const line = lines[route];
- for (const node of line) {
- const from = `${node[0]},${node[1]}`,
- to = `${node[2]},${node[3]}`;
- if (drawed[`${from}-${to}`] || drawed[`${to}-${from}`])
- continue;
- drawed[`${from}-${to}`] = true;
- let lineWidth = scale / 2;
- core.drawLine(
- ctx,
- node[0] * scale,
- node[1] * scale,
- node[2] * scale,
- node[3] * scale,
- '#fff',
- lineWidth
- );
- }
- }
- // 再绘制楼层
- 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
- );
- let dx = 0,
- dy = 0; // 避免绘图误差
- if (loc[2] % 2 === 0) dx = 0.5 * scale;
- if (loc[3] % 2 === 0) dy = 0.5 * scale;
- const fx = x - w / 2 - dx,
- fy = y - h / 2 - dy;
- core.fillRect(ctx, fx, fy, w, h, color);
- if (id === selecting)
- core.strokeRect(ctx, fx, fy, w, h, 'gold', scale / 2);
- else core.strokeRect(ctx, fx, fy, w, h, '#fff', scale / 2);
- const layer = info.upOrDown[id];
- const min = Math.min(w, h);
- if (layer?.includes('upFloor'))
- core.drawIcon(
- ctx,
- defaultChange.upFloor,
- fx,
- fy,
- min / 3,
- min / 3
- );
- if (layer?.includes('downFloor'))
- core.drawIcon(
- ctx,
- defaultChange.downFloor,
- fx + w - min / 3,
- fy + h - min / 3,
- min / 3,
- min / 3
- );
- // 显示漏怪数量
- if (showEnemy) {
- ctx.textAlign = 'center';
- ctx.textBaseline = 'middle';
- const c = `${drawingMap}_${nowDepth}_${noBorder}`;
- const n = Object.keys(mapCache[c].enemies[id]).length;
- color = '#3f3';
- if (n > 0) color = '#fff';
- if (n > 10) color = '#fc3';
- if (n > 20) color = '#f22';
- ctx.shadowBlur = 0.6 * nowScale;
- ctx.shadowColor = '#000';
- core.fillText(
- ctx,
- `怪物数量:${n}`,
- x,
- y,
- color,
- `${2 * nowScale}px normal`
- );
- ctx.shadowBlur = 0;
- }
- }
- }
- checkThumbnail();
- }
-
- /**
- * 重新绘制缩略图
- * @param {Sprite} sprite
- * @param {string} floor
- */
- function drawThumbnail(sprite, floor, x, y, w, h) {
- const ctx = sprite.context;
- const scale = nowScale;
- core.drawThumbnail(floor, void 0, {
- ctx: ctx,
- x: x - w / 2,
- y: y - h / 2,
- damage: true,
- all: true,
- size: Math.max(w, h) / Math.max(core._PX_, core._PY_),
- fromMap: true
- });
- const color = floor === core.status.floorId ? 'gold' : '#fff';
- if (!noBorder)
- core.strokeRect(
- ctx,
- x - w / 2,
- y - h / 2,
- w,
- h,
- color,
- scale / 2
- );
- }
-
- /** 检查是否需要绘制缩略图 */
- function checkThumbnail() {
- const id = `${drawingMap}_${nowDepth}_${noBorder}`;
- const locs = drawCache[id].locs;
- const map = canDrag[`__flyMap__`];
- for (const id in locs) {
- const loc = locs[id];
- const scale = nowScale;
- const [x, y, w, h] = loc.map(
- v => typeof v === 'number' && v * scale
- );
- let dx = 0,
- dy = 0; // 避免绘图误差
- if (loc[2] % 2 === 0) dx = 0.5 * scale;
- if (loc[3] % 2 === 0) dy = 0.5 * scale;
- if (
- !drawedThumbnail[id] &&
- x + map.x > 0 &&
- x + map.x < core._PX_ &&
- y + map.y > 0 &&
- y + map.y < core._PY_
- ) {
- if (!noBorder && core.hasVisitedFloor(id) && scale > 5) {
- drawThumbnail(map, id, x - dx, y - dy, w, h);
- drawedThumbnail[id] = true;
- }
- if (noBorder) {
- drawThumbnail(map, id, x - dx, y - dy, w, h);
- drawedThumbnail[id] = true;
- if (!core.hasVisitedFloor(id))
- core.fillRect(
- map.context,
- x - dx - w / 2,
- y - dy - h / 2,
- w,
- h,
- 'rgba(255,0,255,0.2)'
- );
- }
- }
- }
- // 如果是无边框模式,那就只绘制当前地图的边框
- if (noBorder) {
- const loc = locs[selecting];
- const scale = nowScale;
- if (loc) {
- const [x, y, w, h] = loc.map(
- v => typeof v === 'number' && v * scale
- );
- core.strokeRect(
- map.context,
- x - w / 2,
- y - h / 2,
- w,
- h,
- 'gold',
- scale / 2
- );
- }
- }
- }
-
- /** 检查点击点是否在以x,y为中心的某一矩形中 */
- function inRect(x, y, w, h, px, py) {
- x -= w / 2;
- y -= h / 2;
- return px > x && px < x + w && py > y && py < y + h;
- }
-
- /** 测试画布是否超过上限,摘自https://github.com/jhildenbiddle/canvas-size */
- function canvasTest(size) {
- const width = Math.max(Math.ceil(size[0]), 1);
- const height = Math.max(Math.ceil(size[1]), 1);
- if (width === 0 || height === 0) return true;
- const fill = [width - 1, height - 1, 1, 1];
- let cropCvs, testCvs;
- cropCvs = document.createElement('canvas');
- cropCvs.width = 1;
- cropCvs.height = 1;
- testCvs = document.createElement('canvas');
- testCvs.width = width;
- testCvs.height = height;
- const cropCtx = cropCvs.getContext('2d');
- const testCtx = testCvs.getContext('2d');
- if (testCtx) {
- testCtx.fillRect.apply(testCtx, fill);
- cropCtx.drawImage(
- testCvs,
- width - 1,
- height - 1,
- 1,
- 1,
- 0,
- 0,
- 1,
- 1
- );
- }
- const isTestPass =
- cropCtx && cropCtx.getImageData(0, 0, 1, 1).data[3] !== 0;
- return isTestPass;
- }
-
- /** 检查浏览器限制 */
- function checkMaximum(before, scale) {
- for (const id in canDrag) {
- const sprite = canDrag[id];
- const rate = scale / before;
- const w = sprite.width * rate * core.domStyle.scale,
- h = sprite.height * rate * core.domStyle.scale;
- const valid = canvasTest([w, h]);
- if (!valid) {
- core.drawTip('画布大小将超过浏览器限制!请勿继续放大!');
- return true;
- }
- }
- return false;
- }
-
- /** 关闭事件 */
- function close() {
- document.body.removeEventListener('keyup', keyboard);
- Object.values(sprites).forEach(v => {
- v.setCss('transition: opacity 0.6s linear;');
- });
- setTimeout(() => {
- Object.values(sprites).forEach(v => {
- v.setCss('opacity: 0;');
- });
- }, 50);
- setTimeout(() => {
- core.unlockControl();
- Object.values(sprites).forEach(v => {
- v.destroy();
- });
- drawedThumbnail = {};
- sprites = {};
- canDrag = {};
- status = 'none';
- core.canvas.data.canvas.style.zIndex = '170';
- }, 650);
- }
-
- /**
- * 点击地图事件,尝试楼层传送
- * @param {MouseEvent} e
- */
- function clickMap(e) {
- if (moved) return (moved = false);
- const { x, y } = core.actions._getClickLoc(e.clientX, e.clientY);
- let px = x / core.domStyle.scale,
- py = y / core.domStyle.scale;
- const scale = nowScale;
- const id = `${drawingMap}_${nowDepth}_${noBorder}`;
- const locs = drawCache[id].locs;
- const sprite = canDrag.__flyMap__;
- px -= sprite.x;
- py -= sprite.y;
- for (const id in locs) {
- const loc = locs[id];
- const [x, y, w, h] = loc.map(
- v => typeof v === 'number' && v * scale
- );
- if (inRect(x, y, w, h, px, py)) {
- return flyTo(id);
- }
- }
- }
-
- /** 飞向某个楼层 */
- function flyTo(id) {
- if (!core.hasItem('fly')) return core.drawTip('你没有楼层传送器');
- sprites.__map_back__.setCss('opacity: 0.2;');
- return core.flyTo(id, () =>
- setTimeout(() => {
- if (sprites.__map_back__) core.lockControl();
- }, 100)
- );
- }
-
- /**
- * 拖拽事件
- * @param {MouseEvent} e
- */
- function drag(e) {
- if (!clicking) return;
- const scale = core.domStyle.scale;
- moveEle(e.movementX / scale, e.movementY / scale);
- }
-
- /**
- * 手机端点击拖动事件
- * @param {TouchEvent} e
- * @this {HTMLCanvasElement}
- */
- function touchDrag(e) {
- moved = true;
- const scale = core.domStyle.scale;
- if (e.touches.length === 1) {
- // 拖拽
- const info = e.touches[0];
- if (!lastTouch[this.id]) {
- lastTouch[this.id] = [info.clientX, info.clientY];
- return;
- }
- const { clientX: x, clientY: y } = info;
- const dx = x - lastTouch[this.id][0],
- dy = y - lastTouch[this.id][1];
- moveEle(dx / scale, dy / scale);
- lastTouch[this.id] = [info.clientX, info.clientY];
- } else if (e.touches.length >= 2) {
- // 双指放缩
- const first = e.touches[0],
- second = e.touches[1];
- const dx = first.clientX - second.clientX,
- dy = first.clientY - second.clientY;
- if (lastLength === 0) {
- lastLength = Math.sqrt(dx * dx + dy * dy);
- return;
- }
- let cx = (first.clientX + second.clientX) / 2,
- cy = (first.clientY + second.clientY) / 2;
- const { x, y } = core.actions._getClickLoc(cx, cy);
- const mx = x / scale;
- const my = y / scale;
- const length = Math.sqrt(dx * dx + dy * dy);
- const delta = (lastLength / length) ** (1 / 3);
- const info = {};
- for (const id in canDrag) {
- const sprite = canDrag[id];
- const sx = sprite.x + sprite.width / 2,
- sy = sprite.y + sprite.height / 2;
- const dx = sx - mx,
- dy = sy - my;
- info[id] = [mx + dx * delta, my + dy * delta];
- }
- scaleMap(delta * nowScale, info);
- }
- }
-
- /**
- * 滚轮缩放
- * @param {WheelEvent} e
- */
- function wheel(e) {
- const delta = 1 - Math.sign(e.deltaY) / 10;
- const { x, y } = core.actions._getClickLoc(e.clientX, e.clientY);
- const scale = core.domStyle.scale;
- const mx = x / scale,
- my = y / scale;
- const info = {};
- for (const id in canDrag) {
- const sprite = canDrag[id];
- const cx = sprite.x + sprite.width / 2,
- cy = sprite.y + sprite.height / 2;
- const dx = cx - mx,
- dy = cy - my;
- info[id] = [mx + dx * delta, my + dy * delta];
- }
- scaleMap(delta * nowScale, info);
- }
-
- /** 切换边框 */
- function changeBorder() {
- noBorder = !noBorder;
- redraw('border');
- }
-
- /** 切换是否显示漏怪数量 */
- function triggerEnemy() {
- showEnemy = !showEnemy;
- redraw('enemy');
- }
-
- /** 改变区域 */
- function changeArea(index) {
- nowArea = index;
- drawAreaList(false);
- drawedThumbnail = {};
- status = 'area';
- nowScale = defaultValue.scale;
- drawMap(core.plugin.getMapDrawInfo(areas[index].maps[0]));
- }
-
- /** 重绘 */
- function redraw(id, px, py, move = true) {
- const { x, y } = canDrag.__flyMap__;
- status = id;
- drawedThumbnail = {};
- drawMap(
- core.plugin.getMapDrawInfo(drawingMap, nowDepth, true),
- nowScale
- );
- if (move) canDrag.__flyMap__.move(px ?? x, py ?? y);
- checkThumbnail();
- }
-
- /**
- * 拖拽时移动需要元素
- * @param {string} dx
- * @param {string} dy
- */
- function moveEle(dx, dy) {
- moved = true;
- for (const id in canDrag) {
- const sprite = canDrag[id];
- const ctx = sprite.context;
- sprite.x += dx;
- sprite.y += dy;
- core.relocateCanvas(ctx, dx, dy, true);
- }
- checkThumbnail();
- }
-
- /**
- * 缩放绘制地图
- * @param {number} target 目标缩放比例
- * @param {{[x: string]: [number, number]}} info 缩放后的sprite位置数据
- */
- function scaleMap(target, info) {
- // 检查浏览器限制
- if (checkMaximum(nowScale, target)) return;
- clearTimeout(lastScale);
- const [x, y] = info.__flyMap__;
- // 先直接修改style,延迟200ms再绘制,进行性能优化
- const sprite = canDrag.__flyMap__;
- const rate = target / nowScale;
- nowScale = target;
- sprite.resize(sprite.width * rate, sprite.height * rate, true);
- sprite.move(x - sprite.width / 2, y - sprite.height / 2);
- lastScale = setTimeout(() => {
- redraw('scale', x - sprite.width / 2, y - sprite.height / 2);
- }, 200);
- }
-
- /** 键盘操作
- * @param {KeyboardEvent} e
- */
- function keyboard(e) {
- if (
- e.key === 'Enter' ||
- e.key === 'C' ||
- e.key === 'c' ||
- e.key === ' '
- ) {
- return flyTo(selecting);
- } else if (e.key === 'Escape' || e.key === 'x' || e.key === 'X') {
- return close();
- } else if (e.key.startsWith('Arrow')) {
- const dir = e.key.slice(5).toLowerCase();
- // 获取目标楼层
- const res =
- mapCache[`${drawingMap}_${nowDepth}_${noBorder}`].res;
- const key = Object.keys(res).find(v => {
- const [floorId, x, y, d] = v.split('_');
- return floorId === selecting && d === dir;
- });
- if (!key) return;
- const target = res[key].split('_')[0];
- selecting = target;
- redraw('key');
- }
- }
-
- /**
- * 给需要的元素添加拖拽等事件
- * @param {HTMLCanvasElement} ele
- */
- function addDrag(ele) {
- ele.addEventListener('wheel', wheel);
- ele.addEventListener('mousemove', drag);
- ele.addEventListener('touchmove', touchDrag);
- ele.addEventListener('click', clickMap);
- ele.addEventListener('mousedown', () => {
- clicking = true;
- });
- ele.addEventListener('mouseup', () => {
- clicking = false;
- });
- ele.addEventListener('touchend', () => {
- lastTouch = {};
- lastLength = 0;
- });
- document.body.addEventListener('keyup', keyboard);
- }
-
- maps.prototype._drawThumbnail_drawToTarget = function (
- floorId,
- options
- ) {
- const ctx = core.getContextByName(options.ctx);
- if (ctx == null) return;
- const x = options.x || 0,
- y = options.y || 0,
- size = options.size || 1;
- // size的含义改为(0,1]范围的系数以适配长方形,默认为1,楼传为3/4,SL界面为0.3
- let w = Math.ceil(size * core._PX_),
- h = Math.ceil(size * core._PY_);
- // 特判是否为编辑器,编辑器中长宽均采用core.js的遗留正方形像素边长,以保证下面的绘制正常
- if (main.mode == 'editor') w = h = size * core.__PIXELS__;
- const width = core.floors[floorId].width,
- height = core.floors[floorId].height;
- let centerX = options.centerX,
- centerY = options.centerY;
- if (centerX == null) centerX = Math.floor(width / 2);
- if (centerY == null) centerY = Math.floor(height / 2);
- const tempCanvas = core.bigmap.tempCanvas;
-
- if (options.all) {
- const tempWidth = tempCanvas.canvas.width,
- tempHeight = tempCanvas.canvas.height;
- // 绘制全景图
- if (tempWidth <= tempHeight) {
- const realHeight = h,
- realWidth = (realHeight * tempWidth) / tempHeight;
- const side = (w - realWidth) / 2;
- if (options.fromMap) {
- return core.drawImage(
- ctx,
- tempCanvas.canvas,
- 0,
- 0,
- tempWidth,
- tempHeight,
- x,
- y,
- realWidth,
- realHeight
- );
- }
- core.fillRect(ctx, x, y, side, realHeight, '#000000');
- core.fillRect(ctx, x + w - side, y, side, realHeight);
- core.drawImage(
- ctx,
- tempCanvas.canvas,
- 0,
- 0,
- tempWidth,
- tempHeight,
- x + side,
- y,
- realWidth,
- realHeight
- );
- } else {
- const realWidth = w,
- realHeight = (realWidth * tempHeight) / tempWidth;
- const side = (h - realHeight) / 2;
- if (options.fromMap) {
- return core.drawImage(
- ctx,
- tempCanvas.canvas,
- 0,
- 0,
- tempWidth,
- tempHeight,
- x,
- y,
- realWidth,
- realHeight
- );
- }
- core.fillRect(ctx, x, y, realWidth, side, '#000000');
- core.fillRect(ctx, x, y + h - side, realWidth, side);
- core.drawImage(
- ctx,
- tempCanvas.canvas,
- 0,
- 0,
- tempWidth,
- tempHeight,
- x,
- y + side,
- realWidth,
- realHeight
- );
- }
- } else {
- // 只绘制可见窗口
- let pw = core._PX_,
- ph = core._PY_,
- hw = core._HALF_WIDTH_,
- hh = core._HALF_HEIGHT_,
- W = core._WIDTH_,
- H = core._HEIGHT_;
- const ratio = core.domStyle.isVertical
- ? core.domStyle.ratio
- : core.domStyle.scale;
- if (main.mode == 'editor') {
- pw = ph = core.__PIXELS__;
- hw = hh = core.__HALF_SIZE__;
- W = H = core.__SIZE__;
- }
- if (options.v2) {
- core.drawImage(
- ctx,
- tempCanvas.canvas,
- 0,
- 0,
- pw * ratio,
- ph * ratio,
- x,
- y,
- w,
- h
- );
- } else {
- const offsetX = core.clamp(centerX - hw, 0, width - W),
- offsetY = core.clamp(centerY - hh, 0, height - H);
- if (options.noHD) {
- core.drawImage(
- ctx,
- tempCanvas.canvas,
- offsetX * 32,
- offsetY * 32,
- pw,
- ph,
- x,
- y,
- w,
- h
- );
- return;
- }
- core.drawImage(
- ctx,
- tempCanvas.canvas,
- offsetX * 32 * ratio,
- offsetY * 32 * ratio,
- pw * ratio,
- ph * ratio,
- x,
- y,
- w,
- h
- );
- }
- }
- };
- },
- fixed: function () {
- return;
- // 该插件可自定义空间很大,可自定义内容请看注释
-
- // -------------------- 安装说明 -------------------- //
- /* 1.安装基于canvas的sprite化插件(2.10以上样板自带)和响应式变量插件(不要使用vue原生版)
- * 2.确保自己的编辑器已安装造塔群内的编辑器升级压缩包(在HTML5魔塔样板文件夹内,2.10.1以上样板自带)
- * 3.将以下代码复制进插件
- */
- // -------------------- 使用说明 -------------------- //
-
- // -------------------- 插件说明 -------------------- //
-
- // 录像验证忽略
- if (main.replayChecking || main.mode === 'editor') return;
-
- // ----- 不可自定义变量
- /** @type {{[x: string]: Sprite}} */
- let sprites = {}; // 所有的sprite
- /** @type {{[x: string]: EnemyBox}} */
- let enemyBoxes = {}; // 所有的enemyBox
- /** @type {{[x: string]: TextBox}} */
- let textBoxes = {}; // 所有的textBox
- let timeout = 0; // 鼠标放到怪物上时setTimeout的id
- let dblTimeout = 0; // 双击时判定双击的timeout的id
- /** @type {EnemyCollection[]} */
- let enemies = []; // 所有的怪物信息
-
- // ----- 不可自定义常量
- const specials = core.getSpecials(); // 所有怪物的属性
- const originClick = main.dom.data.onmouseup;
-
- // ----- 可自定义变量
- let allowMap = true; // 是否允许直接在地图上移动鼠标显示怪物信息
- let allowDbl = true; // 是否允许双击地图上的怪物显示其详细信息,当然在点击怪物时会发生约0.2s的卡顿,以判断双击
- let guardsFirst = false; // 先攻击支援怪还是后攻击支援怪,用于计算每个怪物的伤害和回合数,请保证与getDamageInfo中相同
- let nDefDamage = true; // 为true时,显示 当前地图宝石倍率 防减伤,为false时,显示1防减伤
-
- // ----- 可自定义常量
- const showStatus = ['name', 'hp', 'atk', 'def', 'money', 'exp']; // 粗略信息显示的项,伤害与特殊属性必显示
- const font = 'normal'; // 默认字体
- const op = 'c'; // 信息框背景的不透明度,范围 0-f 十六进制
-
- // 属性名对应的颜色
- const colorDict = {
- name: '#fff',
- hp: '#8f8',
- atk: '#f88',
- def: '#88f',
- money: 'gold',
- exp: '#7f7'
- };
-
- /** 背景 */
- class Back extends Sprite {
- constructor(name, color, z, time = 0.6) {
- super(0, 0, core._PX_, core._PY_, z, 'game', name);
- sprites[name] = this;
- this.setCss(`
- background-color: ${color};
- opacity: 0;
- transition: all ${time}s linear;
- `);
- setTimeout(() => this.setCss(`opacity: 1;`), 50);
- }
-
- destroy() {
- this.setCss(`opacity: 0;`);
- setTimeout(() => super.destroy(), 600);
- delete sprites[this.name];
- }
- }
-
- /** 怪物 */
- class EnemyBox extends Sprite {
- constructor(name, x, y, w, h, id, big, e) {
- const scale = core.domStyle.scale;
- const s = 1 / scale / 2;
- super(x - s, y - s, w + 2 * s, h + 2 * s, 300, 'game', name);
- this.id = id;
- /** @type {EnemyCollection} */
- this.enemy = e;
- this.setCss(`
- border: 1px solid #ddd;
- background-color: #222;
- opacity: 0;
- transition: all 0.6s ease-out, transform 0.2s linear;
- `);
- setTimeout(() => this.setCss(`opacity: 1;`), 50);
- this.animate(big);
- this.frame = 0;
- enemyBoxes[this.name] = sprites[this.name] = this;
- this.listen();
- }
-
- /** 播放动画 */
- animate(big) {
- const ctx = this.context;
- this.interval = setInterval(() => {
- const size = big ? 32 : void 0;
- this.frame++;
- this.frame %= 2;
- // 用drawBlock还不如用drawIcon呢
- core.clearMap(ctx);
- core.drawIcon(ctx, this.id, 0, 0, size, size, this.frame);
- }, core.values.animateSpeed);
- }
-
- destroy() {
- clearInterval(this.interval);
- delete enemyBoxes[this.name];
- super.destroy();
- }
-
- /** 监听 */
- listen() {
- this.addEventListener('mouseenter', () => {
- this.setCss(`transform: scale(1.1);`);
- drawRough(this.enemy);
- });
- this.addEventListener('mouseleave', () => {
- this.setCss(`transform: none;`);
- textBoxes[
- `_text_${this.enemy.loc.x}_${this.enemy.loc.y}_`
- ].destroy();
- });
- }
- }
-
- /** 文字框 */
- class TextBox extends Sprite {
- constructor(x, y, w, h, text, fontSize, ex, ey) {
- const id = `_text_${ex}_${ey}_`;
- super(x, y, w, h, 310, 'game', id);
- this.setCss(`
- opacity: 0;
- border: thick double #32a1ce;
- transition: opacity 0.2s linear;
- background-color: #333${op};
- box-shadow: 0px 0px 3px #000;
- `);
- setTimeout(() => this.setCss(`opacity: 1;`), 50);
- setTimeout(() => {
- clearInterval(core.status.event.interval);
- this.render(text, fontSize);
- }, 250);
- textBoxes[id] = sprites[id] = this;
- this.ex = ex;
- this.ey = ey;
- }
-
- render(text, fontSize) {
- /** @type {TextContentConfig} */
- const config = {
- left: 10,
- top: 10,
- maxWidth: this.width - 20,
- time: 10,
- fontSize,
- font
- };
- core.drawTextContent(this.context, text, config);
- }
-
- destroy() {
- this.setCss(`opacity: 0;`);
- setTimeout(() => super.destroy(), 200);
- delete textBoxes[`_text_${this.ex}_${this.ey}_`];
- }
- }
-
- /** 打开定点查看界面 */
- this.openFixed = function () {
- if (core.isReplaying()) return;
- const info = getEnemies();
- enemies = info;
- drawFixed(info);
- core.lockControl();
- };
-
- // 监听 & 复写
- main.dom.data.addEventListener('mousemove', moveOnPlaying);
- main.dom.data.addEventListener('dblclick', dblClick);
- main.dom.data.onmouseup = e => {
- if (allowDbl) {
- clearTimeout(dblTimeout);
- dblTimeout = setTimeout(() => {
- originClick.call(main.dom.data, e);
- }, 200);
- } else {
- originClick.call(main.dom.data, e);
- }
- };
-
- /**
- * 获取怪物位置和其属性
- * @param {string} floorId 地图id
- * @returns {EnemyCollection[]} 怪物信息数组
- */
- function getEnemies(floorId = core.status.floorId) {
- const res = [];
- // 遍历所有图块,然后找出在显示范围内的怪物,异步执行,
- core.extractBlocks(floorId);
- const blocks = core.status.maps[floorId].blocks;
- for (const block of blocks) {
- const x = block.x,
- y = block.y;
- // 判断是否为怪物
- if (block.event.trigger !== 'battle') continue;
- // 判断是否在范围内
- if (!inView(x, y)) continue;
- res.push(generateCollection(block.event.id, x, y, floorId));
- }
- return res;
- }
-
- function generateCollection(id, x, y, floorId) {
- const enemy = core.material.enemys[id];
- const info = core.getEnemyInfo(id, void 0, x, y, floorId);
- const data = Object.assign({}, enemy);
- for (const key in info) data[key] = info[key];
- return { loc: { x, y }, data };
- }
-
- /**
- * 根据属性名获得颜色
- * @param {string} status
- */
- function color(status) {
- return colorDict[status] ?? 'white';
- }
-
- /**
- * 根据伤害获得伤害颜色
- * @param {number} damage
- */
- function colorDamage(damage) {
- if (typeof damage === 'string' || !damage) return '#f00';
- const hp = core.status.hero.hp;
- const n = ~~((damage / hp) * 255);
- return `rgb(${n}, ${255 - n}, 0)`;
- }
-
- /**
- * 获取怪物的粗略信息
- * @param {Enemy} info
- */
- function getRough(info, x, y) {
- // 先获得常量中明确指定的
- const text = showStatus.map(v => {
- return `\\r[${color(v)}]${core.getStatusLabel(v)}\\r[]:${
- info[v]
- }`;
- });
- // 特殊属性
- if (info.special?.length > 0) {
- const names = core.getSpecialText(info);
- const color = core.getSpecialColor(info);
- const all = names.map((v, i) => `\\r[${color[i]}]${v}\\r[]`);
- text.push(`\\r[#f8f]特殊属性\\r[]:${all.join` `}`);
- }
- // 伤害
- const damage = core.getDamageInfo(info, void 0, x, y)?.damage;
- const d = core.formatBigNumber(damage);
- text.push(
- `\\r[#f44]伤害\\r[]:\\r[${colorDamage(damage)}]${
- d === '???' ? '无法战胜' : d
- }\\r[]`
- );
- // 支援
- if (info.guards?.length > 0) {
- const guards = getGuards(info, x, y);
- text.push(
- `\\r[#3cf]支援\\r[]:${guards.map(v => `\\i[${v.id}]`)
- .join` `}`
- );
- text.push(`支援怪攻击顺序 -->`);
- }
- if (allowDbl) text.push('双击怪物查看详细信息');
- return text.join`\n`;
- }
-
- /**
- * 获得特殊属性说明、名称、颜色
- * @param {SpecialCollection} data
- * @param {Enemy} enemy
- */
- function executeSpecial(data, enemy) {
- let name = '';
- if (typeof data[1] === 'string') name = data[1];
- else name = data[1](enemy);
- let text = '';
- if (typeof data[2] === 'string') text = data[2];
- else text = data[2](enemy);
- return { name, text, color: data[3] };
- }
-
- /**
- * 获得某个怪物的详细信息,包括特殊属性说明、支援怪攻击顺序
- * @param {EnemyCollection} info getEnemies获取的怪物信息
- */
- function getDetail(info) {
- // ----- status
- const status = {};
- showStatus.forEach(v => {
- status[v] = {
- id: v,
- name: core.getStatusLabel(v),
- value: info.data[v]
- };
- });
- // ----- special
- const text = [];
- const special = info.data.special;
- if (special?.length > 0) {
- for (const n of special) {
- const data = specials.find(v => v[0] === n);
- if (!data)
- throw new ReferenceError(
- `'${info.data.name}'拥有不存在的特殊属性'${n}'`
- );
- const {
- name,
- text: desc,
- color
- } = executeSpecial(data, info.data);
- text.push(`\\r[${color}]${name}\\r[]:${desc}`);
- }
- }
- // ---- damage & turn
- const damageInfo = core.getDamageInfo(
- info.data,
- void 0,
- info.loc.x,
- info.loc.y
- );
- let damage = core.formatBigNumber(damageInfo?.damage);
- if (damage === '???') damage = '无法战胜';
- const color = colorDamage(damageInfo?.damage);
- const turn = damageInfo?.turn ?? 0;
- // ----- 4 criticals & n def
- const criticals = core.nextCriticals(
- info.data,
- 4,
- info.loc.x,
- info.loc.y
- );
- const n = nDefDamage ? core.status.thisMap.ratio : 1;
- const def = core.getDefDamage(info.data, n, info.loc.x, info.loc.y);
- return {
- status,
- text,
- damage: { damage, color, turn },
- criticals,
- def
- };
- }
-
- /**
- * 获取支援怪信息,攻击顺序
- * @param {Enemy} info 怪物信息
- * @param {EnemyCollection[]} all 所有的怪物信息
- * @returns {GuardCollection[]} 支援怪的顺序信息
- */
- function getGuards(info, all) {
- /** @type {[number, number, string][]} */
- const guards = info.guards;
- if (!guards) return;
- return guards.map(([x, y, id]) => {
- const res = {
- loc: { x, y },
- id
- };
- // 寻找符合条件的怪物
- const enemy = all.find(v => v.loc.x === x && v.loc.y === y);
- res.enemy = enemy;
- return res;
- });
- }
-
- /**
- * 获取每个支援怪造成的伤害、回合数等
- * @param {EnemyCollection} info
- */
- function getGuardsDetail(info) {
- // 很神秘的一个功能
- const guards = getGuards(info, enemies); // 这时候获得的已经是按顺序排好的了
- const col = { enemy: info.data, loc: info.loc };
- if (guardsFirst) guards.push(col);
- else guards.unshift(col);
- const turn = ref(0);
- const res = [];
- watch(turn, v => (flags.__extraTurn__ = v)); // 使用样板的额外回合flag
- const status = ['atk', 'def', 'hp'].map(v => ({
- [v]: core.getRealStatus(v)
- }));
- const hero = Object.assign({}, ...status, { mdef: 0 });
- for (let i = 0; i < guards.length; i++) {
- const e = guards[i];
- const data = core.getDamageInfo(
- e.enemy,
- i === 0 ? void 0 : hero,
- e.loc.x,
- e.loc.y
- );
- if (!data) {
- res.push({ battlable: false });
- continue;
- }
- turn.value += data.turn;
- res.push({
- battlable: true,
- damage: data.damage,
- turn: data.turn
- });
- }
- return res;
- }
-
- /**
- * 是否在视野范围内
- * @param {number} x 要判断的格子
- * @param {number} y
- */
- function inView(x, y) {
- const { x: hx, y: hy } = core.status.hero.loc;
- const w = core._WIDTH_,
- h = core._HEIGHT_;
- return x <= hx + w && x >= hx - w && y <= hy + h && y >= hy - h;
- }
-
- /**
- * 计算像素位置
- * @param {number} x
- * @param {number} y
- * @param {number} w
- * @param {number} h
- */
- function calPixel(x, y, w, h) {
- const px = x * 32 + 16 - w / 2,
- py = (y + 1) * 32 - h;
- return { px, py, w, h };
- }
-
- /**
- * 根据鼠标位置获得矩形的绘制信息
- * @param {number} px
- * @param {number} py
- */
- function calRect(px, py, text) {
- const onRight = px >= core._PX_ / 2;
- let x = px + 32;
- const width = Math.min(
- core._PX_ / 2 - 32,
- onRight ? px - 32 : core._PX_ - x
- );
- if (onRight) x = px - width - 32;
- const config = {
- maxWidth: width - 20,
- font,
- fontSize: 19,
- left: 10
- };
- let height = 500;
- while (height > core._PY_ - 20) {
- config.fontSize--;
- height = core.getTextContentHeight(text, config) + 20;
- }
- const y = core.clamp(py - height / 2, 10, core._PY_ - 20 - height);
- return { x, y, width, height, font: config.fontSize };
- }
-
- /**
- * 绘制定点查看界面
- * @param {EnemyCollection[]} info 怪物信息
- */
- function drawFixed(info) {
- // 绘制,当然还有动画
- new Back('_fixed_sback_', 'rgba(0, 0, 0, 0.9)', 200);
- drawChoice(info);
- const exit = new Sprite(
- core._PX_ - 60,
- 4,
- 56,
- 24,
- 400,
- 'game',
- '_exit_'
- );
- exit.setCss(`
- background-color: #aaa;
- box-shadow: 0px 0px 3px #000;
- cursor: pointer;
- transition: all 0.6s linear;
- opacity: 0;
- `);
- setTimeout(() => exit.setCss(`opacity: 1;`), 50);
- const ctx = exit.context;
- ctx.shadowBlur = 3;
- ctx.shadowColor = '#000';
- ctx.textAlign = 'center';
- ctx.textBaseline = 'middle';
- core.fillText(ctx, '退出', 28, 12, '#fff', '18px normal');
- exit.addEventListener('click', close);
- sprites['_exit_'] = exit;
- }
-
- /**
- * 绘制每个怪物
- * @param {EnemyCollection[]} info
- */
- function drawChoice(info) {
- for (const e of info) {
- const { x, y } = e.loc;
- const data = e.data;
- const { bigImage, height } = core.getBlockInfo(data.id);
- const w = bigImage?.width ?? 32,
- h = bigImage?.height ?? height;
- const { px, py } = calPixel(x, y, w, h);
- new EnemyBox(
- `_enemybox_${x}_${y}_`,
- px,
- py,
- w,
- h,
- data.id,
- !!bigImage,
- e
- );
- }
- }
-
- /**
- * 绘制怪物的粗略信息
- * @param {EnemyCollection} info
- */
- function drawRough(info) {
- const { x, y } = info.loc;
- const text = getRough(info.data, x, y);
- const rect = calRect(x * 32 + 16, y * 32 + 16, text);
- new TextBox(
- rect.x,
- rect.y,
- rect.width,
- rect.height,
- text,
- rect.font,
- x,
- y
- );
- }
-
- /**
- * 绘制详细信息的主界面
- * @param {EnemyCollection} info
- * @param {EnemyBox} enemyBox
- */
- function drawMain(info, enemyBox) {
- const { bigImage, height } = core.getBlockInfo(info.data.id);
- const w = bigImage?.width ?? 32,
- h = bigImage?.height ?? height;
- const box =
- enemyBox ??
- new EnemyBox(
- `_enemy_main_`,
- 16,
- 16,
- w,
- h,
- info.data.id,
- !!bigImage,
- info
- );
- box.move(16, 16);
- box.setCss(`
- border: 0;
- background-color: transparent;
- transform: none;
- z-index: 1000;
- `);
- const { status, text, damage, criticals, def } = getDetail(info);
- const back = new Back(
- `_detail_back_`,
- 'linear-gradient(to bottom, #333, #777)',
- 600,
- 0.2
- );
- // draw
- const sv = Object.values(status);
- sv.forEach(e => {});
- }
-
- /**
- * 绘制怪物详细信息界面
- * @param {EnemyCollection} info 怪物的信息
- * @param {boolean} animate 是否要有动画
- */
- function drawDetail(info, animate) {
- const { x, y } = info.loc;
- const box = enemyBoxes[`_enemybox_${x}_${y}_`];
- if (!animate) box?.destroy();
- drawMain(info, box);
- }
-
- /** 关闭界面 */
- function close() {
- Object.values(sprites).forEach(v => v.destroy());
- setTimeout(core.unlockControl, 600);
- }
-
- function getEnemy(px, py) {
- const evenX = core._WIDTH_ % 2 === 0 ? 0.5 : 0,
- evenY = core._HEIGHT_ % 2 === 0 ? 0.5 : 0;
- const bx = Math.round(
- ~~(px / 32) - core.bigmap.offsetX / 32 + evenX
- ),
- by = Math.round(~~(py / 32) - core.bigmap.offsetY / 32 + evenY);
- const loc = `${bx},${by}`;
- const blocks = core.getMapBlocksObj();
- const block = blocks[loc];
- if (!block) return;
- if (block?.event?.trigger === 'battle')
- return generateCollection(block.event.id, bx, by);
- }
-
- /**
- * 在游戏时移动鼠标,延迟500ms显示怪物信息
- * @param {MouseEvent} e
- */
- function moveOnPlaying(e) {
- if (!allowMap) return;
- if (!core.isPlaying()) return;
- const { x, y } = core.actions._getClickLoc(e.clientX, e.clientY);
- const px = x / core.domStyle.scale,
- py = y / core.domStyle.scale;
- clearTimeout(timeout);
- // 清空所有的信息栏
- Object.values(textBoxes).forEach(v => v.destroy());
- const enemy = getEnemy(px, py);
- if (block?.event?.trigger !== 'battle') return;
- lastLoc = loc;
- timeout = setTimeout(() => {
- drawRough(enemy);
- }, 500);
- }
-
- /**
- * 双击鼠标时
- * @param {MouseEvent} e
- */
- function dblClick(e) {
- if (!allowDbl) return;
- if (!core.isPlaying()) return;
- if (e.detail !== 2) return;
- clearTimeout(dblTimeout);
- clearTimeout(timeout);
- const { x, y } = core.actions._getClickLoc(e.clientX, e.clientY);
- const px = x / core.domStyle.scale,
- py = y / core.domStyle.scale;
- const enemy = getEnemy(px, py);
- drawDetail(enemy);
- }
- },
itemDetail: function () {
/* 宝石血瓶左下角显示数值
* 需要将 变量:itemDetail改为true才可正常运行
@@ -5613,475 +3626,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
}
};
},
- loopMap: function () {
- // 循环式地图相关
- // 防止重开游戏出问题
- ////// 加载某个楼层(从剧本或存档中) //////
- maps.prototype.loadFloor = function (floorId, map, fromReset) {
- var floor = fromReset ? main.floors[floorId] : core.floors[floorId];
- if (!map) map = floor.map;
- if (map instanceof Array) {
- map = { map: map };
- }
- if (!map.map) map.map = core.clone(floor.map);
- var content = {};
- var notCopy = this._loadFloor_doNotCopy();
- for (var name in floor) {
- if (notCopy.indexOf(name) == -1 && floor[name] != null)
- content[name] = core.clone(floor[name]);
- }
- for (var name in map) {
- if (notCopy.indexOf(name) == -1 && map[name] != null)
- content[name] = core.clone(map[name]);
- }
- content.map = map.map;
- if (main.mode == 'editor') {
- this.extractBlocks(content);
- }
- return content;
- };
- ////// 自动存档 //////
- control.prototype.autosave = function (removeLast) {
- if (
- core.hasFlag('__forbidSave__') ||
- core.status.floorId == 'tower6'
- )
- return;
- var x = null;
- if (removeLast) {
- x = core.status.route.pop();
- core.status.route.push('turn:' + core.getHeroLoc('direction'));
- }
- if (core.status.event.id == 'action')
- // 事件中的自动存档
- core.setFlag('__events__', core.clone(core.status.event.data));
- if (core.saves.autosave.data == null) {
- core.saves.autosave.data = [];
- }
- core.saves.autosave.data.splice(
- core.saves.autosave.now,
- 0,
- core.saveData()
- );
- core.saves.autosave.now += 1;
- if (core.saves.autosave.data.length > core.saves.autosave.max) {
- if (core.saves.autosave.now < core.saves.autosave.max / 2)
- core.saves.autosave.data.pop();
- else {
- core.saves.autosave.data.shift();
- core.saves.autosave.now = core.saves.autosave.now - 1;
- }
- }
- core.saves.autosave.updated = true;
- core.saves.ids[0] = true;
- core.removeFlag('__events__');
- if (removeLast) {
- core.status.route.pop();
- if (x) core.status.route.push(x);
- }
- };
- ////// 重置地图 //////
- maps.prototype.resetMap = function (floorId) {
- floorId = floorId || core.status.floorId;
- if (!floorId) return;
- if (typeof floorId == 'string') floorId = [floorId];
- var needRefresh = false;
- floorId.forEach(t => {
- core.status.maps[t] = core.maps.loadFloor(t, null, true);
- // 重置本层的全部独立事件
- Object.keys(core.status.hero.flags).forEach(one => {
- if (one.startsWith(floorId + '@'))
- delete core.status.hero.flags[one];
- });
- // 重置本层的图块删除信息
- delete (flags.__disabled__ || {})[t];
- delete (core.status.mapBlockObjs || {})[t];
- if (t == core.status.floorId) needRefresh = true;
- ['bg', 'bg2', 'fg', 'fg2'].forEach(layer => {
- core.floors[floorId] = main.floors[floorId];
- });
- });
- if (needRefresh) this.drawMap();
- core.drawTip('地图重置成功');
- };
- // 勇士不动图层动
- control.prototype._moveAction_moving = function (callback) {
- core.setHeroMoveInterval(() => {
- if (core.status.floorId != 'tower6') {
- core.setHeroLoc('x', core.nextX(), true);
- } else {
- if (
- core.status.hero.loc.direction != 'down' &&
- core.status.hero.loc.direction != 'up'
- ) {
- core.setHeroLoc('x', 12, true);
- var block = core.getMapBlocksObj(core.status.floorId)[
- core.nextX() + ',' + core.nextY
- ];
- if (block) var trigger = block.event.trigger;
- else var trigger = '';
- if (trigger != 'battle') {
- core.changeEventsBgFg(
- core.status.hero.loc.direction,
- 'tower6',
- ['tower1', 'tower2', 'tower4', 'tower5']
- );
- }
- core.drawMap();
- }
- }
- core.setHeroLoc('y', core.nextY(), true);
- var direction = core.getHeroLoc('direction');
- core.control._moveAction_popAutomaticRoute();
- core.status.route.push(direction);
- core.moveOneStep();
- core.checkRouteFolding();
- if (callback) callback();
- });
- };
- ////// 设置行走的效果动画 //////
- control.prototype.setHeroMoveInterval = function (callback) {
- if (core.status.heroMoving > 0) return;
- if (core.status.replay.speed == 24) {
- if (callback) callback();
- return;
- }
- core.status.heroMoving = 1;
- var toAdd = 1;
- if (core.status.replay.speed > 3) toAdd = 2;
- if (core.status.replay.speed > 6) toAdd = 4;
- if (core.status.replay.speed > 12) toAdd = 8;
- core.interval.heroMoveInterval = window.setInterval(() => {
- core.status.heroMoving += toAdd;
- if (core.status.floorId == 'tower6')
- core.backgroundImage('tower6.jpeg');
- if (core.status.heroMoving >= 8) {
- clearInterval(core.interval.heroMoveInterval);
- core.status.heroMoving = 0;
- if (callback) callback();
- }
- }, ((core.values.moveSpeed / 8) * toAdd) / core.status.replay.speed);
- };
- // 事件层前景层背景层平移
- this.changeEventsBgFg = function (direction, floorId, fromIds) {
- if (direction == 'up' || direction == 'down') return;
- var floor = core.floors[floorId];
- // 原始层楼层转换平移
- fromIds.forEach(id => {
- var toChanges = {};
- for (var one in core.floors[id].changeFloor) {
- var data = core.floors[id].changeFloor[one];
- var x = data.loc[0],
- y = data.loc[1];
- var blocks = core.getMapBlocksObj(id);
- var toFloor = data.floorId;
- if (blocks[one] && !blocks[one].event.id.startsWith('A')) {
- toChanges[one] = { floorId: toFloor, loc: [x, y] };
- continue;
- } else {
- if (direction == 'left')
- x = x >= floor.width - 1 ? 0 : x + 1;
- else x = x <= 0 ? floor.width - 1 : x - 1;
- toChanges[one] = { floorId: toFloor, loc: [x, y] };
- }
- }
- // 转换
- delete core.floors[id].changeFloor;
- core.floors[id].changeFloor = toChanges;
- delete core.status.maps[id].blocks;
- core.extractBlocks(id);
- core.getMapBlocksObj(id, true);
- });
- var list = ['events', 'changeFloor'];
- list.forEach(name => {
- var toEvents = {};
- // 获得事件并删除原事件
- for (var one in floor[name]) {
- var loc = one.split(',');
- var x = parseInt(loc[0]),
- y = parseInt(loc[1]);
- if (direction == 'left') {
- var toX = x == floor.width - 1 ? 0 : x + 1;
- toEvents[toX + ',' + y] = floor[name][one];
- } else {
- var toX = x == 0 ? floor.width - 1 : x - 1;
- toEvents[toX + ',' + y] = floor[name][one];
- }
- delete core.floors[floorId][name][one];
- }
- // 转换
- core.floors[floorId][name] = toEvents;
- });
- // 前景事件背景层图块平移
- list = ['bgmap', 'bg2map', 'map', 'fgmap', 'fg2map'];
- list.forEach(one => {
- if (one == 'map') {
- var toBlocks = core.clone(core.status.maps[floorId].map);
- } else {
- var toBlocks = core.clone(floor[one]);
- }
- if (toBlocks.length == 0) return;
- for (var y = 0; y < toBlocks.length; y++) {
- for (var x = 0; x < toBlocks[y].length; x++) {
- if (direction == 'left') {
- if (one != 'map')
- floor[one][y][x] =
- toBlocks[y][
- x == 0 ? floor.width - 1 : x - 1
- ];
- else
- core.status.maps[floorId].map[y][x] =
- toBlocks[y][
- x == 0 ? floor.width - 1 : x - 1
- ];
- } else {
- if (one != 'map')
- floor[one][y][x] =
- toBlocks[y][
- x == floor.width - 1 ? 0 : x + 1
- ];
- else
- core.status.maps[floorId].map[y][x] =
- toBlocks[y][
- x == floor.width - 1 ? 0 : x + 1
- ];
- }
- }
- }
- });
- delete core.status.maps[floorId].blocks;
- core.setMapBlockDisabled(
- floorId,
- core.nextX(),
- core.nextY(),
- false
- );
- core.extractBlocks(floorId);
- core.getMapBlocksObj(floorId, true);
- };
- // 背景图
- this.backgroundImage = function (image) {
- if (typeof image == 'string') {
- image = core.getMappedName(image);
- image = core.material.images.images[image];
- if (!image) return;
- }
- var h = image.height,
- w = image.width;
- // 裁剪
- var sx = w / 2 - 240,
- sy =
- (core.bigmap.offsetY /
- (core.status.thisMap.height * 32 - 480)) *
- (h - 480);
- // 背景层遮挡
- core.createCanvas('bImage', 0, 0, 480, 480, 25);
- // 事件层遮挡
- core.createCanvas('eImage', 0, 0, 480, 480, 70);
- core.clearMap('bImage');
- // 左半边
- core.drawImage('bImage', image, sx, sy, 96, 480, 0, 0, 96, 480);
- core.drawImage('eImage', image, sx, sy, 64, 480, 0, 0, 64, 480);
- // 右半边
- sx = w / 2 + 144;
- core.drawImage('bImage', image, sx, sy, 96, 480, 384, 0, 96, 480);
- core.drawImage(
- 'eImage',
- image,
- sx + 32,
- sy,
- 64,
- 480,
- 416,
- 0,
- 64,
- 480
- );
- };
- // 到达地图重定位
- this.relocateLoopMap = function (floorId, heroLoc, fromIds) {
- var floor = core.floors[floorId];
- var nowX = heroLoc.x;
- var toX = Math.floor(floor.width / 2);
- if (nowX == toX) return;
- // 设置勇士位置
- core.setHeroLoc('x', 12);
- // 计算偏移量
- var dx = toX - nowX;
- // 转换
- // 原始层楼层转换平移
- if (floorId == 'tower6')
- fromIds = ['tower1', 'tower2', 'tower4', 'tower5'];
- fromIds.forEach(id => {
- var toChanges = {};
- for (var one in core.floors[id].changeFloor) {
- var data = core.floors[id].changeFloor[one];
- var x = data.loc[0],
- y = data.loc[1];
- var blocks = core.getMapBlocksObj(id);
- var toFloor = data.floorId;
- if (blocks[one] && !blocks[one].event.id.startsWith('A')) {
- toChanges[one] = { floorId: toFloor, loc: [x, y] };
- continue;
- }
- if (dx > 0)
- x =
- x + dx > floor.width - 1
- ? dx + x - floor.width
- : dx + x;
- else x = x + dx < 0 ? dx + x + floor.width : dx + x;
- toChanges[one] = { floorId: toFloor, loc: [x, y] };
- }
- // 转换
- delete core.floors[id].changeFloor;
- core.floors[id].changeFloor = toChanges;
- delete core.status.maps[id].blocks;
- core.extractBlocks(id);
- core.getMapBlocksObj(id, true);
- });
- var list = ['events', 'changeFloor'];
- list.forEach(name => {
- var toEvents = {};
- // 获得事件并删除原事件
- for (var one in floor[name]) {
- var loc = one.split(',');
- var x = parseInt(loc[0]),
- y = parseInt(loc[1]);
- if (x + dx > floor.width - 1) {
- x = dx + x - floor.width;
- } else if (x + dx < 0) {
- x = x + dx + floor.width;
- } else {
- x += dx;
- }
- toEvents[x + ',' + y] = floor[name][one];
- delete core.floors[floorId][name][one];
- }
- // 转换
- core.floors[floorId][name] = toEvents;
- });
- dx = -dx;
- // 前景事件背景层图块平移
- list = ['bgmap', 'bg2map', 'map', 'fgmap', 'fg2map'];
- list.forEach(one => {
- if (one == 'map') {
- var toBlocks = core.clone(core.status.maps[floorId].map);
- } else {
- var toBlocks = core.clone(floor[one]);
- }
- if (toBlocks.length == 0) return;
- for (var y = 0; y < toBlocks.length; y++) {
- for (var x = 0; x < toBlocks[y].length; x++) {
- if (dx > 0) {
- if (one != 'map')
- floor[one][y][x] =
- toBlocks[y][
- x + dx > floor.width - 1
- ? dx + x - floor.width
- : dx + x
- ];
- else
- core.status.maps[floorId].map[y][x] =
- toBlocks[y][
- x + dx > floor.width - 1
- ? dx + x - floor.width
- : dx + x
- ];
- } else {
- if (one != 'map')
- floor[one][y][x] =
- toBlocks[y][
- x + dx < 0
- ? dx + x + floor.width
- : dx + x
- ];
- else
- core.status.maps[floorId].map[y][x] =
- toBlocks[y][
- x + dx < 0
- ? dx + x + floor.width
- : dx + x
- ];
- }
- }
- }
- });
- delete core.status.maps[floorId].blocks;
- core.extractBlocks(floorId);
- core.getMapBlocksObj(floorId, true);
- };
- ////// 将当前地图重新变成数字,以便于存档 //////
- maps.prototype.saveMap = function (floorId) {
- if (floorId == 'tower6') return;
- var maps = core.status.maps;
- if (!floorId) {
- var map = {};
- for (var id in maps) {
- if (id == 'tower6') continue;
- var obj = this.saveMap(id);
- if (Object.keys(obj).length > 0) map[id] = obj;
- }
- return map;
- }
- // 砍层状态:直接返回
- if ((flags.__removed__ || []).indexOf(floorId) >= 0) {
- return {};
- }
-
- var map = maps[floorId];
- var thisFloor = this._compressFloorData(map, core.floors[floorId]);
- var mapArr = this.compressMap(
- map.blocks
- ? this._getMapArrayFromBlocks(
- map.blocks,
- map.width,
- map.height,
- true
- )
- : map.map,
- floorId
- );
- if (mapArr != null) thisFloor.map = mapArr;
- return thisFloor;
- };
- // 存档问题
- this.saveLoopMap = function (floorId, fromIds) {
- // 当前层
- var data = {};
- ['bg2map', 'bgmap', 'changeFloor', 'fgmap', 'fg2map'].forEach(
- one => {
- data[one] = core.floors[floorId][one];
- }
- );
- // 可以到达该层的楼层转换
- data.map = core.status.maps[floorId].map;
- data.changes = {};
- fromIds.forEach(id => {
- data.changes[id] = core.floors[id].changeFloor;
- });
- return data;
- };
- // 读档
- this.loadLoopMap = function (data, floorId) {
- if (!data) return;
- for (var one in data) {
- // 非楼层转换
- if (one != 'changes') {
- core.floors[floorId][one] = data[one];
- } else {
- // 楼层转换
- for (var id in data.changes) {
- core.floors[id].changeFloor = data.changes[id];
- }
- }
- }
- // 解析图块
- if (data.changes)
- for (var id in data.changes) {
- core.extractBlocks(id);
- }
- };
- },
towerBoss: function () {
// 智慧boss
// 变量们
@@ -7773,7 +5317,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
}
};
},
- weatherSuperimpose: function () {},
popupDamage: function () {
// 伤害弹出
// 复写阻激夹域检测
@@ -7783,7 +5326,14 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
loc = x + ',' + y;
var damage = core.status.checkBlock.damage[loc];
if (damage) {
- core.addPop(x * 32 + 12, y * 32 + 20, damage, '#f00', '#000');
+ if (!main.replayChecking)
+ core.addPop(
+ x * 32 + 12,
+ y * 32 + 20,
+ damage,
+ '#f00',
+ '#000'
+ );
core.status.hero.hp -= damage;
var text =
Object.keys(core.status.checkBlock.type[loc] || {}).join(
@@ -8645,128 +6195,6 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
}
})();
},
- hide: function () {
- if (main.mode === 'editor' || main.replayChecking) return;
- /**
- * 所有的会被视为房间的墙
- */
- const WALLS = [
- 'yellowWall',
- 'yellowDoor',
- 'blueDoor',
- 'redDoor',
- 'greenDoor'
- ];
- /**
- * 房间的最大大小
- */
- const MAX_AREA = 25;
- /**
- * 要隐藏的点
- */
- const HIDE_POS = [
- ['MT1', 2, 3],
- ['MT2', 4, 5],
- ['MT3', 7, 1]
- ];
-
- let showed = {};
-
- /// 初始化游戏
- events.prototype.resetGame = function (
- hero,
- hard,
- floorId,
- maps,
- values
- ) {
- this.eventdata.resetGame(hero, hard, floorId, maps, values);
- showed = core.getFlag('__showed__', {});
- flags.__showed__ = flags.__showed__ ?? {};
- hide();
- };
-
- /**
- * 显示一个区域
- * @param {string} floor
- * @param {number} x
- * @param {number} y
- */
- this.showHidden = function (floor, x, y) {
- const pos = bfs(floor, x, y);
- for (const [x, y] of pos) {
- core.setBgFgBlock('fg', 0, x, y, floor);
- const id = `${floor}_${x}_${y}`;
- showed[id] = true;
- flags.__showed__[id] = true;
- }
- };
-
- /**
- * 隐藏
- */
- function hide() {
- for (const pos of HIDE_POS) {
- const id = pos.join('_');
- if (showed[id]) continue;
- const p = bfs(...pos);
- if (p.length >= MAX_AREA) continue;
- for (const [x, y] of p) {
- core.setBgFgBlock('fg', 4, x, y, pos[0]);
- const id = `${pos[0]}_${x}_${y}`;
- showed[id] = true;
- flags.__showed__[id] = false;
- }
- }
- }
-
- /**
- * @returns {[number, number][]}
- */
- function bfs(floorId, x, y) {
- core.extractBlocks(floorId);
- const blocks = core.getMapBlocksObj(floorId);
- const mapped = {
- [`${x},${y}`]: true
- };
- const queue = [[x, y]];
- /** @type {[direction, number, number][]} */
- const dir = Object.entries(core.utils.scan).map(v => [
- v[0],
- v[1].x,
- v[1].y
- ]);
- const res = [[x, y]];
-
- while (queue.length > 0) {
- const [nx, ny] = queue.shift();
- dir.forEach(v => {
- const [tx, ty] = [nx + v[1], ny + v[2]];
- const floor = core.status.maps[floorId];
- if (
- tx < 0 ||
- ty < 0 ||
- tx >= floor.width ||
- ty >= floor.height
- )
- return;
- const loc = `${tx},${ty}`;
- if (mapped[loc]) return;
- const block = blocks[loc];
- mapped[loc] = true;
- if (!block) {
- queue.push([tx, ty]);
- res.push([tx, ty]);
- return;
- }
- if (WALLS.includes(block.event.id)) return;
- queue.push([tx, ty]);
- res.push([tx, ty]);
- });
- }
- return res;
- }
- },
uiChange: function () {
if (main.replayChecking) return;
@@ -8836,5 +6264,12 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
core.plugin.chapterContent.value = chapter;
core.plugin.chapterShowed.value = true;
};
+ },
+ remainEnemy: function () {
+ /**
+ * 检查漏怪
+ * @param {FloorIds[]} floorIds
+ */
+ this.checkRemainEnemy = function(floorIds) {}
}
};