mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-19 12:49:25 +08:00
refactor: 循环式地图
This commit is contained in:
parent
2bf0fbe781
commit
48ce4a2fb7
@ -370,7 +370,76 @@ events.prototype.doSystemEvent = function (type, data, callback) {
|
|||||||
|
|
||||||
////// 触发(x,y)点的事件 //////
|
////// 触发(x,y)点的事件 //////
|
||||||
events.prototype.trigger = function (x, y, callback) {
|
events.prototype.trigger = function (x, y, callback) {
|
||||||
// see src/plugin/game/loopMap.js
|
var _executeCallback = function () {
|
||||||
|
// 因为trigger之后还有可能触发其他同步脚本(比如阻激夹域检测)
|
||||||
|
// 所以这里强制callback被异步触发
|
||||||
|
if (callback) {
|
||||||
|
setTimeout(callback, 1); // +1是为了录像检测系统
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if (core.status.gameOver) return _executeCallback();
|
||||||
|
if (core.status.event.id == 'action') {
|
||||||
|
core.insertAction(
|
||||||
|
{
|
||||||
|
type: 'function',
|
||||||
|
function:
|
||||||
|
'function () { core.events._trigger_inAction(' +
|
||||||
|
x +
|
||||||
|
',' +
|
||||||
|
y +
|
||||||
|
'); }',
|
||||||
|
async: true
|
||||||
|
},
|
||||||
|
void 0,
|
||||||
|
void 0,
|
||||||
|
void 0,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
return _executeCallback();
|
||||||
|
}
|
||||||
|
if (core.status.event.id) return _executeCallback();
|
||||||
|
|
||||||
|
let block = core.getBlock(x, y);
|
||||||
|
|
||||||
|
if (block == null) return _executeCallback();
|
||||||
|
|
||||||
|
// 执行该点的脚本
|
||||||
|
if (block.event.script) {
|
||||||
|
core.clearRouteFolding();
|
||||||
|
try {
|
||||||
|
eval(block.event.script);
|
||||||
|
} catch (ee) {
|
||||||
|
console.error(ee);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 碰触事件
|
||||||
|
if (block.event.event) {
|
||||||
|
core.clearRouteFolding();
|
||||||
|
core.insertAction(block.event.event, block.x, block.y);
|
||||||
|
// 不再执行该点的系统事件
|
||||||
|
return _executeCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block.event.trigger && block.event.trigger !== 'null') {
|
||||||
|
var noPass = block.event.noPass,
|
||||||
|
trigger = block.event.trigger;
|
||||||
|
if (noPass) core.clearAutomaticRouteNode(x, y);
|
||||||
|
|
||||||
|
// 转换楼层能否穿透
|
||||||
|
if (
|
||||||
|
trigger == 'changeFloor' &&
|
||||||
|
!noPass &&
|
||||||
|
this._trigger_ignoreChangeFloor(block) &&
|
||||||
|
!loop
|
||||||
|
)
|
||||||
|
return _executeCallback();
|
||||||
|
// @ts-ignore
|
||||||
|
core.status.automaticRoute.moveDirectly = false;
|
||||||
|
this.doSystemEvent(trigger, block);
|
||||||
|
}
|
||||||
|
return _executeCallback();
|
||||||
};
|
};
|
||||||
|
|
||||||
events.prototype._trigger_inAction = function (x, y) {
|
events.prototype._trigger_inAction = function (x, y) {
|
||||||
@ -687,7 +756,16 @@ events.prototype._getNextItem = function (direction, noRoute) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
events.prototype._sys_changeFloor = function (data, callback) {
|
events.prototype._sys_changeFloor = function (data, callback) {
|
||||||
// see src/plugin/game/loopMap.js
|
data = data.event.data;
|
||||||
|
let heroLoc = {};
|
||||||
|
if (data.loc) heroLoc = { x: data.loc[0], y: data.loc[1] };
|
||||||
|
if (data.direction) heroLoc.direction = data.direction;
|
||||||
|
// @ts-ignore
|
||||||
|
if (core.status.event.id != 'action') core.status.event.id = null;
|
||||||
|
core.changeFloor(data.floorId, data.stair, heroLoc, data.time, function () {
|
||||||
|
core.replay();
|
||||||
|
if (callback) callback();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
////// 楼层切换 //////
|
////// 楼层切换 //////
|
||||||
|
@ -715,8 +715,59 @@ maps.prototype.getMapBlocksObj = function (floorId, noCache) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
////// 将背景前景层变成二维数组的形式 //////
|
////// 将背景前景层变成二维数组的形式 //////
|
||||||
|
|
||||||
maps.prototype._getBgFgMapArray = function (name, floorId, noCache) {
|
maps.prototype._getBgFgMapArray = function (name, floorId, noCache) {
|
||||||
// see src/plugin/game/loopMap.js
|
floorId = floorId || core.status.floorId;
|
||||||
|
if (!floorId) return [];
|
||||||
|
var width = core.floors[floorId].width;
|
||||||
|
var height = core.floors[floorId].height;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
if (!noCache && core.status[name + 'maps'][floorId])
|
||||||
|
// @ts-ignore
|
||||||
|
return core.status[name + 'maps'][floorId];
|
||||||
|
|
||||||
|
var arr =
|
||||||
|
main.mode == 'editor' &&
|
||||||
|
// @ts-ignore
|
||||||
|
!(window.editor && editor.uievent && editor.uievent.isOpen)
|
||||||
|
? // @ts-ignore
|
||||||
|
core.cloneArray(editor[name + 'map'])
|
||||||
|
: null;
|
||||||
|
if (arr == null)
|
||||||
|
// @ts-ignore
|
||||||
|
arr = core.cloneArray(core.floors[floorId][name + 'map'] || []);
|
||||||
|
|
||||||
|
for (var y = 0; y < height; ++y) {
|
||||||
|
if (arr[y] == null) arr[y] = Array(width).fill(0);
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
(core.getFlag('__' + name + 'v__', {})[floorId] || []).forEach(
|
||||||
|
// @ts-ignore
|
||||||
|
function (one) {
|
||||||
|
arr[one[1]][one[0]] = one[2] || 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
// @ts-ignore
|
||||||
|
(core.getFlag('__' + name + 'd__', {})[floorId] || []).forEach(
|
||||||
|
// @ts-ignore
|
||||||
|
function (one) {
|
||||||
|
arr[one[1]][one[0]] = 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (main.mode == 'editor') {
|
||||||
|
for (var x = 0; x < width; x++) {
|
||||||
|
for (var y = 0; y < height; y++) {
|
||||||
|
// @ts-ignore
|
||||||
|
arr[y][x] = arr[y][x].idnum || arr[y][x] || 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
if (core.status[name + 'maps'])
|
||||||
|
// @ts-ignore
|
||||||
|
core.status[name + 'maps'][floorId] = arr;
|
||||||
|
return arr;
|
||||||
};
|
};
|
||||||
|
|
||||||
maps.prototype.getBgMapArray = function (floorId) {
|
maps.prototype.getBgMapArray = function (floorId) {
|
||||||
|
@ -120,8 +120,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
|||||||
// 正在切换楼层过程中执行的操作;此函数的执行时间是“屏幕完全变黑“的那一刻
|
// 正在切换楼层过程中执行的操作;此函数的执行时间是“屏幕完全变黑“的那一刻
|
||||||
// floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置
|
// floorId为要切换到的楼层ID;heroLoc表示勇士切换到的位置
|
||||||
|
|
||||||
const { checkLoopMap } = Mota.Plugin.require('loopMap_g');
|
|
||||||
|
|
||||||
// ---------- 此时还没有进行切换,当前floorId还是原来的 ---------- //
|
// ---------- 此时还没有进行切换,当前floorId还是原来的 ---------- //
|
||||||
var currentId = core.status.floorId || null; // 获得当前的floorId,可能为null
|
var currentId = core.status.floorId || null; // 获得当前的floorId,可能为null
|
||||||
var fromLoad = core.hasFlag('__fromLoad__'); // 是否是读档造成的切换
|
var fromLoad = core.hasFlag('__fromLoad__'); // 是否是读档造成的切换
|
||||||
@ -178,7 +176,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
|||||||
if (weather) core.setWeather(weather[0], weather[1]);
|
if (weather) core.setWeather(weather[0], weather[1]);
|
||||||
else core.setWeather();
|
else core.setWeather();
|
||||||
|
|
||||||
checkLoopMap();
|
|
||||||
core.updateDamage();
|
core.updateDamage();
|
||||||
|
|
||||||
// ...可以新增一些其他内容,比如创建个画布在右上角显示什么内容等等
|
// ...可以新增一些其他内容,比如创建个画布在右上角显示什么内容等等
|
||||||
@ -385,8 +382,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
|||||||
// 2, 将楼层属性中的cannotMoveDirectly这个开关勾上,即禁止在该层楼使用瞬移。
|
// 2, 将楼层属性中的cannotMoveDirectly这个开关勾上,即禁止在该层楼使用瞬移。
|
||||||
// 3. 将flag:cannotMoveDirectly置为true,即可使用flag控制在某段剧情范围内禁止瞬移。
|
// 3. 将flag:cannotMoveDirectly置为true,即可使用flag控制在某段剧情范围内禁止瞬移。
|
||||||
|
|
||||||
const { checkLoopMap } = Mota.Plugin.require('loopMap_g');
|
|
||||||
|
|
||||||
// 增加步数
|
// 增加步数
|
||||||
core.status.hero.steps++;
|
core.status.hero.steps++;
|
||||||
// 更新跟随者状态,并绘制
|
// 更新跟随者状态,并绘制
|
||||||
@ -433,8 +428,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkLoopMap();
|
|
||||||
|
|
||||||
// 如需强行终止行走可以在这里条件判定:
|
// 如需强行终止行走可以在这里条件判定:
|
||||||
// core.stopAutomaticRoute();
|
// core.stopAutomaticRoute();
|
||||||
Mota.require('var', 'hook').emit(
|
Mota.require('var', 'hook').emit(
|
||||||
|
@ -109,6 +109,12 @@ interface IRenderTickerSupport {
|
|||||||
* @returns 是否删除成功,比如对应ticker不存在,就是删除失败
|
* @returns 是否删除成功,比如对应ticker不存在,就是删除失败
|
||||||
*/
|
*/
|
||||||
removeTicker(id: number, callEnd?: boolean): boolean;
|
removeTicker(id: number, callEnd?: boolean): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否包含一个委托函数
|
||||||
|
* @param id 函数id
|
||||||
|
*/
|
||||||
|
hasTicker(id: number): boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ERenderItemEvent {
|
export interface ERenderItemEvent {
|
||||||
@ -373,9 +379,14 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
|||||||
RenderItem.ticker.remove(delegation.fn);
|
RenderItem.ticker.remove(delegation.fn);
|
||||||
window.clearTimeout(delegation.timeout);
|
window.clearTimeout(delegation.timeout);
|
||||||
if (callEnd) delegation.endFn?.();
|
if (callEnd) delegation.endFn?.();
|
||||||
|
RenderItem.tickerMap.delete(id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hasTicker(id: number): boolean {
|
||||||
|
return RenderItem.tickerMap.has(id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 隐藏这个元素
|
* 隐藏这个元素
|
||||||
*/
|
*/
|
||||||
|
@ -197,9 +197,9 @@ export class HeroRenderer
|
|||||||
* 勇士移动定时器
|
* 勇士移动定时器
|
||||||
*/
|
*/
|
||||||
private moveTick(time: number) {
|
private moveTick(time: number) {
|
||||||
if (!this.moving) return;
|
|
||||||
if (!this.renderable) return;
|
if (!this.renderable) return;
|
||||||
|
|
||||||
|
if (this.moving) {
|
||||||
const progress = (time - this.lastStepTime) / this.speed;
|
const progress = (time - this.lastStepTime) / this.speed;
|
||||||
|
|
||||||
const { x: dx, y: dy } = this.stepDelta;
|
const { x: dx, y: dy } = this.stepDelta;
|
||||||
@ -214,9 +214,10 @@ export class HeroRenderer
|
|||||||
this.renderable.x = rx;
|
this.renderable.x = rx;
|
||||||
this.renderable.y = ry;
|
this.renderable.y = ry;
|
||||||
}
|
}
|
||||||
this.emit('moveTick', this.renderable.x, this.renderable.y);
|
|
||||||
this.layer.update(this.layer);
|
this.layer.update(this.layer);
|
||||||
}
|
}
|
||||||
|
this.emit('moveTick', this.renderable.x, this.renderable.y);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 进行下一步的移动准备,设置移动信息
|
* 进行下一步的移动准备,设置移动信息
|
||||||
|
@ -34,7 +34,8 @@ Mota.register('var', 'loading', loading);
|
|||||||
// ----- 模块注册
|
// ----- 模块注册
|
||||||
Mota.register('module', 'Mechanism', {
|
Mota.register('module', 'Mechanism', {
|
||||||
BluePalace: miscMechanism.BluePalace,
|
BluePalace: miscMechanism.BluePalace,
|
||||||
NightSpecial: miscMechanism.NightSpecial
|
NightSpecial: miscMechanism.NightSpecial,
|
||||||
|
MiscData: miscMechanism.MiscData
|
||||||
});
|
});
|
||||||
Mota.register('module', 'State', {
|
Mota.register('module', 'State', {
|
||||||
ItemState,
|
ItemState,
|
||||||
|
@ -2,6 +2,14 @@ import { backDir, has } from '@/plugin/game/utils';
|
|||||||
import { loading } from '../game';
|
import { loading } from '../game';
|
||||||
import type { LayerDoorAnimate } from '@/core/render/preset/floor';
|
import type { LayerDoorAnimate } from '@/core/render/preset/floor';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 一些零散机制的数据
|
||||||
|
*/
|
||||||
|
export namespace MiscData {
|
||||||
|
/** 循环式地图 */
|
||||||
|
export const loopMaps: Set<FloorIds> = new Set(['tower6']);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 永夜/极昼
|
* 永夜/极昼
|
||||||
*/
|
*/
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import EventEmitter from 'eventemitter3';
|
import EventEmitter from 'eventemitter3';
|
||||||
import { backDir, toDir } from './utils';
|
import { backDir, checkCanMoveExtended, toDir } from './utils';
|
||||||
import { loading } from '../game';
|
import { loading } from '../game';
|
||||||
import type { RenderAdapter } from '@/core/render/adapter';
|
import type { RenderAdapter } from '@/core/render/adapter';
|
||||||
import type { HeroRenderer } from '@/core/render/preset/hero';
|
import type { HeroRenderer } from '@/core/render/preset/hero';
|
||||||
@ -8,10 +8,11 @@ import type { HeroKeyMover } from '@/core/main/action/move';
|
|||||||
import type {
|
import type {
|
||||||
FloorLayer,
|
FloorLayer,
|
||||||
Layer,
|
Layer,
|
||||||
|
LayerGroup,
|
||||||
LayerMovingRenderable
|
LayerMovingRenderable
|
||||||
} from '@/core/render/preset/layer';
|
} from '@/core/render/preset/layer';
|
||||||
import type { LayerFloorBinder } from '@/core/render/preset/floor';
|
import type { LayerFloorBinder } from '@/core/render/preset/floor';
|
||||||
import { BluePalace } from '../mechanism/misc';
|
import { BluePalace, MiscData } from '../mechanism/misc';
|
||||||
|
|
||||||
interface MoveStepDir {
|
interface MoveStepDir {
|
||||||
type: 'dir';
|
type: 'dir';
|
||||||
@ -425,7 +426,9 @@ const enum HeroMoveCode {
|
|||||||
/** 不能移动,同时当前格有CannotOut,或目标格有CannotIn,不会触发前面一格的触发器 */
|
/** 不能移动,同时当前格有CannotOut,或目标格有CannotIn,不会触发前面一格的触发器 */
|
||||||
CannotMove,
|
CannotMove,
|
||||||
/** 进入传送门 */
|
/** 进入传送门 */
|
||||||
Portal
|
Portal,
|
||||||
|
/** 循环式地图 */
|
||||||
|
Loop
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HeroMover extends ObjectMoverBase {
|
export class HeroMover extends ObjectMoverBase {
|
||||||
@ -478,8 +481,10 @@ export class HeroMover extends ObjectMoverBase {
|
|||||||
protected async onMoveStart(controller: IMoveController): Promise<void> {
|
protected async onMoveStart(controller: IMoveController): Promise<void> {
|
||||||
this.beforeMoveSpeed = this.moveSpeed;
|
this.beforeMoveSpeed = this.moveSpeed;
|
||||||
const adapter = HeroMover.adapter;
|
const adapter = HeroMover.adapter;
|
||||||
if (!adapter) return;
|
const viewport = HeroMover.viewport;
|
||||||
|
if (!adapter || !viewport) return;
|
||||||
await adapter.all('readyMove');
|
await adapter.all('readyMove');
|
||||||
|
viewport.sync('startMove');
|
||||||
adapter.sync('startAnimate');
|
adapter.sync('startAnimate');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -487,8 +492,10 @@ export class HeroMover extends ObjectMoverBase {
|
|||||||
this.moveSpeed = this.beforeMoveSpeed;
|
this.moveSpeed = this.beforeMoveSpeed;
|
||||||
this.onSetMoveSpeed(this.moveSpeed, controller);
|
this.onSetMoveSpeed(this.moveSpeed, controller);
|
||||||
const adapter = HeroMover.adapter;
|
const adapter = HeroMover.adapter;
|
||||||
if (!adapter) return;
|
const viewport = HeroMover.viewport;
|
||||||
|
if (!adapter || !viewport) return;
|
||||||
await adapter.all('endMove');
|
await adapter.all('endMove');
|
||||||
|
viewport.sync('endMove');
|
||||||
adapter.sync('endAnimate');
|
adapter.sync('endAnimate');
|
||||||
core.clearContinueAutomaticRoute();
|
core.clearContinueAutomaticRoute();
|
||||||
core.stopAutomaticRoute();
|
core.stopAutomaticRoute();
|
||||||
@ -536,6 +543,25 @@ export class HeroMover extends ObjectMoverBase {
|
|||||||
if (!canMove) return HeroMoveCode.CannotMove;
|
if (!canMove) return HeroMoveCode.CannotMove;
|
||||||
else return HeroMoveCode.Hit;
|
else return HeroMoveCode.Hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const floorId = core.status.floorId;
|
||||||
|
if (MiscData.loopMaps.has(core.status.floorId)) {
|
||||||
|
const floor = core.status.maps[floorId];
|
||||||
|
const width = floor.width;
|
||||||
|
if (x === 0 && dir === 'left') {
|
||||||
|
await Promise.all([
|
||||||
|
this.renderHeroLoop(),
|
||||||
|
this.moveAnimate(nx, ny, showDir, dir)
|
||||||
|
]);
|
||||||
|
return HeroMoveCode.Loop;
|
||||||
|
} else if (x === width - 1 && dir === 'right') {
|
||||||
|
await Promise.all([
|
||||||
|
this.renderHeroLoop(),
|
||||||
|
this.moveAnimate(nx, ny, showDir, dir)
|
||||||
|
]);
|
||||||
|
return HeroMoveCode.Loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 可以移动,显示移动动画
|
// 可以移动,显示移动动画
|
||||||
@ -572,13 +598,21 @@ export class HeroMover extends ObjectMoverBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 本次移动正常完成
|
// 本次移动正常完成
|
||||||
if (code === HeroMoveCode.Step || code === HeroMoveCode.Portal) {
|
if (
|
||||||
|
code === HeroMoveCode.Step ||
|
||||||
|
code === HeroMoveCode.Portal ||
|
||||||
|
code === HeroMoveCode.Loop
|
||||||
|
) {
|
||||||
if (code === HeroMoveCode.Portal) {
|
if (code === HeroMoveCode.Portal) {
|
||||||
const data = this.portalData;
|
const data = this.portalData;
|
||||||
if (!data) return;
|
if (!data) return;
|
||||||
core.setHeroLoc('x', data.x);
|
core.setHeroLoc('x', data.x);
|
||||||
core.setHeroLoc('y', data.y);
|
core.setHeroLoc('y', data.y);
|
||||||
core.setHeroLoc('direction', data.dir);
|
core.setHeroLoc('direction', data.dir);
|
||||||
|
} else if (code === HeroMoveCode.Loop) {
|
||||||
|
const map = core.status.thisMap;
|
||||||
|
if (x === 0) core.setHeroLoc('x', map.width - 1);
|
||||||
|
else core.setHeroLoc('x', 0);
|
||||||
} else {
|
} else {
|
||||||
core.setHeroLoc('x', nx, true);
|
core.setHeroLoc('x', nx, true);
|
||||||
core.setHeroLoc('y', ny, true);
|
core.setHeroLoc('y', ny, true);
|
||||||
@ -644,6 +678,21 @@ export class HeroMover extends ObjectMoverBase {
|
|||||||
* @param dir 移动方向
|
* @param dir 移动方向
|
||||||
*/
|
*/
|
||||||
private checkCanMove(x: number, y: number, dir: Dir): CanMoveStatus {
|
private checkCanMove(x: number, y: number, dir: Dir): CanMoveStatus {
|
||||||
|
// 如果是循环式地图
|
||||||
|
const floorId = core.status.floorId;
|
||||||
|
if (MiscData.loopMaps.has(floorId)) {
|
||||||
|
const floor = core.status.maps[floorId];
|
||||||
|
const width = floor.width;
|
||||||
|
if (x === 0 && dir === 'left') {
|
||||||
|
const noPass = core.noPass(width - 1, y);
|
||||||
|
const move = checkCanMoveExtended(0, y, width - 1, y, 'left');
|
||||||
|
return { noPass, canMove: move };
|
||||||
|
} else if (x === width - 1 && dir === 'right') {
|
||||||
|
const noPass = core.noPass(0, y);
|
||||||
|
const move = checkCanMoveExtended(width - 1, y, 0, y, 'right');
|
||||||
|
return { noPass, canMove: move };
|
||||||
|
}
|
||||||
|
}
|
||||||
const { x: nx, y: ny } = this.nextLoc(x, y, dir);
|
const { x: nx, y: ny } = this.nextLoc(x, y, dir);
|
||||||
const noPass = core.noPass(nx, ny);
|
const noPass = core.noPass(nx, ny);
|
||||||
const canMove = core.canMoveHero(x, y, dir);
|
const canMove = core.canMoveHero(x, y, dir);
|
||||||
@ -777,6 +826,64 @@ export class HeroMover extends ObjectMoverBase {
|
|||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private renderHeroLoop() {
|
||||||
|
const adapter = HeroMover.adapter;
|
||||||
|
const viewport = HeroMover.viewport;
|
||||||
|
if (!adapter || !viewport) return;
|
||||||
|
const MotaRenderer = Mota.require('module', 'Render').MotaRenderer;
|
||||||
|
const render = MotaRenderer.get('render-main');
|
||||||
|
const group = render?.getElementById('layer-loop') as LayerGroup;
|
||||||
|
const layer = group?.getLayer('event');
|
||||||
|
const mainGroup = render?.getElementById('layer-main') as LayerGroup;
|
||||||
|
const mainLayer = mainGroup?.getLayer('event');
|
||||||
|
const hero = mainLayer?.getExtends('floor-hero') as HeroRenderer;
|
||||||
|
const renderable = hero?.renderable;
|
||||||
|
if (!layer || !hero || !renderable) return;
|
||||||
|
const { x, y } = core.status.hero.loc;
|
||||||
|
const width = core.status.thisMap.width;
|
||||||
|
const loopHero = { ...renderable };
|
||||||
|
layer.moving.add(loopHero);
|
||||||
|
|
||||||
|
let target: number;
|
||||||
|
let from: number;
|
||||||
|
if (x === 0) {
|
||||||
|
from = width;
|
||||||
|
target = width - 1;
|
||||||
|
} else {
|
||||||
|
from = -1;
|
||||||
|
target = 0;
|
||||||
|
}
|
||||||
|
const delta = target - from;
|
||||||
|
loopHero.x = from;
|
||||||
|
|
||||||
|
layer.requestUpdateMoving();
|
||||||
|
|
||||||
|
const startTime = Date.now();
|
||||||
|
return new Promise<void>(res => {
|
||||||
|
layer.delegateTicker(
|
||||||
|
() => {
|
||||||
|
const progress = (Date.now() - startTime) / this.moveSpeed;
|
||||||
|
const dx = delta * progress;
|
||||||
|
loopHero.x = dx + from;
|
||||||
|
layer.update(layer);
|
||||||
|
console.log(
|
||||||
|
loopHero.x,
|
||||||
|
loopHero.y,
|
||||||
|
renderable.x,
|
||||||
|
renderable.y
|
||||||
|
);
|
||||||
|
},
|
||||||
|
this.moveSpeed,
|
||||||
|
() => {
|
||||||
|
layer.moving.delete(loopHero);
|
||||||
|
layer.requestUpdateMoving();
|
||||||
|
viewport.all('setPosition', x === 0 ? width - 1 : 0, y);
|
||||||
|
res();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HeroMoveCollection {
|
interface HeroMoveCollection {
|
||||||
|
@ -33,3 +33,75 @@ export function backDir(dir: Dir2): Dir2;
|
|||||||
export function backDir(dir: Dir2): Dir2 {
|
export function backDir(dir: Dir2): Dir2 {
|
||||||
return backDirMap[dir];
|
return backDirMap[dir];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function locInMap(x: number, y: number, floorId: FloorIds) {
|
||||||
|
const { width, height } = core.status.maps[floorId];
|
||||||
|
return x >= 0 && y >= 0 && x < width && y < height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 广义检查能否移动,指定两个点以及行走方向,返回能否执行上述移动。
|
||||||
|
* 可以传入地图之外的点,视为可以随意移动。仅检查 cannotIn 和 cannotOut,不检查 noPass
|
||||||
|
* @param fx 出点横坐标
|
||||||
|
* @param fy 出点纵坐标
|
||||||
|
* @param tx 入点横坐标
|
||||||
|
* @param ty 入点纵坐标
|
||||||
|
* @param dir 行走方向
|
||||||
|
* @param fromFloorId 出点楼层id
|
||||||
|
* @param toFloorId 入点楼层id
|
||||||
|
*/
|
||||||
|
export function checkCanMoveExtended(
|
||||||
|
fx: number,
|
||||||
|
fy: number,
|
||||||
|
tx: number,
|
||||||
|
ty: number,
|
||||||
|
dir: Dir,
|
||||||
|
fromFloorId: FloorIds = core.status.floorId,
|
||||||
|
toFloorId: FloorIds = core.status.floorId
|
||||||
|
) {
|
||||||
|
const fromInMap = locInMap(fx, fy, fromFloorId);
|
||||||
|
const toInMap = locInMap(tx, ty, toFloorId);
|
||||||
|
const map = maps_90f36752_8815_4be8_b32b_d7fad1d0542e;
|
||||||
|
|
||||||
|
if (fromInMap) {
|
||||||
|
const cannotMove = core.floors[fromFloorId].cannotMove;
|
||||||
|
const fromIndex: LocString = `${fx},${fy}`;
|
||||||
|
// 检查当前点是否有不可出
|
||||||
|
if (cannotMove[fromIndex]?.includes(dir)) return false;
|
||||||
|
const blocks = getBlockForLoc(fx, fy, fromFloorId);
|
||||||
|
const can = blocks.some(v => {
|
||||||
|
if (v === 0) return false;
|
||||||
|
const out = map[v as Exclude<AllNumbers, 0>]?.cannotOut;
|
||||||
|
return out?.includes(dir);
|
||||||
|
});
|
||||||
|
if (can) return false;
|
||||||
|
}
|
||||||
|
if (toInMap) {
|
||||||
|
const cannotMoveIn = core.floors[toFloorId].cannotMoveIn;
|
||||||
|
const toIndex: LocString = `${tx},${ty}`;
|
||||||
|
const back = backDir(dir);
|
||||||
|
// 检查目标点是否有不可入
|
||||||
|
if (cannotMoveIn[toIndex]?.includes(back)) return false;
|
||||||
|
const blocks = getBlockForLoc(tx, ty, toFloorId);
|
||||||
|
const can = blocks.some(v => {
|
||||||
|
if (v === 0) return false;
|
||||||
|
const out = map[v as Exclude<AllNumbers, 0>]?.cannotIn;
|
||||||
|
return out?.includes(back);
|
||||||
|
});
|
||||||
|
if (can) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBlockForLoc(x: number, y: number, floorId: FloorIds) {
|
||||||
|
const map = core.status.maps[floorId];
|
||||||
|
const floor = core.floors[floorId];
|
||||||
|
return [
|
||||||
|
floor.bgmap[y][x],
|
||||||
|
floor.bg2map[y][x],
|
||||||
|
map.map[y][x],
|
||||||
|
floor.bgmap[y][x],
|
||||||
|
floor.bg2map[y][x]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
@ -106,13 +106,13 @@ interface ModuleInterface {
|
|||||||
Mechanism: {
|
Mechanism: {
|
||||||
BluePalace: typeof misc.BluePalace;
|
BluePalace: typeof misc.BluePalace;
|
||||||
NightSpecial: typeof misc.NightSpecial;
|
NightSpecial: typeof misc.NightSpecial;
|
||||||
|
MiscData: typeof misc.MiscData;
|
||||||
};
|
};
|
||||||
Effect: {
|
Effect: {
|
||||||
Portal: typeof portal;
|
Portal: typeof portal;
|
||||||
};
|
};
|
||||||
Render: {
|
Render: {
|
||||||
texture: typeof texture;
|
texture: typeof texture;
|
||||||
main: MotaRenderer;
|
|
||||||
MotaRenderer: typeof MotaRenderer;
|
MotaRenderer: typeof MotaRenderer;
|
||||||
Container: typeof Container;
|
Container: typeof Container;
|
||||||
Sprite: typeof Sprite;
|
Sprite: typeof Sprite;
|
||||||
@ -161,7 +161,6 @@ interface PluginInterface {
|
|||||||
frag_r: typeof import('../plugin/fx/frag');
|
frag_r: typeof import('../plugin/fx/frag');
|
||||||
// 游戏进程定义的插件
|
// 游戏进程定义的插件
|
||||||
utils_g: typeof import('../plugin/game/utils');
|
utils_g: typeof import('../plugin/game/utils');
|
||||||
loopMap_g: typeof import('../plugin/game/loopMap');
|
|
||||||
shop_g: typeof import('../plugin/game/shop');
|
shop_g: typeof import('../plugin/game/shop');
|
||||||
replay_g: typeof import('../plugin/game/replay');
|
replay_g: typeof import('../plugin/game/replay');
|
||||||
skillTree_g: typeof import('../plugin/game/skillTree');
|
skillTree_g: typeof import('../plugin/game/skillTree');
|
||||||
|
@ -3,7 +3,6 @@ import * as fiveLayer from './fiveLayer';
|
|||||||
import * as itemDetail from './fx/itemDetail';
|
import * as itemDetail from './fx/itemDetail';
|
||||||
import * as replay from './replay';
|
import * as replay from './replay';
|
||||||
import * as ui from './ui';
|
import * as ui from './ui';
|
||||||
import * as loopMap from './loopMap';
|
|
||||||
import * as removeMap from './removeMap';
|
import * as removeMap from './removeMap';
|
||||||
import * as shop from './shop';
|
import * as shop from './shop';
|
||||||
import * as skill from './skill';
|
import * as skill from './skill';
|
||||||
@ -17,7 +16,6 @@ import * as fallback from './fallback';
|
|||||||
import './hook';
|
import './hook';
|
||||||
|
|
||||||
Mota.Plugin.register('utils_g', utils);
|
Mota.Plugin.register('utils_g', utils);
|
||||||
Mota.Plugin.register('loopMap_g', loopMap, loopMap.init);
|
|
||||||
Mota.Plugin.register('shop_g', shop);
|
Mota.Plugin.register('shop_g', shop);
|
||||||
Mota.Plugin.register('replay_g', replay, replay.init);
|
Mota.Plugin.register('replay_g', replay, replay.init);
|
||||||
Mota.Plugin.register('skillTree_g', skillTree);
|
Mota.Plugin.register('skillTree_g', skillTree);
|
||||||
|
@ -1,256 +0,0 @@
|
|||||||
import { slide } from './utils';
|
|
||||||
|
|
||||||
const list = ['tower6'];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置循环地图的偏移量
|
|
||||||
* @param offset 横向偏移量
|
|
||||||
*/
|
|
||||||
function setLoopMap(offset: number, floorId: FloorIds) {
|
|
||||||
const floor = core.status.maps[floorId];
|
|
||||||
if (offset < 9) {
|
|
||||||
moveMap(floor.width - 17, floorId);
|
|
||||||
}
|
|
||||||
if (offset > floor.width - 9) {
|
|
||||||
moveMap(17 - floor.width, floorId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 当勇士移动时自动设置循环地图
|
|
||||||
*/
|
|
||||||
function autoSetLoopMap(floorId: FloorIds) {
|
|
||||||
setLoopMap(core.status.hero.loc.x, floorId);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function checkLoopMap() {
|
|
||||||
if (isLoopMap(core.status.floorId)) {
|
|
||||||
autoSetLoopMap(core.status.floorId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 移动地图
|
|
||||||
*/
|
|
||||||
function moveMap(delta: number, floorId: FloorIds) {
|
|
||||||
core.extractBlocks(floorId);
|
|
||||||
const floor = core.status.maps[floorId];
|
|
||||||
core.setHeroLoc('x', core.status.hero.loc.x + delta);
|
|
||||||
flags[`loop_${floorId}`] += delta;
|
|
||||||
flags[`loop_${floorId}`] %= floor.width;
|
|
||||||
const origin = floor.blocks.slice();
|
|
||||||
for (let i = 0; i < origin.length; i++) {
|
|
||||||
core.removeBlockByIndex(0, floorId);
|
|
||||||
core.removeGlobalAnimate(origin[i].x, origin[i].y);
|
|
||||||
}
|
|
||||||
origin.forEach(v => {
|
|
||||||
let to = v.x + delta;
|
|
||||||
if (to >= floor.width) to -= floor.width;
|
|
||||||
if (to < 0) to += floor.width;
|
|
||||||
core.setBlock(v.id, to, v.y, floorId, true);
|
|
||||||
core.setMapBlockDisabled(floorId, to, v.y, false);
|
|
||||||
});
|
|
||||||
core.drawMap();
|
|
||||||
core.drawHero();
|
|
||||||
}
|
|
||||||
|
|
||||||
function isLoopMap(floorId: FloorIds) {
|
|
||||||
return list.includes(floorId);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function init() {
|
|
||||||
events.prototype._sys_changeFloor = function (
|
|
||||||
data: any,
|
|
||||||
callback: () => void
|
|
||||||
) {
|
|
||||||
data = data.event.data;
|
|
||||||
let heroLoc: Partial<DiredLoc> = {};
|
|
||||||
if (isLoopMap(data.floorId)) {
|
|
||||||
const floor = core.status.maps[data.floorId as FloorIds] as Floor;
|
|
||||||
flags[`loop_${data.floorId}`] ??= 0;
|
|
||||||
let tx = data.loc[0] + flags[`loop_${data.floorId}`];
|
|
||||||
tx %= floor.width;
|
|
||||||
if (tx < 0) tx += floor.width;
|
|
||||||
heroLoc = {
|
|
||||||
x: tx,
|
|
||||||
y: data.loc[1]
|
|
||||||
};
|
|
||||||
} else if (data.loc) heroLoc = { x: data.loc[0], y: data.loc[1] };
|
|
||||||
if (data.direction) heroLoc.direction = data.direction;
|
|
||||||
// @ts-ignore
|
|
||||||
if (core.status.event.id != 'action') core.status.event.id = null;
|
|
||||||
core.changeFloor(
|
|
||||||
data.floorId,
|
|
||||||
data.stair,
|
|
||||||
heroLoc,
|
|
||||||
data.time,
|
|
||||||
function () {
|
|
||||||
core.replay();
|
|
||||||
if (callback) callback();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
events.prototype.trigger = function (
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
callback: () => void
|
|
||||||
) {
|
|
||||||
var _executeCallback = function () {
|
|
||||||
// 因为trigger之后还有可能触发其他同步脚本(比如阻激夹域检测)
|
|
||||||
// 所以这里强制callback被异步触发
|
|
||||||
if (callback) {
|
|
||||||
setTimeout(callback, 1); // +1是为了录像检测系统
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if (core.status.gameOver) return _executeCallback();
|
|
||||||
if (core.status.event.id == 'action') {
|
|
||||||
core.insertAction(
|
|
||||||
{
|
|
||||||
type: 'function',
|
|
||||||
function:
|
|
||||||
'function () { core.events._trigger_inAction(' +
|
|
||||||
x +
|
|
||||||
',' +
|
|
||||||
y +
|
|
||||||
'); }',
|
|
||||||
async: true
|
|
||||||
},
|
|
||||||
void 0,
|
|
||||||
void 0,
|
|
||||||
void 0,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
return _executeCallback();
|
|
||||||
}
|
|
||||||
if (core.status.event.id) return _executeCallback();
|
|
||||||
|
|
||||||
let block = core.getBlock(x, y);
|
|
||||||
const id = core.status.floorId;
|
|
||||||
const loop = isLoopMap(id);
|
|
||||||
if (loop && flags[`loop_${id}`] !== 0) {
|
|
||||||
if (block && block.event.trigger === 'changeFloor') {
|
|
||||||
delete block.event.trigger;
|
|
||||||
// @ts-ignore
|
|
||||||
core.maps._addInfo(block);
|
|
||||||
} else {
|
|
||||||
const floor = core.status.maps[id];
|
|
||||||
let tx = x - flags[`loop_${id}`];
|
|
||||||
tx %= floor.width;
|
|
||||||
if (tx < 0) tx += floor.width;
|
|
||||||
const c = core.floors[id].changeFloor[`${tx},${y}`];
|
|
||||||
if (c) {
|
|
||||||
const b: DeepPartial<Block> = { event: {}, x: tx, y };
|
|
||||||
b.event!.data = c;
|
|
||||||
b.event!.trigger = 'changeFloor';
|
|
||||||
block = b as Block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (block == null) return _executeCallback();
|
|
||||||
|
|
||||||
// 执行该点的脚本
|
|
||||||
if (block.event.script) {
|
|
||||||
core.clearRouteFolding();
|
|
||||||
try {
|
|
||||||
eval(block.event.script);
|
|
||||||
} catch (ee) {
|
|
||||||
console.error(ee);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 碰触事件
|
|
||||||
if (block.event.event) {
|
|
||||||
core.clearRouteFolding();
|
|
||||||
core.insertAction(block.event.event, block.x, block.y);
|
|
||||||
// 不再执行该点的系统事件
|
|
||||||
return _executeCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (block.event.trigger && block.event.trigger !== 'null') {
|
|
||||||
var noPass = block.event.noPass,
|
|
||||||
trigger = block.event.trigger;
|
|
||||||
if (noPass) core.clearAutomaticRouteNode(x, y);
|
|
||||||
|
|
||||||
// 转换楼层能否穿透
|
|
||||||
if (
|
|
||||||
trigger == 'changeFloor' &&
|
|
||||||
!noPass &&
|
|
||||||
this._trigger_ignoreChangeFloor(block) &&
|
|
||||||
!loop
|
|
||||||
)
|
|
||||||
return _executeCallback();
|
|
||||||
// @ts-ignore
|
|
||||||
core.status.automaticRoute.moveDirectly = false;
|
|
||||||
this.doSystemEvent(trigger, block);
|
|
||||||
}
|
|
||||||
return _executeCallback();
|
|
||||||
};
|
|
||||||
|
|
||||||
maps.prototype._getBgFgMapArray = function (
|
|
||||||
name: string,
|
|
||||||
floorId: FloorIds,
|
|
||||||
noCache: boolean = false
|
|
||||||
) {
|
|
||||||
floorId = floorId || core.status.floorId;
|
|
||||||
if (!floorId) return [];
|
|
||||||
var width = core.floors[floorId].width;
|
|
||||||
var height = core.floors[floorId].height;
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
if (!noCache && core.status[name + 'maps'][floorId])
|
|
||||||
// @ts-ignore
|
|
||||||
return core.status[name + 'maps'][floorId];
|
|
||||||
|
|
||||||
var arr: number[][] =
|
|
||||||
main.mode == 'editor' &&
|
|
||||||
// @ts-ignore
|
|
||||||
!(window.editor && editor.uievent && editor.uievent.isOpen)
|
|
||||||
? // @ts-ignore
|
|
||||||
core.cloneArray(editor[name + 'map'])
|
|
||||||
: null;
|
|
||||||
if (arr == null)
|
|
||||||
// @ts-ignore
|
|
||||||
arr = core.cloneArray(core.floors[floorId][name + 'map'] || []);
|
|
||||||
|
|
||||||
if (isLoopMap(floorId) && window.flags) {
|
|
||||||
flags[`loop_${floorId}`] ??= 0;
|
|
||||||
arr.forEach(v => {
|
|
||||||
slide(v, flags[`loop_${floorId}`] % width);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var y = 0; y < height; ++y) {
|
|
||||||
if (arr[y] == null) arr[y] = Array(width).fill(0);
|
|
||||||
}
|
|
||||||
// @ts-ignore
|
|
||||||
(core.getFlag('__' + name + 'v__', {})[floorId] || []).forEach(
|
|
||||||
// @ts-ignore
|
|
||||||
function (one) {
|
|
||||||
arr[one[1]][one[0]] = one[2] || 0;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
// @ts-ignore
|
|
||||||
(core.getFlag('__' + name + 'd__', {})[floorId] || []).forEach(
|
|
||||||
// @ts-ignore
|
|
||||||
function (one) {
|
|
||||||
arr[one[1]][one[0]] = 0;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (main.mode == 'editor') {
|
|
||||||
for (var x = 0; x < width; x++) {
|
|
||||||
for (var y = 0; y < height; y++) {
|
|
||||||
// @ts-ignore
|
|
||||||
arr[y][x] = arr[y][x].idnum || arr[y][x] || 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// @ts-ignore
|
|
||||||
if (core.status[name + 'maps'])
|
|
||||||
// @ts-ignore
|
|
||||||
core.status[name + 'maps'][floorId] = arr;
|
|
||||||
return arr;
|
|
||||||
};
|
|
||||||
}
|
|
@ -6,6 +6,7 @@ import * as frag from './fx/frag';
|
|||||||
import * as use from './use';
|
import * as use from './use';
|
||||||
import * as gameCanvas from './fx/gameCanvas';
|
import * as gameCanvas from './fx/gameCanvas';
|
||||||
import * as animateController from './animateController';
|
import * as animateController from './animateController';
|
||||||
|
import './loopMap';
|
||||||
|
|
||||||
Mota.Plugin.register('fly_r', fly);
|
Mota.Plugin.register('fly_r', fly);
|
||||||
Mota.Plugin.register('chase_r', chase);
|
Mota.Plugin.register('chase_r', chase);
|
||||||
|
104
src/plugin/loopMap.ts
Normal file
104
src/plugin/loopMap.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { Container } from '@/core/render/container';
|
||||||
|
import { FloorDamageExtends } from '@/core/render/preset/damage';
|
||||||
|
import { LayerGroupFloorBinder } from '@/core/render/preset/floor';
|
||||||
|
import { HeroRenderer } from '@/core/render/preset/hero';
|
||||||
|
import { FloorLayer, LayerGroup } from '@/core/render/preset/layer';
|
||||||
|
import { FloorViewport } from '@/core/render/preset/viewport';
|
||||||
|
import { MotaRenderer } from '@/core/render/render';
|
||||||
|
import { Transform } from '@/core/render/transform';
|
||||||
|
import { FloorItemDetail } from '@/plugin/fx/itemDetail';
|
||||||
|
|
||||||
|
const loopMaps = Mota.require('module', 'Mechanism').MiscData.loopMaps;
|
||||||
|
|
||||||
|
let loopLayer: LayerGroup;
|
||||||
|
let show: boolean = false;
|
||||||
|
/** 循环式地图中,更新视角的委托ticker */
|
||||||
|
let delegation: number = -1;
|
||||||
|
|
||||||
|
const hook = Mota.require('var', 'hook');
|
||||||
|
hook.on('changingFloor', (floorId, heroLoc) => {
|
||||||
|
enableLoopMapElement(floorId);
|
||||||
|
});
|
||||||
|
|
||||||
|
function createLayer() {
|
||||||
|
const group = new LayerGroup();
|
||||||
|
['bg', 'bg2', 'event', 'fg', 'fg2'].forEach(v => {
|
||||||
|
group.addLayer(v as FloorLayer);
|
||||||
|
});
|
||||||
|
|
||||||
|
const damage = new FloorDamageExtends();
|
||||||
|
const detail = new FloorItemDetail();
|
||||||
|
group.extends(damage);
|
||||||
|
group.extends(detail);
|
||||||
|
|
||||||
|
loopLayer = group;
|
||||||
|
group.setZIndex(20);
|
||||||
|
group.id = 'layer-loop';
|
||||||
|
}
|
||||||
|
|
||||||
|
function enableLoopMapElement(floorId: FloorIds) {
|
||||||
|
if (!loopMaps.has(floorId)) {
|
||||||
|
disableLoopMapElement();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!loopLayer) createLayer();
|
||||||
|
const render = MotaRenderer.get('render-main');
|
||||||
|
const draw = render?.getElementById('map-draw') as Container;
|
||||||
|
const group = render?.getElementById('layer-main') as LayerGroup;
|
||||||
|
if (!draw || !group) return;
|
||||||
|
const ex = loopLayer.getExtends('floor-binder') as LayerGroupFloorBinder;
|
||||||
|
const viewport = group.getExtends('viewport') as FloorViewport;
|
||||||
|
if (!ex || !viewport) return;
|
||||||
|
ex.bindFloor(floorId);
|
||||||
|
|
||||||
|
draw.appendChild(loopLayer);
|
||||||
|
show = true;
|
||||||
|
|
||||||
|
const floor = core.status.maps[floorId];
|
||||||
|
viewport.setAutoBound(false);
|
||||||
|
const transform = group.camera;
|
||||||
|
const width = floor.width;
|
||||||
|
const testPos = width * loopLayer.cellSize;
|
||||||
|
|
||||||
|
loopLayer.removeTicker(delegation);
|
||||||
|
delegation = loopLayer.delegateTicker(() => {
|
||||||
|
const [x1] = Transform.transformed(transform, 0, 0);
|
||||||
|
const camera = loopLayer.camera;
|
||||||
|
if (x1 > 0) {
|
||||||
|
// 这个是计算循环地图应该显示在哪
|
||||||
|
const [, y2] = Transform.transformed(transform, x1 - testPos, 0);
|
||||||
|
camera.reset();
|
||||||
|
camera.translate(core._PX_ - testPos, y2);
|
||||||
|
loopLayer.pos(transform.x - core._PX_, 0);
|
||||||
|
loopLayer.show();
|
||||||
|
loopLayer.update(loopLayer);
|
||||||
|
} else {
|
||||||
|
const [x2, y2] = Transform.transformed(transform, testPos, 0);
|
||||||
|
if (x2 < core._PX_) {
|
||||||
|
// 这个不用做其他运算,可以直接显示
|
||||||
|
camera.reset();
|
||||||
|
camera.translate(0, y2);
|
||||||
|
loopLayer.pos(x2, 0);
|
||||||
|
loopLayer.show();
|
||||||
|
loopLayer.update(loopLayer);
|
||||||
|
} else {
|
||||||
|
loopLayer.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function disableLoopMapElement() {
|
||||||
|
if (!show) return;
|
||||||
|
show = false;
|
||||||
|
loopLayer.remove();
|
||||||
|
|
||||||
|
const render = MotaRenderer.get('render-main');
|
||||||
|
const group = render?.getElementById('layer-main') as LayerGroup;
|
||||||
|
if (!group) return;
|
||||||
|
const viewport = group.getExtends('viewport') as FloorViewport;
|
||||||
|
if (!viewport) return;
|
||||||
|
|
||||||
|
viewport.setAutoBound(true);
|
||||||
|
loopLayer.removeTicker(delegation);
|
||||||
|
}
|
2
src/types/core.d.ts
vendored
2
src/types/core.d.ts
vendored
@ -1422,6 +1422,8 @@ interface MapDataOf<T extends keyof NumberToId> {
|
|||||||
faceIds?: Record<Dir, AllIds>;
|
faceIds?: Record<Dir, AllIds>;
|
||||||
animate?: number;
|
animate?: number;
|
||||||
autotileConnection?: (AllIds | AllNumbers)[];
|
autotileConnection?: (AllIds | AllNumbers)[];
|
||||||
|
cannotOut?: Dir[];
|
||||||
|
cannotIn?: Dir[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
10
src/types/map.d.ts
vendored
10
src/types/map.d.ts
vendored
@ -251,11 +251,21 @@ interface ResolvedFloor<T extends FloorIds = FloorIds> extends FloorBase<T> {
|
|||||||
*/
|
*/
|
||||||
bgmap: number[][];
|
bgmap: number[][];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 背景2层
|
||||||
|
*/
|
||||||
|
bg2map: number[][];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 前景层
|
* 前景层
|
||||||
*/
|
*/
|
||||||
fgmap: number[][];
|
fgmap: number[][];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 前景2层
|
||||||
|
*/
|
||||||
|
fg2map: number[][];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 楼层切换
|
* 楼层切换
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user