2022-10-22 19:23:02 +08:00
|
|
|
|
var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 =
|
2022-10-16 21:58:52 +08:00
|
|
|
|
{
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"init": function () {
|
2022-11-03 23:17:58 +08:00
|
|
|
|
this._afterLoadResources = function () {
|
|
|
|
|
// 本函数将在所有资源加载完毕后,游戏开启前被执行
|
|
|
|
|
}
|
2022-11-20 15:50:50 +08:00
|
|
|
|
try {
|
|
|
|
|
window.screen.orientation.lock("landscape-primary");
|
|
|
|
|
} catch (e) {}
|
|
|
|
|
|
2022-11-03 23:17:58 +08:00
|
|
|
|
core.control.hideStatusBar();
|
|
|
|
|
core.control.resize = function () {
|
|
|
|
|
if (main.mode == 'editor') return;
|
|
|
|
|
var clientWidth = main.dom.body.clientWidth,
|
|
|
|
|
clientHeight = main.dom.body.clientHeight;
|
|
|
|
|
var BORDER = 0;
|
|
|
|
|
var extendToolbar = core.flags.extendToolbar;
|
|
|
|
|
var BAR_WIDTH = extendToolbar ? 0 : Math.round(core._PY_ / 3);
|
|
|
|
|
|
|
|
|
|
var horizontalMaxRatio = (clientHeight - 2 * BORDER - (extendToolbar ? BORDER : 0)) / (core._PY_ + (extendToolbar ? 38 : 0));
|
|
|
|
|
|
|
|
|
|
|
2022-11-20 15:50:50 +08:00
|
|
|
|
// 横屏
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
core.domStyle.availableScale = [];
|
|
|
|
|
[1, 1.25, 1.5, 1.75, 2, 2.25, 2.5].forEach(function (v) {
|
|
|
|
|
if (clientWidth - 3 * BORDER >= v * (core._PX_ + BAR_WIDTH) && horizontalMaxRatio >= v) {
|
|
|
|
|
core.domStyle.availableScale.push(v);
|
2022-10-20 22:22:21 +08:00
|
|
|
|
}
|
2022-11-20 15:50:50 +08:00
|
|
|
|
});
|
|
|
|
|
if (core.domStyle.availableScale.indexOf(core.domStyle.scale) < 0) {
|
|
|
|
|
core.domStyle.scale = Math.min(1, horizontalMaxRatio);
|
|
|
|
|
}
|
|
|
|
|
if (clientWidth - 3 * BORDER >= core._PX_ + BAR_WIDTH || (clientWidth > clientHeight && horizontalMaxRatio < 1)) {
|
|
|
|
|
core.domStyle.isVertical = false;
|
|
|
|
|
core.clearMap('Vertical');
|
2022-11-03 23:17:58 +08:00
|
|
|
|
} else {
|
|
|
|
|
// 竖屏
|
|
|
|
|
core.domStyle.isVertical = true;
|
2022-11-20 15:50:50 +08:00
|
|
|
|
core.createCanvas('Vertical', 0, 0, 480, 480, 200);
|
|
|
|
|
core.drawWindowSkin('winskin.png', 'Vertical', 30, 150, 400, 100);
|
|
|
|
|
core.drawTextContent('Vertical', '\r[#ff8080]强烈建议建议使用最新版浏览器\n开启手机自动旋转功能进行横屏游戏', {
|
|
|
|
|
left: 50,
|
|
|
|
|
top: 180,
|
|
|
|
|
maxWidth: 400,
|
|
|
|
|
fontSize: 20,
|
|
|
|
|
lineHeight: 20,
|
|
|
|
|
bold: true,
|
|
|
|
|
});
|
|
|
|
|
// core.domStyle.scale = Math.min((clientWidth - 2 * BORDER) / core._PX_);
|
|
|
|
|
// core.domStyle.availableScale = [];
|
|
|
|
|
// extendToolbar = false;
|
|
|
|
|
// BAR_WIDTH = Math.round(core._PX_ * 0.3);
|
2022-11-03 23:17:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var statusDisplayArr = this._shouldDisplayStatus(),
|
|
|
|
|
count = statusDisplayArr.length;
|
|
|
|
|
var statusCanvas = core.flags.statusCanvas,
|
|
|
|
|
statusCanvasRows = core.values.statusCanvasRowsOnMobile || 3;
|
|
|
|
|
var col = statusCanvas ? statusCanvasRows : Math.ceil(count / 3);
|
|
|
|
|
if (col > 5) {
|
|
|
|
|
if (statusCanvas) alert("自绘状态栏的在竖屏下的行数应不超过5!");
|
|
|
|
|
else alert("当前状态栏数目(" + count + ")大于15,请调整到不超过15以避免手机端出现显示问题。");
|
|
|
|
|
}
|
|
|
|
|
var globalAttribute = core.status.globalAttribute || core.initStatus.globalAttribute;
|
|
|
|
|
|
|
|
|
|
var obj = {
|
|
|
|
|
clientWidth: clientWidth,
|
|
|
|
|
clientHeight: clientHeight,
|
|
|
|
|
BORDER: BORDER,
|
|
|
|
|
BAR_WIDTH: BAR_WIDTH,
|
|
|
|
|
TOOLBAR_HEIGHT: 38,
|
|
|
|
|
outerWidth: core._PX_ * core.domStyle.scale + 2 * BORDER,
|
|
|
|
|
outerHeight: core._PY_ * core.domStyle.scale + 2 * BORDER,
|
|
|
|
|
globalAttribute: globalAttribute,
|
|
|
|
|
border: '0px ' + core.arrayToRGBA(globalAttribute.borderColor) + ' solid',
|
|
|
|
|
statusDisplayArr: statusDisplayArr,
|
|
|
|
|
count: count,
|
|
|
|
|
col: col,
|
|
|
|
|
statusBarHeightInVertical: core.domStyle.isVertical ? (32 * col + 6) * core.domStyle.scale + 2 * BORDER : 0,
|
|
|
|
|
toolbarHeightInVertical: core.domStyle.isVertical ? 38 * core.domStyle.scale + 2 * BORDER : 0,
|
|
|
|
|
extendToolbar: extendToolbar,
|
|
|
|
|
is15x15: false
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this._doResize(obj);
|
|
|
|
|
this.setToolbarButton();
|
|
|
|
|
core.updateStatusBar();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
core.control._resize_statusBar = function (obj) {
|
|
|
|
|
// statusBar
|
|
|
|
|
var statusBar = core.dom.statusBar;
|
|
|
|
|
if (core.domStyle.isVertical) {
|
|
|
|
|
statusBar.style.width = obj.outerWidth + "px";
|
|
|
|
|
statusBar.style.height = obj.statusBarHeightInVertical + "px";
|
|
|
|
|
statusBar.style.background = obj.globalAttribute.statusTopBackground;
|
|
|
|
|
statusBar.style.fontSize = 16 * core.domStyle.scale + "px";
|
|
|
|
|
} else {
|
|
|
|
|
statusBar.style.width = (obj.BAR_WIDTH * core.domStyle.scale + obj.BORDER) + "px";
|
|
|
|
|
statusBar.style.height = obj.outerHeight + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0) + "px";
|
|
|
|
|
statusBar.style.background = obj.globalAttribute.statusLeftBackground;
|
|
|
|
|
// --- 计算文字大小
|
|
|
|
|
if (obj.extendToolbar) {
|
2022-10-20 22:22:21 +08:00
|
|
|
|
statusBar.style.fontSize = 16 * core.domStyle.scale + "px";
|
2022-11-03 23:17:58 +08:00
|
|
|
|
} else {
|
|
|
|
|
statusBar.style.fontSize = 16 * Math.min(1, (core._HEIGHT_ - 4) / obj.count) * core.domStyle.scale + "px";
|
2022-10-23 23:22:45 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-03 23:17:58 +08:00
|
|
|
|
statusBar.style.display = obj.extendToolbar ? 'none' : 'block';
|
|
|
|
|
statusBar.style.borderTop = statusBar.style.borderLeft = obj.border;
|
|
|
|
|
statusBar.style.borderRight = core.domStyle.isVertical ? obj.border : '';
|
|
|
|
|
statusBar.style.borderBottom = core.domStyle.isVertical ? '' : obj.border;
|
|
|
|
|
// 自绘状态栏
|
|
|
|
|
if (core.domStyle.isVertical) {
|
|
|
|
|
core.dom.statusCanvas.style.width = core._PX_ * core.domStyle.scale + "px";
|
|
|
|
|
core.dom.statusCanvas.style.height = obj.statusBarHeightInVertical - 3 + "px";
|
|
|
|
|
core.maps._setHDCanvasSize(core.dom.statusCanvasCtx, core._PX_, obj.col * 32 + 9);
|
|
|
|
|
} else {
|
|
|
|
|
core.dom.statusCanvas.style.width = obj.BAR_WIDTH * core.domStyle.scale + "px";
|
|
|
|
|
core.dom.statusCanvas.style.height = obj.outerHeight - 2 * obj.BORDER + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0) + "px";
|
|
|
|
|
core.maps._setHDCanvasSize(core.dom.statusCanvasCtx, obj.BAR_WIDTH, core._PY_ + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT + obj.BORDER : 0));
|
2022-10-23 03:51:08 +08:00
|
|
|
|
}
|
2022-11-03 23:17:58 +08:00
|
|
|
|
if (core.domStyle.isVertical) {
|
|
|
|
|
core.dom.caidan1.style.width = core._PX_ * core.domStyle.scale + "px";
|
|
|
|
|
core.dom.caidan1.style.height = obj.statusBarHeightInVertical - 3 + "px";
|
|
|
|
|
core.maps._setHDCanvasSize(core.dom.caidan1Ctx, core._PX_, obj.col * 32 + 9);
|
|
|
|
|
} else {
|
|
|
|
|
core.dom.caidan1.style.width = obj.BAR_WIDTH * core.domStyle.scale + "px";
|
|
|
|
|
core.dom.caidan1.style.height = obj.outerHeight - 2 * obj.BORDER + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0) + "px";
|
|
|
|
|
core.maps._setHDCanvasSize(core.dom.caidan1Ctx, obj.BAR_WIDTH, core._PY_ + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT + obj.BORDER : 0));
|
|
|
|
|
}
|
|
|
|
|
core.dom.statusCanvas.style.display = core.flags.statusCanvas && !obj.extendToolbar ? "block" : "none";
|
|
|
|
|
}
|
|
|
|
|
core.registerResize("statusBar", core.control._resize_statusBar);
|
|
|
|
|
core.control._resize_gameGroup = function (obj) {
|
|
|
|
|
var startBackground = core.domStyle.isVertical ? (main.styles.startVerticalBackground || main.styles.startBackground) : main.styles.startBackground;
|
|
|
|
|
if (main.dom.startBackground.getAttribute('__src__') != startBackground) {
|
|
|
|
|
main.dom.startBackground.setAttribute('__src__', startBackground);
|
|
|
|
|
main.dom.startBackground.src = startBackground;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var gameGroup = core.dom.gameGroup;
|
|
|
|
|
var totalWidth, totalHeight;
|
|
|
|
|
if (core.domStyle.isVertical) {
|
|
|
|
|
totalWidth = obj.outerWidth;
|
|
|
|
|
totalHeight = obj.outerHeight + obj.statusBarHeightInVertical + obj.toolbarHeightInVertical
|
|
|
|
|
} else {
|
|
|
|
|
totalWidth = obj.outerWidth + obj.BAR_WIDTH * core.domStyle.scale + (obj.extendToolbar ? 0 : obj.BORDER);
|
|
|
|
|
totalHeight = obj.outerHeight + (obj.extendToolbar ? obj.TOOLBAR_HEIGHT * core.domStyle.scale + obj.BORDER : 0);
|
|
|
|
|
}
|
|
|
|
|
gameGroup.style.width = totalWidth + "px";
|
|
|
|
|
gameGroup.style.height = totalHeight + "px";
|
|
|
|
|
gameGroup.style.left = (obj.clientWidth - totalWidth) / 2 + "px";
|
|
|
|
|
gameGroup.style.top = (obj.clientHeight - totalHeight) / 2 + "px";
|
|
|
|
|
gameGroup.style.overflow = "hidden";
|
|
|
|
|
var whole = core.dom.whole;
|
|
|
|
|
whole.style.width = totalWidth + "px";
|
|
|
|
|
whole.style.height = totalHeight + "px";
|
|
|
|
|
// floorMsgGroup
|
|
|
|
|
var floorMsgGroup = core.dom.floorMsgGroup;
|
|
|
|
|
floorMsgGroup.style = obj.globalAttribute.floorChangingStyle;
|
|
|
|
|
floorMsgGroup.style.width = obj.outerWidth - 2 * obj.BORDER + "px";
|
|
|
|
|
floorMsgGroup.style.height = totalHeight - 2 * obj.BORDER + "px";
|
|
|
|
|
floorMsgGroup.style.fontSize = 16 * core.domStyle.scale + "px";
|
|
|
|
|
// startPanel
|
|
|
|
|
core.dom.startPanel.style.fontSize = 16 * core.domStyle.scale + "px";
|
|
|
|
|
// musicBtn
|
|
|
|
|
if (core.domStyle.isVertical || core.domStyle.scale < 1) {
|
|
|
|
|
core.dom.musicBtn.style.right = core.dom.musicBtn.style.bottom = "3px";
|
|
|
|
|
} else {
|
|
|
|
|
core.dom.musicBtn.style.right = (obj.clientWidth - totalWidth) / 2 + "px";
|
|
|
|
|
core.dom.musicBtn.style.bottom = (obj.clientHeight - totalHeight) / 2 - 27 + "px";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
core.registerResize("gameGroup", core.control._resize_gameGroup);
|
|
|
|
|
core.maps._drawThumbnail_realDrawTempCanvas = function (floorId, blocks, options) {
|
|
|
|
|
// 缩略图:背景
|
|
|
|
|
this.drawBg(floorId, options);
|
|
|
|
|
// 缩略图:事件
|
|
|
|
|
this.drawEvents(floorId, blocks, options);
|
|
|
|
|
// 缩略图:勇士
|
|
|
|
|
if (options.heroLoc) {
|
|
|
|
|
options.heroIcon = options.heroIcon || core.status.hero.image || 'hero.png';
|
|
|
|
|
options.heroIcon = core.getMappedName(options.heroIcon);
|
|
|
|
|
var icon = core.material.icons.hero[options.heroLoc.direction];
|
|
|
|
|
var height = core.material.images.images[options.heroIcon].height / 4;
|
|
|
|
|
var width = (core.material.images.images[options.heroIcon].width || 128) / 4;
|
|
|
|
|
core.drawImage(options.ctx, core.material.images.images[options.heroIcon], icon.stop * width, icon.loc * height, width, height,
|
|
|
|
|
32 * options.heroLoc.x + 32 - width, 32 * options.heroLoc.y + 32 - height, width, height);
|
|
|
|
|
}
|
|
|
|
|
// 缩略图:卷轴
|
|
|
|
|
if (floorId != 'nandu') core.drawImage(options.ctx, 'caidan.png', -161, 0);
|
|
|
|
|
// 缩略图:前景
|
|
|
|
|
this.drawFg(floorId, options);
|
|
|
|
|
// 缩略图:显伤
|
|
|
|
|
if (options.damage && core.hasItem('book')) {
|
|
|
|
|
core.updateCheckBlock(floorId);
|
|
|
|
|
core.control.updateDamage(floorId, options.ctx);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
core.maps._drawMap_drawAll = function (floorId, config) {
|
|
|
|
|
floorId = floorId || core.status.floorId;
|
|
|
|
|
this.drawBg(floorId, config);
|
|
|
|
|
this.drawEvents(floorId);
|
|
|
|
|
this.drawFg(floorId, config);
|
|
|
|
|
if (floorId == "nandu") {
|
|
|
|
|
core.maps._drawFloorImages(floorId, core.dom.wholeCtx, 'whole', null, null, (config || {}).onMap);
|
|
|
|
|
} else core.dom.wholeCtx.clearRect(0, 0, core.dom.whole.width, core.dom.whole.height);
|
|
|
|
|
}
|
|
|
|
|
core.control._animationFrame_globalAnimate = function (timestamp) {
|
|
|
|
|
if (timestamp - core.animateFrame.globalTime <= core.values.animateSpeed) return;
|
|
|
|
|
core.status.globalAnimateStatus++;
|
|
|
|
|
if (core.status.floorId) {
|
|
|
|
|
// Global Animate
|
|
|
|
|
core.status.globalAnimateObjs.forEach(function (block) {
|
|
|
|
|
core.drawBlock(block, core.status.globalAnimateStatus);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Global floor images
|
|
|
|
|
core.maps._drawFloorImages(core.status.floorId, core.canvas.bg, 'bg', core.status.floorAnimateObjs || [], core.status.globalAnimateStatus);
|
|
|
|
|
core.maps._drawFloorImages(core.status.floorId, core.canvas.fg, 'fg', core.status.floorAnimateObjs || [], core.status.globalAnimateStatus);
|
|
|
|
|
core.maps._drawFloorImages(core.status.floorId, core.dom.wholeCtx, 'whole', core.status.floorAnimateObjs || [], core.status.globalAnimateStatus);
|
|
|
|
|
|
|
|
|
|
// Global Autotile Animate
|
|
|
|
|
core.status.autotileAnimateObjs.forEach(function (block) {
|
|
|
|
|
core.maps._drawAutotileAnimate(block, core.status.globalAnimateStatus);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Global hero animate
|
|
|
|
|
if ((core.status.hero || {}).animate && core.status.heroMoving == 0 && main.mode == 'play' && !core.status.preview.enabled) {
|
|
|
|
|
core.drawHero('stop', null, core.status.globalAnimateStatus);
|
2022-10-25 00:13:37 +08:00
|
|
|
|
}
|
2022-11-03 23:17:58 +08:00
|
|
|
|
}
|
|
|
|
|
// Box animate
|
|
|
|
|
core.drawBoxAnimate();
|
|
|
|
|
core.animateFrame.globalTime = timestamp;
|
|
|
|
|
}
|
|
|
|
|
core.control.registerAnimationFrame("globalAnimate", true, core.control._animationFrame_globalAnimate);
|
|
|
|
|
core.ui.createCanvas2 = function (name, x, y, width, height, z) {
|
|
|
|
|
// 如果画布已存在则直接调用
|
|
|
|
|
if (core.dymCanvas[name]) {
|
|
|
|
|
core.deleteCanvas(name);
|
|
|
|
|
}
|
|
|
|
|
var newCanvas = document.createElement("canvas");
|
|
|
|
|
newCanvas.id = name;
|
|
|
|
|
newCanvas.style.display = 'block';
|
|
|
|
|
newCanvas.setAttribute("_left", x);
|
|
|
|
|
newCanvas.setAttribute("_top", y);
|
|
|
|
|
newCanvas.style.width = width * core.domStyle.scale + 'px';
|
|
|
|
|
newCanvas.style.height = height * core.domStyle.scale + 'px';
|
|
|
|
|
newCanvas.style.left = x * core.domStyle.scale + 'px';
|
|
|
|
|
newCanvas.style.top = y * core.domStyle.scale + 'px';
|
|
|
|
|
newCanvas.style.zIndex = z;
|
|
|
|
|
newCanvas.style.position = 'absolute';
|
|
|
|
|
newCanvas.style.pointerEvents = 'none';
|
|
|
|
|
core.dymCanvas[name] = newCanvas.getContext('2d');
|
|
|
|
|
core.maps._setHDCanvasSize(core.dymCanvas[name], width, height);
|
|
|
|
|
core.dom.gameGroup.appendChild(newCanvas);
|
|
|
|
|
return core.dymCanvas[name];
|
|
|
|
|
}
|
|
|
|
|
core.ui.deleteCanvas = function (name) {
|
|
|
|
|
if (name instanceof Function) {
|
|
|
|
|
Object.keys(core.dymCanvas).forEach(function (one) {
|
|
|
|
|
if (name(one)) core.deleteCanvas(one);
|
|
|
|
|
});
|
2022-11-03 20:37:02 +08:00
|
|
|
|
return;
|
|
|
|
|
}
|
2022-11-03 23:17:58 +08:00
|
|
|
|
|
|
|
|
|
if (!core.dymCanvas[name]) return null;
|
|
|
|
|
var temp = core.dymCanvas[name].canvas.parentElement.id;
|
|
|
|
|
if (temp == "gameDraw") core.dom.gameDraw.removeChild(core.dymCanvas[name].canvas);
|
|
|
|
|
if (temp == "gameGroup") core.dom.gameGroup.removeChild(core.dymCanvas[name].canvas);
|
|
|
|
|
delete core.dymCanvas[name];
|
|
|
|
|
}
|
|
|
|
|
core.events.showImage2 = function (code, image, sloc, loc, opacityVal, time, callback) {
|
|
|
|
|
var imageName = null;
|
|
|
|
|
if (typeof image == 'string') {
|
|
|
|
|
imageName = image;
|
|
|
|
|
if (image.endsWith(':x') || image.endsWith(':y') || image.endsWith(':o')) {
|
|
|
|
|
image = image.substring(0, image.length - 2);
|
|
|
|
|
}
|
|
|
|
|
image = core.getMappedName(image);
|
|
|
|
|
image = core.material.images.images[image];
|
|
|
|
|
}
|
|
|
|
|
if (!image) {
|
|
|
|
|
if (callback) callback();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
sloc = sloc || [];
|
|
|
|
|
var sx = core.calValue(sloc[0]) || 0,
|
|
|
|
|
sy = core.calValue(sloc[1]) || 0;
|
|
|
|
|
var sw = core.calValue(sloc[2]),
|
|
|
|
|
sh = core.calValue(sloc[3]);
|
|
|
|
|
if (sw == null) sw = image.width;
|
|
|
|
|
if (sh == null) sh = image.height;
|
|
|
|
|
loc = loc || [];
|
|
|
|
|
var x = core.calValue(loc[0]) || 0,
|
|
|
|
|
y = core.calValue(loc[1]) || 0;
|
|
|
|
|
var w = core.calValue(loc[2]),
|
|
|
|
|
h = core.calValue(loc[3]);
|
|
|
|
|
if (w == null) w = sw;
|
|
|
|
|
if (h == null) h = sh;
|
|
|
|
|
var zIndex = code + 100;
|
|
|
|
|
time = time || 0;
|
|
|
|
|
var name = "image" + zIndex;
|
|
|
|
|
var ctx = core.ui.createCanvas2(name, x, y, w, h, zIndex);
|
|
|
|
|
core.drawImage(ctx, imageName == null ? image : imageName, sx, sy, sw, sh, 0, 0, w, h);
|
|
|
|
|
if (time == 0) {
|
|
|
|
|
core.setOpacity(name, opacityVal);
|
|
|
|
|
if (callback) callback();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
core.setOpacity(name, 0);
|
|
|
|
|
this.moveImage(code, null, opacityVal, null, time, callback);
|
|
|
|
|
}
|
|
|
|
|
core.events._action_showImage2 = function (data, x, y, prefix) {
|
|
|
|
|
if (core.isReplaying()) data.time = 0;
|
|
|
|
|
this.__action_doAsyncFunc(data.async || data.time == 0, core.events.showImage2,
|
|
|
|
|
data.code, data.image + (data.reverse || ''), data.sloc, data.loc, data.opacity, data.time);
|
|
|
|
|
}
|
|
|
|
|
core.ui._drawCenterFly = function () {
|
|
|
|
|
core.lockControl();
|
|
|
|
|
core.status.event.id = 'centerFly';
|
|
|
|
|
var fillstyle = 'rgba(255,0,0,0.5)';
|
|
|
|
|
if (core.canUseItem('centerFly')) fillstyle = 'rgba(0,255,0,0.5)';
|
|
|
|
|
var toX = core.bigmap.width - 1 - core.getHeroLoc('x'),
|
|
|
|
|
toY = core.bigmap.height - 3 - core.getHeroLoc('y');
|
|
|
|
|
this.clearUI();
|
|
|
|
|
core.fillRect('ui', 0, 0, core._PX_, core._PY_, '#000000');
|
|
|
|
|
core.drawThumbnail(null, null, { heroLoc: core.status.hero.loc, heroIcon: core.status.hero.image, ctx: 'ui', centerX: toX, centerY: toY });
|
|
|
|
|
var offsetX = core.clamp(toX - core._HALF_WIDTH_, 0, core.bigmap.width - core._WIDTH_),
|
|
|
|
|
offsetY = core.clamp(toY - core._HALF_HEIGHT_, 0, core.bigmap.height - core._HEIGHT_);
|
|
|
|
|
core.fillRect('ui', (toX - offsetX) * 32, (toY - offsetY) * 32, 32, 32, fillstyle);
|
|
|
|
|
core.status.event.data = { "x": toX, "y": toY, "posX": toX - offsetX, "posY": toY - offsetY };
|
|
|
|
|
core.playSound('打开界面');
|
|
|
|
|
core.drawTip("请确认当前" + core.material.items['centerFly'].name + "的位置", 'centerFly');
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-11-08 20:29:36 +08:00
|
|
|
|
core.control.setAutomaticRoute = function (destX, destY, stepPostfix) {
|
|
|
|
|
if (!core.status.played || core.status.lockControl) return;
|
|
|
|
|
if (this._setAutomaticRoute_isMoving(destX, destY)) return;
|
|
|
|
|
if (this._setAutomaticRoute_isTurning(destX, destY, stepPostfix)) return;
|
|
|
|
|
if (this._setAutomaticRoute_clickMoveDirectly(destX, destY, stepPostfix)) return;
|
|
|
|
|
// 找寻自动寻路路线
|
|
|
|
|
if (destY == 13 || destY == 14) {
|
|
|
|
|
if (destX == 2 || destX == 3) {
|
|
|
|
|
destY == 13 ? core.openBook(true) : core.ui._drawHelp();
|
|
|
|
|
}
|
|
|
|
|
if (destX == 4 || destX == 5) {
|
|
|
|
|
destY == 13 ? core.useFly(true) : core.turnHero();
|
|
|
|
|
}
|
|
|
|
|
if (destX == 6 || destX == 7 || destX == 8) {
|
|
|
|
|
destY == 13 ? core.openToolbox(true) : core.openQuickShop(true);
|
|
|
|
|
}
|
|
|
|
|
if (destX == 9 || destX == 10) {
|
|
|
|
|
destY == 13 ? core.save(true) : core.openSettings(true);
|
|
|
|
|
}
|
|
|
|
|
if (destX == 11 || destX == 12) {
|
|
|
|
|
destY == 13 ? core.load(true) : core.openSettings(true);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var moveStep = core.automaticRoute(destX, destY);
|
|
|
|
|
if (moveStep.length == 0 && (destX != core.status.hero.loc.x || destY != core.status.hero.loc.y || stepPostfix.length == 0))
|
|
|
|
|
return;
|
|
|
|
|
moveStep = moveStep.concat(stepPostfix);
|
|
|
|
|
core.status.automaticRoute.destX = destX;
|
|
|
|
|
core.status.automaticRoute.destY = destY;
|
|
|
|
|
this._setAutomaticRoute_drawRoute(moveStep);
|
|
|
|
|
this._setAutomaticRoute_setAutoSteps(moveStep);
|
|
|
|
|
// 立刻移动
|
|
|
|
|
core.setAutoHeroMove();
|
|
|
|
|
}
|
2022-11-09 21:38:10 +08:00
|
|
|
|
////// 绘制一个对话框 //////
|
|
|
|
|
core.ui.drawTextBox = function (content, config) {
|
|
|
|
|
config = config || {};
|
|
|
|
|
|
|
|
|
|
this.clearUI();
|
|
|
|
|
content = core.replaceText(content);
|
|
|
|
|
|
|
|
|
|
let ctx = core.getContextByName(config.ctx || 'ui');
|
|
|
|
|
if (ctx && main.mode == 'play') {
|
|
|
|
|
core.createCanvas(ctx, 0, 0, core._PX_, core._PY_, 141);
|
|
|
|
|
ctx = core.getContextByName(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 1: 获得标题信息和位置信息
|
|
|
|
|
var textAttribute = core.status.textAttribute;
|
|
|
|
|
var titleInfo = this._getTitleAndIcon(content);
|
|
|
|
|
var posInfo = this._getPosition(titleInfo.content);
|
|
|
|
|
if (posInfo.position != 'up' && posInfo.position != 'down') posInfo.px = posInfo.py = null;
|
|
|
|
|
if (!posInfo.position) posInfo.position = textAttribute.position;
|
|
|
|
|
content = this._drawTextBox_drawImages(posInfo.content, config.ctx);
|
|
|
|
|
if (config.pos) {
|
|
|
|
|
delete posInfo.px;
|
|
|
|
|
delete posInfo.py;
|
|
|
|
|
posInfo.pos = config.pos;
|
|
|
|
|
}
|
|
|
|
|
posInfo.ctx = ctx;
|
|
|
|
|
|
|
|
|
|
// Step 2: 计算对话框的矩形位置
|
|
|
|
|
var hPos = this._drawTextBox_getHorizontalPosition(content, titleInfo, posInfo);
|
|
|
|
|
var vPos = this._drawTextBox_getVerticalPosition(content, titleInfo, posInfo, hPos.validWidth);
|
|
|
|
|
posInfo.xoffset = hPos.xoffset;
|
|
|
|
|
posInfo.yoffset = vPos.yoffset - 4;
|
|
|
|
|
|
|
|
|
|
if (ctx && main.mode == 'play') {
|
|
|
|
|
ctx.canvas.setAttribute('_text_left', hPos.left);
|
|
|
|
|
ctx.canvas.setAttribute('_text_top', vPos.top);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 3: 绘制背景图
|
|
|
|
|
var isWindowSkin = this.drawBackground(hPos.left, vPos.top, hPos.right, vPos.bottom, posInfo);
|
|
|
|
|
|
|
|
|
|
if (titleInfo.title) {
|
|
|
|
|
let titlefont = core.status.textAttribute.titlefont,
|
|
|
|
|
titleStyle = core.arrayToRGBA(core.status.textAttribute.title);
|
|
|
|
|
let tf = this._buildFont(titlefont, true),
|
|
|
|
|
width = this.calWidth(ctx, titleInfo.title, tf);
|
|
|
|
|
this.drawBackground(hPos.left, vPos.top - titlefont - 12, hPos.left + width + 30, vPos.top, posInfo);
|
|
|
|
|
ctx.save();
|
|
|
|
|
ctx.textAlign = 'center';
|
|
|
|
|
ctx.textBaseline = 'middle';
|
|
|
|
|
core.fillText(ctx, titleInfo.title, hPos.left + (width + 30) / 2, vPos.top - (titlefont + 12) / 2, titleStyle, tf);
|
|
|
|
|
ctx.restore();
|
|
|
|
|
}
|
|
|
|
|
titleInfo.title = null;
|
|
|
|
|
|
|
|
|
|
var alpha = isWindowSkin ? this._drawWindowSkin_getOpacity() : textAttribute.background[3];
|
|
|
|
|
|
|
|
|
|
// Step 4: 绘制标题、头像、动画
|
|
|
|
|
var content_top = this._drawTextBox_drawTitleAndIcon(titleInfo, hPos, vPos, alpha, config.ctx);
|
|
|
|
|
|
|
|
|
|
// Step 5: 绘制正文
|
|
|
|
|
var config = this.drawTextContent(config.ctx || 'ui', content, {
|
|
|
|
|
left: hPos.content_left,
|
|
|
|
|
top: content_top,
|
|
|
|
|
maxWidth: hPos.validWidth,
|
|
|
|
|
lineHeight: vPos.lineHeight,
|
|
|
|
|
time: (config.showAll || config.async || textAttribute.time <= 0 || core.status.event.id != 'action') ? 0 : textAttribute.time
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Step 6: 绘制光标
|
|
|
|
|
if (main.mode == 'play') {
|
|
|
|
|
main.dom.next.style.display = 'block';
|
|
|
|
|
main.dom.next.style.borderRightColor = main.dom.next.style.borderBottomColor = core.arrayToRGB(textAttribute.text);
|
|
|
|
|
main.dom.next.style.top = (vPos.bottom - 20) * core.domStyle.scale + "px";
|
|
|
|
|
var left = (hPos.left + hPos.right) / 2;
|
|
|
|
|
if (posInfo.position == 'up' && !posInfo.noPeak && posInfo.px != null && Math.abs(posInfo.px * 32 + 16 - left) < 50)
|
|
|
|
|
left = hPos.right - 64;
|
|
|
|
|
main.dom.next.style.left = left * core.domStyle.scale + "px";
|
|
|
|
|
}
|
|
|
|
|
return config;
|
|
|
|
|
}
|
2022-11-11 21:12:25 +08:00
|
|
|
|
core.ui._drawSettings = function () {
|
|
|
|
|
core.status.event.id = 'settings';
|
|
|
|
|
this.drawChoices(null, [
|
|
|
|
|
"系统设置", "虚拟键盘", "浏览地图", "存档笔记", "同步存档", "游戏信息", "返回标题", "返回游戏", "数值显示: " + (core.getFlag("itemDetail") ? "[ON]" : "[OFF]")
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
core.actions._clickSettings = function (x, y) {
|
|
|
|
|
if (this._out(x)) return;
|
|
|
|
|
var choices = core.status.event.ui.choices;
|
|
|
|
|
var topIndex = this._getChoicesTopIndex(choices.length);
|
|
|
|
|
if (y >= topIndex && y < topIndex + choices.length) {
|
|
|
|
|
var selection = y - topIndex;
|
|
|
|
|
core.status.event.selection = selection;
|
|
|
|
|
switch (selection) {
|
2022-11-17 13:00:36 +08:00
|
|
|
|
case 0:
|
|
|
|
|
core.status.event.selection = 0;
|
|
|
|
|
core.playSound('确定');
|
|
|
|
|
core.ui._drawSwitchs();
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
// core.playSound('确定');
|
|
|
|
|
core.ui._drawKeyBoard();
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
// core.playSound('确定');
|
|
|
|
|
core.clearUI();
|
|
|
|
|
core.ui._drawViewMaps();
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
core.status.event.selection = 0;
|
|
|
|
|
core.playSound('确定');
|
|
|
|
|
core.ui._drawNotes();
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
core.status.event.selection = 0;
|
|
|
|
|
core.playSound('确定');
|
|
|
|
|
core.ui._drawSyncSave();
|
|
|
|
|
break;
|
|
|
|
|
case 5:
|
|
|
|
|
core.status.event.selection = 0;
|
|
|
|
|
core.playSound('确定');
|
|
|
|
|
core.ui._drawGameInfo();
|
|
|
|
|
break;
|
|
|
|
|
case 6:
|
|
|
|
|
return core.confirmRestart();
|
|
|
|
|
case 7:
|
|
|
|
|
core.playSound('取消');
|
|
|
|
|
core.ui.closePanel();
|
|
|
|
|
break;
|
|
|
|
|
case 8:
|
|
|
|
|
core.playSound('确定');
|
|
|
|
|
core.setFlag("itemDetail", !core.getFlag("itemDetail"));
|
|
|
|
|
core.getItemDetail();
|
|
|
|
|
core.ui.closePanel();
|
|
|
|
|
break;
|
2022-11-11 21:12:25 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-11-12 19:58:49 +08:00
|
|
|
|
////// 获得某个物品 //////
|
|
|
|
|
core.events.getItem = function (id, num, x, y, isGentleClick, callback) {
|
|
|
|
|
if (num == null) num = 1;
|
|
|
|
|
var itemCls = core.material.items[id].cls;
|
|
|
|
|
core.removeBlock(x, y);
|
|
|
|
|
core.items.getItemEffect(id, num);
|
|
|
|
|
var text = '获得 ' + core.material.items[id].name;
|
|
|
|
|
if (num > 1) text += "x" + num;
|
|
|
|
|
if (itemCls === 'items' && num == 1) text += core.items.getItemEffectTip(id);
|
|
|
|
|
core.drawTip(text, id);
|
2022-11-17 13:00:36 +08:00
|
|
|
|
|
2022-11-12 19:58:49 +08:00
|
|
|
|
// --- 首次获得道具的提示
|
|
|
|
|
if (!core.hasFlag("__itemHint__")) core.setFlag("__itemHint__", []);
|
|
|
|
|
var itemHint = core.getFlag("__itemHint__");
|
|
|
|
|
if (core.flags.itemFirstText && itemHint.indexOf(id) < 0 && itemCls != 'items') {
|
|
|
|
|
var hint = core.material.items[id].text || "该道具暂无描述";
|
|
|
|
|
try {
|
|
|
|
|
hint = core.replaceText(hint);
|
2022-11-17 13:00:36 +08:00
|
|
|
|
} catch (e) {}
|
2022-11-12 19:58:49 +08:00
|
|
|
|
if (!core.status.event.id || core.status.event.id == 'action') {
|
2022-11-20 15:50:50 +08:00
|
|
|
|
//core.insertAction("\t[" + core.material.items[id].name + "," + id + "]\b[center]" + hint + "\n"
|
|
|
|
|
//+
|
|
|
|
|
// (id.endsWith('Key') ? "(钥匙类道具,遇到对应的门时自动打开)" :
|
|
|
|
|
// itemCls == 'tools' ? "(消耗类道具,请按T在道具栏使用)" :
|
|
|
|
|
// itemCls == 'constants' ? "(永久类道具,请按T在道具栏使用)" :
|
|
|
|
|
// itemCls == 'equips' ? "(装备类道具,请按Q在装备栏进行装备)" : ""));
|
|
|
|
|
core.insertAction("\b[center]\\c[32]\\i[" + id + "]\\c[22]" + core.material.items[id].name + '\n\n' + hint + "\n");
|
|
|
|
|
|
2022-11-12 19:58:49 +08:00
|
|
|
|
}
|
|
|
|
|
itemHint.push(id);
|
|
|
|
|
}
|
2022-11-17 13:00:36 +08:00
|
|
|
|
|
2022-11-12 19:58:49 +08:00
|
|
|
|
this.afterGetItem(id, x, y, isGentleClick);
|
|
|
|
|
if (callback) callback();
|
|
|
|
|
}
|
2022-11-12 21:35:25 +08:00
|
|
|
|
core.enemys.getDamageString = function (enemy, x, y, floorId) {
|
|
|
|
|
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
|
|
|
|
|
var damage = this.getDamage(enemy, x, y, floorId);
|
2022-11-17 13:00:36 +08:00
|
|
|
|
|
2022-11-12 21:35:25 +08:00
|
|
|
|
var color = '#000000';
|
2022-11-17 13:00:36 +08:00
|
|
|
|
|
2022-11-12 21:35:25 +08:00
|
|
|
|
if (damage == null) {
|
|
|
|
|
damage = "???";
|
|
|
|
|
color = '#FF2222';
|
2022-11-17 13:00:36 +08:00
|
|
|
|
} else {
|
2022-11-12 21:35:25 +08:00
|
|
|
|
if (damage < 0) color = '#11FF11';
|
|
|
|
|
else if (damage == 0) color = '#FFFFFF';
|
|
|
|
|
else if (damage < core.status.hero.hp / 3) color = '#FFFF00';
|
|
|
|
|
else if (damage < core.status.hero.hp * 2 / 3) color = '#FF9933';
|
|
|
|
|
else if (damage < core.status.hero.hp) color = '#FF9933';
|
|
|
|
|
else color = '#FF2222';
|
2022-11-17 13:00:36 +08:00
|
|
|
|
|
2022-11-12 21:35:25 +08:00
|
|
|
|
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 += "^";
|
|
|
|
|
}
|
2022-11-17 13:00:36 +08:00
|
|
|
|
|
2022-11-12 21:35:25 +08:00
|
|
|
|
return {
|
|
|
|
|
"damage": damage,
|
|
|
|
|
"color": color
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
core.ui._drawBook_drawBackground = function () {
|
|
|
|
|
core.setAlpha('ui', 1);
|
2022-11-17 13:00:36 +08:00
|
|
|
|
//core.setFillStyle('ui', '#000000');
|
|
|
|
|
//core.fillRect('ui', 0, 0, core._PX_, core._PY_);删除绘制的黑底
|
|
|
|
|
core.createCanvas('bookBg', 0, 0, 480, 480, 138); ///创建一个动态画布用于绘制手册bg
|
|
|
|
|
core.drawWindowSkin('winskin.png', 'bookBg', 0, 0, core._PX_, core._PY_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ui.prototype._drawBook_drawOne = function (floorId, index, enemy, pageinfo, selected) {
|
|
|
|
|
var top = pageinfo.per_height * index + pageinfo.padding_top; // 最上面margin默认是12px
|
|
|
|
|
enemy.floorId = floorId;
|
|
|
|
|
// 横向规划:
|
|
|
|
|
// 22 + 42 = 64 是头像框
|
|
|
|
|
this._drawBook_drawBox(index, enemy, top, pageinfo);
|
|
|
|
|
var left = 64,
|
|
|
|
|
total_width = core._PX_ - left;
|
|
|
|
|
var name_width = total_width * 10 / 35;
|
|
|
|
|
this._drawBook_drawName(index, enemy, top, left, name_width);
|
|
|
|
|
this._drawBook_drawContent(index, enemy, top, left + name_width);
|
|
|
|
|
if (selected)
|
|
|
|
|
core.drawUIEventSelector(1, 'winskin.png', 10, top + 1, core._PX_ - 10 * 2, pageinfo.per_height, 139); ////绘制光标
|
|
|
|
|
//core.strokeRoundRect('ui', 10, top + 1, core._PX_ - 10 * 2, pageinfo.per_height, 10, core.status.globalAttribute.selectColor);取消原本的黄色框框
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui.prototype._drawBook_drawBox = function (index, enemy, top, pageinfo) {
|
|
|
|
|
// 横向:22+42;纵向:10 + 42 + 10(正好居中);内部图像 32x32
|
|
|
|
|
var border_top = top + (pageinfo.per_height - 42) / 2,
|
|
|
|
|
border_left = 22;
|
|
|
|
|
var img_top = border_top + 5,
|
|
|
|
|
img_left = border_left + 5;
|
|
|
|
|
//core.strokeRect('ui', 22, border_top, 42, 42, '#DDDDDD', 2); //删除怪物边框
|
|
|
|
|
var blockInfo = core.getBlockInfo(enemy.id);
|
|
|
|
|
core.drawIcon('ui', enemy.id, 22 + 5, border_top + 5, 32, 32) ///取消用动画的绘制,改用图标绘制
|
|
|
|
|
/*
|
|
|
|
|
// 检查大怪物
|
|
|
|
|
if (blockInfo.bigImage) {
|
|
|
|
|
core.status.boxAnimateObjs.push({
|
|
|
|
|
bigImage: blockInfo.bigImage,
|
|
|
|
|
face: blockInfo.face,
|
|
|
|
|
centerX: border_left + 21,
|
|
|
|
|
centerY: border_top + 21,
|
|
|
|
|
max_width: 60
|
|
|
|
|
});
|
|
|
|
|
} else if (blockInfo.height >= 42) {
|
|
|
|
|
var originEnemy = core.material.enemys[enemy.id] || {};
|
|
|
|
|
// 检查上半部分是不是纯透明的;取用原始值避免重复计算
|
|
|
|
|
if (originEnemy.is32x32 == null) {
|
|
|
|
|
originEnemy.is32x32 = this._drawBook_is32x32(blockInfo);
|
|
|
|
|
}
|
|
|
|
|
if (originEnemy.is32x32) {
|
|
|
|
|
core.status.boxAnimateObjs.push({
|
|
|
|
|
'bgx': border_left,
|
|
|
|
|
'bgy': border_top,
|
|
|
|
|
'bgWidth': 42,
|
|
|
|
|
'bgHeight': 42,
|
|
|
|
|
'x': img_left,
|
|
|
|
|
'y': img_top,
|
|
|
|
|
'height': 32,
|
|
|
|
|
'animate': blockInfo.animate,
|
|
|
|
|
'image': blockInfo.image,
|
|
|
|
|
'pos': blockInfo.posY * blockInfo.height + blockInfo.height - 32
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
var drawWidth = 42 * 32 / blockInfo.height;
|
|
|
|
|
core.status.boxAnimateObjs.push({
|
|
|
|
|
'bgx': border_left,
|
|
|
|
|
'bgy': border_top,
|
|
|
|
|
'bgWidth': 42,
|
|
|
|
|
'bgHeight': 42,
|
|
|
|
|
'x': img_left - 5 + (42 - drawWidth) / 2,
|
|
|
|
|
'y': img_top - 5,
|
|
|
|
|
'dw': drawWidth,
|
|
|
|
|
'dh': 42,
|
|
|
|
|
'height': blockInfo.height,
|
|
|
|
|
'animate': blockInfo.animate,
|
|
|
|
|
'image': blockInfo.image,
|
|
|
|
|
'pos': blockInfo.posY * blockInfo.height
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
core.status.boxAnimateObjs.push({
|
|
|
|
|
'bgx': border_left,
|
|
|
|
|
'bgy': border_top,
|
|
|
|
|
'bgWidth': 42,
|
|
|
|
|
'bgHeight': 42,
|
|
|
|
|
'x': img_left,
|
|
|
|
|
'y': img_top,
|
|
|
|
|
'height': 32,
|
|
|
|
|
'animate': blockInfo.animate,
|
|
|
|
|
'image': blockInfo.image,
|
|
|
|
|
'pos': blockInfo.posY * blockInfo.height
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui.prototype._drawBook_drawName = function (index, enemy, top, left, width) {
|
|
|
|
|
// 绘制第零列(名称和特殊属性)
|
|
|
|
|
// 如果需要添加自己的比如怪物的称号等,也可以在这里绘制
|
|
|
|
|
core.setTextAlign('ui', 'center');
|
|
|
|
|
if (enemy.specialText.length == 0) {
|
|
|
|
|
core.fillText('ui', enemy.name, left + width / 2,
|
|
|
|
|
top + 35, '#ffffff', this._buildFont(enemy.name.length >= 5 ? 18 : 20, false), width); /////修改怪物名字的颜色,取消加粗
|
|
|
|
|
} else {
|
|
|
|
|
core.fillText('ui', enemy.name, left + width / 2,
|
|
|
|
|
top + 28, '#ffffff', this._buildFont(enemy.name.length >= 5 ? 18 : 20, false), width); /////修改怪物名字颜色,取消加粗
|
|
|
|
|
switch (enemy.specialText.length) {
|
|
|
|
|
case 1:
|
|
|
|
|
core.fillText('ui', enemy.specialText[0][0] + ' ' + enemy.specialText[0][1], left + width / 2, ////单属性两个字中间空一格
|
|
|
|
|
top + 50, core.arrayToRGBA((enemy.specialColor || [])[0] || '#FF6A6A'),
|
|
|
|
|
this._buildFont(20, false), width); ////调大怪物字号,取消加粗
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
// Step 1: 计算字体
|
|
|
|
|
var text = enemy.specialText[0] + "" + enemy.specialText[1]; ///减少空格
|
|
|
|
|
core.setFontForMaxWidth('ui', text, width, this._buildFont(20, false)); ////调大怪物属性的字号,取消加粗
|
|
|
|
|
// Step 2: 计算总宽度
|
|
|
|
|
var totalWidth = core.calWidth('ui', text);
|
|
|
|
|
var leftWidth = core.calWidth('ui', enemy.specialText[0]);
|
|
|
|
|
var rightWidth = core.calWidth('ui', enemy.specialText[1]);
|
|
|
|
|
// Step 3: 绘制
|
|
|
|
|
core.fillText('ui', enemy.specialText[0], left + (width + leftWidth - totalWidth) / 2,
|
|
|
|
|
top + 50, core.arrayToRGBA((enemy.specialColor || [])[0] || '#FF6A6A'));
|
|
|
|
|
core.fillText('ui', enemy.specialText[1], left + (width + totalWidth - rightWidth) / 2,
|
|
|
|
|
top + 50, core.arrayToRGBA((enemy.specialColor || [])[1] || '#FF6A6A'));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
core.fillText('ui', '多属性...', left + width / 2,
|
|
|
|
|
top + 50, '#FF6A6A', this._buildFont(15, true), width);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ui.prototype._drawBook_drawRow1 = function (index, enemy, top, left, width, position) {
|
|
|
|
|
// 绘制第一行
|
|
|
|
|
core.setTextAlign('ui', 'left');
|
|
|
|
|
var b13 = this._buildFont(13, true),
|
|
|
|
|
f13 = this._buildFont(13, false);
|
|
|
|
|
var col1 = left,
|
|
|
|
|
col2 = left + width * 9 / 25,
|
|
|
|
|
col3 = left + width * 17 / 25;
|
|
|
|
|
var colour = '#80ffff'; ////单数行颜色
|
|
|
|
|
if (index % 2 === 0)
|
|
|
|
|
colour = '#80ff80'; ////双数行颜色
|
|
|
|
|
core.fillText('ui', core.getStatusLabel('hp'), col1, position, colour, f13);
|
|
|
|
|
core.fillText('ui', core.formatBigNumber(enemy.hp || 0), col1 + 30, position, null, b13);
|
|
|
|
|
core.fillText('ui', core.getStatusLabel('atk'), col2, position, colour, f13);
|
|
|
|
|
core.fillText('ui', core.formatBigNumber(enemy.atk || 0), col2 + 30, position, null, b13);
|
|
|
|
|
core.fillText('ui', core.getStatusLabel('def'), col3, position, colour, f13);
|
|
|
|
|
core.fillText('ui', core.formatBigNumber(enemy.def || 0), col3 + 30, position, null, b13);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui.prototype._drawBook_drawRow2 = function (index, enemy, top, left, width, position) {
|
|
|
|
|
// 绘制第二行
|
|
|
|
|
core.setTextAlign('ui', 'left');
|
|
|
|
|
var b13 = this._buildFont(13, true),
|
|
|
|
|
f13 = this._buildFont(13, false);
|
|
|
|
|
var col1 = left,
|
|
|
|
|
col2 = left + width * 9 / 25,
|
|
|
|
|
col3 = left + width * 17 / 25;
|
|
|
|
|
var colour = '#80ffff'; ////单数行颜色
|
|
|
|
|
if (index % 2 === 0)
|
|
|
|
|
colour = '#80ff80'; ////双数行颜色
|
|
|
|
|
// 获得第二行绘制的内容
|
|
|
|
|
var second_line = [];
|
|
|
|
|
if (core.flags.statusBarItems.indexOf('enableMoney') >= 0) second_line.push([core.getStatusLabel('money'), core.formatBigNumber(enemy.money || 0)]);
|
|
|
|
|
if (core.flags.enableAddPoint) second_line.push([core.getStatusLabel('point'), core.formatBigNumber(enemy.point || 0)]);
|
|
|
|
|
if (core.flags.statusBarItems.indexOf('enableExp') >= 0) second_line.push([core.getStatusLabel('exp'), core.formatBigNumber(enemy.exp || 0)]);
|
|
|
|
|
|
|
|
|
|
var damage_offset = col1 + (core._PX_ - col1) / 2 - 12;
|
|
|
|
|
// 第一列
|
|
|
|
|
if (second_line.length > 0) {
|
|
|
|
|
var one = second_line.shift();
|
|
|
|
|
core.fillText('ui', one[0], col1, position, colour, f13);
|
|
|
|
|
core.fillText('ui', one[1], col1 + 30, position, colour, b13);
|
|
|
|
|
damage_offset = col2 + (core._PX_ - col2) / 2 - 12;
|
|
|
|
|
}
|
|
|
|
|
// 第二列
|
|
|
|
|
if (second_line.length > 0) {
|
|
|
|
|
var one = second_line.shift();
|
|
|
|
|
core.fillText('ui', one[0], col2, position, colour, f13);
|
|
|
|
|
core.fillText('ui', one[1], col2 + 30, position, colour, b13);
|
|
|
|
|
damage_offset = col3 + (core._PX_ - col3) / 2 - 12;
|
|
|
|
|
}
|
|
|
|
|
// 忽略第三列,直接绘制伤害
|
|
|
|
|
core.fillText('ui', '伤害', col3, position, colour, f13); ////增加绘制伤害两字
|
|
|
|
|
this._drawBook_drawDamage(index, enemy, damage_offset, position);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui.prototype._drawBook_drawRow3 = function (index, enemy, top, left, width, position) {
|
|
|
|
|
// 绘制第三行
|
|
|
|
|
core.setTextAlign('ui', 'left');
|
|
|
|
|
var b13 = this._buildFont(13, true),
|
|
|
|
|
f13 = this._buildFont(13, false);
|
|
|
|
|
var col1 = left,
|
|
|
|
|
col2 = left + width * 9 / 25,
|
|
|
|
|
col3 = left + width * 17 / 25;
|
|
|
|
|
var colour = '#80ffff'; ////单数行颜色
|
|
|
|
|
if (index % 2 === 0)
|
|
|
|
|
colour = '#80ff80'; ////双数行颜色
|
|
|
|
|
core.fillText('ui', '临界', col1, position, colour, f13);
|
|
|
|
|
core.fillText('ui', core.formatBigNumber(enemy.critical || 0), col1 + 30, position, colour, b13);
|
|
|
|
|
core.fillText('ui', '减伤', col2, position, colour, f13);
|
|
|
|
|
core.fillText('ui', core.formatBigNumber(enemy.criticalDamage || 0), col2 + 30, position, colour, b13);
|
|
|
|
|
core.fillText('ui', '加防', col3, position, colour, f13);
|
|
|
|
|
core.fillText('ui', core.formatBigNumber(enemy.defDamage || 0), col3 + 30, position, colour, b13);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui.prototype._drawBook_drawDamage = function (index, enemy, offset, position) { //////修改了颜色
|
|
|
|
|
offset -= 5; //往左移5像素
|
|
|
|
|
//core.setTextAlign('ui', 'center');取消居中对齐
|
|
|
|
|
var damage = enemy.damage,
|
|
|
|
|
color = '#e6de0d';
|
|
|
|
|
if (damage == null) {
|
|
|
|
|
damage = '????'; ////////无法战斗怪物手册中改为????显示
|
|
|
|
|
color = '#ff8080';
|
|
|
|
|
} else {
|
|
|
|
|
if (damage >= core.status.hero.hp) color = '#ff8080';
|
|
|
|
|
else if (damage >= core.status.hero.hp * 2 / 3) color = '#ffc080';
|
|
|
|
|
else if (damage <= 0) color = '#ffffff';
|
|
|
|
|
damage = core.formatBigNumber(damage);
|
|
|
|
|
if (core.enemys.hasSpecial(enemy, 19)) damage += "+";
|
|
|
|
|
if (core.enemys.hasSpecial(enemy, 21)) damage += "-";
|
|
|
|
|
if (core.enemys.hasSpecial(enemy, 11)) damage += "^";
|
|
|
|
|
}
|
|
|
|
|
if (enemy.notBomb) damage += "[b]";
|
|
|
|
|
core.fillText('ui', damage, offset, position, color, this._buildFont(13, true));
|
2022-11-12 21:35:25 +08:00
|
|
|
|
}
|
2022-11-17 13:00:36 +08:00
|
|
|
|
|
|
|
|
|
////// 绘制怪物属性的详细信息 //////
|
|
|
|
|
ui.prototype._drawBookDetail = function (index) {
|
|
|
|
|
var info = this._drawBookDetail_getInfo(index),
|
|
|
|
|
enemy = info[0];
|
|
|
|
|
if (!enemy) return;
|
|
|
|
|
var content = info[1].join("\n");
|
|
|
|
|
core.status.event.id = 'book-detail';
|
|
|
|
|
core.animateFrame.tip = null;
|
|
|
|
|
core.clearMap('data');
|
|
|
|
|
|
|
|
|
|
var left = 10,
|
|
|
|
|
width = core._PX_ - 2 * left,
|
|
|
|
|
right = left + width;
|
|
|
|
|
var content_left = left + 25,
|
|
|
|
|
validWidth = right - content_left - 13;
|
|
|
|
|
var height = Math.max(this.getTextContentHeight(content, { fontSize: 16, lineHeight: 24, maxWidth: validWidth }) + 58, 80),
|
|
|
|
|
top = (core._PY_ - height) / 2,
|
|
|
|
|
bottom = top + height;
|
|
|
|
|
|
|
|
|
|
core.drawWindowSkin('winskin.png', 'data', left, top, width, height); ////用winskin绘制一个对话框
|
|
|
|
|
/// core.setAlpha('data', 0.9);///注销原本的黑底边框
|
|
|
|
|
///core.fillRect('data', left, top, width, height, '#000000');
|
|
|
|
|
// core.setAlpha('data', 1);
|
|
|
|
|
// core.strokeRect('data', left - 1, top - 1, width + 1, height + 1,
|
|
|
|
|
// core.arrayToRGBA(core.status.globalAttribute.borderColor), 2);
|
|
|
|
|
core.playSound('确定');
|
|
|
|
|
this._drawBookDetail_drawContent(enemy, content, { top: top, content_left: content_left, bottom: bottom, validWidth: validWidth });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////// 结束一切事件和绘制,关闭UI窗口,返回游戏进程 //////
|
|
|
|
|
ui.prototype.closePanel = function () {
|
|
|
|
|
|
|
|
|
|
core.clearMap('bookBg'); ////清空手册Bg
|
|
|
|
|
core.clearMap('itemBg'); ////清空道具栏Bg
|
|
|
|
|
core.clearUIEventSelector(1); ////清除绘制的光标
|
|
|
|
|
|
|
|
|
|
if (core.status.hero && core.status.hero.flags) {
|
|
|
|
|
// 清除全部临时变量
|
|
|
|
|
Object.keys(core.status.hero.flags).forEach(function (name) {
|
|
|
|
|
if (name.startsWith("@temp@") || /^arg\d+$/.test(name)) {
|
|
|
|
|
delete core.status.hero.flags[name];
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
this.clearUI();
|
|
|
|
|
core.maps.generateGroundPattern();
|
|
|
|
|
core.updateStatusBar(true);
|
|
|
|
|
core.unlockControl();
|
|
|
|
|
core.status.event.data = null;
|
|
|
|
|
core.status.event.id = null;
|
|
|
|
|
core.status.event.selection = null;
|
|
|
|
|
core.status.event.ui = null;
|
|
|
|
|
core.status.event.interval = null;
|
|
|
|
|
// 清除onDownInterval
|
|
|
|
|
clearInterval(core.interval.onDownInterval);
|
|
|
|
|
core.interval.onDownInterval = 'tmp';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui.prototype._drawToolbox_drawBackground = function () {
|
|
|
|
|
// 绘制
|
|
|
|
|
core.clearMap('ui');
|
|
|
|
|
/// core.setAlpha('ui', 0.85);
|
|
|
|
|
/// core.fillRect('ui', 0, 0, core._PX_, core._PY_, '#000000');
|
|
|
|
|
core.createCanvas('itemBg', 0, 0, 480, 480, 138); ///创建一个动态画布用于绘制道具栏bg
|
|
|
|
|
core.drawWindowSkin('winskin.png', 'itemBg', 0, 0, core._PX_, core._PY_); ///道具栏背景用winskin绘制
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ui.prototype._drawToolbox_drawContent = function (info, line, items, page, drawCount) {
|
|
|
|
|
var n = core._HALF_WIDTH_;
|
|
|
|
|
core.setTextAlign('ui', 'right');
|
|
|
|
|
for (var i = 0; i < core._WIDTH_ - 1; i++) {
|
|
|
|
|
var item = items[(core._WIDTH_ - 1) * (page - 1) + i];
|
|
|
|
|
if (!item) continue;
|
|
|
|
|
var yoffset = line + 54 * Math.floor(i / n) + 19;
|
|
|
|
|
var icon = core.material.icons.items[item],
|
|
|
|
|
image = core.material.images.items;
|
|
|
|
|
core.drawImage('ui', image, 0, 32 * icon, 32, 32, 64 * (i % n) + 21, yoffset, 32, 32);
|
|
|
|
|
if (drawCount)
|
|
|
|
|
core.fillText('ui', core.itemCount(item), 64 * (i % n) + 56, yoffset + 33, '#FFFFFF', this._buildFont(14, true));
|
|
|
|
|
if (info.selectId == item)
|
|
|
|
|
core.drawUIEventSelector(1, 'winskin.png', 64 * (i % n) + 17, yoffset - 4, 40, 40, 139); ////绘制光标
|
|
|
|
|
//core.strokeRoundRect('ui', 64 * (i % n) + 17, yoffset - 4, 40, 40, 6, core.status.globalAttribute.selectColor);删除原本绘制的黄色边框
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-12 21:35:25 +08:00
|
|
|
|
core.ui.drawFly = function (page) {
|
|
|
|
|
core.status.event.data = page;
|
|
|
|
|
var floorId = core.floorIds[page];
|
|
|
|
|
var title = core.status.maps[floorId].title;
|
|
|
|
|
core.clearMap('ui');
|
|
|
|
|
core.setAlpha('ui', 0.85);
|
|
|
|
|
core.fillRect('ui', 0, 0, core._PX_, core._PY_, '#000000');
|
|
|
|
|
core.setAlpha('ui', 1);
|
|
|
|
|
core.setTextAlign('ui', 'center');
|
|
|
|
|
core.fillText('ui', '楼层跳跃', core._PX_ / 2, 48, '#FFFFFF', this._buildFont(28, true));
|
|
|
|
|
core.fillText('ui', '返回游戏', core._PX_ / 2, core._PY_ - 13, null, this._buildFont(15, true))
|
|
|
|
|
core.setTextAlign('ui', 'right');
|
|
|
|
|
core.fillText('ui', '浏览地图时也', core._PX_ - 10, core._PY_ - 23, '#aaaaaa', this._buildFont(10, false));
|
|
|
|
|
core.fillText('ui', '可楼层跳跃!', core._PX_ - 10, core._PY_ - 11, null, this._buildFont(10, false));
|
|
|
|
|
core.setTextAlign('ui', 'center');
|
2022-11-17 13:00:36 +08:00
|
|
|
|
|
2022-11-12 21:35:25 +08:00
|
|
|
|
var middle = core._PY_ / 2 + 39;
|
2022-11-17 13:00:36 +08:00
|
|
|
|
|
2022-11-12 21:35:25 +08:00
|
|
|
|
// 换行
|
|
|
|
|
var lines = core.splitLines('ui', title, 120, this._buildFont(19, true));
|
|
|
|
|
var start_y = middle - (lines.length - 1) * 11;
|
|
|
|
|
for (var i in lines) {
|
|
|
|
|
core.fillText('ui', lines[i], core._PX_ - 53, start_y, '#FFFFFF', this._buildFont(17, true));
|
|
|
|
|
start_y += 22;
|
|
|
|
|
}
|
|
|
|
|
if (core.actions._getNextFlyFloor(1) != page) {
|
|
|
|
|
core.fillText('ui', '▲', core._PX_ - 60, middle - 64, null, this._buildFont(17, false));
|
|
|
|
|
core.fillText('ui', '▲', core._PX_ - 60, middle - 96);
|
|
|
|
|
core.fillText('ui', '▲', core._PX_ - 60, middle - 96 - 7);
|
|
|
|
|
}
|
|
|
|
|
if (core.actions._getNextFlyFloor(-1) != page) {
|
|
|
|
|
core.fillText('ui', '▼', core._PX_ - 60, middle + 64, null, this._buildFont(17, false));
|
|
|
|
|
core.fillText('ui', '▼', core._PX_ - 60, middle + 96);
|
|
|
|
|
core.fillText('ui', '▼', core._PX_ - 60, middle + 96 + 7);
|
|
|
|
|
}
|
|
|
|
|
var size = 0.75;
|
|
|
|
|
core.strokeRect('ui', 16, 64, size * core._PX_, size * core._PY_, '#FFFFFF', 2);
|
|
|
|
|
core.drawThumbnail(floorId, null, { ctx: 'ui', x: 16, y: 64, size: size, damage: true, all: true });
|
|
|
|
|
}
|
2022-11-03 23:17:58 +08:00
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"drawLight": function () {
|
2022-10-16 21:58:52 +08:00
|
|
|
|
|
|
|
|
|
// 绘制灯光/漆黑层效果。调用方式 core.plugin.drawLight(...)
|
|
|
|
|
// 【参数说明】
|
|
|
|
|
// name:必填,要绘制到的画布名;可以是一个系统画布,或者是个自定义画布;如果不存在则创建
|
|
|
|
|
// color:可选,只能是一个0~1之间的数,为不透明度的值。不填则默认为0.9。
|
|
|
|
|
// lights:可选,一个数组,定义了每个独立的灯光。
|
|
|
|
|
// 其中每一项是三元组 [x,y,r] x和y分别为该灯光的横纵坐标,r为该灯光的半径。
|
|
|
|
|
// lightDec:可选,0到1之间,光从多少百分比才开始衰减(在此范围内保持全亮),不设置默认为0。
|
|
|
|
|
// 比如lightDec为0.5代表,每个灯光部分内圈50%的范围全亮,50%以后才开始快速衰减。
|
|
|
|
|
// 【调用样例】
|
|
|
|
|
// core.plugin.drawLight('curtain'); // 在curtain层绘制全图不透明度0.9,等价于更改画面色调为[0,0,0,0.9]。
|
|
|
|
|
// core.plugin.drawLight('ui', 0.95, [[25,11,46]]); // 在ui层绘制全图不透明度0.95,其中在(25,11)点存在一个半径为46的灯光效果。
|
|
|
|
|
// core.plugin.drawLight('test', 0.2, [[25,11,46,0.1]]); // 创建一个test图层,不透明度0.2,其中在(25,11)点存在一个半径为46的灯光效果,灯光中心不透明度0.1。
|
|
|
|
|
// core.plugin.drawLight('test2', 0.9, [[25,11,46],[105,121,88],[301,221,106]]); // 创建test2图层,且存在三个灯光效果,分别是中心(25,11)半径46,中心(105,121)半径88,中心(301,221)半径106。
|
|
|
|
|
// core.plugin.drawLight('xxx', 0.3, [[25,11,46],[105,121,88,0.2]], 0.4); // 存在两个灯光效果,它们在内圈40%范围内保持全亮,40%后才开始衰减。
|
|
|
|
|
this.drawLight = function (name, color, lights, lightDec) {
|
|
|
|
|
|
|
|
|
|
// 清空色调层;也可以修改成其它层比如animate/weather层,或者用自己创建的canvas
|
|
|
|
|
var ctx = core.getContextByName(name);
|
|
|
|
|
if (ctx == null) {
|
|
|
|
|
if (typeof name == 'string')
|
|
|
|
|
ctx = core.createCanvas(name, 0, 0, core._PX_ || core.__PIXELS__, core._PY_ || core.__PIXELS__, 98);
|
|
|
|
|
else return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctx.mozImageSmoothingEnabled = false;
|
|
|
|
|
ctx.webkitImageSmoothingEnabled = false;
|
|
|
|
|
ctx.msImageSmoothingEnabled = false;
|
|
|
|
|
ctx.imageSmoothingEnabled = false;
|
|
|
|
|
|
|
|
|
|
core.clearMap(name);
|
|
|
|
|
// 绘制色调层,默认不透明度
|
|
|
|
|
if (color == null) color = 0.9;
|
|
|
|
|
ctx.fillStyle = "rgba(0,0,0," + color + ")";
|
|
|
|
|
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
|
|
|
|
|
|
|
|
lightDec = core.clamp(lightDec, 0, 1);
|
|
|
|
|
|
|
|
|
|
// 绘制每个灯光效果
|
|
|
|
|
ctx.globalCompositeOperation = 'destination-out';
|
|
|
|
|
lights.forEach(function (light) {
|
|
|
|
|
// 坐标,半径,中心不透明度
|
|
|
|
|
var x = light[0],
|
|
|
|
|
y = light[1],
|
|
|
|
|
r = light[2];
|
|
|
|
|
// 计算衰减距离
|
|
|
|
|
var decDistance = parseInt(r * lightDec);
|
|
|
|
|
// 正方形区域的直径和左上角坐标
|
|
|
|
|
var grd = ctx.createRadialGradient(x, y, decDistance, x, y, r);
|
|
|
|
|
grd.addColorStop(0, "rgba(0,0,0,1)");
|
|
|
|
|
grd.addColorStop(1, "rgba(0,0,0,0)");
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
ctx.fillStyle = grd;
|
|
|
|
|
ctx.arc(x, y, r, 0, 2 * Math.PI);
|
|
|
|
|
ctx.fill();
|
|
|
|
|
});
|
|
|
|
|
ctx.globalCompositeOperation = 'source-over';
|
|
|
|
|
// 可以在任何地方(如afterXXX或自定义脚本事件)调用函数,方法为 core.plugin.xxx();
|
|
|
|
|
}
|
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"shop": function () {
|
2022-10-16 21:58:52 +08:00
|
|
|
|
// 【全局商店】相关的功能
|
|
|
|
|
//
|
|
|
|
|
// 打开一个全局商店
|
|
|
|
|
// shopId:要打开的商店id;noRoute:是否不计入录像
|
|
|
|
|
this.openShop = function (shopId, noRoute) {
|
|
|
|
|
var shop = core.status.shops[shopId];
|
|
|
|
|
// Step 1: 检查能否打开此商店
|
|
|
|
|
if (!this.canOpenShop(shopId)) {
|
|
|
|
|
core.drawTip("该商店尚未开启");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 2: (如有必要)记录打开商店的脚本事件
|
|
|
|
|
if (!noRoute) {
|
|
|
|
|
core.status.route.push("shop:" + shopId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 3: 检查道具商店 or 公共事件
|
|
|
|
|
if (shop.item) {
|
|
|
|
|
if (core.openItemShop) {
|
|
|
|
|
core.openItemShop(shopId);
|
|
|
|
|
} else {
|
|
|
|
|
core.playSound('操作失败');
|
|
|
|
|
core.insertAction("道具商店插件不存在!请检查是否存在该插件!");
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (shop.commonEvent) {
|
|
|
|
|
core.insertCommonEvent(shop.commonEvent, shop.args);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_shouldProcessKeyUp = true;
|
|
|
|
|
|
|
|
|
|
// Step 4: 执行标准公共商店
|
|
|
|
|
core.insertAction(this._convertShop(shop));
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////// 将一个全局商店转变成可预览的公共事件 //////
|
|
|
|
|
this._convertShop = function (shop) {
|
|
|
|
|
return [
|
|
|
|
|
{ "type": "function", "function": "function() {core.addFlag('@temp@shop', 1);}" },
|
|
|
|
|
{
|
|
|
|
|
"type": "while",
|
|
|
|
|
"condition": "true",
|
|
|
|
|
"data": [
|
|
|
|
|
// 检测能否访问该商店
|
|
|
|
|
{
|
|
|
|
|
"type": "if",
|
|
|
|
|
"condition": "core.isShopVisited('" + shop.id + "')",
|
|
|
|
|
"true": [
|
|
|
|
|
// 可以访问,直接插入执行效果
|
|
|
|
|
{ "type": "function", "function": "function() { core.plugin._convertShop_replaceChoices('" + shop.id + "', false) }" },
|
|
|
|
|
],
|
|
|
|
|
"false": [
|
|
|
|
|
// 不能访问的情况下:检测能否预览
|
|
|
|
|
{
|
|
|
|
|
"type": "if",
|
|
|
|
|
"condition": shop.disablePreview,
|
|
|
|
|
"true": [
|
|
|
|
|
// 不可预览,提示并退出
|
|
|
|
|
{ "type": "playSound", "name": "操作失败" },
|
|
|
|
|
"当前无法访问该商店!",
|
|
|
|
|
{ "type": "break" },
|
|
|
|
|
],
|
|
|
|
|
"false": [
|
|
|
|
|
// 可以预览:将商店全部内容进行替换
|
|
|
|
|
{ "type": "tip", "text": "当前处于预览模式,不可购买" },
|
|
|
|
|
{ "type": "function", "function": "function() { core.plugin._convertShop_replaceChoices('" + shop.id + "', true) }" },
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{ "type": "function", "function": "function() {core.addFlag('@temp@shop', -1);}" }
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._convertShop_replaceChoices = function (shopId, previewMode) {
|
|
|
|
|
var shop = core.status.shops[shopId];
|
|
|
|
|
var choices = (shop.choices || []).filter(function (choice) {
|
|
|
|
|
if (choice.condition == null || choice.condition == '') return true;
|
|
|
|
|
try { return core.calValue(choice.condition); } catch (e) { return true; }
|
|
|
|
|
}).map(function (choice) {
|
|
|
|
|
var ableToBuy = core.calValue(choice.need);
|
|
|
|
|
return {
|
|
|
|
|
"text": choice.text,
|
|
|
|
|
"icon": choice.icon,
|
|
|
|
|
"color": ableToBuy && !previewMode ? choice.color : [153, 153, 153, 1],
|
|
|
|
|
"action": ableToBuy && !previewMode ? [{ "type": "playSound", "name": "商店" }].concat(choice.action) : [
|
|
|
|
|
{ "type": "playSound", "name": "操作失败" },
|
|
|
|
|
{ "type": "tip", "text": previewMode ? "预览模式下不可购买" : "购买条件不足" }
|
|
|
|
|
]
|
|
|
|
|
};
|
|
|
|
|
}).concat({ "text": "离开", "action": [{ "type": "playSound", "name": "取消" }, { "type": "break" }] });
|
|
|
|
|
core.insertAction({ "type": "choices", "text": shop.text, "choices": choices });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 是否访问过某个快捷商店
|
|
|
|
|
this.isShopVisited = function (id) {
|
|
|
|
|
if (!core.hasFlag("__shops__")) core.setFlag("__shops__", {});
|
|
|
|
|
var shops = core.getFlag("__shops__");
|
|
|
|
|
if (!shops[id]) shops[id] = {};
|
|
|
|
|
return shops[id].visited;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 当前应当显示的快捷商店列表
|
|
|
|
|
this.listShopIds = function () {
|
|
|
|
|
return Object.keys(core.status.shops).filter(function (id) {
|
|
|
|
|
return core.isShopVisited(id) || !core.status.shops[id].mustEnable;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 是否能够打开某个商店
|
|
|
|
|
this.canOpenShop = function (id) {
|
|
|
|
|
if (this.isShopVisited(id)) return true;
|
|
|
|
|
var shop = core.status.shops[id];
|
|
|
|
|
if (shop.item || shop.commonEvent || shop.mustEnable) return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 启用或禁用某个快捷商店
|
|
|
|
|
this.setShopVisited = function (id, visited) {
|
|
|
|
|
if (!core.hasFlag("__shops__")) core.setFlag("__shops__", {});
|
|
|
|
|
var shops = core.getFlag("__shops__");
|
|
|
|
|
if (!shops[id]) shops[id] = {};
|
|
|
|
|
if (visited) shops[id].visited = true;
|
|
|
|
|
else delete shops[id].visited;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// 能否使用快捷商店
|
|
|
|
|
this.canUseQuickShop = function (id) {
|
|
|
|
|
// 如果返回一个字符串,表示不能,字符串为不能使用的提示
|
|
|
|
|
// 返回null代表可以使用
|
|
|
|
|
|
|
|
|
|
// 检查当前楼层的canUseQuickShop选项是否为false
|
|
|
|
|
if (core.status.thisMap.canUseQuickShop === false)
|
|
|
|
|
return '当前楼层不能使用快捷商店。';
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _shouldProcessKeyUp = true;
|
|
|
|
|
|
|
|
|
|
/// 允许商店X键退出
|
|
|
|
|
core.registerAction('keyUp', 'shops', function (keycode) {
|
|
|
|
|
if (!core.status.lockControl || core.status.event.id != 'action') return false;
|
|
|
|
|
if ((keycode == 13 || keycode == 32) && !_shouldProcessKeyUp) {
|
|
|
|
|
_shouldProcessKeyUp = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!core.hasFlag("@temp@shop") || core.status.event.data.type != 'choices') return false;
|
|
|
|
|
var data = core.status.event.data.current;
|
|
|
|
|
var choices = data.choices;
|
|
|
|
|
var topIndex = core.actions._getChoicesTopIndex(choices.length);
|
|
|
|
|
if (keycode == 88 || keycode == 27) { // X, ESC
|
|
|
|
|
core.actions._clickAction(core._HALF_WIDTH_ || core.__HALF_SIZE__, topIndex + choices.length - 1);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}, 60);
|
|
|
|
|
|
|
|
|
|
/// 允许长按空格或回车连续执行操作
|
|
|
|
|
core.registerAction('keyDown', 'shops', function (keycode) {
|
|
|
|
|
if (!core.status.lockControl || !core.hasFlag("@temp@shop") || core.status.event.id != 'action') return false;
|
|
|
|
|
if (core.status.event.data.type != 'choices') return false;
|
|
|
|
|
core.status.onShopLongDown = true;
|
|
|
|
|
var data = core.status.event.data.current;
|
|
|
|
|
var choices = data.choices;
|
|
|
|
|
var topIndex = core.actions._getChoicesTopIndex(choices.length);
|
|
|
|
|
if (keycode == 13 || keycode == 32) { // Space, Enter
|
|
|
|
|
core.actions._clickAction(core._HALF_WIDTH_ || core.__HALF_SIZE__, topIndex + core.status.event.selection);
|
|
|
|
|
_shouldProcessKeyUp = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}, 60);
|
|
|
|
|
|
|
|
|
|
// 允许长按屏幕连续执行操作
|
|
|
|
|
core.registerAction('longClick', 'shops', function (x, y, px, py) {
|
|
|
|
|
if (!core.status.lockControl || !core.hasFlag("@temp@shop") || core.status.event.id != 'action') return false;
|
|
|
|
|
if (core.status.event.data.type != 'choices') return false;
|
|
|
|
|
var data = core.status.event.data.current;
|
|
|
|
|
var choices = data.choices;
|
|
|
|
|
var topIndex = core.actions._getChoicesTopIndex(choices.length);
|
|
|
|
|
if (Math.abs(x - (core._HALF_WIDTH_ || core.__HALF_SIZE__)) <= 2 && y >= topIndex && y < topIndex + choices.length) {
|
|
|
|
|
core.actions._clickAction(x, y);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}, 60);
|
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"removeMap": function () {
|
2022-10-16 21:58:52 +08:00
|
|
|
|
// 高层塔砍层插件,删除后不会存入存档,不可浏览地图也不可飞到。
|
|
|
|
|
// 推荐用法:
|
|
|
|
|
// 对于超高层或分区域塔,当在1区时将2区以后的地图删除;1区结束时恢复2区,进二区时删除1区地图,以此类推
|
|
|
|
|
// 这样可以大幅减少存档空间,以及加快存读档速度
|
|
|
|
|
|
|
|
|
|
// 删除楼层
|
|
|
|
|
// core.removeMaps("MT1", "MT300") 删除MT1~MT300之间的全部层
|
|
|
|
|
// core.removeMaps("MT10") 只删除MT10层
|
|
|
|
|
this.removeMaps = function (fromId, toId) {
|
|
|
|
|
toId = toId || fromId;
|
|
|
|
|
var fromIndex = core.floorIds.indexOf(fromId),
|
|
|
|
|
toIndex = core.floorIds.indexOf(toId);
|
|
|
|
|
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
|
|
|
|
flags.__visited__ = flags.__visited__ || {};
|
|
|
|
|
flags.__removed__ = flags.__removed__ || [];
|
|
|
|
|
flags.__disabled__ = flags.__disabled__ || {};
|
|
|
|
|
flags.__leaveLoc__ = flags.__leaveLoc__ || {};
|
|
|
|
|
for (var i = fromIndex; i <= toIndex; ++i) {
|
|
|
|
|
var floorId = core.floorIds[i];
|
|
|
|
|
if (core.status.maps[floorId].deleted) continue;
|
|
|
|
|
delete flags.__visited__[floorId];
|
|
|
|
|
flags.__removed__.push(floorId);
|
|
|
|
|
delete flags.__disabled__[floorId];
|
|
|
|
|
delete flags.__leaveLoc__[floorId];
|
|
|
|
|
(core.status.autoEvents || []).forEach(function (event) {
|
|
|
|
|
if (event.floorId == floorId && event.currentFloor) {
|
|
|
|
|
core.autoEventExecuting(event.symbol, false);
|
|
|
|
|
core.autoEventExecuted(event.symbol, false);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
core.status.maps[floorId].deleted = true;
|
|
|
|
|
core.status.maps[floorId].canFlyTo = false;
|
|
|
|
|
core.status.maps[floorId].canFlyFrom = false;
|
|
|
|
|
core.status.maps[floorId].cannotViewMap = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 恢复楼层
|
|
|
|
|
// core.resumeMaps("MT1", "MT300") 恢复MT1~MT300之间的全部层
|
|
|
|
|
// core.resumeMaps("MT10") 只恢复MT10层
|
|
|
|
|
this.resumeMaps = function (fromId, toId) {
|
|
|
|
|
toId = toId || fromId;
|
|
|
|
|
var fromIndex = core.floorIds.indexOf(fromId),
|
|
|
|
|
toIndex = core.floorIds.indexOf(toId);
|
|
|
|
|
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
|
|
|
|
flags.__removed__ = flags.__removed__ || [];
|
|
|
|
|
for (var i = fromIndex; i <= toIndex; ++i) {
|
|
|
|
|
var floorId = core.floorIds[i];
|
|
|
|
|
if (!core.status.maps[floorId].deleted) continue;
|
|
|
|
|
flags.__removed__ = flags.__removed__.filter(function (f) { return f != floorId; });
|
|
|
|
|
core.status.maps[floorId] = core.loadFloor(floorId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 分区砍层相关
|
|
|
|
|
var inAnyPartition = function (floorId) {
|
|
|
|
|
var inPartition = false;
|
|
|
|
|
(core.floorPartitions || []).forEach(function (floor) {
|
|
|
|
|
var fromIndex = core.floorIds.indexOf(floor[0]);
|
|
|
|
|
var toIndex = core.floorIds.indexOf(floor[1]);
|
|
|
|
|
var index = core.floorIds.indexOf(floorId);
|
|
|
|
|
if (fromIndex < 0 || index < 0) return;
|
|
|
|
|
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
|
|
|
|
if (index >= fromIndex && index <= toIndex) inPartition = true;
|
|
|
|
|
});
|
|
|
|
|
return inPartition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 分区砍层
|
|
|
|
|
this.autoRemoveMaps = function (floorId) {
|
|
|
|
|
if (main.mode != 'play' || !inAnyPartition(floorId)) return;
|
|
|
|
|
// 根据分区信息自动砍层与恢复
|
|
|
|
|
(core.floorPartitions || []).forEach(function (floor) {
|
|
|
|
|
var fromIndex = core.floorIds.indexOf(floor[0]);
|
|
|
|
|
var toIndex = core.floorIds.indexOf(floor[1]);
|
|
|
|
|
var index = core.floorIds.indexOf(floorId);
|
|
|
|
|
if (fromIndex < 0 || index < 0) return;
|
|
|
|
|
if (toIndex < 0) toIndex = core.floorIds.length - 1;
|
|
|
|
|
if (index >= fromIndex && index <= toIndex) {
|
|
|
|
|
core.resumeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]);
|
|
|
|
|
} else {
|
|
|
|
|
core.removeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"fiveLayers": function () {
|
2022-10-16 21:58:52 +08:00
|
|
|
|
// 是否启用五图层(增加背景2层和前景2层) 将__enable置为true即会启用;启用后请保存后刷新编辑器
|
|
|
|
|
// 背景层2将会覆盖背景层 被事件层覆盖 前景层2将会覆盖前景层
|
|
|
|
|
// 另外 请注意加入两个新图层 会让大地图的性能降低一些
|
|
|
|
|
// 插件作者:ad
|
|
|
|
|
var __enable = false;
|
|
|
|
|
if (!__enable) return;
|
|
|
|
|
|
|
|
|
|
// 创建新图层
|
|
|
|
|
function createCanvas (name, zIndex) {
|
|
|
|
|
if (!name) return;
|
|
|
|
|
var canvas = document.createElement('canvas');
|
|
|
|
|
canvas.id = name;
|
|
|
|
|
canvas.className = 'gameCanvas';
|
|
|
|
|
// 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高
|
|
|
|
|
if (main.mode != "editor") canvas.style.zIndex = zIndex || 0;
|
|
|
|
|
// 将图层插入进游戏内容
|
|
|
|
|
document.getElementById('gameDraw').appendChild(canvas);
|
|
|
|
|
var ctx = canvas.getContext('2d');
|
|
|
|
|
core.canvas[name] = ctx;
|
|
|
|
|
canvas.width = core._PX_ || core.__PIXELS__;
|
|
|
|
|
canvas.height = core._PY_ || core.__PIXELS__;
|
|
|
|
|
return canvas;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var bg2Canvas = createCanvas('bg2', 20);
|
|
|
|
|
var fg2Canvas = createCanvas('fg2', 63);
|
|
|
|
|
// 大地图适配
|
|
|
|
|
core.bigmap.canvas = ["bg2", "fg2", "bg", "event", "event2", "fg", "damage"];
|
|
|
|
|
core.initStatus.bg2maps = {};
|
|
|
|
|
core.initStatus.fg2maps = {};
|
|
|
|
|
|
|
|
|
|
if (main.mode == 'editor') {
|
|
|
|
|
/*插入编辑器的图层 不做此步新增图层无法在编辑器显示*/
|
|
|
|
|
// 编辑器图层覆盖优先级 eui > efg > fg(前景层) > event2(48*32图块的事件层) > event(事件层) > bg(背景层)
|
|
|
|
|
// 背景层2(bg2) 插入事件层(event)之前(即bg与event之间)
|
|
|
|
|
document.getElementById('mapEdit').insertBefore(bg2Canvas, document.getElementById('event'));
|
|
|
|
|
// 前景层2(fg2) 插入编辑器前景(efg)之前(即fg之后)
|
|
|
|
|
document.getElementById('mapEdit').insertBefore(fg2Canvas, document.getElementById('ebm'));
|
|
|
|
|
// 原本有三个图层 从4开始添加
|
|
|
|
|
var num = 4;
|
|
|
|
|
// 新增图层存入editor.dom中
|
|
|
|
|
editor.dom.bg2c = core.canvas.bg2.canvas;
|
|
|
|
|
editor.dom.bg2Ctx = core.canvas.bg2;
|
|
|
|
|
editor.dom.fg2c = core.canvas.fg2.canvas;
|
|
|
|
|
editor.dom.fg2Ctx = core.canvas.fg2;
|
|
|
|
|
editor.dom.maps.push('bg2map', 'fg2map');
|
|
|
|
|
editor.dom.canvas.push('bg2', 'fg2');
|
|
|
|
|
|
|
|
|
|
// 创建编辑器上的按钮
|
|
|
|
|
var createCanvasBtn = function (name) {
|
|
|
|
|
// 电脑端创建按钮
|
|
|
|
|
var input = document.createElement('input');
|
|
|
|
|
// layerMod4/layerMod5
|
|
|
|
|
var id = 'layerMod' + num++;
|
|
|
|
|
// bg2map/fg2map
|
|
|
|
|
var value = name + 'map';
|
|
|
|
|
input.type = 'radio';
|
|
|
|
|
input.name = 'layerMod';
|
|
|
|
|
input.id = id;
|
|
|
|
|
input.value = value;
|
|
|
|
|
editor.dom[id] = input;
|
|
|
|
|
input.onchange = function () {
|
|
|
|
|
editor.uifunctions.setLayerMod(value);
|
|
|
|
|
}
|
|
|
|
|
return input;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var createCanvasBtn_mobile = function (name) {
|
|
|
|
|
// 手机端往选择列表中添加子选项
|
|
|
|
|
var input = document.createElement('option');
|
|
|
|
|
var id = 'layerMod' + num++;
|
|
|
|
|
var value = name + 'map';
|
|
|
|
|
input.name = 'layerMod';
|
|
|
|
|
input.value = value;
|
|
|
|
|
editor.dom[id] = input;
|
|
|
|
|
return input;
|
|
|
|
|
};
|
|
|
|
|
if (!editor.isMobile) {
|
|
|
|
|
var input = createCanvasBtn('bg2');
|
|
|
|
|
var input2 = createCanvasBtn('fg2');
|
|
|
|
|
// 获取事件层及其父节点
|
|
|
|
|
var child = document.getElementById('layerMod'),
|
|
|
|
|
parent = child.parentNode;
|
|
|
|
|
// 背景层2插入事件层前
|
|
|
|
|
parent.insertBefore(input, child);
|
|
|
|
|
// 不能直接更改背景层2的innerText 所以创建文本节点
|
|
|
|
|
var txt = document.createTextNode('bg2');
|
|
|
|
|
// 插入事件层前(即新插入的背景层2前)
|
|
|
|
|
parent.insertBefore(txt, child);
|
|
|
|
|
// 向最后插入前景层2(即插入前景层后)
|
|
|
|
|
parent.appendChild(input2);
|
|
|
|
|
var txt2 = document.createTextNode('fg2');
|
|
|
|
|
parent.appendChild(txt2);
|
|
|
|
|
parent.childNodes[2].replaceWith("bg");
|
|
|
|
|
parent.childNodes[6].replaceWith("事件");
|
|
|
|
|
parent.childNodes[8].replaceWith("fg");
|
|
|
|
|
} else {
|
|
|
|
|
var input = createCanvasBtn_mobile('bg2');
|
|
|
|
|
var input2 = createCanvasBtn_mobile('fg2');
|
|
|
|
|
// 手机端因为是选项 所以可以直接改innerText
|
|
|
|
|
input.innerText = '背景层2';
|
|
|
|
|
input2.innerText = '前景层2';
|
|
|
|
|
var parent = document.getElementById('layerMod');
|
|
|
|
|
parent.insertBefore(input, parent.children[1]);
|
|
|
|
|
parent.appendChild(input2);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _loadFloor_doNotCopy = core.maps._loadFloor_doNotCopy;
|
|
|
|
|
core.maps._loadFloor_doNotCopy = function () {
|
|
|
|
|
return ["bg2map", "fg2map"].concat(_loadFloor_doNotCopy());
|
|
|
|
|
}
|
|
|
|
|
////// 绘制背景和前景层 //////
|
|
|
|
|
core.maps._drawBg_draw = function (floorId, toDrawCtx, cacheCtx, config) {
|
|
|
|
|
config.ctx = cacheCtx;
|
|
|
|
|
core.maps._drawBg_drawBackground(floorId, config);
|
|
|
|
|
// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制背景图块;后绘制的覆盖先绘制的。
|
|
|
|
|
core.maps._drawFloorImages(floorId, config.ctx, 'bg', null, null, config.onMap);
|
|
|
|
|
core.maps._drawBgFgMap(floorId, 'bg', config);
|
|
|
|
|
if (config.onMap) {
|
|
|
|
|
core.drawImage(toDrawCtx, cacheCtx.canvas, core.bigmap.v2 ? -32 : 0, core.bigmap.v2 ? -32 : 0);
|
|
|
|
|
core.clearMap('bg2');
|
|
|
|
|
core.clearMap(cacheCtx);
|
|
|
|
|
}
|
|
|
|
|
core.maps._drawBgFgMap(floorId, 'bg2', config);
|
|
|
|
|
if (config.onMap) core.drawImage('bg2', cacheCtx.canvas, core.bigmap.v2 ? -32 : 0, core.bigmap.v2 ? -32 : 0);
|
|
|
|
|
config.ctx = toDrawCtx;
|
|
|
|
|
}
|
|
|
|
|
core.maps._drawFg_draw = function (floorId, toDrawCtx, cacheCtx, config) {
|
|
|
|
|
config.ctx = cacheCtx;
|
|
|
|
|
// ------ 调整这两行的顺序来控制是先绘制贴图还是先绘制前景图块;后绘制的覆盖先绘制的。
|
|
|
|
|
core.maps._drawFloorImages(floorId, config.ctx, 'fg', null, null, config.onMap);
|
|
|
|
|
core.maps._drawBgFgMap(floorId, 'fg', config);
|
|
|
|
|
if (config.onMap) {
|
|
|
|
|
core.drawImage(toDrawCtx, cacheCtx.canvas, core.bigmap.v2 ? -32 : 0, core.bigmap.v2 ? -32 : 0);
|
|
|
|
|
core.clearMap('fg2');
|
|
|
|
|
core.clearMap(cacheCtx);
|
|
|
|
|
}
|
|
|
|
|
core.maps._drawBgFgMap(floorId, 'fg2', config);
|
|
|
|
|
if (config.onMap) core.drawImage('fg2', cacheCtx.canvas, core.bigmap.v2 ? -32 : 0, core.bigmap.v2 ? -32 : 0);
|
|
|
|
|
config.ctx = toDrawCtx;
|
|
|
|
|
}
|
|
|
|
|
////// 移动判定 //////
|
|
|
|
|
core.maps._generateMovableArray_arrays = function (floorId) {
|
|
|
|
|
return {
|
|
|
|
|
bgArray: this.getBgMapArray(floorId),
|
|
|
|
|
fgArray: this.getFgMapArray(floorId),
|
|
|
|
|
eventArray: this.getMapArray(floorId),
|
|
|
|
|
bg2Array: this._getBgFgMapArray('bg2', floorId),
|
|
|
|
|
fg2Array: this._getBgFgMapArray('fg2', floorId)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"itemShop": function () {
|
2022-10-23 03:51:08 +08:00
|
|
|
|
// 道具商店相关的插件
|
|
|
|
|
// 可在全塔属性-全局商店中使用「道具商店」事件块进行编辑(如果找不到可以在入口方块中找)
|
|
|
|
|
|
|
|
|
|
var shopId = null; // 当前商店ID
|
|
|
|
|
var type = 0; // 当前正在选中的类型,0买入1卖出
|
|
|
|
|
var selectItem = 0; // 当前正在选中的道具
|
|
|
|
|
var selectCount = 0; // 当前已经选中的数量
|
|
|
|
|
var page = 0;
|
|
|
|
|
var totalPage = 0;
|
|
|
|
|
var totalMoney = 0;
|
|
|
|
|
var list = [];
|
|
|
|
|
var shopInfo = null; // 商店信息
|
|
|
|
|
var choices = []; // 商店选项
|
|
|
|
|
var use = 'money';
|
|
|
|
|
var useText = '金币';
|
|
|
|
|
|
|
|
|
|
var bigFont = core.ui._buildFont(20, false),
|
|
|
|
|
middleFont = core.ui._buildFont(18, false);
|
|
|
|
|
|
|
|
|
|
this._drawItemShop = function () {
|
|
|
|
|
// 绘制道具商店
|
|
|
|
|
|
|
|
|
|
// Step 1: 背景和固定的几个文字
|
|
|
|
|
core.ui._createUIEvent();
|
|
|
|
|
core.clearMap('uievent');
|
|
|
|
|
core.ui.clearUIEventSelector();
|
|
|
|
|
core.setTextAlign('uievent', 'left');
|
|
|
|
|
core.setTextBaseline('uievent', 'top');
|
|
|
|
|
core.fillRect('uievent', 0, 0, 480, 480, 'black');
|
|
|
|
|
core.drawWindowSkin('winskin.png', 'uievent', 0, 0, 480, 64);
|
|
|
|
|
core.drawWindowSkin('winskin.png', 'uievent', 0, 64, 360, 64);
|
|
|
|
|
core.drawWindowSkin('winskin.png', 'uievent', 0, 128, 360, 352);
|
|
|
|
|
core.drawWindowSkin('winskin.png', 'uievent', 360, 64, 120, 64);
|
|
|
|
|
core.drawWindowSkin('winskin.png', 'uievent', 360, 128, 120, 352);
|
|
|
|
|
core.setFillStyle('uievent', 'white');
|
|
|
|
|
core.setStrokeStyle('uievent', 'white');
|
|
|
|
|
core.fillText("uievent", "购买", 32, 84, 'white', bigFont);
|
|
|
|
|
core.fillText("uievent", "卖出", 152, 84);
|
|
|
|
|
core.fillText("uievent", "离开", 272, 84);
|
|
|
|
|
core.fillText("uievent", "当前" + useText, 374, 75, null, middleFont);
|
|
|
|
|
core.setTextAlign("uievent", "right");
|
|
|
|
|
core.fillText("uievent", core.formatBigNumber(core.status.hero.money), 466, 100);
|
|
|
|
|
core.setTextAlign("uievent", "left");
|
|
|
|
|
core.ui.drawUIEventSelector(1, "winskin.png", 22 + 120 * type, 76, 60, 33);
|
|
|
|
|
if (selectItem != null) {
|
|
|
|
|
core.setTextAlign('uievent', 'center');
|
|
|
|
|
core.fillText("uievent", type == 0 ? "买入个数" : "卖出个数", 420, 360, null, bigFont);
|
|
|
|
|
core.fillText("uievent", "< " + selectCount + " >", 420, 390);
|
|
|
|
|
core.fillText("uievent", "确定", 420, 420);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Step 2:获得列表并展示
|
|
|
|
|
list = choices.filter(function (one) {
|
|
|
|
|
if (one.condition != null && one.condition != '') {
|
|
|
|
|
try { if (!core.calValue(one.condition)) return false; } catch (e) {}
|
|
|
|
|
}
|
|
|
|
|
return (type == 0 && one.money != null) || (type == 1 && one.sell != null);
|
|
|
|
|
});
|
|
|
|
|
var per_page = 7;
|
|
|
|
|
totalPage = Math.ceil(list.length / per_page);
|
|
|
|
|
page = Math.floor((selectItem || 0) / per_page) + 1;
|
|
|
|
|
|
|
|
|
|
// 绘制分页
|
|
|
|
|
if (totalPage > 1) {
|
|
|
|
|
var half = 180;
|
|
|
|
|
core.setTextAlign('uievent', 'center');
|
|
|
|
|
core.fillText('uievent', page + " / " + totalPage, half, 450, null, middleFont);
|
|
|
|
|
if (page > 1) core.fillText('uievent', '上一页', half - 80, 450);
|
|
|
|
|
if (page < totalPage) core.fillText('uievent', '下一页', half + 80, 450);
|
|
|
|
|
}
|
|
|
|
|
core.setTextAlign('uievent', 'left');
|
|
|
|
|
|
|
|
|
|
// 绘制每一项
|
|
|
|
|
var start = (page - 1) * per_page;
|
|
|
|
|
for (var i = 0; i < per_page; ++i) {
|
|
|
|
|
var curr = start + i;
|
|
|
|
|
if (curr >= list.length) break;
|
|
|
|
|
var item = list[curr];
|
|
|
|
|
core.drawIcon('uievent', item.id, 10, 141 + i * 40);
|
2022-10-16 21:58:52 +08:00
|
|
|
|
core.setTextAlign('uievent', 'left');
|
2022-10-23 03:51:08 +08:00
|
|
|
|
core.fillText('uievent', core.material.items[item.id].name, 50, 148 + i * 40, null, bigFont);
|
|
|
|
|
core.setTextAlign('uievent', 'right');
|
|
|
|
|
core.fillText('uievent', (type == 0 ? core.calValue(item.money) : core.calValue(item.sell)) + useText + "/个", 340, 149 + i * 40, null, middleFont);
|
2022-10-16 21:58:52 +08:00
|
|
|
|
core.setTextAlign("uievent", "left");
|
2022-10-23 03:51:08 +08:00
|
|
|
|
if (curr == selectItem) {
|
|
|
|
|
// 绘制描述,文字自动放缩
|
|
|
|
|
var text = core.material.items[item.id].text || "该道具暂无描述";
|
|
|
|
|
try { text = core.replaceText(text); } catch (e) {}
|
|
|
|
|
for (var fontSize = 20; fontSize >= 8; fontSize -= 2) {
|
|
|
|
|
var config = { left: 10, fontSize: fontSize, maxWidth: 467 };
|
|
|
|
|
var height = core.getTextContentHeight(text, config);
|
|
|
|
|
if (height <= 60) {
|
|
|
|
|
config.top = (64 - height) / 2;
|
|
|
|
|
core.drawTextContent("uievent", text, config);
|
|
|
|
|
break;
|
2022-10-16 21:58:52 +08:00
|
|
|
|
}
|
2022-10-23 03:51:08 +08:00
|
|
|
|
}
|
|
|
|
|
core.ui.drawUIEventSelector(2, "winskin.png", 8, 137 + i * 40, 343, 40);
|
|
|
|
|
if (type == 0 && item.number != null) {
|
|
|
|
|
core.fillText("uievent", "存货", 370, 152, null, bigFont);
|
2022-10-16 21:58:52 +08:00
|
|
|
|
core.setTextAlign("uievent", "right");
|
2022-10-23 03:51:08 +08:00
|
|
|
|
core.fillText("uievent", item.number, 470, 152, null, null, 60);
|
|
|
|
|
} else if (type == 1) {
|
|
|
|
|
core.fillText("uievent", "数量", 370, 152, null, bigFont);
|
2022-10-16 21:58:52 +08:00
|
|
|
|
core.setTextAlign("uievent", "right");
|
2022-10-23 03:51:08 +08:00
|
|
|
|
core.fillText("uievent", core.itemCount(item.id), 470, 152, null, null, 40);
|
2022-10-16 21:58:52 +08:00
|
|
|
|
}
|
2022-10-23 03:51:08 +08:00
|
|
|
|
core.setTextAlign("uievent", "left");
|
|
|
|
|
core.fillText("uievent", "预计" + useText, 370, 280);
|
|
|
|
|
core.setTextAlign("uievent", "right");
|
|
|
|
|
totalMoney = selectCount * (type == 0 ? core.calValue(item.money) : core.calValue(item.sell));
|
|
|
|
|
core.fillText("uievent", core.formatBigNumber(totalMoney), 470, 310);
|
2022-10-16 21:58:52 +08:00
|
|
|
|
|
2022-10-23 03:51:08 +08:00
|
|
|
|
core.setTextAlign("uievent", "left");
|
|
|
|
|
core.fillText("uievent", type == 0 ? "已购次数" : "已卖次数", 370, 190);
|
|
|
|
|
core.setTextAlign("uievent", "right");
|
|
|
|
|
core.fillText("uievent", (type == 0 ? item.money_count : item.sell_count) || 0, 470, 220);
|
2022-10-16 21:58:52 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 03:51:08 +08:00
|
|
|
|
core.setTextAlign('uievent', 'left');
|
|
|
|
|
core.setTextBaseline('uievent', 'alphabetic');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _add = function (item, delta) {
|
|
|
|
|
if (item == null) return;
|
|
|
|
|
selectCount = core.clamp(
|
|
|
|
|
selectCount + delta, 0,
|
|
|
|
|
Math.min(type == 0 ? Math.floor(core.status.hero[use] / core.calValue(item.money)) : core.itemCount(item.id),
|
|
|
|
|
type == 0 && item.number != null ? item.number : Number.MAX_SAFE_INTEGER)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _confirm = function (item) {
|
|
|
|
|
if (item == null || selectCount == 0) return;
|
|
|
|
|
if (type == 0) {
|
|
|
|
|
core.status.hero[use] -= totalMoney;
|
|
|
|
|
core.getItem(item.id, selectCount);
|
|
|
|
|
core.stopSound();
|
|
|
|
|
core.playSound('确定');
|
|
|
|
|
if (item.number != null) item.number -= selectCount;
|
|
|
|
|
item.money_count = (item.money_count || 0) + selectCount;
|
|
|
|
|
} else {
|
|
|
|
|
core.status.hero[use] += totalMoney;
|
|
|
|
|
core.removeItem(item.id, selectCount);
|
|
|
|
|
core.playSound('确定');
|
|
|
|
|
core.drawTip("成功卖出" + selectCount + "个" + core.material.items[item.id].name, item.id);
|
|
|
|
|
if (item.number != null) item.number += selectCount;
|
|
|
|
|
item.sell_count = (item.sell_count || 0) + selectCount;
|
2022-10-16 21:58:52 +08:00
|
|
|
|
}
|
2022-10-23 03:51:08 +08:00
|
|
|
|
selectCount = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._performItemShopKeyBoard = function (keycode) {
|
|
|
|
|
var item = list[selectItem] || null;
|
|
|
|
|
// 键盘操作
|
|
|
|
|
switch (keycode) {
|
|
|
|
|
case 38: // up
|
|
|
|
|
if (selectItem == null) break;
|
|
|
|
|
if (selectItem == 0) selectItem = null;
|
|
|
|
|
else selectItem--;
|
|
|
|
|
selectCount = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 37: // left
|
|
|
|
|
if (selectItem == null) {
|
|
|
|
|
if (type > 0) type--;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
_add(item, -1);
|
|
|
|
|
break;
|
|
|
|
|
case 39: // right
|
|
|
|
|
if (selectItem == null) {
|
|
|
|
|
if (type < 2) type++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
_add(item, 1);
|
|
|
|
|
break;
|
|
|
|
|
case 40: // down
|
|
|
|
|
if (selectItem == null) {
|
|
|
|
|
if (list.length > 0) selectItem = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (list.length == 0) break;
|
|
|
|
|
selectItem = Math.min(selectItem + 1, list.length - 1);
|
|
|
|
|
selectCount = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 13:
|
|
|
|
|
case 32: // Enter/Space
|
|
|
|
|
if (selectItem == null) {
|
|
|
|
|
if (type == 2)
|
|
|
|
|
core.insertAction({ "type": "break" });
|
|
|
|
|
else if (list.length > 0)
|
|
|
|
|
selectItem = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
_confirm(item);
|
|
|
|
|
break;
|
|
|
|
|
case 27: // ESC
|
|
|
|
|
if (selectItem == null) {
|
|
|
|
|
core.insertAction({ "type": "break" });
|
|
|
|
|
break;
|
2022-10-16 21:58:52 +08:00
|
|
|
|
}
|
2022-10-23 03:51:08 +08:00
|
|
|
|
selectItem = null;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._performItemShopClick = function (px, py) {
|
|
|
|
|
var item = list[selectItem] || null;
|
|
|
|
|
// 鼠标操作
|
|
|
|
|
if (px >= 22 && px <= 82 && py >= 81 && py <= 112) {
|
|
|
|
|
// 买
|
|
|
|
|
if (type != 0) {
|
|
|
|
|
type = 0;
|
|
|
|
|
selectItem = null;
|
|
|
|
|
selectCount = 0;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (px >= 142 && px <= 202 && py >= 81 && py <= 112) {
|
|
|
|
|
// 卖
|
|
|
|
|
if (type != 1) {
|
|
|
|
|
type = 1;
|
|
|
|
|
selectItem = null;
|
|
|
|
|
selectCount = 0;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (px >= 262 && px <= 322 && py >= 81 && py <= 112) // 离开
|
|
|
|
|
return core.insertAction({ "type": "break" });
|
|
|
|
|
// <,>
|
|
|
|
|
if (px >= 370 && px <= 395 && py >= 392 && py <= 415)
|
|
|
|
|
return _add(item, -1);
|
|
|
|
|
if (px >= 445 && px <= 470 && py >= 302 && py <= 415)
|
|
|
|
|
return _add(item, 1);
|
|
|
|
|
// 确定
|
|
|
|
|
if (px >= 392 && px <= 443 && py >= 421 && py <= 446)
|
|
|
|
|
return _confirm(item);
|
|
|
|
|
|
|
|
|
|
// 上一页/下一页
|
|
|
|
|
if (px >= 70 && px <= 130 && py >= 450) {
|
|
|
|
|
if (page > 1) {
|
|
|
|
|
selectItem -= 7;
|
|
|
|
|
selectCount = 0;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (px >= 230 && px <= 290 && py >= 450) {
|
|
|
|
|
if (page < totalPage) {
|
|
|
|
|
selectItem = Math.min(selectItem + 7, list.length - 1);
|
|
|
|
|
selectCount = 0;
|
2022-10-16 21:58:52 +08:00
|
|
|
|
}
|
2022-10-23 03:51:08 +08:00
|
|
|
|
return;
|
2022-10-16 21:58:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-10-23 03:51:08 +08:00
|
|
|
|
// 实际区域
|
|
|
|
|
if (px >= 9 && px <= 351 && py >= 142 && py < 422) {
|
|
|
|
|
if (list.length == 0) return;
|
|
|
|
|
var index = parseInt((py - 142) / 40);
|
|
|
|
|
var newItem = 7 * (page - 1) + index;
|
|
|
|
|
if (newItem >= list.length) newItem = list.length - 1;
|
|
|
|
|
if (newItem != selectItem) {
|
|
|
|
|
selectItem = newItem;
|
|
|
|
|
selectCount = 0;
|
|
|
|
|
}
|
|
|
|
|
return;
|
2022-10-16 21:58:52 +08:00
|
|
|
|
}
|
2022-10-23 03:51:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this._performItemShopAction = function () {
|
|
|
|
|
if (flags.type == 0) return this._performItemShopKeyBoard(flags.keycode);
|
|
|
|
|
else return this._performItemShopClick(flags.px, flags.py);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.openItemShop = function (itemShopId) {
|
|
|
|
|
shopId = itemShopId;
|
|
|
|
|
type = 0;
|
|
|
|
|
page = 0;
|
|
|
|
|
selectItem = null;
|
|
|
|
|
selectCount = 0;
|
|
|
|
|
core.isShopVisited(itemShopId);
|
|
|
|
|
shopInfo = flags.__shops__[shopId];
|
|
|
|
|
if (shopInfo.choices == null) shopInfo.choices = core.clone(core.status.shops[shopId].choices);
|
|
|
|
|
choices = shopInfo.choices;
|
|
|
|
|
use = core.status.shops[shopId].use;
|
|
|
|
|
if (use != 'exp') use = 'money';
|
|
|
|
|
useText = use == 'money' ? '金币' : '经验';
|
|
|
|
|
|
|
|
|
|
core.insertAction([{
|
2022-10-16 21:58:52 +08:00
|
|
|
|
"type": "while",
|
|
|
|
|
"condition": "true",
|
|
|
|
|
"data": [
|
|
|
|
|
{ "type": "function", "function": "function () { core.plugin._drawItemShop(); }" },
|
|
|
|
|
{ "type": "wait" },
|
|
|
|
|
{ "type": "function", "function": "function() { core.plugin._performItemShopAction(); }" }
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"type": "function",
|
|
|
|
|
"function": "function () { core.deleteCanvas('uievent'); core.ui.clearUIEventSelector(); }"
|
|
|
|
|
}
|
2022-10-23 03:51:08 +08:00
|
|
|
|
]);
|
|
|
|
|
}
|
2022-10-16 21:58:52 +08:00
|
|
|
|
|
2022-10-23 03:51:08 +08:00
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"enemyLevel": function () {
|
2022-10-16 21:58:52 +08:00
|
|
|
|
// 此插件将提供怪物手册中的怪物境界显示
|
|
|
|
|
// 使用此插件需要先给每个怪物定义境界,方法如下:
|
|
|
|
|
// 点击怪物的【配置表格】,找到“【怪物】相关的表格配置”,然后在【名称】仿照增加境界定义:
|
|
|
|
|
/*
|
|
|
|
|
"level": {
|
|
|
|
|
"_leaf": true,
|
|
|
|
|
"_type": "textarea",
|
|
|
|
|
"_string": true,
|
|
|
|
|
"_data": "境界"
|
|
|
|
|
},
|
|
|
|
|
*/
|
|
|
|
|
// 然后保存刷新,可以看到怪物的属性定义中出现了【境界】。再开启本插件即可。
|
|
|
|
|
|
|
|
|
|
// 是否开启本插件,默认禁用;将此改成 true 将启用本插件。
|
|
|
|
|
var __enable = false;
|
|
|
|
|
if (!__enable) return;
|
|
|
|
|
|
|
|
|
|
// 这里定义每个境界的显示颜色;可以写'red', '#RRGGBB' 或者[r,g,b,a]四元数组
|
|
|
|
|
var levelToColors = {
|
|
|
|
|
"萌新一阶": "red",
|
|
|
|
|
"萌新二阶": "#FF0000",
|
|
|
|
|
"萌新三阶": [255, 0, 0, 1],
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 复写 _drawBook_drawName
|
|
|
|
|
var originDrawBook = core.ui._drawBook_drawName;
|
|
|
|
|
core.ui._drawBook_drawName = function (index, enemy, top, left, width) {
|
|
|
|
|
// 如果没有境界,则直接调用原始代码绘制
|
|
|
|
|
if (!enemy.level) return originDrawBook.call(core.ui, index, enemy, top, left, width);
|
|
|
|
|
// 存在境界,则额外进行绘制
|
|
|
|
|
core.setTextAlign('ui', 'center');
|
|
|
|
|
if (enemy.specialText.length == 0) {
|
|
|
|
|
core.fillText('ui', enemy.name, left + width / 2,
|
|
|
|
|
top + 27, '#DDDDDD', this._buildFont(17, true));
|
|
|
|
|
core.fillText('ui', enemy.level, left + width / 2,
|
|
|
|
|
top + 51, core.arrayToRGBA(levelToColors[enemy.level] || '#DDDDDD'), this._buildFont(14, true));
|
|
|
|
|
} else {
|
|
|
|
|
core.fillText('ui', enemy.name, left + width / 2,
|
|
|
|
|
top + 20, '#DDDDDD', this._buildFont(17, true), width);
|
|
|
|
|
switch (enemy.specialText.length) {
|
|
|
|
|
case 1:
|
|
|
|
|
core.fillText('ui', enemy.specialText[0], left + width / 2,
|
|
|
|
|
top + 38, core.arrayToRGBA((enemy.specialColor || [])[0] || '#FF6A6A'),
|
|
|
|
|
this._buildFont(14, true), width);
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
// Step 1: 计算字体
|
|
|
|
|
var text = enemy.specialText[0] + " " + enemy.specialText[1];
|
|
|
|
|
core.setFontForMaxWidth('ui', text, width, this._buildFont(14, true));
|
|
|
|
|
// Step 2: 计算总宽度
|
|
|
|
|
var totalWidth = core.calWidth('ui', text);
|
|
|
|
|
var leftWidth = core.calWidth('ui', enemy.specialText[0]);
|
|
|
|
|
var rightWidth = core.calWidth('ui', enemy.specialText[1]);
|
|
|
|
|
// Step 3: 绘制
|
|
|
|
|
core.fillText('ui', enemy.specialText[0], left + (width + leftWidth - totalWidth) / 2,
|
|
|
|
|
top + 38, core.arrayToRGBA((enemy.specialColor || [])[0] || '#FF6A6A'));
|
|
|
|
|
core.fillText('ui', enemy.specialText[1], left + (width + totalWidth - rightWidth) / 2,
|
|
|
|
|
top + 38, core.arrayToRGBA((enemy.specialColor || [])[1] || '#FF6A6A'));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
core.fillText('ui', '多属性...', left + width / 2,
|
|
|
|
|
top + 38, '#FF6A6A', this._buildFont(14, true), width);
|
|
|
|
|
}
|
|
|
|
|
core.fillText('ui', enemy.level, left + width / 2,
|
|
|
|
|
top + 56, core.arrayToRGBA(levelToColors[enemy.level] || '#DDDDDD'), this._buildFont(14, true));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 也可以复写其他的属性颜色如怪物攻防等,具体参见下面的例子的注释部分
|
|
|
|
|
core.ui._drawBook_drawRow1 = function (index, enemy, top, left, width, position) {
|
|
|
|
|
// 绘制第一行
|
|
|
|
|
core.setTextAlign('ui', 'left');
|
|
|
|
|
var b13 = this._buildFont(13, true),
|
|
|
|
|
f13 = this._buildFont(13, false);
|
|
|
|
|
var col1 = left,
|
|
|
|
|
col2 = left + width * 9 / 25,
|
|
|
|
|
col3 = left + width * 17 / 25;
|
|
|
|
|
core.fillText('ui', '生命', col1, position, '#DDDDDD', f13);
|
|
|
|
|
core.fillText('ui', core.formatBigNumber(enemy.hp || 0), col1 + 30, position, /*'red' */ null, b13);
|
|
|
|
|
core.fillText('ui', '攻击', col2, position, null, f13);
|
|
|
|
|
core.fillText('ui', core.formatBigNumber(enemy.atk || 0), col2 + 30, position, /* '#FF0000' */ null, b13);
|
|
|
|
|
core.fillText('ui', '防御', col3, position, null, f13);
|
|
|
|
|
core.fillText('ui', core.formatBigNumber(enemy.def || 0), col3 + 30, position, /* [255, 0, 0, 1] */ null, b13);
|
|
|
|
|
}
|
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"multiHeros": function () {
|
2022-10-16 21:58:52 +08:00
|
|
|
|
// 多角色插件
|
|
|
|
|
// Step 1: 启用本插件
|
|
|
|
|
// Step 2: 定义每个新的角色各项初始数据(参见下方注释)
|
|
|
|
|
// Step 3: 在游戏中的任何地方都可以调用 `core.changeHero()` 进行切换;也可以 `core.changeHero(1)` 来切换到某个具体的角色上
|
|
|
|
|
|
|
|
|
|
// 是否开启本插件,默认禁用;将此改成 true 将启用本插件。
|
|
|
|
|
var __enable = false;
|
|
|
|
|
if (!__enable) return;
|
|
|
|
|
|
|
|
|
|
// 在这里定义全部的新角色属性
|
|
|
|
|
// 请注意,在这里定义的内容不会多角色共用,在切换时会进行恢复。
|
|
|
|
|
// 你也可以自行新增或删除,比如不共用金币则可以加上"money"的初始化,不共用道具则可以加上"items"的初始化,
|
|
|
|
|
// 多角色共用hp的话则删除hp,等等。总之,不共用的属性都在这里进行定义就好。
|
|
|
|
|
var hero1 = {
|
|
|
|
|
"floorId": "MT0", // 该角色初始楼层ID;如果共用楼层可以注释此项
|
|
|
|
|
"image": "brave.png", // 角色的行走图名称;此项必填不然会报错
|
|
|
|
|
"name": "1号角色",
|
|
|
|
|
"lv": 1,
|
|
|
|
|
"hp": 10000, // 如果HP共用可注释此项
|
|
|
|
|
"atk": 1000,
|
|
|
|
|
"def": 1000,
|
|
|
|
|
"mdef": 0,
|
|
|
|
|
// "money": 0, // 如果要不共用金币则取消此项注释
|
|
|
|
|
// "exp": 0, // 如果要不共用经验则取消此项注释
|
|
|
|
|
"loc": { "x": 0, "y": 0, "direction": "up" }, // 该角色初始位置;如果共用位置可注释此项
|
|
|
|
|
"items": {
|
|
|
|
|
"tools": {}, // 如果共用消耗道具(含钥匙)则可注释此项
|
|
|
|
|
// "constants": {}, // 如果不共用永久道具(如手册)可取消注释此项
|
|
|
|
|
"equips": {}, // 如果共用在背包的装备可注释此项
|
|
|
|
|
},
|
|
|
|
|
"equipment": [], // 如果共用装备可注释此项;此项和上面的「共用在背包的装备」需要拥有相同状态,不然可能出现问题
|
|
|
|
|
};
|
|
|
|
|
// 也可以类似新增其他角色
|
|
|
|
|
// 新增的角色,各项属性共用与不共用的选择必须和上面完全相同,否则可能出现问题。
|
|
|
|
|
// var hero2 = { ...
|
|
|
|
|
|
|
|
|
|
var heroCount = 2; // 包含默认角色在内总共多少个角色,该值需手动修改。
|
|
|
|
|
|
|
|
|
|
this.initHeros = function () {
|
|
|
|
|
core.setFlag("hero1", core.clone(hero1)); // 将属性值存到变量中
|
|
|
|
|
// core.setFlag("hero2", core.clone(hero2)); // 更多的角色也存入变量中;每个定义的角色都需要新增一行
|
|
|
|
|
|
|
|
|
|
// 检测是否存在装备
|
|
|
|
|
if (hero1.equipment) {
|
|
|
|
|
if (!hero1.items || !hero1.items.equips) {
|
|
|
|
|
alert('多角色插件的equipment和道具中的equips必须拥有相同状态!');
|
|
|
|
|
}
|
|
|
|
|
// 存99号套装为全空
|
|
|
|
|
var saveEquips = core.getFlag("saveEquips", []);
|
|
|
|
|
saveEquips[99] = [];
|
|
|
|
|
core.setFlag("saveEquips", saveEquips);
|
|
|
|
|
} else {
|
|
|
|
|
if (hero1.items && hero1.items.equips) {
|
|
|
|
|
alert('多角色插件的equipment和道具中的equips必须拥有相同状态!');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 在游戏开始注入initHeros
|
|
|
|
|
var _startGame_setHard = core.events._startGame_setHard;
|
|
|
|
|
core.events._startGame_setHard = function () {
|
|
|
|
|
_startGame_setHard.call(core.events);
|
|
|
|
|
core.initHeros();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 切换角色
|
|
|
|
|
// 可以使用 core.changeHero() 来切换到下一个角色
|
|
|
|
|
// 也可以 core.changeHero(1) 来切换到某个角色(默认角色为0)
|
|
|
|
|
this.changeHero = function (toHeroId) {
|
|
|
|
|
var currHeroId = core.getFlag("heroId", 0); // 获得当前角色ID
|
|
|
|
|
if (toHeroId == null) {
|
|
|
|
|
toHeroId = (currHeroId + 1) % heroCount;
|
|
|
|
|
}
|
|
|
|
|
if (currHeroId == toHeroId) return;
|
|
|
|
|
|
|
|
|
|
var saveList = Object.keys(hero1);
|
|
|
|
|
|
|
|
|
|
// 保存当前内容
|
|
|
|
|
var toSave = {};
|
|
|
|
|
// 暂时干掉 drawTip 和 音效,避免切装时的提示
|
|
|
|
|
var _drawTip = core.ui.drawTip;
|
|
|
|
|
core.ui.drawTip = function () { };
|
|
|
|
|
var _playSound = core.control.playSound;
|
|
|
|
|
core.control.playSound = function () { }
|
|
|
|
|
// 记录当前录像,因为可能存在换装问题
|
|
|
|
|
core.clearRouteFolding();
|
|
|
|
|
var routeLength = core.status.route.length;
|
|
|
|
|
// 优先判定装备
|
|
|
|
|
if (hero1.equipment) {
|
|
|
|
|
core.items.quickSaveEquip(100 + currHeroId);
|
|
|
|
|
core.items.quickLoadEquip(99);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
saveList.forEach(function (name) {
|
|
|
|
|
if (name == 'floorId') toSave[name] = core.status.floorId; // 楼层单独设置
|
|
|
|
|
else if (name == 'items') {
|
|
|
|
|
toSave.items = core.clone(core.status.hero.items);
|
|
|
|
|
Object.keys(toSave.items).forEach(function (one) {
|
|
|
|
|
if (!hero1.items[one]) delete toSave.items[one];
|
|
|
|
|
});
|
|
|
|
|
} else toSave[name] = core.clone(core.status.hero[name]); // 使用core.clone()来创建新对象
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
core.setFlag("hero" + currHeroId, toSave); // 将当前角色信息进行保存
|
|
|
|
|
var data = core.getFlag("hero" + toHeroId); // 获得要切换的角色保存内容
|
|
|
|
|
|
|
|
|
|
// 设置角色的属性值
|
|
|
|
|
saveList.forEach(function (name) {
|
|
|
|
|
if (name == "floorId");
|
|
|
|
|
else if (name == "items") {
|
|
|
|
|
Object.keys(core.status.hero.items).forEach(function (one) {
|
|
|
|
|
if (data.items[one]) core.status.hero.items[one] = core.clone(data.items[one]);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
core.status.hero[name] = core.clone(data[name]);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// 最后装上装备
|
|
|
|
|
if (hero1.equipment) {
|
|
|
|
|
core.items.quickLoadEquip(100 + toHeroId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
core.ui.drawTip = _drawTip;
|
|
|
|
|
core.control.playSound = _playSound;
|
|
|
|
|
core.status.route = core.status.route.slice(0, routeLength);
|
|
|
|
|
core.control._bindRoutePush();
|
|
|
|
|
|
|
|
|
|
// 插入事件:改变角色行走图并进行楼层切换
|
|
|
|
|
var toFloorId = data.floorId || core.status.floorId;
|
|
|
|
|
var toLoc = data.loc || core.status.hero.loc;
|
|
|
|
|
core.insertAction([
|
|
|
|
|
{ "type": "setHeroIcon", "name": data.image || "hero.png" }, // 改变行走图
|
|
|
|
|
// 同层则用changePos,不同层则用changeFloor;这是为了避免共用楼层造成触发eachArrive
|
|
|
|
|
toFloorId != core.status.floorId ? {
|
|
|
|
|
"type": "changeFloor",
|
|
|
|
|
"floorId": toFloorId,
|
|
|
|
|
"loc": [toLoc.x, toLoc.y],
|
|
|
|
|
"direction": toLoc.direction,
|
|
|
|
|
"time": 0 // 可以在这里设置切换时间
|
|
|
|
|
} : { "type": "changePos", "loc": [toLoc.x, toLoc.y], "direction": toLoc.direction }
|
|
|
|
|
// 你还可以在这里执行其他事件,比如增加或取消跟随效果
|
|
|
|
|
]);
|
|
|
|
|
core.setFlag("heroId", toHeroId); // 保存切换到的角色ID
|
|
|
|
|
}
|
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"heroFourFrames": function () {
|
2022-10-16 21:58:52 +08:00
|
|
|
|
// 样板的勇士/跟随者移动时只使用2、4两帧,观感较差。本插件可以将四帧全用上。
|
|
|
|
|
|
|
|
|
|
// 是否启用本插件
|
|
|
|
|
var __enable = true;
|
|
|
|
|
if (!__enable) return;
|
|
|
|
|
|
|
|
|
|
["up", "down", "left", "right"].forEach(function (one) {
|
|
|
|
|
// 指定中间帧动画
|
|
|
|
|
core.material.icons.hero[one].midFoot = 2;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var heroMoving = function (timestamp) {
|
|
|
|
|
if (core.status.heroMoving <= 0) return;
|
|
|
|
|
if (timestamp - core.animateFrame.moveTime > core.values.moveSpeed) {
|
|
|
|
|
core.animateFrame.leftLeg++;
|
|
|
|
|
core.animateFrame.moveTime = timestamp;
|
|
|
|
|
}
|
|
|
|
|
core.drawHero(['stop', 'leftFoot', 'midFoot', 'rightFoot'][core.animateFrame.leftLeg % 4], 4 * core.status.heroMoving);
|
|
|
|
|
}
|
|
|
|
|
core.registerAnimationFrame('heroMoving', true, heroMoving);
|
|
|
|
|
|
|
|
|
|
core.events._eventMoveHero_moving = function (step, moveSteps) {
|
|
|
|
|
var curr = moveSteps[0];
|
|
|
|
|
var direction = curr[0], x = core.getHeroLoc('x'), y = core.getHeroLoc('y');
|
|
|
|
|
// ------ 前进/后退
|
|
|
|
|
var o = direction == 'backward' ? -1 : 1;
|
|
|
|
|
if (direction == 'forward' || direction == 'backward') direction = core.getHeroLoc('direction');
|
|
|
|
|
var faceDirection = direction;
|
|
|
|
|
if (direction == 'leftup' || direction == 'leftdown') faceDirection = 'left';
|
|
|
|
|
if (direction == 'rightup' || direction == 'rightdown') faceDirection = 'right';
|
|
|
|
|
core.setHeroLoc('direction', direction);
|
|
|
|
|
if (curr[1] <= 0) {
|
|
|
|
|
core.setHeroLoc('direction', faceDirection);
|
|
|
|
|
moveSteps.shift();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (step <= 4) core.drawHero('stop', 4 * o * step);
|
|
|
|
|
else if (step <= 8) core.drawHero('leftFoot', 4 * o * step);
|
|
|
|
|
else if (step <= 12) core.drawHero('midFoot', 4 * o * (step - 8));
|
|
|
|
|
else if (step <= 16) core.drawHero('rightFoot', 4 * o * (step - 8)); // if (step == 8) {
|
|
|
|
|
if (step == 8 || step == 16) {
|
|
|
|
|
core.setHeroLoc('x', x + o * core.utils.scan2[direction].x, true);
|
|
|
|
|
core.setHeroLoc('y', y + o * core.utils.scan2[direction].y, true);
|
|
|
|
|
core.updateFollowers();
|
|
|
|
|
curr[1]--;
|
|
|
|
|
if (curr[1] <= 0) moveSteps.shift();
|
|
|
|
|
core.setHeroLoc('direction', faceDirection);
|
|
|
|
|
return step == 16;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"routeFixing": function () {
|
2022-10-16 21:58:52 +08:00
|
|
|
|
// 是否开启本插件,true 表示启用,false 表示禁用。
|
|
|
|
|
var __enable = true;
|
|
|
|
|
if (!__enable) return;
|
|
|
|
|
/*
|
|
|
|
|
使用说明:启用本插件后,录像回放时您可以用数字键1或6分别切换到原速或24倍速,
|
|
|
|
|
暂停播放时按数字键7(电脑按N)可以单步播放。(手机端可以点击难度单词切换出数字键)
|
|
|
|
|
数字键2-5可以进行录像自助精修,具体描述见下(实际弹窗请求您输入时不要带有任何空格):
|
|
|
|
|
|
|
|
|
|
up down left right 勇士向某个方向「行走一步或撞击」
|
|
|
|
|
item:ID 使用某件道具,如 item:bomb 表示使用炸弹
|
|
|
|
|
unEquip:n 卸掉身上第(n+1)件装备(n从0开始),如 unEquip:1 默认表示卸掉盾牌
|
|
|
|
|
equip:ID 穿上某件装备,如 equip:sword1 表示装上铁剑
|
|
|
|
|
saveEquip:n 将身上的当前套装保存到第n套快捷套装(n从0开始)
|
|
|
|
|
loadEquip:n 快捷换上之前保存好的第n套套装
|
|
|
|
|
fly:ID 使用楼传飞到某一层,如 fly:MT10 表示飞到主塔10层
|
|
|
|
|
choices:none 确认框/选择项「超时」(作者未设置超时时间则此项视为缺失)
|
|
|
|
|
choices:n 确认框/选择项选择第(n+1)项(选择项n从0开始,确认框n为0表示「确定」,1表示「取消」)
|
|
|
|
|
选择项n为负数时表示选择倒数第 -n 项,如 -1 表示最后一项(V2.8.2起标准全局商店的「离开」项)
|
|
|
|
|
此项缺失的话,确认框将选择作者指定的默认项(初始光标位置),选择项将弹窗请求补选(后台录像验证中选最后一项,可以复写函数来修改)
|
|
|
|
|
shop:ID 打开某个全局商店,如 shop:itemShop 表示打开道具商店。因此连载塔千万不要中途修改商店ID!
|
|
|
|
|
turn 单击勇士(Z键)转身,core.turnHero() 会产生此项,因此通过事件等方式强制让勇士转向应该用 core.setHeroLoc()
|
|
|
|
|
turn:dir 勇士转向某个方向,dir 可以为 up down left right(此项一般是读取自动存档产生的,属于样板的不良特性,请勿滥用)
|
|
|
|
|
getNext 轻按获得身边道具,优先获得面前的(面前没有则按上下左右顺序依次获得),身边如果没有道具则此项会被跳过
|
|
|
|
|
input:none “等待用户操作事件”中超时(作者未设置超时时间则此项会导致报错)
|
|
|
|
|
input:xxx 可能表示“等待用户操作事件”的一个操作(如按键操作将直接记录 input:keycode ),
|
|
|
|
|
也可能表示一个“接受用户输入数字”的输入,后者的情况下 xxx 为输入的整数。此项缺失的话前者将直接报错,后者将用0代替(后者现在支持负数了)
|
|
|
|
|
input2:xxx 可能表示“读取全局存储(core.getGlobal)”读取到的值,也可能表示一个“接受用户输入文本”的输入,
|
|
|
|
|
两种情况下 xxx 都为 base64 编码。此项缺失的话前者将重新现场读取,后者将用空字符串代替
|
|
|
|
|
no 走到可穿透的楼梯上不触发楼层切换事件,通过本插件可以让勇士停在旁边没有障碍物的楼梯上哦~
|
|
|
|
|
move:x:y 尝试瞬移到 [x,y] 点(不改变朝向),该点甚至可以和勇士相邻或者位于视野外
|
|
|
|
|
key:n 松开键值为n的键,如 key:49 表示松开大键盘数字键1,默认会触发使用破墙镐
|
|
|
|
|
click:n:px:py 点击自绘状态栏,n为0表示横屏1表示竖屏,[px,py] 为点击的像素坐标
|
|
|
|
|
random:n 生成了随机数n,即 core.rand2(num) 的返回结果,n必须在 [0,num-1] 范围,num必须为正整数。此项缺失将导致现场重新随机生成数值,可能导致回放结果不一致!
|
|
|
|
|
作者自定义的新项(一般为js对象,可以先JSON.stringify()再core.encodeBase64()得到纯英文数字的内容)需要用(半角圆括弧)括起来。
|
|
|
|
|
|
|
|
|
|
当您使用数字键5将一些项追加到即将播放内容的开头时,请注意要逆序逐项追加,或者每追加一项就按下数字键7或字母键N单步播放一步。
|
|
|
|
|
但是【input input2 random choices】是被动读取的,单步播放如果触发了相应的事件就会连续读取,这时候只能提前逐项追加好。
|
|
|
|
|
电脑端熟练以后推荐直接在控制台操作 core.status.route 和 core.status.replay.toReplay(后者录像回放时才有),配合 core.push() 和 core.unshift() 更加灵活自由哦!
|
|
|
|
|
*/
|
|
|
|
|
core.actions.registerAction('onkeyUp', '_sys_onkeyUp_replay', function (e) {
|
|
|
|
|
if (this._checkReplaying()) {
|
|
|
|
|
if (e.keyCode == 27) // ESCAPE
|
|
|
|
|
core.stopReplay();
|
|
|
|
|
else if (e.keyCode == 90) // Z
|
|
|
|
|
core.speedDownReplay();
|
|
|
|
|
else if (e.keyCode == 67) // C
|
|
|
|
|
core.speedUpReplay();
|
|
|
|
|
else if (e.keyCode == 32) // SPACE
|
|
|
|
|
core.triggerReplay();
|
|
|
|
|
else if (e.keyCode == 65) // A
|
|
|
|
|
core.rewindReplay();
|
|
|
|
|
else if (e.keyCode == 83) // S
|
|
|
|
|
core.control._replay_SL();
|
|
|
|
|
else if (e.keyCode == 88) // X
|
|
|
|
|
core.control._replay_book();
|
|
|
|
|
else if (e.keyCode == 33 || e.keyCode == 34) // PgUp/PgDn
|
|
|
|
|
core.control._replay_viewMap();
|
|
|
|
|
else if (e.keyCode == 78) // N
|
|
|
|
|
core.stepReplay();
|
|
|
|
|
else if (e.keyCode == 84) // T
|
|
|
|
|
core.control._replay_toolbox();
|
|
|
|
|
else if (e.keyCode == 81) // Q
|
|
|
|
|
core.control._replay_equipbox();
|
|
|
|
|
else if (e.keyCode == 66) // B
|
|
|
|
|
core.ui._drawStatistics();
|
|
|
|
|
else if (e.keyCode == 49 || e.keyCode == 54) // 1/6,原速/24倍速播放
|
|
|
|
|
core.setReplaySpeed(e.keyCode == 49 ? 1 : 24);
|
|
|
|
|
else if (e.keyCode > 49 && e.keyCode < 54) { // 2-5,录像精修
|
|
|
|
|
switch (e.keyCode - 48) {
|
|
|
|
|
case 2: // pop
|
|
|
|
|
alert("您已移除已录制内容的最后一项:" + core.status.route.pop());
|
|
|
|
|
break;
|
|
|
|
|
case 3: // push
|
|
|
|
|
core.utils.myprompt("请输入您要追加到已录制内容末尾的项:", "", function (value) {
|
|
|
|
|
if (value != null) core.status.route.push(value);
|
|
|
|
|
});
|
|
|
|
|
break;
|
|
|
|
|
case 4: // shift
|
|
|
|
|
alert("您已移除即将播放内容的第一项:" + core.status.replay.toReplay.shift());
|
|
|
|
|
break;
|
|
|
|
|
case 5: // unshift
|
|
|
|
|
core.utils.myprompt("请输入您要追加到即将播放内容开头的项:", "", function (value) {
|
|
|
|
|
if (value != null) core.status.replay.toReplay.unshift(value);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}, 100);
|
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"numpad": function () {
|
2022-10-16 21:58:52 +08:00
|
|
|
|
// 样板自带的整数输入事件为白屏弹窗且可以误输入任意非法内容但不支持负整数,观感较差。本插件可以将其美化成仿RM样式,使其支持负整数同时带有音效
|
|
|
|
|
// 另一方面,4399等第三方平台不允许使用包括 core.myprompt() 和 core.myconfirm() 在内的弹窗,因此也需要此插件来替代,不然类似生命魔杖的道具就不好实现了
|
|
|
|
|
// 关于负整数输入,V2.8.2原生支持其录像的压缩和解压,只是默认的 core.events._action_input() 函数将负数取了绝对值,可以只复写下面的 core.isReplaying() 部分来取消
|
|
|
|
|
|
|
|
|
|
// 是否启用本插件,false表示禁用,true表示启用
|
|
|
|
|
var __enable = true;
|
|
|
|
|
if (!__enable) return;
|
|
|
|
|
|
|
|
|
|
core.events._action_input = function (data, x, y, prefix) { // 复写整数输入事件
|
|
|
|
|
if (core.isReplaying()) { // 录像回放时,处理方式不变,但增加负整数支持
|
|
|
|
|
core.events.__action_getInput(core.replaceText(data.text, prefix), false, function (value) {
|
|
|
|
|
value = parseInt(value) || 0; // 去掉了取绝对值的步骤
|
|
|
|
|
core.status.route.push("input:" + value);
|
|
|
|
|
core.setFlag("input", value);
|
|
|
|
|
core.doAction();
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// 正常游戏中,采用暂停录制的方式然后用事件流循环“绘制-等待-变量操作”三板斧实现(按照13*13适配的)。
|
|
|
|
|
// 您可以自行修改循环内的内容来适配15*15或其他需求,或干脆作为公共事件编辑。
|
|
|
|
|
core.insertAction([
|
|
|
|
|
// 记录当前录像长度,下面的循环结束后裁剪。达到“暂停录制”的效果
|
|
|
|
|
{ "type": "function", "function": "function(){flags['@temp@length']=core.status.route.length}" },
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "0" },
|
|
|
|
|
{
|
|
|
|
|
"type": "while",
|
|
|
|
|
"condition": "true",
|
|
|
|
|
"data": [
|
|
|
|
|
{ "type": "drawBackground", "background": "winskin.png", "x": 16, "y": 16, "width": 384, "height": 384 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10181", "x": 32, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10185", "x": 64, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10186", "x": 96, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10187", "x": 128, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10188", "x": 160, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10189", "x": 192, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10193", "x": 224, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10194", "x": 256, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10195", "x": 288, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10196", "x": 320, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10197", "x": 352, "y": 288 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10286", "x": 32, "y": 352 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10169", "x": 96, "y": 352 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10232", "x": 128, "y": 352 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10185", "x": 320, "y": 352 },
|
|
|
|
|
{ "type": "drawIcon", "id": "X10242", "x": 352, "y": 352 },
|
|
|
|
|
{ "type": "fillBoldText", "x": 48, "y": 256, "style": [255, 255, 255, 1], "font": "bold 32px Consolas", "text": "${flag:input}" },
|
|
|
|
|
{ "type": "fillBoldText", "x": 32, "y": 48, "style": [255, 255, 255, 1], "font": "16px Consolas", "text": core.replaceText(data.text, prefix) },
|
|
|
|
|
{
|
|
|
|
|
"type": "wait",
|
|
|
|
|
"forceChild": true,
|
|
|
|
|
"data": [{
|
|
|
|
|
"case": "keyboard",
|
|
|
|
|
"keycode": "48,49,50,51,52,53,54,55,56,57",
|
|
|
|
|
"action": [
|
|
|
|
|
// 按下数字键,追加到已输入内容的末尾,但禁止越界。变量:keycode-48就是末位数字
|
|
|
|
|
{ "type": "playSound", "name": "光标移动" },
|
|
|
|
|
{
|
|
|
|
|
"type": "if",
|
|
|
|
|
"condition": "(flag:input<0)",
|
|
|
|
|
"true": [
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "10*flag:input-(flag:keycode-48)" },
|
|
|
|
|
],
|
|
|
|
|
"false": [
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "10*flag:input+(flag:keycode-48)" },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "core.clamp(flag:input,-9e15,9e15)" },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"case": "keyboard",
|
|
|
|
|
"keycode": "189",
|
|
|
|
|
"action": [
|
|
|
|
|
// 按下减号键,变更已输入内容的符号
|
|
|
|
|
{ "type": "playSound", "name": "跳跃" },
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "-flag:input" },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"case": "keyboard",
|
|
|
|
|
"keycode": "8",
|
|
|
|
|
"action": [
|
|
|
|
|
// 按下退格键,从已输入内容的末尾删除一位
|
|
|
|
|
{ "type": "playSound", "name": "取消" },
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "operator": "//=", "value": "10" },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"case": "keyboard",
|
|
|
|
|
"keycode": "27",
|
|
|
|
|
"action": [
|
|
|
|
|
// 按下ESC键,清空已输入内容
|
|
|
|
|
{ "type": "playSound", "name": "读档" },
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "0" },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"case": "keyboard",
|
|
|
|
|
"keycode": "13",
|
|
|
|
|
"action": [
|
|
|
|
|
// 按下回车键,确定
|
|
|
|
|
{ "type": "break", "n": 1 },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"case": "mouse",
|
|
|
|
|
"px": [32, 63],
|
|
|
|
|
"py": [288, 320],
|
|
|
|
|
"action": [
|
|
|
|
|
// 点击减号,变号。右边界写63防止和下面重叠
|
|
|
|
|
{ "type": "playSound", "name": "跳跃" },
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "-flag:input" },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"case": "mouse",
|
|
|
|
|
"px": [64, 384],
|
|
|
|
|
"py": [288, 320],
|
|
|
|
|
"action": [
|
|
|
|
|
// 点击数字,追加到已输入内容的末尾,但禁止越界。变量:x-2就是末位数字
|
|
|
|
|
{ "type": "playSound", "name": "光标移动" },
|
|
|
|
|
{
|
|
|
|
|
"type": "if",
|
|
|
|
|
"condition": "(flag:input<0)",
|
|
|
|
|
"true": [
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "10*flag:input-(flag:x-2)" },
|
|
|
|
|
],
|
|
|
|
|
"false": [
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "10*flag:input+(flag:x-2)" },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "core.clamp(flag:input,-9e15,9e15)" },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"case": "mouse",
|
|
|
|
|
"px": [32, 64],
|
|
|
|
|
"py": [352, 384],
|
|
|
|
|
"action": [
|
|
|
|
|
// 点击左箭头,退格
|
|
|
|
|
{ "type": "playSound", "name": "取消" },
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "operator": "//=", "value": "10" },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"case": "mouse",
|
|
|
|
|
"px": [96, 160],
|
|
|
|
|
"py": [352, 384],
|
|
|
|
|
"action": [
|
|
|
|
|
// 点击CE,清空
|
|
|
|
|
{ "type": "playSound", "name": "读档" },
|
|
|
|
|
{ "type": "setValue", "name": "flag:input", "value": "0" },
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"case": "mouse",
|
|
|
|
|
"px": [320, 384],
|
|
|
|
|
"py": [352, 384],
|
|
|
|
|
"action": [
|
|
|
|
|
// 点击OK,确定
|
|
|
|
|
{ "type": "break", "n": 1 },
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{ "type": "clearMap" },
|
|
|
|
|
// 裁剪录像,只保留'input:n',然后继续录制
|
|
|
|
|
{ "type": "function", "function": "function(){core.status.route.splice(flags['@temp@length']);core.status.route.push('input:'+core.getFlag('input',0))}" }
|
|
|
|
|
], x, y);
|
|
|
|
|
core.events.doAction();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
2022-10-22 19:23:02 +08:00
|
|
|
|
"sprites": function () {
|
2022-10-16 21:58:52 +08:00
|
|
|
|
// 基于canvas的sprite化,摘编整理自万宁魔塔
|
|
|
|
|
//
|
|
|
|
|
// ---------------------------------------- 第一部分 js代码 (必装) --------------------------------------- //
|
|
|
|
|
|
|
|
|
|
/* ---------------- 用法说明 ---------------- *
|
|
|
|
|
* 1. 创建sprite: var sprite = new Sprite(x, y, w, h, z, reference, name);
|
|
|
|
|
* 其中x y w h为画布的横纵坐标及长宽,reference为参考系,只能填game(相对于游戏画面)和window(相对于窗口)
|
|
|
|
|
* 且当为相对游戏画面时,长宽与坐标将会乘以放缩比例(相当于用createCanvas创建)
|
|
|
|
|
* z为纵深,表示不同元素之间的覆盖关系,大的覆盖小的
|
|
|
|
|
* name为自定义名称,可以不填
|
|
|
|
|
* 2. 删除: sprite.destroy();
|
|
|
|
|
* 3. 设置css特效: sprite.setCss(css);
|
|
|
|
|
* 其中css直接填 box-shadow: 0px 0px 10px black;的形式即可,与style标签与css文件内写法相同
|
|
|
|
|
* 对于已设置的特效,如果之后不需要再次设置,可以不填
|
|
|
|
|
* 4. 添加事件监听器: sprite.addEventListener(); 用法与html元素的addEventListener完全一致
|
|
|
|
|
* 5. 移除事件监听器: sprite.removeEventListener(); 用法与html元素的removeEventListener完全一致
|
|
|
|
|
* 6. 属性列表
|
|
|
|
|
* (1) sprite.x | sprite.y | sprite.width | sprite.height | sprite.zIndex | sprite.reference 顾名思义
|
|
|
|
|
* (2) sprite.canvas 该sprite的画布
|
|
|
|
|
* (3) sprite.context 该画布的CanvasRenderingContext2d对象,即样板中常见的ctx
|
|
|
|
|
* (4) sprite.count 不要改这个玩意
|
|
|
|
|
* 7. 使用样板api进行绘制
|
|
|
|
|
* 示例:
|
|
|
|
|
* var ctx = sprite.context;
|
|
|
|
|
* core.fillText(ctx, 'xxx', 100, 100);
|
|
|
|
|
* core.fillRect(ctx, 0, 0, 50, 50);
|
|
|
|
|
* 当然也可以使用原生js
|
|
|
|
|
* ctx.moveTo(0, 0);
|
|
|
|
|
* ctx.bezierCurveTo(50, 50, 100, 0, 100, 50);
|
|
|
|
|
* ctx.stroke();
|
|
|
|
|
* ---------------- 用法说明 ---------------- */
|
|
|
|
|
|
|
|
|
|
var count = 0;
|
|
|
|
|
|
|
|
|
|
/** 创建一个sprite画布
|
|
|
|
|
* @param {number} x
|
|
|
|
|
* @param {number} y
|
|
|
|
|
* @param {number} w
|
|
|
|
|
* @param {number} h
|
|
|
|
|
* @param {number} z
|
|
|
|
|
* @param {'game' | 'window'} reference 参考系,游戏画面或者窗口
|
|
|
|
|
* @param {string} name 可选,sprite的名称,方便通过core.dymCanvas获取
|
|
|
|
|
*/
|
|
|
|
|
function Sprite (x, y, w, h, z, reference, name) {
|
|
|
|
|
this.x = x;
|
|
|
|
|
this.y = y;
|
|
|
|
|
this.width = w;
|
|
|
|
|
this.height = h;
|
|
|
|
|
this.zIndex = z;
|
|
|
|
|
this.reference = reference;
|
|
|
|
|
this.canvas = null;
|
|
|
|
|
this.context = null;
|
|
|
|
|
this.count = 0;
|
|
|
|
|
this.name = name || '_sprite_' + count;
|
|
|
|
|
this.style = null;
|
|
|
|
|
/** 初始化 */
|
|
|
|
|
this.init = function () {
|
|
|
|
|
if (reference === 'window') {
|
|
|
|
|
var canvas = document.createElement('canvas');
|
|
|
|
|
this.canvas = canvas;
|
|
|
|
|
this.context = canvas.getContext('2d');
|
|
|
|
|
canvas.width = w;
|
|
|
|
|
canvas.height = h;
|
|
|
|
|
canvas.style.width = w + 'px';
|
|
|
|
|
canvas.style.height = h + 'px';
|
|
|
|
|
canvas.style.position = 'absolute';
|
|
|
|
|
canvas.style.top = y + 'px';
|
|
|
|
|
canvas.style.left = x + 'px';
|
|
|
|
|
canvas.style.zIndex = z.toString();
|
|
|
|
|
document.body.appendChild(canvas);
|
|
|
|
|
this.style = canvas.style;
|
|
|
|
|
} else {
|
|
|
|
|
this.context = core.createCanvas(this.name || '_sprite_' + count, x, y, w, h, z);
|
|
|
|
|
this.canvas = this.context.canvas;
|
|
|
|
|
this.canvas.style.pointerEvents = 'auto';
|
|
|
|
|
this.style = this.canvas.style;
|
|
|
|
|
}
|
|
|
|
|
this.count = count;
|
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
this.init();
|
|
|
|
|
|
|
|
|
|
/** 设置css特效
|
|
|
|
|
* @param {string} css
|
|
|
|
|
*/
|
|
|
|
|
this.setCss = function (css) {
|
|
|
|
|
css = css.replace('\n', ';').replace(';;', ';');
|
|
|
|
|
var effects = css.split(';');
|
|
|
|
|
var self = this;
|
|
|
|
|
effects.forEach(function (v) {
|
|
|
|
|
var content = v.split(':');
|
|
|
|
|
var name = content[0];
|
|
|
|
|
var value = content[1];
|
|
|
|
|
name = name.trim().split('-').reduce(function (pre, curr, i, a) {
|
|
|
|
|
if (i === 0 && curr !== '') return curr;
|
|
|
|
|
if (a[0] === '' && i === 1) return curr;
|
|
|
|
|
return pre + curr.toUpperCase()[0] + curr.slice(1);
|
|
|
|
|
}, '');
|
|
|
|
|
var canvas = self.canvas;
|
|
|
|
|
if (name in canvas.style) canvas.style[name] = value;
|
|
|
|
|
});
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 移动sprite
|
|
|
|
|
* @param {boolean} isDelta 是否是相对位置,如果是,那么sprite会相对于原先的位置进行移动
|
|
|
|
|
*/
|
|
|
|
|
this.move = function (x, y, isDelta) {
|
|
|
|
|
if (x !== undefined && x !== null) this.x = x;
|
|
|
|
|
if (y !== undefined && y !== null) this.y = y;
|
|
|
|
|
if (this.reference === 'window') {
|
|
|
|
|
var ele = this.canvas;
|
|
|
|
|
ele.style.left = x + (isDelta ? parseFloat(ele.style.left) : 0) + 'px';
|
|
|
|
|
ele.style.top = y + (isDelta ? parseFloat(ele.style.top) : 0) + 'px';
|
|
|
|
|
} else core.relocateCanvas(this.context, x, y, isDelta);
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 重新设置sprite的大小
|
|
|
|
|
* @param {boolean} styleOnly 是否只修改css效果,如果是,那么将会不高清,如果不是,那么会清空画布
|
|
|
|
|
*/
|
|
|
|
|
this.resize = function (w, h, styleOnly) {
|
|
|
|
|
if (w !== undefined && w !== null) this.w = w;
|
|
|
|
|
if (h !== undefined && h !== null) this.h = h;
|
|
|
|
|
if (reference === 'window') {
|
|
|
|
|
var ele = this.canvas;
|
|
|
|
|
ele.style.width = w + 'px';
|
|
|
|
|
ele.style.height = h + 'px';
|
|
|
|
|
if (!styleOnly) {
|
|
|
|
|
ele.width = w;
|
|
|
|
|
ele.height = h;
|
|
|
|
|
}
|
|
|
|
|
} else core.resizeCanvas(this.context, w, h, styleOnly);
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 旋转画布
|
|
|
|
|
*/
|
|
|
|
|
this.rotate = function (angle, cx, cy) {
|
|
|
|
|
if (this.reference === 'window') {
|
|
|
|
|
var left = this.x;
|
|
|
|
|
var top = this.y;
|
|
|
|
|
this.canvas.style.transformOrigin = (cx - left) + 'px ' + (cy - top) + 'px';
|
|
|
|
|
if (angle === 0) {
|
|
|
|
|
canvas.style.transform = '';
|
|
|
|
|
} else {
|
|
|
|
|
canvas.style.transform = 'rotate(' + angle + 'deg)';
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
core.rotateCanvas(this.context, angle, cx, cy);
|
|
|
|
|
}
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 清除sprite
|
|
|
|
|
*/
|
|
|
|
|
this.clear = function (x, y, w, h) {
|
|
|
|
|
if (this.reference === 'window') {
|
|
|
|
|
this.context.clearRect(x, y, w, h);
|
|
|
|
|
} else {
|
|
|
|
|
core.clearMap(this.context, x, y, w, h);
|
|
|
|
|
}
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 删除 */
|
|
|
|
|
this.destroy = function () {
|
|
|
|
|
if (this.reference === 'window') {
|
|
|
|
|
if (this.canvas) document.body.removeChild(this.canvas);
|
|
|
|
|
} else {
|
|
|
|
|
core.deleteCanvas(this.name || '_sprite_' + this.count);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 添加事件监听器 */
|
|
|
|
|
this.addEventListener = function () {
|
|
|
|
|
this.canvas.addEventListener.apply(this.canvas, arguments);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** 移除事件监听器 */
|
|
|
|
|
this.removeEventListener = function () {
|
|
|
|
|
this.canvas.removeEventListener.apply(this.canvas, arguments);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window.Sprite = Sprite;
|
2022-10-22 19:23:02 +08:00
|
|
|
|
},
|
|
|
|
|
"跳字": function () {
|
|
|
|
|
// 在此增加新插件
|
|
|
|
|
this.tiaozi1 = function (neirong, yanse) { //跳字一
|
|
|
|
|
if (core.status.replay.replaying) {} else {
|
|
|
|
|
core.createCanvas('tiaozi', 0, 0, 416, 416, 77);
|
|
|
|
|
core.setFlag("tiaozizhong", core.getFlag("tiaozizhong", 0) + 1);
|
|
|
|
|
var tiaozihao = core.getFlag("tiaozizhong");
|
|
|
|
|
var shangsheng = 1;
|
|
|
|
|
var gaodu = 0;
|
|
|
|
|
var herox = core.status.hero.loc.x,
|
|
|
|
|
heroy = core.status.hero.loc.y;
|
|
|
|
|
var fade = setInterval(function () {
|
|
|
|
|
core.clearMap('tiaozi', 0, 0, 416, 416);
|
|
|
|
|
if (gaodu >= -6 && shangsheng == 1) {
|
|
|
|
|
gaodu = gaodu - 1;
|
|
|
|
|
if (gaodu == -6) { shangsheng = 0 }
|
|
|
|
|
} else if (gaodu <= 12) {
|
|
|
|
|
gaodu = gaodu + 1;
|
|
|
|
|
if (gaodu == 12) { var tiaozizhong = 1 }
|
|
|
|
|
};
|
|
|
|
|
core.fillText('tiaozi', neirong, herox * 32 - 13, heroy * 32 + gaodu, yanse, "bold 17px Verdana");
|
|
|
|
|
if (tiaozizhong == 1 || core.getFlag("tiaozizhong") > tiaozihao) {
|
|
|
|
|
core.setFlag("tiaozizhong", core.getFlag("tiaozizhong", 0) - 1);
|
|
|
|
|
core.clearMap('tiaozi', 0, 0, 416, 416);
|
|
|
|
|
clearInterval(fade);
|
|
|
|
|
}
|
|
|
|
|
}, 16);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.tiaozi2 = function (neirong1, neirong2, yanse1, yanse2) { //二段跳字
|
|
|
|
|
if (core.status.replay.replaying) {} else {
|
|
|
|
|
core.createCanvas('tiaozi', 0, 0, 416, 416, 77);
|
|
|
|
|
core.setFlag("tiaozizhong", core.getFlag("tiaozizhong", 0) + 1);
|
|
|
|
|
var tiaozihao = core.getFlag("tiaozizhong");
|
|
|
|
|
var shangsheng = 1;
|
|
|
|
|
var gaodu = 0;
|
|
|
|
|
var huanzi = 0;
|
|
|
|
|
var herox = core.status.hero.loc.x,
|
|
|
|
|
heroy = core.status.hero.loc.y;
|
|
|
|
|
var fade = setInterval(function () {
|
|
|
|
|
core.clearMap('tiaozi', 0, 0, 416, 416);
|
|
|
|
|
if (gaodu >= -6 && shangsheng == 1) {
|
|
|
|
|
gaodu = gaodu - 1;
|
|
|
|
|
if (gaodu == -6) { shangsheng = 0 }
|
|
|
|
|
} else if (gaodu <= 12) {
|
|
|
|
|
gaodu = gaodu + 1;
|
|
|
|
|
if (gaodu == 12) {
|
|
|
|
|
if (huanzi == 1) { var tiaozizhong = 1 } else {
|
|
|
|
|
huanzi = 1;
|
|
|
|
|
gaodu = 0;
|
|
|
|
|
shangsheng = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
if (huanzi == 0) core.fillText('tiaozi', neirong1, herox * 32 - 13, heroy * 32 + gaodu, yanse1, "bold 17px Verdana");
|
|
|
|
|
else core.fillText('tiaozi', neirong2, herox * 32 - 13, heroy * 32 + gaodu, yanse2, "bold 17px Verdana");
|
|
|
|
|
if (tiaozizhong == 1 || core.getFlag("tiaozizhong") > tiaozihao) {
|
|
|
|
|
core.setFlag("tiaozizhong", core.getFlag("tiaozizhong", 0) - 1);
|
|
|
|
|
core.clearMap('tiaozi', 0, 0, 416, 416);
|
|
|
|
|
clearInterval(fade);
|
|
|
|
|
}
|
|
|
|
|
}, 16);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.tiaozi3 = function (neirong1, neirong2, neirong3, yanse1, yanse2, yanse3) { //三段跳字
|
|
|
|
|
if (core.status.replay.replaying) {} else {
|
|
|
|
|
core.createCanvas('tiaozi', 0, 0, 416, 416, 77);
|
|
|
|
|
core.setFlag("tiaozizhong", core.getFlag("tiaozizhong", 0) + 1);
|
|
|
|
|
var tiaozihao = core.getFlag("tiaozizhong");
|
|
|
|
|
var shangsheng = 1;
|
|
|
|
|
var gaodu = 0;
|
|
|
|
|
var huanzi = 0;
|
|
|
|
|
var herox = core.status.hero.loc.x,
|
|
|
|
|
heroy = core.status.hero.loc.y;
|
|
|
|
|
var fade = setInterval(function () {
|
|
|
|
|
core.clearMap('tiaozi', 0, 0, 416, 416);
|
|
|
|
|
if (gaodu >= -6 && shangsheng == 1) {
|
|
|
|
|
gaodu = gaodu - 1;
|
|
|
|
|
if (gaodu == -6) { shangsheng = 0 }
|
|
|
|
|
} else if (gaodu <= 12) {
|
|
|
|
|
gaodu = gaodu + 1;
|
|
|
|
|
if (gaodu == 12) {
|
|
|
|
|
switch (huanzi) {
|
|
|
|
|
case 0:
|
|
|
|
|
{
|
|
|
|
|
huanzi = 1;
|
|
|
|
|
gaodu = 0;
|
|
|
|
|
shangsheng = 1;
|
|
|
|
|
};
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
{
|
|
|
|
|
huanzi = 2;
|
|
|
|
|
gaodu = 0;
|
|
|
|
|
shangsheng = 1;
|
|
|
|
|
};
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
var tiaozizhong = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
switch (huanzi) {
|
|
|
|
|
case 0:
|
|
|
|
|
core.fillText('tiaozi', neirong1, herox * 32 - 13, heroy * 32 + gaodu, yanse1, "bold 17px Verdana");
|
|
|
|
|
break;
|
|
|
|
|
case 1:
|
|
|
|
|
core.fillText('tiaozi', neirong2, herox * 32 - 13, heroy * 32 + gaodu, yanse2, "bold 17px Verdana");
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
core.fillText('tiaozi', neirong3, herox * 32 - 13, heroy * 32 + gaodu, yanse3, "bold 17px Verdana");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (tiaozizhong == 1 || core.getFlag("tiaozizhong") > tiaozihao) {
|
|
|
|
|
core.setFlag("tiaozizhong", core.getFlag("tiaozizhong", 0) - 1);
|
|
|
|
|
core.clearMap('tiaozi', 0, 0, 416, 416);
|
|
|
|
|
clearInterval(fade);
|
|
|
|
|
}
|
|
|
|
|
}, 16);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.donghuas = function () {
|
|
|
|
|
core.plugin.donghua();
|
|
|
|
|
for (var i = 1; i <= 20; i++)
|
|
|
|
|
if (core.plugin['donghua' + i]) core.plugin['donghua' + i]();
|
|
|
|
|
}
|
|
|
|
|
this.donghua = function () {
|
|
|
|
|
if (core.status.floorId == "MT0") {
|
2022-11-02 21:12:18 +08:00
|
|
|
|
if (core.isReplaying()) {setTimeout(core.plugin.donghua, 100); return;}
|
2022-10-22 19:23:02 +08:00
|
|
|
|
core.setFlag("linshi", core.drawAnimate("jingu", 10, 10, false, function () {
|
|
|
|
|
|
|
|
|
|
core.plugin.donghua();
|
|
|
|
|
}));
|
|
|
|
|
} else core.stopAnimate(core.getFlag("linshi", 0), false);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
this.donghua1 = function () {
|
|
|
|
|
if (core.status.floorId == "MT14") {
|
|
|
|
|
core.setFlag("linshi1", core.drawAnimate("dianji", 4, 5, false, function () {
|
|
|
|
|
|
|
|
|
|
core.plugin.donghua1();
|
|
|
|
|
}));
|
|
|
|
|
} else core.stopAnimate(core.getFlag("linshi1", 0), false);
|
|
|
|
|
}
|
|
|
|
|
this.donghua2 = function () {
|
|
|
|
|
if (core.status.floorId == "MT14") {
|
|
|
|
|
core.setFlag("linshi2", core.drawAnimate("dianji", 10, 5, false, function () {
|
|
|
|
|
|
|
|
|
|
core.plugin.donghua2();
|
|
|
|
|
}));
|
|
|
|
|
} else core.stopAnimate(core.getFlag("linshi2", 0), false);
|
|
|
|
|
}
|
|
|
|
|
this.donghua3 = function () {
|
2022-11-13 02:56:18 +08:00
|
|
|
|
if (core.getFlag("poison")) {
|
|
|
|
|
core.setFlag("linshi3", core.drawHeroAnimate("dufa",
|
2022-10-22 19:23:02 +08:00
|
|
|
|
function () {
|
|
|
|
|
core.plugin.donghua3();
|
|
|
|
|
}));
|
|
|
|
|
} else core.stopAnimate(core.getFlag("linshi3", 0), false);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
this.donghua4 = function () {
|
|
|
|
|
if (core.getFlag("bofang", 0) == 1) {
|
|
|
|
|
core.setFlag("linshi4", core.drawHeroAnimate("STruoli",
|
|
|
|
|
function () {
|
|
|
|
|
core.plugin.donghua4();
|
|
|
|
|
}));
|
|
|
|
|
} else core.stopAnimate(core.getFlag("linshi4", 0), false);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
this.donghua5 = function () {
|
|
|
|
|
if (core.getFlag("bofang", 0) == 1) {
|
|
|
|
|
core.setFlag("linshi5", core.drawHeroAnimate("lansebaofa",
|
|
|
|
|
function () {
|
|
|
|
|
core.plugin.donghua5();
|
|
|
|
|
}));
|
|
|
|
|
} else core.stopAnimate(core.getFlag("linshi5", 0), false);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
this.donghua6 = function () {
|
|
|
|
|
if (core.getFlag("bofang", 0) == 1) {
|
|
|
|
|
if (core.status.floorId == "MT81") {
|
|
|
|
|
core.setFlag("linshi6", core.drawAnimate("shenlanbaofa", 7, 5, false, function () {
|
|
|
|
|
|
|
|
|
|
core.plugin.donghua6();
|
|
|
|
|
}));
|
|
|
|
|
} else core.stopAnimate(core.getFlag("linshi6", 0), false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.donghua7 = function () {
|
|
|
|
|
if (core.status.floorId == "MT64") {
|
|
|
|
|
if (core.getPlayingAnimates().includes(core.getFlag("linshi7", 0))) return;
|
|
|
|
|
core.setFlag("linshi7", core.drawAnimate("jingu", 7, 1, false, function () {
|
|
|
|
|
|
|
|
|
|
core.plugin.donghua7();
|
|
|
|
|
}));
|
|
|
|
|
} else core.stopAnimate(core.getFlag("linshi7", 0), false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
this.donghua8 = function () {
|
|
|
|
|
if (core.getFlag("bofang8", 0) == 1) {
|
|
|
|
|
if (core.status.floorId == "jiange") {
|
|
|
|
|
core.setFlag("linshi8", core.drawAnimate("lvbaofa", 9, 8, false, function () {
|
|
|
|
|
|
|
|
|
|
core.plugin.donghua8();
|
|
|
|
|
}));
|
|
|
|
|
} else core.stopAnimate(core.getFlag("linshi8", 0), false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.donghua9 = function () {
|
|
|
|
|
if (core.getFlag("bofang9", 0) == 1) {
|
|
|
|
|
core.setFlag("linshi9", core.drawHeroAnimate("lansebaofa",
|
|
|
|
|
function () {
|
|
|
|
|
core.plugin.donghua9();
|
|
|
|
|
}));
|
|
|
|
|
} else core.stopAnimate(core.getFlag("linshi9", 0), false);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"楼层切换": function () {
|
|
|
|
|
// 在此增加新插件
|
|
|
|
|
////// 楼层切换 //////
|
|
|
|
|
core.events.changeFloor = function (floorId, stair, heroLoc, time, callback) {
|
|
|
|
|
var info = this._changeFloor_getInfo(floorId, stair, heroLoc, time);
|
|
|
|
|
var tempCanvas = {};
|
|
|
|
|
core.createCanvas("first", 0, 0, core.__PIXELS__, core.__PIXELS__, 61);
|
|
|
|
|
if (!core.isReplaying()) {
|
|
|
|
|
tempCanvas = core.createCanvas("_save_", 0, 0, core.__PIXELS__, core.__PIXELS__);
|
|
|
|
|
core.clearMap("_save_");
|
|
|
|
|
core.drawImage(tempCanvas, core.dom.gameCanvas.bg, 0, 0, core.__PIXELS__, core.__PIXELS__);
|
|
|
|
|
core.drawImage(tempCanvas, core.dom.gameCanvas.event, 0, 0, core.__PIXELS__, core.__PIXELS__);
|
|
|
|
|
core.drawImage(tempCanvas, core.dom.gameCanvas.event2, 0, 0, core.__PIXELS__, core.__PIXELS__);
|
|
|
|
|
core.drawImage(tempCanvas, core.dom.gameCanvas.fg, 0, 0, core.__PIXELS__, core.__PIXELS__);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
info.tempCanvas = tempCanvas.canvas;
|
|
|
|
|
if (info == null) {
|
|
|
|
|
if (callback) callback();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
floorId = info.floorId;
|
|
|
|
|
info.locked = core.status.lockControl;
|
|
|
|
|
|
|
|
|
|
core.dom.floorNameLabel.innerText = core.status.maps[floorId].title;
|
|
|
|
|
core.lockControl();
|
|
|
|
|
core.stopAutomaticRoute();
|
|
|
|
|
core.clearContinueAutomaticRoute();
|
|
|
|
|
core.status.replay.animate = true;
|
|
|
|
|
clearInterval(core.interval.onDownInterval);
|
|
|
|
|
core.interval.onDownInterval = 'tmp';
|
|
|
|
|
|
|
|
|
|
this._changeFloor_beforeChange(info, callback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
core.events._changeFloor_beforeChange = function (info, callback) {
|
|
|
|
|
this._changeFloor_playSound();
|
|
|
|
|
// 需要 setTimeout 执行,不然会出错
|
|
|
|
|
window.setTimeout(function () {
|
|
|
|
|
core.events._changeFloor_changing(info, callback);
|
|
|
|
|
/*if (info.time == 0)
|
|
|
|
|
core.events._changeFloor_changing(info, callback);
|
|
|
|
|
else
|
|
|
|
|
core.showWithAnimate(core.dom.floorMsgGroup, info.time / 2, function () {
|
|
|
|
|
core.events._changeFloor_changing(info, callback);
|
|
|
|
|
});*/
|
|
|
|
|
}, 25)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
core.events._changeFloor_changing = function (info, callback) {
|
|
|
|
|
this.changingFloor(info.floorId, info.heroLoc);
|
|
|
|
|
// 回归视角
|
|
|
|
|
var __lockViewport__ = flags.__lockViewport__;
|
|
|
|
|
core.setFlag('__lockViewport__', null);
|
|
|
|
|
core.drawHero();
|
|
|
|
|
core.setFlag('__lockViewport__', __lockViewport__);
|
|
|
|
|
var obj = core.getContextByName("first").canvas;
|
|
|
|
|
var end = function () {
|
|
|
|
|
clearInterval(core.__floor);
|
|
|
|
|
core.clearMap("first");
|
|
|
|
|
obj.style.opacity = 1;
|
|
|
|
|
obj.style.display = "block";
|
|
|
|
|
core.__floor = null;
|
|
|
|
|
}
|
|
|
|
|
var deleteCanvas = function () {
|
|
|
|
|
core.deleteCanvas("_save_");
|
|
|
|
|
info.tempCanvas = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info.time == 0 || main.mode != 'play') {
|
|
|
|
|
end();
|
|
|
|
|
deleteCanvas();
|
|
|
|
|
} else {
|
|
|
|
|
if (core.__floor) end();
|
|
|
|
|
core.drawImage("first", info.tempCanvas, 0, 0, core.__PIXELS__, core.__PIXELS__);
|
|
|
|
|
obj.style.opacity = 1;
|
|
|
|
|
var opacityVal = 1;
|
|
|
|
|
core.__floor = window.setInterval(function () {
|
|
|
|
|
opacityVal -= 0.03;
|
|
|
|
|
obj.style.opacity = opacityVal;
|
|
|
|
|
if (opacityVal < 0) {
|
|
|
|
|
end();
|
|
|
|
|
deleteCanvas();
|
|
|
|
|
}
|
|
|
|
|
}, info.time / 1.7);
|
|
|
|
|
}
|
|
|
|
|
core.events._changeFloor_afterChange(info, callback);
|
|
|
|
|
/*core.hideWithAnimate(core.dom.floorMsgGroup, info.time / 4, function () {
|
|
|
|
|
core.events._changeFloor_afterChange(info, callback);
|
|
|
|
|
});*/
|
2022-10-16 21:58:52 +08:00
|
|
|
|
}
|
2022-11-03 23:17:58 +08:00
|
|
|
|
},
|
|
|
|
|
"标题动画": function () {
|
|
|
|
|
|
|
|
|
|
var start = document.getElementById('startPanel');
|
|
|
|
|
var list = [];
|
|
|
|
|
var id = 0;
|
|
|
|
|
|
|
|
|
|
// 标题
|
|
|
|
|
var title = document.getElementById('startTitle');
|
|
|
|
|
core.registerResize('startTitle', function () {
|
|
|
|
|
title.style.width = 300 * core.domStyle.scale + 'px';
|
|
|
|
|
title.style.height = 187 * core.domStyle.scale + 'px';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 星星动画,使用sprite化方法
|
|
|
|
|
function draw() {
|
|
|
|
|
if (start.style.display === 'none') return;
|
|
|
|
|
// 每帧有10%的概率出
|
|
|
|
|
if (Math.random() < 0.1) {
|
|
|
|
|
var config = {
|
|
|
|
|
x: Math.random() * 450 * core.domStyle.scale,
|
|
|
|
|
y: -187 * core.domStyle.scale,
|
|
|
|
|
id: id++
|
|
|
|
|
};
|
|
|
|
|
if (id > 100) id -= 100;
|
|
|
|
|
list.push(config);
|
|
|
|
|
// 追加新的ele
|
|
|
|
|
var img = document.createElement('img');
|
|
|
|
|
img.src = './project/images/Title_starlong.png';
|
|
|
|
|
img.style.position = 'absolute';
|
|
|
|
|
img.style.zIndex = '280';
|
|
|
|
|
img.style.left = config.x + 'px';
|
|
|
|
|
img.style.top = '0px';
|
|
|
|
|
img.style.transform = 'scale(' + core.domStyle.scale * 100 + '%)'
|
|
|
|
|
img.id = id + '_star';
|
|
|
|
|
list[list.length - 1].ele = img;
|
|
|
|
|
start.appendChild(img);
|
|
|
|
|
}
|
|
|
|
|
update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 每帧更新动画
|
|
|
|
|
function update() {
|
|
|
|
|
for (var i = 0; i < list.length; i++) {
|
|
|
|
|
// 一定要匀速运动
|
|
|
|
|
var one = list[i];
|
|
|
|
|
if (one.x < -154 * core.domStyle.scale) {
|
|
|
|
|
list.splice(i, 1);
|
|
|
|
|
i--;
|
|
|
|
|
one.ele.remove();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
one.x -= 3 * core.domStyle.scale;
|
|
|
|
|
one.y += 3 * core.domStyle.scale;
|
|
|
|
|
one.ele.style.top = one.y + 'px';
|
|
|
|
|
one.ele.style.left = one.x + 'px';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
core.registerAnimationFrame('startAnimation', false, draw);
|
2022-11-09 00:32:27 +08:00
|
|
|
|
},
|
|
|
|
|
"showValue": function () {
|
|
|
|
|
/* 宝石血瓶左下角显示数值
|
|
|
|
|
* 需要将 变量:itemDetail改为true才可正常运行
|
|
|
|
|
* 请尽量减少勇士的属性数量,否则可能会出现严重卡顿
|
|
|
|
|
* 注意:这里的属性必须是core.status.hero里面的,flag无法显示
|
|
|
|
|
* 如果不想显示,可以core.setFlag("itemDetail", false);
|
|
|
|
|
* 然后再core.getItemDetail();
|
|
|
|
|
* 如有bug在大群或造塔群@古祠
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// 谁tm在即捡即用效果里面调用带有含刷新状态栏的函数
|
|
|
|
|
var origin = core.control.updateStatusBar;
|
|
|
|
|
core.updateStatusBar = core.control.updateStatusBar = function () {
|
|
|
|
|
if (core.getFlag('__statistics__')) return;
|
|
|
|
|
else return origin.apply(core.control, arguments);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
core.bigmap.threshold = 256;
|
|
|
|
|
|
|
|
|
|
core.control.updateDamage = function (floorId, ctx) {
|
|
|
|
|
floorId = floorId || core.status.floorId;
|
|
|
|
|
if (!floorId || core.status.gameOver || main.mode != 'play') return;
|
|
|
|
|
var onMap = ctx == null;
|
|
|
|
|
|
|
|
|
|
// 没有怪物手册
|
|
|
|
|
if (!core.hasItem('book')) return;
|
|
|
|
|
core.status.damage.posX = core.bigmap.posX;
|
|
|
|
|
core.status.damage.posY = core.bigmap.posY;
|
|
|
|
|
if (!onMap) {
|
|
|
|
|
var width = core.floors[floorId].width,
|
|
|
|
|
height = core.floors[floorId].height;
|
|
|
|
|
// 地图过大的缩略图不绘制显伤
|
|
|
|
|
if (width * height > core.bigmap.threshold) return;
|
|
|
|
|
}
|
|
|
|
|
this._updateDamage_damage(floorId, onMap);
|
|
|
|
|
this._updateDamage_extraDamage(floorId, onMap);
|
|
|
|
|
core.getItemDetail(floorId); // 宝石血瓶详细信息
|
|
|
|
|
this.drawDamage(ctx);
|
|
|
|
|
};
|
|
|
|
|
// 绘制地图显示
|
|
|
|
|
control.prototype._drawDamage_draw = function (ctx, onMap) {
|
|
|
|
|
if (!core.hasItem('book')) return;
|
|
|
|
|
// *** 下一句话可以更改你想要的显示字体
|
|
|
|
|
core.setFont(ctx, "bold 11px Arial");
|
|
|
|
|
// ***
|
|
|
|
|
core.setTextAlign(ctx, 'left');
|
|
|
|
|
core.status.damage.data.forEach(function (one) {
|
|
|
|
|
var px = one.px,
|
|
|
|
|
py = one.py;
|
|
|
|
|
if (onMap && core.bigmap.v2) {
|
|
|
|
|
px -= core.bigmap.posX * 32;
|
|
|
|
|
py -= core.bigmap.posY * 32;
|
|
|
|
|
if (px < -32 * 2 || px > core.__PX__ + 32 || py < -32 || py > core.__PY__ + 32)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
core.fillBoldText(ctx, one.text, px, py, one.color);
|
|
|
|
|
});
|
|
|
|
|
core.setTextAlign(ctx, 'center');
|
|
|
|
|
core.status.damage.extraData.forEach(function (one) {
|
|
|
|
|
var px = one.px,
|
|
|
|
|
py = one.py;
|
|
|
|
|
if (onMap && core.bigmap.v2) {
|
|
|
|
|
px -= core.bigmap.posX * 32;
|
|
|
|
|
py -= core.bigmap.posY * 32;
|
|
|
|
|
if (px < -32 || px > core.__PX__ + 32 || py < -32 || py > core.__PY__ + 32)
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
core.fillBoldText(ctx, one.text, px, py, one.color);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
// 获取宝石信息 并绘制
|
|
|
|
|
this.getItemDetail = function (floorId) {
|
|
|
|
|
if (!core.getFlag("itemDetail")) return;
|
|
|
|
|
floorId = floorId || core.status.thisMap.floorId;
|
|
|
|
|
core.status.maps[floorId].blocks.forEach(function (block) {
|
|
|
|
|
if (block.event.cls !== 'items' || block.event.id === 'superPotion') return;
|
|
|
|
|
var x = block.x,
|
|
|
|
|
y = block.y;
|
|
|
|
|
// v2优化,只绘制范围内的部分
|
|
|
|
|
if (core.bigmap.v2) {
|
|
|
|
|
if (x < core.bigmap.posX - core.bigmap.extend || x > core.bigmap.posX + core.__SIZE__ + core.bigmap.extend ||
|
|
|
|
|
y < core.bigmap.posY - core.bigmap.extend || y > core.bigmap.posY + core.__SIZE__ + core.bigmap.extend) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
var id = block.event.id;
|
|
|
|
|
var item = core.material.items[id];
|
|
|
|
|
if (item.cls === 'equips') {
|
|
|
|
|
// 装备也显示
|
|
|
|
|
var diff = core.clone(item.equip.value || {});
|
|
|
|
|
var per = item.equip.percentage;
|
|
|
|
|
for (var name in per) {
|
|
|
|
|
diff[name + 'per'] = per[name].toString() + '%';
|
|
|
|
|
}
|
|
|
|
|
drawItemDetail(diff, x, y);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
var before = core.clone(core.status.hero);
|
|
|
|
|
// 跟数据统计原理一样 执行效果 前后比较
|
|
|
|
|
core.setFlag("__statistics__", true);
|
|
|
|
|
try {
|
|
|
|
|
eval(item.itemEffect);
|
|
|
|
|
} catch (error) {}
|
|
|
|
|
var diff = compareObject(before, core.status.hero);
|
|
|
|
|
core.status.hero = hero = before;
|
|
|
|
|
flags = core.status.hero.flags;
|
|
|
|
|
drawItemDetail(diff, x, y);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
// 比较两个对象之间每一项的数值差异(弱等于) 返回数值差异
|
|
|
|
|
function compareObject(a, b) {
|
|
|
|
|
a = a || {};
|
|
|
|
|
b = b || {};
|
|
|
|
|
var diff = {}; // 差异
|
|
|
|
|
for (var name in a) {
|
|
|
|
|
diff[name] = b[name] - (a[name] || 0);
|
|
|
|
|
if (!diff[name]) diff[name] = void 0;
|
|
|
|
|
}
|
|
|
|
|
return diff;
|
|
|
|
|
};
|
|
|
|
|
// 绘制
|
|
|
|
|
function drawItemDetail(diff, x, y) {
|
|
|
|
|
var px = 32 * x + 2,
|
|
|
|
|
py = 32 * y + 30;
|
|
|
|
|
var content = "";
|
|
|
|
|
// 获得数据和颜色
|
|
|
|
|
var i = 0;
|
|
|
|
|
for (var name in diff) {
|
|
|
|
|
if (!diff[name]) continue;
|
|
|
|
|
var color = "#ffffff";
|
|
|
|
|
if (typeof diff[name] === 'number')
|
|
|
|
|
diff[name] = core.formatBigNumber(diff[name], true);
|
|
|
|
|
switch (name) {
|
|
|
|
|
case 'atk':
|
|
|
|
|
case 'atkper':
|
|
|
|
|
color = "#FF7A7A";
|
|
|
|
|
break;
|
|
|
|
|
case 'def':
|
|
|
|
|
case 'defper':
|
|
|
|
|
color = "#00E6F1";
|
|
|
|
|
break;
|
|
|
|
|
case 'mdef':
|
|
|
|
|
case 'mdefper':
|
|
|
|
|
color = "#6EFF83";
|
|
|
|
|
break;
|
|
|
|
|
case 'hp':
|
|
|
|
|
color = "#A4FF00";
|
|
|
|
|
break;
|
|
|
|
|
case 'hpmax':
|
|
|
|
|
case 'hpmaxper':
|
|
|
|
|
color = "#F9FF00";
|
|
|
|
|
break;
|
|
|
|
|
case 'mana':
|
|
|
|
|
color = "#cc6666";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
content = diff[name];
|
|
|
|
|
// 绘制
|
|
|
|
|
core.status.damage.data.push({ text: content, px: px, py: py - 10 * i, color: color });
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"autoBattle": function () {
|
|
|
|
|
/**
|
|
|
|
|
* --------------- 安装说明 ---------------
|
|
|
|
|
*
|
|
|
|
|
* 复制到插件编写里面即可
|
|
|
|
|
*
|
|
|
|
|
* --------------- 使用说明 ---------------
|
|
|
|
|
*
|
|
|
|
|
* 把变量 __autoBattle__ 设置成true开启,设置成false关闭,然后在想要清的时刻,比如战后,每步后等加上core.autoBattle()即可
|
|
|
|
|
*
|
|
|
|
|
* --------------- 自定义说明 ---------------
|
|
|
|
|
*
|
|
|
|
|
* 可以更改canBattle函数自定义某个怪物是否应该被清
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 是否清这个怪,可以修改这里来实现对不同怪的不同操作
|
|
|
|
|
* @param {string} enemy
|
|
|
|
|
* @param {number} x
|
|
|
|
|
* @param {number} y
|
|
|
|
|
*/
|
|
|
|
|
function canBattle(enemy, x, y) {
|
|
|
|
|
const loc = `${x},${y}`;
|
|
|
|
|
const floor = core.floors[core.status.floorId];
|
|
|
|
|
const e = core.material.enemys[enemy];
|
|
|
|
|
const hasEvent =
|
|
|
|
|
has(floor.afterBattle[loc]) ||
|
|
|
|
|
has(floor.beforeBattle[loc]) ||
|
|
|
|
|
has(e.beforeBattle) ||
|
|
|
|
|
has(e.afterBattle) ||
|
|
|
|
|
has(floor.events[loc]);
|
|
|
|
|
// 有事件,不清
|
|
|
|
|
if (hasEvent) return false;
|
|
|
|
|
const damage = core.getDamageInfo(enemy, void 0, x, y);
|
|
|
|
|
// 0伤或负伤,清
|
|
|
|
|
if (has(damage) && has(damage.damage) && damage.damage <= 0) return true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @template T
|
|
|
|
|
* @param {T} v
|
|
|
|
|
* @returns {v is NonNullable<T>}
|
|
|
|
|
*/
|
|
|
|
|
function has(v) {
|
|
|
|
|
return v !== null && v !== undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 广搜,搜索可以到达的需要清的怪
|
|
|
|
|
* @param {string} floorId
|
|
|
|
|
*/
|
|
|
|
|
function bfs(floorId, deep = Infinity) {
|
|
|
|
|
core.extractBlocks(floorId);
|
|
|
|
|
const objs = core.getMapBlocksObj(floorId);
|
|
|
|
|
const { x, y } = core.status.hero.loc;
|
|
|
|
|
/** @type {[direction, number, number][]} */
|
|
|
|
|
const dir = Object.entries(core.utils.scan).map(v => [
|
|
|
|
|
v[0],
|
|
|
|
|
v[1].x,
|
|
|
|
|
v[1].y
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
/** @type {[number, number][]} */
|
|
|
|
|
const queue = [
|
|
|
|
|
[x, y]
|
|
|
|
|
];
|
|
|
|
|
const mapped = {
|
|
|
|
|
[`${x},${y}`]: true
|
|
|
|
|
};
|
|
|
|
|
while (queue.length > 0 && deep > 0) {
|
|
|
|
|
const [nx, ny] = queue.shift();
|
|
|
|
|
dir.forEach(v => {
|
|
|
|
|
const [tx, ty] = [nx + v[1], ny + v[2]];
|
|
|
|
|
const loc = `${tx},${ty}`;
|
|
|
|
|
if (mapped[loc]) return;
|
|
|
|
|
const block = objs[loc];
|
|
|
|
|
mapped[loc] = true;
|
|
|
|
|
const isEnemy =
|
|
|
|
|
has(block) && block.event.cls.startsWith('enemy');
|
|
|
|
|
const changeFloor = core.floors[floorId].changeFloor[loc];
|
|
|
|
|
if (
|
|
|
|
|
(!core.canMoveHero(nx, ny, v[0]) && !isEnemy) ||
|
|
|
|
|
(has(block) && block.event.cls === 'items') ||
|
|
|
|
|
(core.noPass(tx, ty) && !isEnemy) ||
|
|
|
|
|
has(core.floors[floorId].events[loc]) ||
|
|
|
|
|
(has(changeFloor) &&
|
|
|
|
|
changeFloor.ignoreChangeFloor === false)
|
|
|
|
|
)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (isEnemy) {
|
|
|
|
|
if (canBattle(block.event.id, tx, ty) && !block.disable) {
|
|
|
|
|
console.log(block.event.id, tx, ty);
|
|
|
|
|
// 能打且没有事件就直接干他丫的
|
|
|
|
|
core.battle(block.event.id, tx, ty);
|
|
|
|
|
} else return;
|
|
|
|
|
}
|
|
|
|
|
// 然后判断目标点是否有地图伤害等,没有就直接添加到队列
|
|
|
|
|
const damage = core.status.checkBlock.damage[loc];
|
|
|
|
|
const ambush = core.status.checkBlock.ambush[loc];
|
|
|
|
|
const repulse = core.status.checkBlock.repulse[loc];
|
|
|
|
|
if (
|
|
|
|
|
(!has(damage) || (has(damage) && damage <= 0)) &&
|
|
|
|
|
!has(ambush) &&
|
|
|
|
|
!has(repulse)
|
|
|
|
|
)
|
|
|
|
|
queue.push([tx, ty]);
|
|
|
|
|
});
|
|
|
|
|
deep--;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.autoBattle = function () {
|
|
|
|
|
if (!flags.__autoBattle__) return;
|
|
|
|
|
// 如果勇士当前点有地图伤害,只清周围
|
|
|
|
|
const { x, y } = core.status.hero.loc;
|
|
|
|
|
const floor = core.floors[core.status.floorId];
|
|
|
|
|
const hasEvent = has(floor.events[`${x},${y}`]);
|
|
|
|
|
if (hasEvent) return;
|
|
|
|
|
const damage = core.status.checkBlock.damage[`${x},${y}`];
|
|
|
|
|
let deep = Infinity;
|
|
|
|
|
if (has(damage) && damage > 0) {
|
|
|
|
|
deep = 1;
|
|
|
|
|
}
|
|
|
|
|
bfs(core.status.floorId, deep);
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
"autoGet": function () {
|
|
|
|
|
var enable = true;
|
|
|
|
|
if (!enable) return;
|
|
|
|
|
//
|
|
|
|
|
// var noUpdate = false;
|
|
|
|
|
////// 更新状态栏 ////// 不建议状态栏刷新后触发 容易导致录像不一致的问题
|
|
|
|
|
//control.prototype.updateStatusBar = function (doNotCheckAutoEvents) {
|
|
|
|
|
// if (!core.isPlaying()) return;
|
|
|
|
|
// if (noUpdate) return;
|
|
|
|
|
// noUpdate = true;
|
|
|
|
|
// core.autoGetItem();
|
|
|
|
|
// noUpdate = false;
|
|
|
|
|
// this.controldata.updateStatusBar();
|
|
|
|
|
// if (!doNotCheckAutoEvents) core.checkAutoEvents();
|
|
|
|
|
// this._updateStatusBar_setToolboxIcon();
|
|
|
|
|
// core.clearRouteFolding();
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
////// 每移动一格后执行的事件 //////
|
|
|
|
|
control.prototype.moveOneStep = function (callback) {
|
|
|
|
|
core.autoGetItem();
|
|
|
|
|
core.autoBattle();
|
|
|
|
|
return this.controldata.moveOneStep(callback);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function bfsFlood(sx, sy, blockfn) {
|
|
|
|
|
var canMoveArray = core.generateMovableArray();
|
|
|
|
|
var blocksObj = core.getMapBlocksObj();
|
|
|
|
|
var bgMap = core.getBgMapArray();
|
|
|
|
|
|
|
|
|
|
var visited = [],
|
|
|
|
|
queue = [];
|
|
|
|
|
visited[sx + "," + sy] = 0;
|
|
|
|
|
queue.push(sx + "," + sy);
|
|
|
|
|
|
|
|
|
|
while (queue.length > 0) {
|
|
|
|
|
var now = queue.shift().split(","),
|
|
|
|
|
x = ~~now[0],
|
|
|
|
|
y = ~~now[1];
|
|
|
|
|
for (var direction in core.utils.scan) {
|
|
|
|
|
if (!core.inArray(canMoveArray[x][y], direction)) continue;
|
|
|
|
|
var nx = x + core.utils.scan[direction].x,
|
|
|
|
|
ny = y + core.utils.scan[direction].y,
|
|
|
|
|
nindex = nx + "," + ny;
|
|
|
|
|
if (visited[nindex]) continue;
|
|
|
|
|
if (core.onSki(bgMap[ny][nx])) continue;
|
|
|
|
|
if (blockfn && !blockfn(blocksObj, nx, ny)) continue;
|
|
|
|
|
visited[nindex] = visited[now] + 1;
|
|
|
|
|
queue.push(nindex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function attractAnimate() {
|
|
|
|
|
var name = 'attractAnimate';
|
|
|
|
|
var isPlaying = false;
|
|
|
|
|
this.nodes = [];
|
|
|
|
|
|
|
|
|
|
this.add = function (id, x, y, callback) {
|
|
|
|
|
this.nodes.push({ id: id, x: x, y: y, callback: callback });
|
|
|
|
|
}
|
|
|
|
|
this.start = function () {
|
|
|
|
|
if (isPlaying) return;
|
|
|
|
|
isPlaying = true;
|
|
|
|
|
core.registerAnimationFrame(name, true, this.update);
|
|
|
|
|
this.ctx = core.createCanvas(name, 0, 0, core.__PIXELS__, core.__PIXELS__, 120);
|
|
|
|
|
}
|
|
|
|
|
this.remove = function () {
|
|
|
|
|
core.unregisterAnimationFrame(name);
|
|
|
|
|
core.deleteCanvas(name);
|
|
|
|
|
isPlaying = false;
|
|
|
|
|
}
|
|
|
|
|
this.clear = function () {
|
|
|
|
|
this.nodes = [];
|
|
|
|
|
this.remove();
|
|
|
|
|
}
|
|
|
|
|
var lastTime = -1;
|
|
|
|
|
var self = this;
|
|
|
|
|
this.update = function (timeStamp) {
|
|
|
|
|
if (lastTime < 0) lastTime = timeStamp;
|
|
|
|
|
if (timeStamp - lastTime < 20) return;
|
|
|
|
|
lastTime = timeStamp;
|
|
|
|
|
core.clearMap(name);
|
|
|
|
|
var cx = core.status.heroCenter.px - 16,
|
|
|
|
|
cy = core.status.heroCenter.py - 16;
|
|
|
|
|
var thr = 5; //缓动比例倒数 越大移动越慢
|
|
|
|
|
self.nodes.forEach(function (n) {
|
|
|
|
|
var dx = cx - n.x,
|
|
|
|
|
dy = cy - n.y;
|
|
|
|
|
if (Math.abs(dx) <= thr && Math.abs(dy) <= thr) {
|
|
|
|
|
n.dead = true;
|
|
|
|
|
} else {
|
|
|
|
|
n.x += ~~(dx / thr);
|
|
|
|
|
n.y += ~~(dy / thr);
|
|
|
|
|
}
|
|
|
|
|
core.drawIcon(name, n.id, n.x, n.y, 32, 32);
|
|
|
|
|
});
|
|
|
|
|
self.nodes = self.nodes.filter(function (n) {
|
|
|
|
|
if (n.dead && n.callback) {
|
|
|
|
|
n.callback();
|
|
|
|
|
}
|
|
|
|
|
return !n.dead;
|
|
|
|
|
});
|
|
|
|
|
if (self.nodes.length == 0)
|
|
|
|
|
self.remove();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var animateHwnd = new attractAnimate();
|
|
|
|
|
|
|
|
|
|
this.stopAttractAnimate = function () {
|
|
|
|
|
animateHwnd.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.autoGetItem = function () {
|
|
|
|
|
if (!flags.__autoGetItem__) return;
|
|
|
|
|
var canGetItems = {};
|
|
|
|
|
if (!core.status.floorId || !core.status.checkBlock.damage || core.status.event.id == 'action' || core.status.lockControl) return;
|
|
|
|
|
|
|
|
|
|
bfsFlood(core.getHeroLoc('x'), core.getHeroLoc('y'), function (blockMap, x, y) {
|
|
|
|
|
var idx = x + ',' + y;
|
|
|
|
|
if (idx in canGetItems) return false;
|
|
|
|
|
var blk = blockMap[idx];
|
|
|
|
|
if (blk && !blk.disable && blk.event.cls == 'items' && !core.isMapBlockDisabled(core.status.floorId, blk.x, blk.y) && blk.event.trigger == 'getItem') {
|
|
|
|
|
canGetItems[idx] = { x: x, y: y, id: blk.event.id };
|
|
|
|
|
return !core.status.checkBlock.damage[idx] && !core.status.checkBlock.ambush[idx];
|
|
|
|
|
}
|
|
|
|
|
return core.maps._canMoveDirectly_checkNextPoint(blockMap, x, y);
|
|
|
|
|
});
|
|
|
|
|
for (var k in canGetItems) {
|
|
|
|
|
var x = canGetItems[k].x,
|
|
|
|
|
y = canGetItems[k].y,
|
|
|
|
|
id = canGetItems[k].id;
|
|
|
|
|
core.trigger(x, y);
|
|
|
|
|
animateHwnd.add(id, x * 32, y * 32);
|
|
|
|
|
}
|
|
|
|
|
animateHwnd.start();
|
|
|
|
|
}
|
2022-11-12 17:11:22 +08:00
|
|
|
|
},
|
|
|
|
|
"怪物手册和显伤": function () {
|
|
|
|
|
// 在此增加新插件
|
|
|
|
|
////// 获得所有特殊属性的名称 /////
|
2022-11-13 02:56:18 +08:00
|
|
|
|
core.enemys.getSpecialText = function (enemy) {
|
2022-11-12 17:11:22 +08:00
|
|
|
|
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
|
|
|
|
|
if (!enemy) return [];
|
|
|
|
|
var special = enemy.special;
|
|
|
|
|
var text = [];
|
|
|
|
|
|
|
|
|
|
var specials = this.getSpecials();
|
|
|
|
|
if (specials) {
|
|
|
|
|
for (var i = 0; i < specials.length; i++) {
|
|
|
|
|
if (this.hasSpecial(special, specials[i][0]))
|
|
|
|
|
text.push(this._calSpecialContent(enemy, specials[i][1]));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (special === 0) {
|
|
|
|
|
text.push('普通'); ///////无特殊属性时增加“普通”属性显示
|
|
|
|
|
}
|
|
|
|
|
return text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////// 获得所有特殊属性的颜色 //////
|
2022-11-13 02:56:18 +08:00
|
|
|
|
core.enemys.getSpecialColor = function (enemy) {
|
2022-11-12 17:11:22 +08:00
|
|
|
|
if (typeof enemy == 'string') enemy = core.material.enemys[enemy];
|
|
|
|
|
if (!enemy) return [];
|
|
|
|
|
var special = enemy.special;
|
|
|
|
|
var colors = [];
|
|
|
|
|
|
|
|
|
|
var specials = this.getSpecials();
|
|
|
|
|
if (specials) {
|
|
|
|
|
for (var i = 0; i < specials.length; i++) {
|
|
|
|
|
if (this.hasSpecial(special, specials[i][0]))
|
|
|
|
|
colors.push(specials[i][3] || null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (special === 0) {
|
|
|
|
|
colors.push("#ffffff"); ////“普通”属性显示为白色
|
|
|
|
|
}
|
|
|
|
|
return colors;
|
|
|
|
|
|
|
|
|
|
}
|
2022-11-17 13:00:36 +08:00
|
|
|
|
|
2022-11-12 17:11:22 +08:00
|
|
|
|
},
|
2022-11-15 21:00:03 +08:00
|
|
|
|
"仿RM渐变效果": function () {
|
|
|
|
|
// 在此增加新插件
|
|
|
|
|
// 准备渐变
|
|
|
|
|
this.maskPrepare = function () {
|
|
|
|
|
// 执行后画面将凝固
|
|
|
|
|
core.createCanvas("mask", 0, 0, core.__PIXELS__, core.__PIXELS__, 155);
|
|
|
|
|
for (var m in core.canvas) {
|
|
|
|
|
core.dymCanvas.mask.drawImage(core.canvas[m].canvas, 0, 0);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 执行渐变
|
|
|
|
|
this.maskFliter = function (time, sample) { // sample为渐变图名称,渐变图需要在全塔属性注册
|
|
|
|
|
var tempCanvas = core.bigmap.tempCanvas;
|
|
|
|
|
var tempWidth = core.__PIXELS__,
|
|
|
|
|
tempHeight = core.__PIXELS__;
|
|
|
|
|
tempCanvas.canvas.width = tempWidth;
|
|
|
|
|
tempCanvas.canvas.height = tempHeight;
|
|
|
|
|
tempCanvas.clearRect(0, 0, tempWidth, tempHeight);
|
|
|
|
|
tempCanvas.drawImage(core.material.images.images[sample], 0, 0, tempWidth, tempHeight);
|
|
|
|
|
// 读取渐变图开始处理
|
|
|
|
|
var sampleData = tempCanvas.getImageData(0, 0, tempWidth, tempHeight);
|
|
|
|
|
var processData = core.dymCanvas.mask.getImageData(0, 0, tempWidth, tempHeight);
|
|
|
|
|
tempCanvas.clearRect(0, 0, tempWidth, tempHeight);
|
|
|
|
|
var timer = 0;
|
|
|
|
|
var animate = setInterval(function () {
|
|
|
|
|
timer++;
|
|
|
|
|
for (var i = 0; i < sampleData.data.length; i += 4) {
|
|
|
|
|
if (sampleData.data[i] < timer) {
|
|
|
|
|
processData.data[i] = 0;
|
|
|
|
|
processData.data[i + 1] = 0;
|
|
|
|
|
processData.data[i + 2] = 0;
|
|
|
|
|
processData.data[i + 3] = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
core.dymCanvas.mask.putImageData(processData, 0, 0);
|
|
|
|
|
if (timer == 255) {
|
|
|
|
|
delete core.animateFrame.asyncId[animate];
|
|
|
|
|
clearInterval(animate);
|
|
|
|
|
core.deleteCanvas("mask");
|
|
|
|
|
}
|
|
|
|
|
}, time / 256);
|
|
|
|
|
core.animateFrame.asyncId[animate] = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-16 21:58:52 +08:00
|
|
|
|
}
|