mirror of
https://github.com/unanmed/HumanBreak.git
synced 2026-11-03 18:24:30 +08:00
refactor: 插件
This commit is contained in:
1 parent
ef9a3d6537
commit
325a1e85ec
69 files changed
+1704
-1549
No files matched your search
@@ -123,7 +123,7 @@ export const camera1: ChaseCameraData[] = [
|
||||
* 追逐战开始前的初始化函数,移除所有血瓶和门等
|
||||
*/
|
||||
export function init1() {
|
||||
return core.plugin.chase.chaseInit1();
|
||||
return Mota.Plugin.require('chase_g').chaseInit1();
|
||||
}
|
||||
|
||||
export function chaseShake(chase: Chase) {
|
||||
@@ -561,7 +561,7 @@ export function para3(chase: Chase) {
|
||||
'MT14',
|
||||
async () => {
|
||||
flags.finishChase1 = true;
|
||||
core.plugin.replay.clip('choices:0');
|
||||
Mota.Plugin.require('replay_g').clip('choices:0');
|
||||
core.showStatusBar();
|
||||
ani.time(750).apply('rect', 0);
|
||||
chase.end();
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
} from './ui/achievement';
|
||||
import { changeLocalStorage } from './utils';
|
||||
import list from '../data/achievement.json';
|
||||
import { loading } from '@/core/loader/load';
|
||||
|
||||
export const floors: Record<number, FloorIds[]> = {
|
||||
1: ['MT0', 'tower7']
|
||||
@@ -21,6 +22,15 @@ export const achiDict: Record<number, number> = {
|
||||
1: 0
|
||||
};
|
||||
|
||||
loading.once('coreInit', () => {
|
||||
Object.values(floors).forEach((v, i) => {
|
||||
const from = core.floorIds.indexOf(v[0]);
|
||||
const to = core.floorIds.indexOf(v[1]);
|
||||
const all = core.floorIds.slice(from, to + 1);
|
||||
floors[i + 1] = all;
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* 检查所有到达过的楼层,用于成就的计算
|
||||
*/
|
||||
|
||||
+39
-40
@@ -7,7 +7,9 @@ tran.value.y = 0;
|
||||
|
||||
let needSmooth = false;
|
||||
|
||||
export default function init() {
|
||||
export function init() {
|
||||
const setting = Mota.require('var', 'mainSetting');
|
||||
|
||||
tran.ticker.add(() => {
|
||||
if (core.isPlaying() && needSmooth) {
|
||||
core.setViewport(tran.value.x, tran.value.y);
|
||||
@@ -18,50 +20,47 @@ export default function init() {
|
||||
needSmooth = false;
|
||||
}, 700);
|
||||
|
||||
control.prototype._drawHero_updateViewport = function (
|
||||
x: number,
|
||||
y: number,
|
||||
offset: Loc
|
||||
) {
|
||||
const ox = core.clamp(
|
||||
(x - core._HALF_WIDTH_) * 32 + offset.x,
|
||||
0,
|
||||
Math.max(32 * core.bigmap.width - core._PX_, 0)
|
||||
);
|
||||
const oy = core.clamp(
|
||||
(y - core._HALF_HEIGHT_) * 32 + offset.y,
|
||||
0,
|
||||
Math.max(32 * core.bigmap.height - core._PY_, 0)
|
||||
);
|
||||
Mota.rewrite(
|
||||
core.control,
|
||||
'_drawHero_updateViewport',
|
||||
'full',
|
||||
(x, y, offset) => {
|
||||
const ox = core.clamp(
|
||||
(x - core._HALF_WIDTH_) * 32 + offset.x,
|
||||
0,
|
||||
Math.max(32 * core.bigmap.width - core._PX_, 0)
|
||||
);
|
||||
const oy = core.clamp(
|
||||
(y - core._HALF_HEIGHT_) * 32 + offset.y,
|
||||
0,
|
||||
Math.max(32 * core.bigmap.height - core._PY_, 0)
|
||||
);
|
||||
|
||||
tran.transition('x', ox).transition('y', oy);
|
||||
tran.transition('x', ox).transition('y', oy);
|
||||
|
||||
if (tran.easeTime > 0) {
|
||||
needSmooth = true;
|
||||
func();
|
||||
} else {
|
||||
core.setViewport(tran.value.x, tran.value.y);
|
||||
const t = setting.getValue('screen.smoothView', false);
|
||||
if (!t) return;
|
||||
if (tran.easeTime > 0) {
|
||||
needSmooth = true;
|
||||
func();
|
||||
} else {
|
||||
core.setViewport(tran.value.x, tran.value.y);
|
||||
}
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
const hso = hyper('sin', 'out');
|
||||
let time2 = Date.now();
|
||||
const origin1 = control.prototype._moveAction_moving;
|
||||
control.prototype._moveAction_moving = function (...params: any[]) {
|
||||
if (Date.now() - time2 > 20)
|
||||
tran.mode(hyper('sin', 'out')).time(200).absolute();
|
||||
return origin1.call(this, ...params);
|
||||
};
|
||||
|
||||
const origin2 = control.prototype.moveDirectly;
|
||||
control.prototype.moveDirectly = function (...params: any[]) {
|
||||
Mota.rewrite(core.control, '_moveAction_moving', 'front', () => {
|
||||
const t = setting.getValue('screen.smoothView', false) ? 200 : 1;
|
||||
if (Date.now() - time2 > 20) tran.mode(hso).time(t).absolute();
|
||||
});
|
||||
Mota.rewrite(core.control, 'moveDirectly', 'front', () => {
|
||||
const t = setting.getValue('screen.smoothView', false) ? 600 : 1;
|
||||
time2 = Date.now();
|
||||
tran.mode(hyper('sin', 'out')).time(600).absolute();
|
||||
return origin2.call(this, ...params);
|
||||
};
|
||||
|
||||
const origin3 = events.prototype._changeFloor_beforeChange;
|
||||
events.prototype._changeFloor_beforeChange = function (...params: any[]) {
|
||||
tran.mode(hso).time(t).absolute();
|
||||
});
|
||||
Mota.rewrite(core.events, '_changeFloor_beforeChange', 'front', () => {
|
||||
tran.time(1).absolute();
|
||||
return origin3.call(this, ...params);
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
export function chaseInit1() {
|
||||
const ids = ['MT13', 'MT14', 'MT15'];
|
||||
const toRemove = [];
|
||||
const ids: FloorIds[] = ['MT13', 'MT14', 'MT15'];
|
||||
const toRemove: [number, number, FloorIds][] = [];
|
||||
ids.forEach(v => {
|
||||
core.status.maps[v].cannotMoveDirectly = true;
|
||||
core.extractBlocks(v);
|
||||
@@ -17,7 +17,3 @@ export function chaseInit1() {
|
||||
core.removeBlock(...v);
|
||||
});
|
||||
}
|
||||
|
||||
core.plugin.chase = {
|
||||
chaseInit1
|
||||
};
|
||||
+210
-218
@@ -22,232 +22,224 @@ export function getEnemy(
|
||||
return enemy;
|
||||
}
|
||||
|
||||
core.enemys.canBattle = function (
|
||||
x: number,
|
||||
y: number,
|
||||
floorId: FloorIds = core.status.floorId
|
||||
) {
|
||||
const enemy = getEnemy(x, y, floorId);
|
||||
const { damage } = enemy.calDamage();
|
||||
return damage < core.status.hero.hp;
|
||||
};
|
||||
export function init() {
|
||||
core.enemys.canBattle = function (
|
||||
x: number,
|
||||
y: number,
|
||||
floorId: FloorIds = core.status.floorId
|
||||
) {
|
||||
const enemy = getEnemy(x, y, floorId);
|
||||
const { damage } = enemy.calDamage();
|
||||
return damage < core.status.hero.hp;
|
||||
};
|
||||
|
||||
core.events.battle = function (
|
||||
x: number,
|
||||
y: number,
|
||||
force: boolean = false,
|
||||
callback?: () => void
|
||||
) {
|
||||
core.saveAndStopAutomaticRoute();
|
||||
const enemy = getEnemy(x, y);
|
||||
// 非强制战斗
|
||||
if (!core.enemys.canBattle(x, y) && !force && !core.status.event.id) {
|
||||
core.stopSound();
|
||||
core.playSound('操作失败');
|
||||
core.drawTip('你打不过此怪物!', enemy.id);
|
||||
return core.clearContinueAutomaticRoute(callback);
|
||||
}
|
||||
// 自动存档
|
||||
if (!core.status.event.id) core.autosave(true);
|
||||
// 战前事件
|
||||
if (!this.beforeBattle(enemy, x, y))
|
||||
return core.clearContinueAutomaticRoute(callback);
|
||||
// 战后事件
|
||||
this.afterBattle(enemy, x, y);
|
||||
callback?.();
|
||||
};
|
||||
|
||||
core.events.beforeBattle = function () {
|
||||
return true;
|
||||
};
|
||||
|
||||
core.events.afterBattle = function (
|
||||
enemy: DamageEnemy,
|
||||
x?: number,
|
||||
y?: number
|
||||
) {
|
||||
const floorId = core.status.floorId;
|
||||
const special = enemy.info.special;
|
||||
|
||||
// 播放战斗动画
|
||||
let animate: AnimationIds = 'hand';
|
||||
// 检查当前装备是否存在攻击动画
|
||||
const equipId = core.getEquip(0);
|
||||
if (equipId && (core.material.items[equipId].equip || {}).animate)
|
||||
animate = core.material.items[equipId].equip.animate;
|
||||
|
||||
// 检查该动画是否存在SE,如果不存在则使用默认音效
|
||||
if (!core.material.animates[animate]?.se) core.playSound('attack.mp3');
|
||||
|
||||
// 战斗伤害
|
||||
const info = enemy.calDamage(core.status.hero);
|
||||
const damage = info.damage;
|
||||
// 判定是否致死
|
||||
if (damage >= core.status.hero.hp) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar(false, true);
|
||||
core.events.lose('战斗失败');
|
||||
return;
|
||||
}
|
||||
|
||||
// 扣减体力值并记录统计数据
|
||||
core.status.hero.hp -= damage;
|
||||
core.status.hero.statistics.battleDamage += damage;
|
||||
core.status.hero.statistics.battle++;
|
||||
|
||||
// 智慧之源
|
||||
if (special.includes(14) && flags.hard === 2) {
|
||||
core.addFlag(
|
||||
'inte_' + floorId,
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10
|
||||
);
|
||||
core.status.hero.mdef -=
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10;
|
||||
}
|
||||
|
||||
// 极昼永夜
|
||||
if (special.includes(22)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] -= enemy.enemy.night!;
|
||||
}
|
||||
if (special.includes(23)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] += enemy.enemy.day;
|
||||
}
|
||||
|
||||
// if (core.plugin.skillTree.getSkillLevel(11) > 0) {
|
||||
// core.plugin.study.declineStudiedSkill();
|
||||
// }
|
||||
|
||||
// 如果是融化怪,需要特殊标记一下
|
||||
if (special.includes(25) && core.has(x) && core.has(y)) {
|
||||
flags[`melt_${floorId}`] ??= {};
|
||||
flags[`melt_${floorId}`][`${x},${y}`] = enemy.enemy.melt;
|
||||
}
|
||||
|
||||
// 获得金币
|
||||
const money = enemy.enemy.money;
|
||||
core.status.hero.money += money;
|
||||
core.status.hero.statistics.money += money;
|
||||
|
||||
// 获得经验
|
||||
const exp = enemy.enemy.exp;
|
||||
core.status.hero.exp += exp;
|
||||
core.status.hero.statistics.exp += exp;
|
||||
|
||||
const hint =
|
||||
'打败 ' + enemy.enemy.name + ',金币+' + money + ',经验+' + exp;
|
||||
core.drawTip(hint, enemy.id);
|
||||
|
||||
if (core.getFlag('bladeOn') && core.getFlag('blade')) {
|
||||
core.setFlag('blade', false);
|
||||
}
|
||||
if (core.getFlag('shieldOn') && core.getFlag('shield')) {
|
||||
core.setFlag('shield', false);
|
||||
}
|
||||
|
||||
// 事件的处理
|
||||
const todo: MotaEvent = [];
|
||||
|
||||
// 战后事件
|
||||
if (has(core.status.floorId)) {
|
||||
const loc = `${x},${y}` as LocString;
|
||||
todo.push(...(core.floors[core.status.floorId].afterBattle[loc] ?? []));
|
||||
}
|
||||
todo.push(...(enemy.enemy.afterBattle ?? []));
|
||||
|
||||
// 如果事件不为空,将其插入
|
||||
if (todo.length > 0) core.insertAction(todo, x, y);
|
||||
|
||||
if (has(x) && has(y)) {
|
||||
core.drawAnimate(animate, x, y);
|
||||
core.removeBlock(x, y);
|
||||
} else core.drawHeroAnimate(animate);
|
||||
|
||||
// 如果已有事件正在处理中
|
||||
if (core.status.event.id == null) core.continueAutomaticRoute();
|
||||
else core.clearContinueAutomaticRoute();
|
||||
};
|
||||
|
||||
core.events._sys_battle = function (data: Block, callback?: () => void) {
|
||||
// 检查战前事件
|
||||
const floor = core.floors[core.status.floorId];
|
||||
const beforeBattle: MotaEvent = [];
|
||||
const loc = `${data.x},${data.y}` as LocString;
|
||||
const enemy = getEnemy(data.x, data.y);
|
||||
|
||||
beforeBattle.push(...(floor.beforeBattle[loc] ?? []));
|
||||
beforeBattle.push(...(enemy.enemy.beforeBattle ?? []));
|
||||
|
||||
if (beforeBattle.length > 0) {
|
||||
beforeBattle.push({ type: 'battle', x: data.x, y: data.y });
|
||||
core.clearContinueAutomaticRoute();
|
||||
|
||||
// 自动存档
|
||||
var inAction = core.status.event.id == 'action';
|
||||
if (inAction) {
|
||||
core.insertAction(beforeBattle, data.x, data.y);
|
||||
core.doAction();
|
||||
} else {
|
||||
core.autosave(true);
|
||||
core.insertAction(beforeBattle, data.x, data.y, callback);
|
||||
core.events.battle = function (
|
||||
x: number,
|
||||
y: number,
|
||||
force: boolean = false,
|
||||
callback?: () => void
|
||||
) {
|
||||
core.saveAndStopAutomaticRoute();
|
||||
const enemy = getEnemy(x, y);
|
||||
// 非强制战斗
|
||||
if (!core.enemys.canBattle(x, y) && !force && !core.status.event.id) {
|
||||
core.stopSound();
|
||||
core.playSound('操作失败');
|
||||
core.drawTip('你打不过此怪物!', enemy.id);
|
||||
return core.clearContinueAutomaticRoute(callback);
|
||||
}
|
||||
} else {
|
||||
this.battle(data.x, data.y, false, callback);
|
||||
}
|
||||
};
|
||||
// 自动存档
|
||||
if (!core.status.event.id) core.autosave(true);
|
||||
// 战前事件
|
||||
// 战后事件
|
||||
this.afterBattle(enemy, x, y);
|
||||
callback?.();
|
||||
};
|
||||
|
||||
core.events._action_battle = function (data, x, y, prefix) {
|
||||
if (data.id) {
|
||||
const enemy = getSingleEnemy(data.id as EnemyIds);
|
||||
// todo: 与不在地图上的怪物战斗
|
||||
} else {
|
||||
if (data.floorId != core.status.floorId) {
|
||||
core.doAction();
|
||||
core.events.afterBattle = function (
|
||||
enemy: DamageEnemy,
|
||||
x?: number,
|
||||
y?: number
|
||||
) {
|
||||
const floorId = core.status.floorId;
|
||||
const special = enemy.info.special;
|
||||
|
||||
// 播放战斗动画
|
||||
let animate: AnimationIds = 'hand';
|
||||
// 检查当前装备是否存在攻击动画
|
||||
const equipId = core.getEquip(0);
|
||||
if (equipId && (core.material.items[equipId].equip || {}).animate)
|
||||
animate = core.material.items[equipId].equip.animate;
|
||||
|
||||
// 检查该动画是否存在SE,如果不存在则使用默认音效
|
||||
if (!core.material.animates[animate]?.se) core.playSound('attack.mp3');
|
||||
|
||||
// 战斗伤害
|
||||
const info = enemy.calDamage(core.status.hero);
|
||||
const damage = info.damage;
|
||||
// 判定是否致死
|
||||
if (damage >= core.status.hero.hp) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar(false, true);
|
||||
core.events.lose('战斗失败');
|
||||
return;
|
||||
}
|
||||
const [ex, ey] = this.__action_getLoc(data.loc, x, y, prefix) as LocArr;
|
||||
this.battle(ex, ey, true, core.doAction);
|
||||
}
|
||||
};
|
||||
|
||||
core.enemys.getCurrentEnemys = function (floorId = core.status.floorId) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
const enemys: CurrentEnemy[] = [];
|
||||
const used: Record<string, DamageEnemy[]> = {};
|
||||
ensureFloorDamage(floorId);
|
||||
const floor = core.status.maps[floorId];
|
||||
floor.enemy.list.forEach(v => {
|
||||
if (!(v.id in used)) {
|
||||
const e = new DamageEnemy(v.enemy);
|
||||
e.calAttribute();
|
||||
e.getRealInfo();
|
||||
e.calDamage();
|
||||
const curr: CurrentEnemy = {
|
||||
enemy: e,
|
||||
onMapEnemy: [v]
|
||||
};
|
||||
enemys.push(curr);
|
||||
used[v.id] = curr.onMapEnemy;
|
||||
} else {
|
||||
used[v.id].push(v);
|
||||
// 扣减体力值并记录统计数据
|
||||
core.status.hero.hp -= damage;
|
||||
core.status.hero.statistics.battleDamage += damage;
|
||||
core.status.hero.statistics.battle++;
|
||||
|
||||
// 智慧之源
|
||||
if (special.includes(14) && flags.hard === 2) {
|
||||
core.addFlag(
|
||||
'inte_' + floorId,
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10
|
||||
);
|
||||
core.status.hero.mdef -=
|
||||
Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10;
|
||||
}
|
||||
});
|
||||
|
||||
return enemys.sort((a, b) => {
|
||||
const ad = a.enemy.calDamage().damage;
|
||||
const bd = b.enemy.calDamage().damage;
|
||||
return ad - bd;
|
||||
});
|
||||
};
|
||||
// 极昼永夜
|
||||
if (special.includes(22)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] -= enemy.enemy.night!;
|
||||
}
|
||||
if (special.includes(23)) {
|
||||
flags[`night_${floorId}`] ??= 0;
|
||||
flags[`night_${floorId}`] += enemy.enemy.day;
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface Events {
|
||||
beforeBattle(enemy: DamageEnemy, x: number, y: number): boolean;
|
||||
afterBattle(enemy: DamageEnemy, x: number, y: number): void;
|
||||
}
|
||||
// if (core.plugin.skillTree.getSkillLevel(11) > 0) {
|
||||
// core.plugin.study.declineStudiedSkill();
|
||||
// }
|
||||
|
||||
interface Enemys {
|
||||
getCurrentEnemys(floorId?: FloorIds): CurrentEnemy[];
|
||||
}
|
||||
// 如果是融化怪,需要特殊标记一下
|
||||
if (special.includes(25) && has(x) && has(y)) {
|
||||
flags[`melt_${floorId}`] ??= {};
|
||||
flags[`melt_${floorId}`][`${x},${y}`] = enemy.enemy.melt;
|
||||
}
|
||||
|
||||
// 获得金币
|
||||
const money = enemy.enemy.money;
|
||||
core.status.hero.money += money;
|
||||
core.status.hero.statistics.money += money;
|
||||
|
||||
// 获得经验
|
||||
const exp = enemy.enemy.exp;
|
||||
core.status.hero.exp += exp;
|
||||
core.status.hero.statistics.exp += exp;
|
||||
|
||||
const hint =
|
||||
'打败 ' + enemy.enemy.name + ',金币+' + money + ',经验+' + exp;
|
||||
core.drawTip(hint, enemy.id);
|
||||
|
||||
if (core.getFlag('bladeOn') && core.getFlag('blade')) {
|
||||
core.setFlag('blade', false);
|
||||
}
|
||||
if (core.getFlag('shieldOn') && core.getFlag('shield')) {
|
||||
core.setFlag('shield', false);
|
||||
}
|
||||
|
||||
// 事件的处理
|
||||
const todo: MotaEvent = [];
|
||||
|
||||
// 战后事件
|
||||
if (has(core.status.floorId)) {
|
||||
const loc = `${x},${y}` as LocString;
|
||||
todo.push(
|
||||
...(core.floors[core.status.floorId].afterBattle[loc] ?? [])
|
||||
);
|
||||
}
|
||||
todo.push(...(enemy.enemy.afterBattle ?? []));
|
||||
|
||||
// 如果事件不为空,将其插入
|
||||
if (todo.length > 0) core.insertAction(todo, x, y);
|
||||
|
||||
if (has(x) && has(y)) {
|
||||
core.drawAnimate(animate, x, y);
|
||||
core.removeBlock(x, y);
|
||||
} else core.drawHeroAnimate(animate);
|
||||
|
||||
// 如果已有事件正在处理中
|
||||
if (core.status.event.id == null) core.continueAutomaticRoute();
|
||||
else core.clearContinueAutomaticRoute();
|
||||
};
|
||||
|
||||
core.events._sys_battle = function (data: Block, callback?: () => void) {
|
||||
// 检查战前事件
|
||||
const floor = core.floors[core.status.floorId];
|
||||
const beforeBattle: MotaEvent = [];
|
||||
const loc = `${data.x},${data.y}` as LocString;
|
||||
const enemy = getEnemy(data.x, data.y);
|
||||
|
||||
beforeBattle.push(...(floor.beforeBattle[loc] ?? []));
|
||||
beforeBattle.push(...(enemy.enemy.beforeBattle ?? []));
|
||||
|
||||
if (beforeBattle.length > 0) {
|
||||
beforeBattle.push({ type: 'battle', x: data.x, y: data.y });
|
||||
core.clearContinueAutomaticRoute();
|
||||
|
||||
// 自动存档
|
||||
var inAction = core.status.event.id == 'action';
|
||||
if (inAction) {
|
||||
core.insertAction(beforeBattle, data.x, data.y);
|
||||
core.doAction();
|
||||
} else {
|
||||
core.autosave(true);
|
||||
core.insertAction(beforeBattle, data.x, data.y, callback);
|
||||
}
|
||||
} else {
|
||||
this.battle(data.x, data.y, false, callback);
|
||||
}
|
||||
};
|
||||
|
||||
core.events._action_battle = function (data, x, y, prefix) {
|
||||
if (data.id) {
|
||||
const enemy = getSingleEnemy(data.id as EnemyIds);
|
||||
// todo: 与不在地图上的怪物战斗
|
||||
} else {
|
||||
if (data.floorId != core.status.floorId) {
|
||||
core.doAction();
|
||||
return;
|
||||
}
|
||||
const [ex, ey] = this.__action_getLoc(
|
||||
data.loc,
|
||||
x,
|
||||
y,
|
||||
prefix
|
||||
) as LocArr;
|
||||
this.battle(ex, ey, true, core.doAction);
|
||||
}
|
||||
};
|
||||
|
||||
core.enemys.getCurrentEnemys = function (floorId = core.status.floorId) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
const enemys: CurrentEnemy[] = [];
|
||||
const used: Record<string, DamageEnemy[]> = {};
|
||||
ensureFloorDamage(floorId);
|
||||
const floor = core.status.maps[floorId];
|
||||
floor.enemy.list.forEach(v => {
|
||||
if (!(v.id in used)) {
|
||||
const e = new DamageEnemy(v.enemy);
|
||||
e.calAttribute();
|
||||
e.getRealInfo();
|
||||
e.calDamage();
|
||||
const curr: CurrentEnemy = {
|
||||
enemy: e,
|
||||
onMapEnemy: [v]
|
||||
};
|
||||
enemys.push(curr);
|
||||
used[v.id] = curr.onMapEnemy;
|
||||
} else {
|
||||
used[v.id].push(v);
|
||||
}
|
||||
});
|
||||
|
||||
return enemys.sort((a, b) => {
|
||||
const ad = a.enemy.calDamage().damage;
|
||||
const bd = b.enemy.calDamage().damage;
|
||||
return ad - bd;
|
||||
});
|
||||
};
|
||||
}
|
||||
+152
-147
@@ -1,157 +1,162 @@
|
||||
import { drawHalo } from '../fx/halo';
|
||||
|
||||
// 伤害弹出
|
||||
// 复写阻激夹域检测
|
||||
control.prototype.checkBlock = function (forceMockery: boolean = false) {
|
||||
const x = core.getHeroLoc('x'),
|
||||
y = core.getHeroLoc('y'),
|
||||
loc = x + ',' + y;
|
||||
const info = core.status.thisMap.enemy.mapDamage[loc];
|
||||
const damage = info?.damage;
|
||||
if (damage) {
|
||||
if (!main.replayChecking) {
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
(x - core.bigmap.offsetX / 32) * 32 + 12,
|
||||
(y - core.bigmap.offsetY / 32) * 32 + 20,
|
||||
(-damage).toString()
|
||||
);
|
||||
}
|
||||
core.status.hero.hp -= damage;
|
||||
const type = [...info.type];
|
||||
const text = type.join(',') || '伤害';
|
||||
core.drawTip('受到' + text + damage + '点');
|
||||
core.drawHeroAnimate('zone');
|
||||
this._checkBlock_disableQuickShop();
|
||||
core.status.hero.statistics.extraDamage += damage;
|
||||
if (core.status.hero.hp <= 0) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar();
|
||||
core.events.lose();
|
||||
return;
|
||||
} else {
|
||||
core.updateStatusBar();
|
||||
}
|
||||
}
|
||||
checkMockery(loc, forceMockery);
|
||||
};
|
||||
|
||||
control.prototype._drawDamage_draw = function (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
onMap: boolean,
|
||||
floorId: FloorIds
|
||||
) {
|
||||
if (!core.hasItem('book')) return;
|
||||
drawHalo(ctx, onMap, floorId);
|
||||
|
||||
core.setFont(ctx, "14px 'normal'");
|
||||
core.setTextAlign(ctx, 'center');
|
||||
core.setTextBaseline(ctx, 'middle');
|
||||
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
|
||||
)
|
||||
export function init() {
|
||||
// 伤害弹出
|
||||
// 复写阻激夹域检测
|
||||
control.prototype.checkBlock = function (forceMockery: boolean = false) {
|
||||
const x = core.getHeroLoc('x'),
|
||||
y = core.getHeroLoc('y'),
|
||||
loc = x + ',' + y;
|
||||
const info = core.status.thisMap.enemy.mapDamage[loc];
|
||||
const damage = info?.damage;
|
||||
if (damage) {
|
||||
if (!main.replayChecking) {
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
(x - core.bigmap.offsetX / 32) * 32 + 12,
|
||||
(y - core.bigmap.offsetY / 32) * 32 + 20,
|
||||
(-damage).toString()
|
||||
);
|
||||
}
|
||||
core.status.hero.hp -= damage;
|
||||
const type = [...info.type];
|
||||
const text = type.join(',') || '伤害';
|
||||
core.drawTip('受到' + text + damage + '点');
|
||||
core.drawHeroAnimate('zone');
|
||||
this._checkBlock_disableQuickShop();
|
||||
core.status.hero.statistics.extraDamage += damage;
|
||||
if (core.status.hero.hp <= 0) {
|
||||
core.status.hero.hp = 0;
|
||||
core.updateStatusBar();
|
||||
core.events.lose();
|
||||
return;
|
||||
} else {
|
||||
core.updateStatusBar();
|
||||
}
|
||||
}
|
||||
var alpha = core.setAlpha(ctx, one.alpha);
|
||||
core.fillBoldText(ctx, one.text, px, py, one.color as string);
|
||||
core.setAlpha(ctx, alpha);
|
||||
});
|
||||
checkMockery(loc, forceMockery);
|
||||
};
|
||||
|
||||
core.setTextAlign(ctx, 'left');
|
||||
core.setTextBaseline(ctx, 'alphabetic');
|
||||
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;
|
||||
control.prototype._drawDamage_draw = function (
|
||||
ctx: CanvasRenderingContext2D,
|
||||
onMap: boolean,
|
||||
floorId: FloorIds
|
||||
) {
|
||||
if (!core.hasItem('book')) return;
|
||||
drawHalo(ctx, onMap, floorId);
|
||||
|
||||
core.setFont(ctx, "14px 'normal'");
|
||||
core.setTextAlign(ctx, 'center');
|
||||
core.setTextBaseline(ctx, 'middle');
|
||||
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;
|
||||
}
|
||||
var alpha = core.setAlpha(ctx, one.alpha);
|
||||
core.fillBoldText(ctx, one.text, px, py, one.color as string);
|
||||
core.setAlpha(ctx, alpha);
|
||||
});
|
||||
|
||||
core.setTextAlign(ctx, 'left');
|
||||
core.setTextBaseline(ctx, 'alphabetic');
|
||||
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 as string);
|
||||
});
|
||||
|
||||
ctx.save();
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.lineWidth = 2;
|
||||
core.status.damage.dir.forEach(v => {
|
||||
let x = v.x;
|
||||
let y = v.y;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
x -= core.bigmap.posX;
|
||||
y -= core.bigmap.posY;
|
||||
}
|
||||
if (x < -1 || x > 15 || y < 0 || y > 15) return;
|
||||
let px = x * 32;
|
||||
let py = y * 32;
|
||||
ctx.beginPath();
|
||||
if (v.dir === 'down') {
|
||||
py -= 32;
|
||||
ctx.moveTo(px + 16, py + 18);
|
||||
ctx.lineTo(px + 16, py + 32);
|
||||
ctx.moveTo(px + 10, py + 26);
|
||||
ctx.lineTo(px + 16, py + 32);
|
||||
ctx.lineTo(px + 22, py + 26);
|
||||
} else if (v.dir === 'left') {
|
||||
px += 32;
|
||||
ctx.moveTo(px + 14, py + 16);
|
||||
ctx.lineTo(px, py + 16);
|
||||
ctx.moveTo(px + 6, py + 10);
|
||||
ctx.lineTo(px, py + 16);
|
||||
ctx.lineTo(px + 6, py + 22);
|
||||
} else if (v.dir === 'up') {
|
||||
py += 32;
|
||||
ctx.moveTo(px + 16, py + 14);
|
||||
ctx.lineTo(px + 16, py);
|
||||
ctx.moveTo(px + 10, py + 6);
|
||||
ctx.lineTo(px + 16, py);
|
||||
ctx.lineTo(px + 22, py + 6);
|
||||
} else {
|
||||
px -= 32;
|
||||
ctx.moveTo(px + 18, py + 16);
|
||||
ctx.lineTo(px + 32, py + 16);
|
||||
ctx.moveTo(px + 26, py + 10);
|
||||
ctx.lineTo(px + 32, py + 16);
|
||||
ctx.lineTo(px + 26, py + 22);
|
||||
}
|
||||
ctx.strokeStyle = 'black';
|
||||
ctx.lineWidth = 2.5;
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = v.color as string;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
});
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
control.prototype.moveHero = function (
|
||||
direction: Dir,
|
||||
callback: () => void
|
||||
) {
|
||||
// 如果正在移动,直接return
|
||||
if (core.status.heroMoving != 0) return;
|
||||
if (core.isset(direction)) core.setHeroLoc('direction', direction);
|
||||
|
||||
const nx = core.nextX();
|
||||
const ny = core.nextY();
|
||||
if (core.status.thisMap.enemy.mapDamage[`${nx},${ny}`]?.mockery) {
|
||||
core.autosave();
|
||||
}
|
||||
core.fillBoldText(ctx, one.text, px, py, one.color as string);
|
||||
});
|
||||
|
||||
ctx.save();
|
||||
ctx.lineCap = 'round';
|
||||
ctx.lineJoin = 'round';
|
||||
ctx.lineWidth = 2;
|
||||
core.status.damage.dir.forEach(v => {
|
||||
let x = v.x;
|
||||
let y = v.y;
|
||||
if (onMap && core.bigmap.v2) {
|
||||
x -= core.bigmap.posX;
|
||||
y -= core.bigmap.posY;
|
||||
}
|
||||
if (x < -1 || x > 15 || y < 0 || y > 15) return;
|
||||
let px = x * 32;
|
||||
let py = y * 32;
|
||||
ctx.beginPath();
|
||||
if (v.dir === 'down') {
|
||||
py -= 32;
|
||||
ctx.moveTo(px + 16, py + 18);
|
||||
ctx.lineTo(px + 16, py + 32);
|
||||
ctx.moveTo(px + 10, py + 26);
|
||||
ctx.lineTo(px + 16, py + 32);
|
||||
ctx.lineTo(px + 22, py + 26);
|
||||
} else if (v.dir === 'left') {
|
||||
px += 32;
|
||||
ctx.moveTo(px + 14, py + 16);
|
||||
ctx.lineTo(px, py + 16);
|
||||
ctx.moveTo(px + 6, py + 10);
|
||||
ctx.lineTo(px, py + 16);
|
||||
ctx.lineTo(px + 6, py + 22);
|
||||
} else if (v.dir === 'up') {
|
||||
py += 32;
|
||||
ctx.moveTo(px + 16, py + 14);
|
||||
ctx.lineTo(px + 16, py);
|
||||
ctx.moveTo(px + 10, py + 6);
|
||||
ctx.lineTo(px + 16, py);
|
||||
ctx.lineTo(px + 22, py + 6);
|
||||
} else {
|
||||
px -= 32;
|
||||
ctx.moveTo(px + 18, py + 16);
|
||||
ctx.lineTo(px + 32, py + 16);
|
||||
ctx.moveTo(px + 26, py + 10);
|
||||
ctx.lineTo(px + 32, py + 16);
|
||||
ctx.lineTo(px + 26, py + 22);
|
||||
}
|
||||
ctx.strokeStyle = 'black';
|
||||
ctx.lineWidth = 2.5;
|
||||
ctx.stroke();
|
||||
ctx.strokeStyle = v.color as string;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
});
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
control.prototype.moveHero = function (direction: Dir, callback: () => void) {
|
||||
// 如果正在移动,直接return
|
||||
if (core.status.heroMoving != 0) return;
|
||||
if (core.isset(direction)) core.setHeroLoc('direction', direction);
|
||||
|
||||
const nx = core.nextX();
|
||||
const ny = core.nextY();
|
||||
if (core.status.thisMap.enemy.mapDamage[`${nx},${ny}`]?.mockery) {
|
||||
core.autosave();
|
||||
}
|
||||
|
||||
if (callback) return this.moveAction(callback);
|
||||
this._moveHero_moving();
|
||||
};
|
||||
if (callback) return this.moveAction(callback);
|
||||
this._moveHero_moving();
|
||||
};
|
||||
}
|
||||
|
||||
function checkMockery(loc: string, force: boolean = false) {
|
||||
if (core.status.lockControl && !force) return;
|
||||
|
||||
@@ -394,7 +394,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
|
||||
getHaloSpecials(): number[] {
|
||||
if (!this.floorId) return [];
|
||||
if (!core.has(this.x) || !core.has(this.y)) return [];
|
||||
if (!has(this.x) || !has(this.y)) return [];
|
||||
const special = this.info.special ?? this.enemy.special;
|
||||
const filter = special.filter(v => {
|
||||
return haloSpecials.includes(v) && !this.providedHalo.includes(v);
|
||||
@@ -424,7 +424,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
|
||||
if (this.progress !== 2) return;
|
||||
this.progress = 3;
|
||||
if (!this.floorId) return;
|
||||
if (!core.has(this.x) || !core.has(this.y)) return;
|
||||
if (!has(this.x) || !has(this.y)) return;
|
||||
const col = this.col ?? core.status.maps[this.floorId].enemy;
|
||||
if (!col) return;
|
||||
const special = this.getHaloSpecials();
|
||||
@@ -950,8 +950,3 @@ declare global {
|
||||
enemy: EnemyCollection;
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.damage = {
|
||||
Enemy: DamageEnemy,
|
||||
Collection: EnemyCollection
|
||||
};
|
||||
@@ -1,27 +1,19 @@
|
||||
///<reference path="../../../../src/types/core.d.ts" />
|
||||
|
||||
// todo: 优化,直接调用 floor.enemy.list 进行计算
|
||||
|
||||
/**
|
||||
* 检查漏怪
|
||||
* @param {FloorIds[]} floorIds
|
||||
*/
|
||||
export function checkRemainEnemy(floorIds) {
|
||||
/**
|
||||
* @type {Record<FloorIds, {loc: LocArr, id: EnemyIds}[]>}
|
||||
*/
|
||||
const enemy = {};
|
||||
export function checkRemainEnemy(floorIds: FloorIds[]) {
|
||||
const enemy: Partial<Record<FloorIds, { loc: LocArr; id: EnemyIds }[]>> =
|
||||
{};
|
||||
floorIds.forEach(v => {
|
||||
core.extractBlocks(v);
|
||||
const blocks = core.status.maps[v].blocks;
|
||||
blocks.forEach(block => {
|
||||
if (!block.event.cls.startsWith('enemy') || block.disable) return;
|
||||
/**
|
||||
* @type {EnemyIds}
|
||||
*/
|
||||
const id = block.event.id;
|
||||
const id: EnemyIds = block.event.id as EnemyIds;
|
||||
enemy[v] ??= [];
|
||||
const info = enemy[v];
|
||||
const info = enemy[v]!;
|
||||
info.push({ loc: [block.x, block.y], id });
|
||||
});
|
||||
});
|
||||
@@ -30,30 +22,23 @@ export function checkRemainEnemy(floorIds) {
|
||||
|
||||
/**
|
||||
* 获取剩余怪物字符串
|
||||
* @param {FloorIds[]} floorIds
|
||||
*/
|
||||
export function getRemainEnemyString(floorIds) {
|
||||
export function getRemainEnemyString(floorIds: FloorIds[]) {
|
||||
const enemy = checkRemainEnemy(floorIds);
|
||||
const str = [];
|
||||
let now = [];
|
||||
for (const floor in enemy) {
|
||||
/**
|
||||
* @type {{loc: LocArr, id: EnemyIds}[]}
|
||||
*/
|
||||
const all = enemy[floor];
|
||||
/**
|
||||
* @type {Record<EnemyIds, number>}
|
||||
*/
|
||||
const remain = {};
|
||||
const all: { loc: LocArr; id: EnemyIds }[] = enemy[floor as FloorIds]!;
|
||||
const remain: Partial<Record<EnemyIds, number>> = {};
|
||||
all.forEach(v => {
|
||||
const id = v.id;
|
||||
remain[id] ??= 0;
|
||||
remain[id]++;
|
||||
remain[id]!++;
|
||||
});
|
||||
const title = core.status.maps[floor].title;
|
||||
const title = core.status.maps[floor as FloorIds].title;
|
||||
for (const id in remain) {
|
||||
const name = core.material.enemys[id].name;
|
||||
now.push(`${title}(${floor}): ${name} * ${remain[id]}`);
|
||||
const name = core.material.enemys[id as EnemyIds].name;
|
||||
now.push(`${title}(${floor}): ${name} * ${remain[id as EnemyIds]}`);
|
||||
if (now.length === 10) {
|
||||
str.push(now.join('\n'));
|
||||
now = [];
|
||||
@@ -67,8 +52,3 @@ export function getRemainEnemyString(floorIds) {
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
core.plugin.remainEnemy = {
|
||||
checkRemainEnemy,
|
||||
getRemainEnemyString
|
||||
};
|
||||
@@ -7,7 +7,7 @@ export interface SpecialDeclaration {
|
||||
color: string;
|
||||
}
|
||||
|
||||
export const enemySpecials: SpecialDeclaration[] = [
|
||||
export const specials: SpecialDeclaration[] = [
|
||||
{
|
||||
code: 0,
|
||||
name: '空',
|
||||
@@ -202,11 +202,3 @@ export const enemySpecials: SpecialDeclaration[] = [
|
||||
color: '#ff6f0a'
|
||||
}
|
||||
];
|
||||
|
||||
declare global {
|
||||
interface PluginDeclaration {
|
||||
special: SpecialDeclaration[];
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.special = enemySpecials;
|
||||
@@ -1,199 +0,0 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
export {};
|
||||
|
||||
// 创建新图层
|
||||
function createCanvas(name, zIndex) {
|
||||
if (!name) return;
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = name;
|
||||
canvas.className = 'gameCanvas no-anti-aliasing';
|
||||
// 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高
|
||||
if (main.mode != 'editor') canvas.style.zIndex = zIndex || 0;
|
||||
// 将图层插入进游戏内容
|
||||
document.getElementById('gameDraw').appendChild(canvas);
|
||||
var ctx = canvas.getContext('2d');
|
||||
core.canvas[name] = ctx;
|
||||
|
||||
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 = 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 = () => {
|
||||
editor.uifunctions.setLayerMod(value);
|
||||
};
|
||||
return input;
|
||||
};
|
||||
|
||||
var createCanvasBtn_mobile = 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('背2');
|
||||
// 插入事件层前(即新插入的背景层2前)
|
||||
parent.insertBefore(txt, child);
|
||||
// 向最后插入前景层2(即插入前景层后)
|
||||
parent.appendChild(input2);
|
||||
var txt2 = document.createTextNode('前2');
|
||||
parent.appendChild(txt2);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
maps.prototype._loadFloor_doNotCopy = function () {
|
||||
return [
|
||||
'firstArrive',
|
||||
'eachArrive',
|
||||
'blocks',
|
||||
'parallelDo',
|
||||
'map',
|
||||
'bgmap',
|
||||
'fgmap',
|
||||
'bg2map',
|
||||
'fg2map',
|
||||
'events',
|
||||
'changeFloor',
|
||||
'afterBattle',
|
||||
'afterGetItem',
|
||||
'afterOpenDoor',
|
||||
'cannotMove',
|
||||
'enemy'
|
||||
];
|
||||
};
|
||||
////// 绘制背景和前景层 //////
|
||||
maps.prototype._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;
|
||||
};
|
||||
maps.prototype._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;
|
||||
};
|
||||
////// 移动判定 //////
|
||||
maps.prototype._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)
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,219 @@
|
||||
// @ts-nocheck
|
||||
|
||||
// 创建新图层
|
||||
function createCanvas(name, zIndex) {
|
||||
if (!name) return;
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = name;
|
||||
canvas.className = 'gameCanvas no-anti-aliasing';
|
||||
// 编辑器模式下设置zIndex会导致加入的图层覆盖优先级过高
|
||||
if (main.mode != 'editor') canvas.style.zIndex = zIndex || 0;
|
||||
// 将图层插入进游戏内容
|
||||
document.getElementById('gameDraw').appendChild(canvas);
|
||||
var ctx = canvas.getContext('2d');
|
||||
core.canvas[name] = ctx;
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
export function init() {
|
||||
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 = 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 = () => {
|
||||
editor.uifunctions.setLayerMod(value);
|
||||
};
|
||||
return input;
|
||||
};
|
||||
|
||||
var createCanvasBtn_mobile = 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('背2');
|
||||
// 插入事件层前(即新插入的背景层2前)
|
||||
parent.insertBefore(txt, child);
|
||||
// 向最后插入前景层2(即插入前景层后)
|
||||
parent.appendChild(input2);
|
||||
var txt2 = document.createTextNode('前2');
|
||||
parent.appendChild(txt2);
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
||||
maps.prototype._loadFloor_doNotCopy = function () {
|
||||
return [
|
||||
'firstArrive',
|
||||
'eachArrive',
|
||||
'blocks',
|
||||
'parallelDo',
|
||||
'map',
|
||||
'bgmap',
|
||||
'fgmap',
|
||||
'bg2map',
|
||||
'fg2map',
|
||||
'events',
|
||||
'changeFloor',
|
||||
'afterBattle',
|
||||
'afterGetItem',
|
||||
'afterOpenDoor',
|
||||
'cannotMove',
|
||||
'enemy'
|
||||
];
|
||||
};
|
||||
////// 绘制背景和前景层 //////
|
||||
maps.prototype._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;
|
||||
};
|
||||
maps.prototype._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;
|
||||
};
|
||||
////// 移动判定 //////
|
||||
maps.prototype._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)
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
///<reference path="../../../../src/types/core.d.ts" />
|
||||
export {};
|
||||
|
||||
['up', 'down', 'left', 'right'].forEach(one => {
|
||||
// 指定中间帧动画
|
||||
core.material.icons.hero[one].midFoot = 2;
|
||||
});
|
||||
|
||||
var heroMoving = 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;
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
// @ts-nocheck
|
||||
|
||||
var heroMoving = 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
|
||||
);
|
||||
};
|
||||
|
||||
export function init() {
|
||||
['up', 'down', 'left', 'right'].forEach(one => {
|
||||
// 指定中间帧动画
|
||||
core.material.icons.hero[one].midFoot = 2;
|
||||
});
|
||||
|
||||
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;
|
||||
};
|
||||
}
|
||||
@@ -1,33 +1,35 @@
|
||||
import { ensureFloorDamage } from '../enemy/damage';
|
||||
|
||||
core.control.updateDamage = function (floorId = core.status.floorId, ctx) {
|
||||
if (!floorId || core.status.gameOver || main.mode !== 'play') return;
|
||||
const onMap = ctx == null;
|
||||
const floor = core.status.maps[floorId];
|
||||
export function init() {
|
||||
core.control.updateDamage = function (floorId = core.status.floorId, ctx) {
|
||||
if (!floorId || core.status.gameOver || main.mode !== 'play') return;
|
||||
const onMap = ctx == null;
|
||||
const floor = core.status.maps[floorId];
|
||||
|
||||
// 没有怪物手册
|
||||
// if (!core.hasItem('book')) return;
|
||||
core.status.damage.posX = core.bigmap.posX;
|
||||
core.status.damage.posY = core.bigmap.posY;
|
||||
if (!onMap) {
|
||||
const width = core.floors[floorId].width,
|
||||
height = core.floors[floorId].height;
|
||||
// 地图过大的缩略图不绘制显伤
|
||||
if (width * height > core.bigmap.threshold) return;
|
||||
}
|
||||
// 计算伤害
|
||||
ensureFloorDamage(floorId);
|
||||
// 没有怪物手册
|
||||
// if (!core.hasItem('book')) return;
|
||||
core.status.damage.posX = core.bigmap.posX;
|
||||
core.status.damage.posY = core.bigmap.posY;
|
||||
if (!onMap) {
|
||||
const width = core.floors[floorId].width,
|
||||
height = core.floors[floorId].height;
|
||||
// 地图过大的缩略图不绘制显伤
|
||||
if (width * height > core.bigmap.threshold) return;
|
||||
}
|
||||
// 计算伤害
|
||||
ensureFloorDamage(floorId);
|
||||
|
||||
floor.enemy.extract();
|
||||
floor.enemy.calDamage(true);
|
||||
floor.enemy.calMapDamage();
|
||||
core.status.damage.data = [];
|
||||
floor.enemy.extract();
|
||||
floor.enemy.calDamage(true);
|
||||
floor.enemy.calMapDamage();
|
||||
core.status.damage.data = [];
|
||||
|
||||
floor.enemy.render(true);
|
||||
floor.enemy.render(true);
|
||||
|
||||
getItemDetail(floorId, onMap); // 宝石血瓶详细信息
|
||||
this.drawDamage(ctx, floorId);
|
||||
};
|
||||
getItemDetail(floorId, onMap); // 宝石血瓶详细信息
|
||||
this.drawDamage(ctx, floorId);
|
||||
};
|
||||
}
|
||||
|
||||
// 获取宝石信息 并绘制
|
||||
function getItemDetail(floorId: FloorIds, onMap: boolean) {
|
||||
|
||||
@@ -1,59 +1,61 @@
|
||||
import { getEnemy } from '../enemy/battle';
|
||||
import { formatDamage } from '../utils';
|
||||
|
||||
core.maps._initDetachedBlock = function (
|
||||
info: BlockInfo,
|
||||
x: number,
|
||||
y: number,
|
||||
displayDamage: boolean = false
|
||||
) {
|
||||
let headCanvas = null,
|
||||
bodyCanvas = '__body_' + x + '_' + y,
|
||||
damageCanvas = null;
|
||||
|
||||
// head
|
||||
if (!info.bigImage && info.height > 32) {
|
||||
headCanvas = '__head_' + x + '_' + y;
|
||||
core.createCanvas(headCanvas, 0, 0, 32, info.height - 32, 55);
|
||||
}
|
||||
// body
|
||||
if (info.bigImage) {
|
||||
var bigImageInfo = this._getBigImageInfo(
|
||||
info.bigImage,
|
||||
info.face,
|
||||
info.posX
|
||||
);
|
||||
const { per_width, per_height } = bigImageInfo;
|
||||
core.createCanvas(bodyCanvas, 0, 0, per_width, per_height, 35);
|
||||
} else {
|
||||
core.createCanvas(bodyCanvas, 0, 0, 32, 32, 35);
|
||||
}
|
||||
|
||||
// 伤害
|
||||
if (
|
||||
info.cls.indexOf('enemy') == 0 &&
|
||||
core.hasItem('book') &&
|
||||
displayDamage
|
||||
export function init() {
|
||||
core.maps._initDetachedBlock = function (
|
||||
info: BlockInfo,
|
||||
x: number,
|
||||
y: number,
|
||||
displayDamage: boolean = false
|
||||
) {
|
||||
const enemy = getEnemy(x, y);
|
||||
const dam = enemy.calDamage();
|
||||
const { damage, color } = formatDamage(dam.damage);
|
||||
let headCanvas = null,
|
||||
bodyCanvas = '__body_' + x + '_' + y,
|
||||
damageCanvas = null;
|
||||
|
||||
damageCanvas = '__damage_' + x + '_' + y;
|
||||
const ctx = core.createCanvas(damageCanvas, 0, 0, 32, 32, 65);
|
||||
ctx.textAlign = 'left';
|
||||
ctx.font = '14px normal';
|
||||
core.fillBoldText(ctx, damage, 1, 31, color as string);
|
||||
if (core.flags.displayCritical) {
|
||||
const critical = enemy.calCritical(1);
|
||||
const atk = core.formatBigNumber(critical[0]?.delta, true);
|
||||
const display = atk === '???' ? '?' : atk;
|
||||
core.fillBoldText(ctx, display, 1, 21, '#FFFFFF');
|
||||
// head
|
||||
if (!info.bigImage && info.height > 32) {
|
||||
headCanvas = '__head_' + x + '_' + y;
|
||||
core.createCanvas(headCanvas, 0, 0, 32, info.height - 32, 55);
|
||||
}
|
||||
}
|
||||
return {
|
||||
headCanvas,
|
||||
bodyCanvas,
|
||||
damageCanvas
|
||||
// body
|
||||
if (info.bigImage) {
|
||||
var bigImageInfo = this._getBigImageInfo(
|
||||
info.bigImage,
|
||||
info.face,
|
||||
info.posX
|
||||
);
|
||||
const { per_width, per_height } = bigImageInfo;
|
||||
core.createCanvas(bodyCanvas, 0, 0, per_width, per_height, 35);
|
||||
} else {
|
||||
core.createCanvas(bodyCanvas, 0, 0, 32, 32, 35);
|
||||
}
|
||||
|
||||
// 伤害
|
||||
if (
|
||||
info.cls.indexOf('enemy') == 0 &&
|
||||
core.hasItem('book') &&
|
||||
displayDamage
|
||||
) {
|
||||
const enemy = getEnemy(x, y);
|
||||
const dam = enemy.calDamage();
|
||||
const { damage, color } = formatDamage(dam.damage);
|
||||
|
||||
damageCanvas = '__damage_' + x + '_' + y;
|
||||
const ctx = core.createCanvas(damageCanvas, 0, 0, 32, 32, 65);
|
||||
ctx.textAlign = 'left';
|
||||
ctx.font = '14px normal';
|
||||
core.fillBoldText(ctx, damage, 1, 31, color as string);
|
||||
if (core.flags.displayCritical) {
|
||||
const critical = enemy.calCritical(1);
|
||||
const atk = core.formatBigNumber(critical[0]?.delta, true);
|
||||
const display = atk === '???' ? '?' : atk;
|
||||
core.fillBoldText(ctx, display, 1, 21, '#FFFFFF');
|
||||
}
|
||||
}
|
||||
return {
|
||||
headCanvas,
|
||||
bodyCanvas,
|
||||
damageCanvas
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -54,6 +54,7 @@ function getRealStatus(
|
||||
name: keyof HeroStatus | 'all' | (keyof HeroStatus)[],
|
||||
floorId: FloorIds = core.status.floorId
|
||||
): any {
|
||||
const { getSkillLevel } = Mota.Plugin.require('skillTree_g');
|
||||
if (name instanceof Array) {
|
||||
return Object.fromEntries(
|
||||
name.map(v => [v, getRealStatus(status, v, floorId)])
|
||||
@@ -84,7 +85,7 @@ function getRealStatus(
|
||||
|
||||
// 技能
|
||||
if (flags.bladeOn && flags.blade) {
|
||||
const level = core.plugin.skillTree.getSkillLevel(2);
|
||||
const level = getSkillLevel(2);
|
||||
if (name === 'atk') {
|
||||
s *= 1 + 0.1 * level;
|
||||
}
|
||||
@@ -93,7 +94,7 @@ function getRealStatus(
|
||||
}
|
||||
}
|
||||
if (flags.shield && flags.shieldOn) {
|
||||
const level = core.plugin.skillTree.getSkillLevel(10);
|
||||
const level = getSkillLevel(10);
|
||||
if (name === 'atk') {
|
||||
s *= 1 - 0.1 * level;
|
||||
}
|
||||
@@ -119,8 +120,3 @@ declare global {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.hero = {
|
||||
getHeroStatusOf,
|
||||
getHeroStatusOn
|
||||
};
|
||||
@@ -1,41 +0,0 @@
|
||||
import './fiveLayer';
|
||||
import './fx/heroFourFrames';
|
||||
import './dev/hotReload';
|
||||
import './fx/itemDetail';
|
||||
import './enemy/checkblock';
|
||||
import './replay';
|
||||
import './ui';
|
||||
import './fx/rewrite';
|
||||
import * as halo from './fx/halo';
|
||||
import * as hero from './hero';
|
||||
import * as loopMap from './loopMap';
|
||||
import * as remainEnemy from './enemy/remainEnemy';
|
||||
import * as removeMap from './removeMap';
|
||||
import * as shop from './shop';
|
||||
import * as skill from './skills';
|
||||
import * as skillTree from './skillTree';
|
||||
import * as study from './study';
|
||||
import * as towerBoss from './towerBoss';
|
||||
import * as utils from './utils';
|
||||
import * as chase from './chase';
|
||||
import * as damage from './enemy/damage';
|
||||
import * as battle from './enemy/battle';
|
||||
import * as special from './enemy/special';
|
||||
|
||||
export {
|
||||
halo,
|
||||
hero,
|
||||
loopMap,
|
||||
remainEnemy,
|
||||
removeMap,
|
||||
shop,
|
||||
skill,
|
||||
skillTree,
|
||||
study,
|
||||
towerBoss,
|
||||
utils,
|
||||
chase,
|
||||
damage,
|
||||
battle,
|
||||
special
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
/* @__PURE__ */ import './dev/hotReload'; // 仅开发会用到
|
||||
import * as fiveLayer from './fiveLayer';
|
||||
import * as heroFourFrames from './fx/heroFourFrames';
|
||||
import * as itemDetail from './fx/itemDetail';
|
||||
import * as checkBlock from './enemy/checkblock';
|
||||
import * as replay from './replay';
|
||||
import * as ui from './ui';
|
||||
import * as rewrite from './fx/rewrite';
|
||||
import * as halo from './fx/halo';
|
||||
import * as hero from './hero';
|
||||
import * as loopMap from './loopMap';
|
||||
import * as remainEnemy from './enemy/remainEnemy';
|
||||
import * as removeMap from './removeMap';
|
||||
import * as shop from './shop';
|
||||
import * as skill from './skill';
|
||||
import * as skillTree from './skillTree';
|
||||
import * as study from './study';
|
||||
import * as towerBoss from './towerBoss';
|
||||
import * as utils from './utils';
|
||||
import * as chase from './chase';
|
||||
import * as damage from './enemy/damage';
|
||||
import * as battle from './enemy/battle';
|
||||
import * as special from './enemy/special';
|
||||
|
||||
Mota.Plugin.register('utils_g', utils);
|
||||
Mota.Plugin.register('loopMap_g', loopMap, loopMap.init);
|
||||
Mota.Plugin.register('shop_g', shop);
|
||||
Mota.Plugin.register('replay_g', replay, replay.init);
|
||||
Mota.Plugin.register('skillTree_g', skillTree);
|
||||
Mota.Plugin.register('removeMap_g', removeMap);
|
||||
Mota.Plugin.register('remainEnemy_g', remainEnemy);
|
||||
Mota.Plugin.register('chase_g', chase);
|
||||
Mota.Plugin.register('skill_g', skill);
|
||||
Mota.Plugin.register('towerBoss_g', towerBoss);
|
||||
Mota.Plugin.register('fiveLayer_g', fiveLayer, fiveLayer.init);
|
||||
Mota.Plugin.register('heroFourFrames_g', heroFourFrames, heroFourFrames.init);
|
||||
Mota.Plugin.register('rewrite_g', rewrite, rewrite.init);
|
||||
Mota.Plugin.register('itemDetail_g', itemDetail, itemDetail.init);
|
||||
Mota.Plugin.register('checkBlock_g', checkBlock, checkBlock.init);
|
||||
Mota.Plugin.register('halo_g', halo);
|
||||
Mota.Plugin.register('study_g', study);
|
||||
// todo: 这几个不应该放到插件
|
||||
Mota.Plugin.register('damage_g', damage);
|
||||
Mota.Plugin.register('battle_g', battle, battle.init);
|
||||
Mota.Plugin.register('special_g', special);
|
||||
Mota.Plugin.register('hero_g', hero);
|
||||
Mota.Plugin.register('ui_g', ui, ui.init);
|
||||
|
||||
// export {
|
||||
// halo,
|
||||
// hero,
|
||||
// loopMap,
|
||||
// remainEnemy,
|
||||
// removeMap,
|
||||
// shop,
|
||||
// skill,
|
||||
// skillTree,
|
||||
// study,
|
||||
// towerBoss,
|
||||
// utils,
|
||||
// chase,
|
||||
// damage,
|
||||
// battle,
|
||||
// special
|
||||
// };
|
||||
@@ -1,230 +0,0 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
import { slide } from './utils';
|
||||
|
||||
const list = ['tower6'];
|
||||
|
||||
/**
|
||||
* 设置循环地图的偏移量
|
||||
* @param {number} offset 横向偏移量
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
function setLoopMap(offset, floorId) {
|
||||
const floor = core.status.maps[floorId];
|
||||
if (offset < 9) {
|
||||
moveMap(floor.width - 17, floorId);
|
||||
}
|
||||
if (offset > floor.width - 9) {
|
||||
moveMap(17 - floor.width, floorId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 当勇士移动时自动设置循环地图
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
function autoSetLoopMap(floorId) {
|
||||
setLoopMap(core.status.hero.loc.x, floorId);
|
||||
}
|
||||
|
||||
export function checkLoopMap() {
|
||||
if (isLoopMap(core.status.floorId)) {
|
||||
autoSetLoopMap(core.status.floorId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动地图
|
||||
* @param {number} delta
|
||||
* @param {FloorIds} floorId
|
||||
*/
|
||||
function moveMap(delta, floorId) {
|
||||
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) {
|
||||
return list.includes(floorId);
|
||||
}
|
||||
|
||||
events.prototype._sys_changeFloor = function (data, callback) {
|
||||
data = data.event.data;
|
||||
let heroLoc = {};
|
||||
if (isLoopMap(data.floorId)) {
|
||||
const floor = core.status.maps[data.floorId];
|
||||
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;
|
||||
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, y, callback) {
|
||||
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
|
||||
},
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
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;
|
||||
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 = { event: {}, x: tx, y };
|
||||
b.event.data = c;
|
||||
b.event.trigger = 'changeFloor';
|
||||
block = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
core.status.automaticRoute.moveDirectly = false;
|
||||
this.doSystemEvent(trigger, block);
|
||||
}
|
||||
return _executeCallback();
|
||||
};
|
||||
|
||||
maps.prototype._getBgFgMapArray = function (name, floorId, noCache) {
|
||||
floorId = floorId || core.status.floorId;
|
||||
if (!floorId) return [];
|
||||
var width = core.floors[floorId].width;
|
||||
var height = core.floors[floorId].height;
|
||||
|
||||
if (!noCache && core.status[name + 'maps'][floorId])
|
||||
return core.status[name + 'maps'][floorId];
|
||||
|
||||
var arr =
|
||||
main.mode == 'editor' &&
|
||||
!(window.editor && editor.uievent && editor.uievent.isOpen)
|
||||
? core.cloneArray(editor[name + 'map'])
|
||||
: null;
|
||||
if (arr == null)
|
||||
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);
|
||||
}
|
||||
(core.getFlag('__' + name + 'v__', {})[floorId] || []).forEach(function (
|
||||
one
|
||||
) {
|
||||
arr[one[1]][one[0]] = one[2] || 0;
|
||||
});
|
||||
(core.getFlag('__' + name + 'd__', {})[floorId] || []).forEach(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++) {
|
||||
arr[y][x] = arr[y][x].idnum || arr[y][x] || 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (core.status[name + 'maps']) core.status[name + 'maps'][floorId] = arr;
|
||||
return arr;
|
||||
};
|
||||
|
||||
core.plugin.loopMap = {
|
||||
checkLoopMap
|
||||
};
|
||||
@@ -0,0 +1,257 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
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
|
||||
) {
|
||||
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;
|
||||
};
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import { has } from './utils';
|
||||
|
||||
type RangeScanFn<C extends Partial<Loc>> = (
|
||||
collection: Range<C>,
|
||||
data: any
|
||||
@@ -77,8 +79,8 @@ Range.registerRangeType(
|
||||
|
||||
return list.filter(v => {
|
||||
return (
|
||||
core.has(v.x) &&
|
||||
core.has(v.y) &&
|
||||
has(v.x) &&
|
||||
has(v.y) &&
|
||||
Math.abs(v.x - x) <= r &&
|
||||
Math.abs(v.y - y) <= r
|
||||
);
|
||||
@@ -87,8 +89,8 @@ Range.registerRangeType(
|
||||
(col, { x, y, d }, item) => {
|
||||
const r = Math.floor(d / 2);
|
||||
return (
|
||||
core.has(item.x) &&
|
||||
core.has(item.y) &&
|
||||
has(item.x) &&
|
||||
has(item.y) &&
|
||||
Math.abs(item.x - x) <= r &&
|
||||
Math.abs(item.y - y) <= r
|
||||
);
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
export function removeMaps(fromId, toId, force) {
|
||||
export function removeMaps(
|
||||
fromId: FloorIds,
|
||||
toId: FloorIds,
|
||||
force: boolean = false
|
||||
) {
|
||||
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__ || {};
|
||||
// @ts-ignore
|
||||
flags.__visited__ ??= {};
|
||||
flags.__removed__ ??= [];
|
||||
flags.__disabled__ ??= {};
|
||||
// @ts-ignore
|
||||
flags.__leaveLoc__ ??= {};
|
||||
flags.__forceDelete__ ??= {};
|
||||
let deleted = false;
|
||||
for (var i = fromIndex; i <= toIndex; ++i) {
|
||||
@@ -36,11 +42,11 @@ export function removeMaps(fromId, toId, force) {
|
||||
deleted = true;
|
||||
}
|
||||
if (deleted && !main.replayChecking) {
|
||||
Mota.Plugin.require('fly').splitArea();
|
||||
Mota.Plugin.require('fly_r').splitArea();
|
||||
}
|
||||
}
|
||||
|
||||
export function deleteFlags(floorId) {
|
||||
export function deleteFlags(floorId: FloorIds) {
|
||||
delete flags[`jump_${floorId}`];
|
||||
delete flags[`inte_${floorId}`];
|
||||
delete flags[`loop_${floorId}`];
|
||||
@@ -51,7 +57,7 @@ export function deleteFlags(floorId) {
|
||||
// 恢复楼层
|
||||
// core.plugin.removeMap.resumeMaps("MT1", "MT300") 恢复MT1~MT300之间的全部层
|
||||
// core.plugin.removeMap.resumeMaps("MT10") 只恢复MT10层
|
||||
export function resumeMaps(fromId, toId) {
|
||||
export function resumeMaps(fromId: FloorIds, toId: FloorIds) {
|
||||
toId = toId || fromId;
|
||||
var fromIndex = core.floorIds.indexOf(fromId),
|
||||
toIndex = core.floorIds.indexOf(toId);
|
||||
@@ -65,19 +71,21 @@ export function resumeMaps(fromId, toId) {
|
||||
flags.__forceDelete__[floorId]
|
||||
)
|
||||
continue;
|
||||
// @ts-ignore
|
||||
flags.__removed__ = flags.__removed__.filter(f => {
|
||||
return f != floorId;
|
||||
});
|
||||
// @ts-ignore
|
||||
core.status.maps[floorId] = core.loadFloor(floorId);
|
||||
}
|
||||
}
|
||||
|
||||
// 分区砍层相关
|
||||
var inAnyPartition = floorId => {
|
||||
var inAnyPartition = (floorId: FloorIds) => {
|
||||
var inPartition = false;
|
||||
(core.floorPartitions || []).forEach(floor => {
|
||||
var fromIndex = core.floorIds.indexOf(floor[0]);
|
||||
var toIndex = core.floorIds.indexOf(floor[1]);
|
||||
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;
|
||||
@@ -87,29 +95,19 @@ var inAnyPartition = floorId => {
|
||||
};
|
||||
|
||||
// 分区砍层
|
||||
export function autoRemoveMaps(floorId) {
|
||||
export function autoRemoveMaps(floorId: FloorIds) {
|
||||
if (main.mode != 'play' || !inAnyPartition(floorId)) return;
|
||||
// 根据分区信息自动砍层与恢复
|
||||
(core.floorPartitions || []).forEach(floor => {
|
||||
var fromIndex = core.floorIds.indexOf(floor[0]);
|
||||
var toIndex = core.floorIds.indexOf(floor[1]);
|
||||
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.plugin.removeMap.resumeMaps(
|
||||
core.floorIds[fromIndex],
|
||||
core.floorIds[toIndex]
|
||||
);
|
||||
resumeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]);
|
||||
} else {
|
||||
removeMaps(core.floorIds[fromIndex], core.floorIds[toIndex]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
core.plugin.removeMap = {
|
||||
removeMaps,
|
||||
deleteFlags,
|
||||
resumeMaps,
|
||||
autoRemoveMaps
|
||||
};
|
||||
@@ -1,122 +0,0 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
import { studySkill, canStudySkill } from './study';
|
||||
|
||||
const replayableSettings = ['autoSkill'];
|
||||
|
||||
let cliping = false;
|
||||
let startIndex = 0;
|
||||
|
||||
export function ready() {}
|
||||
|
||||
export function readyClip() {
|
||||
cliping = true;
|
||||
return (startIndex = core.status.route.length - 1);
|
||||
}
|
||||
|
||||
export function clip(...replace) {
|
||||
if (!cliping) return;
|
||||
cliping = false;
|
||||
|
||||
core.status.route.splice(startIndex);
|
||||
core.status.route.push(...replace);
|
||||
}
|
||||
|
||||
// 注册修改设置的录像操作
|
||||
core.registerReplayAction('settings', name => {
|
||||
if (!name.startsWith('set:')) return false;
|
||||
const [, setting, value] = name.split(':');
|
||||
const v = eval(value);
|
||||
if (typeof v !== 'boolean') return false;
|
||||
if (!replayableSettings.includes(setting)) return false;
|
||||
flags[setting] = v;
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('upgradeSkill', name => {
|
||||
if (!name.startsWith('skill:')) return false;
|
||||
const skill = parseInt(name.slice(6));
|
||||
core.plugin.skillTree.upgradeSkill(skill);
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('study', name => {
|
||||
// todo
|
||||
// if (!name.startsWith('study:')) return false;
|
||||
// const [num, x, y] = name
|
||||
// .slice(6)
|
||||
// .split(',')
|
||||
// .map(v => parseInt(v));
|
||||
// if (!canStudySkill(num)) return false;
|
||||
// const id = core.getBlockId(x, y);
|
||||
// const enemy = core.getEnemyInfo(id, void 0, x, y);
|
||||
// if (!enemy.special.includes(num)) return false;
|
||||
// studySkill(enemy, num);
|
||||
// core.status.route.push(name);
|
||||
// core.replay();
|
||||
// return true;
|
||||
});
|
||||
|
||||
// 商店
|
||||
let shopOpened = false;
|
||||
let openedShopId = '';
|
||||
core.registerReplayAction('openShop', name => {
|
||||
if (!name.startsWith('openShop:')) return false;
|
||||
if (shopOpened) return false;
|
||||
openedShopId = name.slice(9);
|
||||
shopOpened = true;
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('buy', name => {
|
||||
if (!name.startsWith('buy:') && !name.startsWith('sell:')) return false;
|
||||
if (!shopOpened) return false;
|
||||
if (!openedShopId) return false;
|
||||
const [type, id, num] = name
|
||||
.split(':')
|
||||
.map(v => (/^\d+$/.test(v) ? parseInt(v) : v));
|
||||
const shop = core.status.shops[openedShopId];
|
||||
const item = shop.choices.find(v => v.id === id);
|
||||
if (!item) return false;
|
||||
flags.itemShop ??= {};
|
||||
flags.itemShop[openedShopId] ??= {};
|
||||
flags.itemShop[openedShopId][id] ??= 0;
|
||||
if (num > item.number - flags.itemShop[openedShopId][id]) {
|
||||
return false;
|
||||
}
|
||||
let cost = 0;
|
||||
if (type === 'buy') {
|
||||
cost = item.money * num;
|
||||
} else {
|
||||
cost = -item.sell * num;
|
||||
}
|
||||
if (cost > core.status.hero.money) return false;
|
||||
core.status.hero.money -= cost;
|
||||
flags.itemShop[openedShopId][id] += type === 'buy' ? num : -num;
|
||||
core.addItem(id, type === 'buy' ? num : -num);
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('closeShop', name => {
|
||||
if (name !== 'closeShop') return false;
|
||||
if (!shopOpened) return false;
|
||||
shopOpened = false;
|
||||
openedShopId = '';
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.plugin.replay = {
|
||||
ready,
|
||||
readyClip,
|
||||
clip
|
||||
};
|
||||
@@ -0,0 +1,121 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
import { upgradeSkill } from './skillTree';
|
||||
|
||||
const replayableSettings = ['autoSkill'];
|
||||
|
||||
let cliping = false;
|
||||
let startIndex = 0;
|
||||
|
||||
export function ready() {}
|
||||
|
||||
export function readyClip() {
|
||||
cliping = true;
|
||||
return (startIndex = core.status.route.length - 1);
|
||||
}
|
||||
|
||||
export function clip(...replace: string[]) {
|
||||
if (!cliping) return;
|
||||
cliping = false;
|
||||
|
||||
core.status.route.splice(startIndex);
|
||||
core.status.route.push(...replace);
|
||||
}
|
||||
|
||||
export function init() {
|
||||
// 注册修改设置的录像操作
|
||||
core.registerReplayAction('settings', name => {
|
||||
if (!name.startsWith('set:')) return false;
|
||||
const [, setting, value] = name.split(':');
|
||||
const v = eval(value);
|
||||
if (typeof v !== 'boolean') return false;
|
||||
if (!replayableSettings.includes(setting)) return false;
|
||||
flags[setting] = v;
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('upgradeSkill', name => {
|
||||
if (!name.startsWith('skill:')) return false;
|
||||
const skill = parseInt(name.slice(6));
|
||||
upgradeSkill(skill);
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('study', name => {
|
||||
// todo
|
||||
// if (!name.startsWith('study:')) return false;
|
||||
// const [num, x, y] = name
|
||||
// .slice(6)
|
||||
// .split(',')
|
||||
// .map(v => parseInt(v));
|
||||
// if (!canStudySkill(num)) return false;
|
||||
// const id = core.getBlockId(x, y);
|
||||
// const enemy = core.getEnemyInfo(id, void 0, x, y);
|
||||
// if (!enemy.special.includes(num)) return false;
|
||||
// studySkill(enemy, num);
|
||||
// core.status.route.push(name);
|
||||
// core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
// 商店
|
||||
let shopOpened = false;
|
||||
let openedShopId = '';
|
||||
core.registerReplayAction('openShop', name => {
|
||||
if (!name.startsWith('openShop:')) return false;
|
||||
if (shopOpened) return false;
|
||||
openedShopId = name.slice(9);
|
||||
shopOpened = true;
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('buy', name => {
|
||||
if (!name.startsWith('buy:') && !name.startsWith('sell:')) return false;
|
||||
if (!shopOpened) return false;
|
||||
if (!openedShopId) return false;
|
||||
const [type, id, num] = name
|
||||
.split(':')
|
||||
.map(v => (/^\d+$/.test(v) ? parseInt(v) : v));
|
||||
const shop = core.status.shops[openedShopId] as ItemShopEvent;
|
||||
const item = shop.choices.find(v => v.id === id);
|
||||
if (!item) return false;
|
||||
flags.itemShop ??= {};
|
||||
flags.itemShop[openedShopId] ??= {};
|
||||
flags.itemShop[openedShopId][id] ??= 0;
|
||||
if ((num as number) > item.number - flags.itemShop[openedShopId][id]) {
|
||||
return false;
|
||||
}
|
||||
let cost = 0;
|
||||
if (type === 'buy') {
|
||||
cost = parseInt(item.money) * (num as number);
|
||||
} else {
|
||||
cost = -item.sell * (num as number);
|
||||
}
|
||||
if (cost > core.status.hero.money) return false;
|
||||
core.status.hero.money -= cost;
|
||||
flags.itemShop[openedShopId][id] += type === 'buy' ? num : -num;
|
||||
core.addItem(
|
||||
id as AllIdsOf<'items'>,
|
||||
(type === 'buy' ? num : -num) as number
|
||||
);
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
|
||||
core.registerReplayAction('closeShop', name => {
|
||||
if (name !== 'closeShop') return false;
|
||||
if (!shopOpened) return false;
|
||||
shopOpened = false;
|
||||
openedShopId = '';
|
||||
core.status.route.push(name);
|
||||
core.replay();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -1,27 +1,29 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
const { openItemShop } = core.plugin.gameUi;
|
||||
|
||||
export function openShop(shopId, noRoute) {
|
||||
var shop = core.status.shops[shopId];
|
||||
export function openShop(shopId: string, noRoute: boolean) {
|
||||
const shop = core.status.shops[shopId] as ItemShopEvent;
|
||||
// Step 1: 检查能否打开此商店
|
||||
if (!this.canOpenShop(shopId)) {
|
||||
if (!canOpenShop(shopId)) {
|
||||
core.drawTip('该商店尚未开启');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3: 检查道具商店 or 公共事件
|
||||
if (shop.item) {
|
||||
if (openItemShop) openItemShop(shopId);
|
||||
Mota.r(() => {
|
||||
if (!core.isReplaying()) {
|
||||
Mota.require('var', 'mainUi').open('shop', {
|
||||
shopId: shopId
|
||||
});
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// 是否访问过某个快捷商店
|
||||
export function isShopVisited(id) {
|
||||
export function isShopVisited(id: string) {
|
||||
flags.__shops__ ??= {};
|
||||
var shops = core.getFlag('__shops__');
|
||||
var shops = core.getFlag<any>('__shops__');
|
||||
if (!shops[id]) shops[id] = {};
|
||||
return shops[id].visited;
|
||||
}
|
||||
@@ -29,25 +31,24 @@ export function isShopVisited(id) {
|
||||
/// 当前应当显示的快捷商店列表
|
||||
export function listShopIds() {
|
||||
return Object.keys(core.status.shops).filter(id => {
|
||||
return (
|
||||
core.plugin.shop.isShopVisited(id) ||
|
||||
!core.status.shops[id].mustEnable
|
||||
);
|
||||
// @ts-ignore
|
||||
return isShopVisited(id) || !core.status.shops[id].mustEnable;
|
||||
});
|
||||
}
|
||||
|
||||
/// 是否能够打开某个商店
|
||||
export function canOpenShop(id) {
|
||||
if (this.isShopVisited(id)) return true;
|
||||
export function canOpenShop(id: string) {
|
||||
if (isShopVisited(id)) return true;
|
||||
var shop = core.status.shops[id];
|
||||
// @ts-ignore
|
||||
if (shop.item || shop.commonEvent || shop.mustEnable) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// 启用或禁用某个快捷商店
|
||||
export function setShopVisited(id, visited) {
|
||||
export function setShopVisited(id: string, visited: boolean) {
|
||||
if (!core.hasFlag('__shops__')) core.setFlag('__shops__', {});
|
||||
var shops = core.getFlag('__shops__');
|
||||
var shops = core.getFlag<any>('__shops__');
|
||||
if (!shops[id]) shops[id] = {};
|
||||
if (visited) shops[id].visited = true;
|
||||
else delete shops[id].visited;
|
||||
@@ -63,12 +64,3 @@ export function canUseQuickShop() {
|
||||
return '当前楼层不能使用快捷商店。';
|
||||
return null;
|
||||
}
|
||||
|
||||
core.plugin.shop = {
|
||||
openShop,
|
||||
isShopVisited,
|
||||
listShopIds,
|
||||
canOpenShop,
|
||||
setShopVisited,
|
||||
canUseQuickShop
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
// @ts-nocheck
|
||||
|
||||
// 所有的主动技能效果
|
||||
var ignoreInJump = {
|
||||
@@ -19,8 +19,7 @@ var ignoreInJump = {
|
||||
]
|
||||
};
|
||||
|
||||
/** @type {FloorIds[]} */
|
||||
export const jumpIgnoreFloor = [
|
||||
export const jumpIgnoreFloor: FloorIds[] = [
|
||||
'MT31',
|
||||
'snowTown',
|
||||
'MT36',
|
||||
@@ -178,8 +177,3 @@ export function jumpSkill() {
|
||||
return { x: x, y: y };
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.skillEffects = {
|
||||
jumpSkill,
|
||||
jumpIgnoreFloor
|
||||
};
|
||||
@@ -1,14 +1,11 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
|
||||
/**
|
||||
* @type {number[]}
|
||||
*/
|
||||
let levels = [];
|
||||
let levels: number[] = [];
|
||||
|
||||
/**
|
||||
* @type {Record<Chapter, Skill[]>}
|
||||
*/
|
||||
const skills = {
|
||||
export const skills: Record<Chapter, Skill[]> = {
|
||||
chapter1: [
|
||||
{
|
||||
index: 0,
|
||||
@@ -195,13 +192,11 @@ const skills = {
|
||||
]
|
||||
};
|
||||
|
||||
core.plugin.skills = skills;
|
||||
|
||||
export function resetSkillLevel() {
|
||||
levels = [];
|
||||
}
|
||||
|
||||
export function getSkillFromIndex(index) {
|
||||
export function getSkillFromIndex(index: number) {
|
||||
for (const [, skill] of Object.entries(skills)) {
|
||||
const s = skill.find(v => v.index === index);
|
||||
if (s) return s;
|
||||
@@ -212,16 +207,21 @@ export function getSkillFromIndex(index) {
|
||||
* 获取技能等级
|
||||
* @param {number} skill
|
||||
*/
|
||||
export function getSkillLevel(skill) {
|
||||
export function getSkillLevel(skill: number) {
|
||||
return (levels[skill] ??= 0);
|
||||
}
|
||||
|
||||
export function getSkillConsume(skill) {
|
||||
export function getSkillConsume(skill: number) {
|
||||
return eval(
|
||||
getSkillFromIndex(skill).consume.replace(/level(:\d+)?/g, (str, $1) => {
|
||||
if ($1) return `core.plugin.skillTree.getSkillLevel(${$1})`;
|
||||
else return `core.plugin.skillTree.getSkillLevel(${skill})`;
|
||||
})
|
||||
getSkillFromIndex(skill)?.consume.replace(
|
||||
/level(:\d+)?/g,
|
||||
(str, $1) => {
|
||||
if ($1)
|
||||
return `Mota.Plugin.require('skillTree_g').getSkillLevel(${$1})`;
|
||||
else
|
||||
return `Mota.Plugin.require('skillTree_g').getSkillLevel(${skill})`;
|
||||
}
|
||||
) ?? ''
|
||||
);
|
||||
}
|
||||
|
||||
@@ -232,17 +232,16 @@ export function openTree() {
|
||||
|
||||
/**
|
||||
* 能否升级某个技能
|
||||
* @param {number} skill
|
||||
*/
|
||||
export function canUpgrade(skill) {
|
||||
const consume = core.plugin.skillTree.getSkillConsume(skill);
|
||||
export function canUpgrade(skill: number) {
|
||||
const consume = getSkillConsume(skill);
|
||||
if (consume > core.status.hero.mdef) return false;
|
||||
const level = core.plugin.skillTree.getSkillLevel(skill);
|
||||
const level = getSkillLevel(skill);
|
||||
const s = getSkillFromIndex(skill);
|
||||
if (level === s.max) return false;
|
||||
const front = s.front;
|
||||
if (level === s?.max) return false;
|
||||
const front = s?.front ?? [];
|
||||
for (const [skill, level] of front) {
|
||||
if (core.plugin.skillTree.getSkillLevel(skill) < level) return false;
|
||||
if (getSkillLevel(skill) < level) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -251,7 +250,7 @@ export function canUpgrade(skill) {
|
||||
* 实际升级效果
|
||||
* @param {number} skill
|
||||
*/
|
||||
export function upgradeSkill(skill) {
|
||||
export function upgradeSkill(skill: number) {
|
||||
if (!canUpgrade(skill)) return false;
|
||||
switch (skill) {
|
||||
case 0: // 力量 +2攻击
|
||||
@@ -302,17 +301,6 @@ export function saveSkillTree() {
|
||||
return levels.slice();
|
||||
}
|
||||
|
||||
export function loadSkillTree(data) {
|
||||
export function loadSkillTree(data: number[]) {
|
||||
levels = data ?? [];
|
||||
}
|
||||
|
||||
core.plugin.skillTree = {
|
||||
getSkillConsume,
|
||||
getSkillFromIndex,
|
||||
getSkillLevel,
|
||||
saveSkillTree,
|
||||
loadSkillTree,
|
||||
upgradeSkill,
|
||||
openTree,
|
||||
resetSkillLevel
|
||||
};
|
||||
@@ -12,7 +12,8 @@ const cannotStudy = [9, 12, 14, 15, 24];
|
||||
|
||||
export function canStudySkill(number: number) {
|
||||
const s = (core.status.hero.special ??= { num: [], last: [] });
|
||||
if (core.plugin.skillTree.getSkillLevel(11) === 0) return false;
|
||||
if (Mota.Plugin.require('skillTree_g').getSkillLevel(11) === 0)
|
||||
return false;
|
||||
if (s.num.length >= 1) return false;
|
||||
if (s.num.includes(number)) return false;
|
||||
if (cannotStudy.includes(number)) return false;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
// @ts-nocheck
|
||||
import { clip } from './replay.js';
|
||||
|
||||
// 1000多行,改不动了,原来什么样就什么样吧
|
||||
@@ -11,7 +11,7 @@ var stage = 1,
|
||||
boomLocs = [], // 随机轰炸
|
||||
heroHp;
|
||||
// 初始化
|
||||
function initTowerBoss() {
|
||||
export function initTowerBoss() {
|
||||
stage = 1;
|
||||
hp = 10000;
|
||||
seconds = 0;
|
||||
@@ -496,7 +496,7 @@ function intelligentArrow(fromSelf) {
|
||||
damaged[loc + direction] = true;
|
||||
core.drawHeroAnimate('hand');
|
||||
core.status.hero.hp -= 1000;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-1000
|
||||
@@ -515,7 +515,7 @@ function intelligentArrow(fromSelf) {
|
||||
damaged[loc + direction] = true;
|
||||
core.drawHeroAnimate('hand');
|
||||
core.status.hero.hp -= 1000;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-1000
|
||||
@@ -645,7 +645,7 @@ function icyMomentem() {
|
||||
if (x == locs[index][0] && y == locs[index][1]) {
|
||||
core.drawHeroAnimate('hand');
|
||||
core.status.hero.hp -= 5000;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-5000
|
||||
@@ -824,7 +824,7 @@ function getThunderDamage(x, y, power) {
|
||||
hy = core.status.hero.loc.y;
|
||||
if (Math.abs(hx - x) <= 1 && Math.abs(hy - y) <= 1) {
|
||||
core.status.hero.hp -= 3000 * power;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-3000 * power
|
||||
@@ -992,7 +992,7 @@ function ballThunder() {
|
||||
) {
|
||||
damaged[i] = true;
|
||||
core.status.hero.hp -= 3000;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-3000
|
||||
@@ -1502,7 +1502,7 @@ function boomingAnimate() {
|
||||
hy = core.status.hero.loc.y;
|
||||
if (loc[0] == hx && loc[1] == hy) {
|
||||
core.status.hero.hp -= 3000;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-3000
|
||||
@@ -1545,7 +1545,7 @@ function lineDamage(x1, y1, x2, y2, damage) {
|
||||
n2 = ((y2 - y1) / (x2 - x1)) * (loc2[0] - x1) + y1 - loc2[1];
|
||||
if (n1 * n2 <= 0) {
|
||||
core.status.hero.hp -= damage;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-damage
|
||||
@@ -1569,7 +1569,7 @@ function lineDamage(x1, y1, x2, y2, damage) {
|
||||
n2 = ((y2 - y1) / (x2 - x1)) * (loc2[0] - x1) + y1 - loc2[1];
|
||||
if (n1 * n2 <= 0) {
|
||||
core.status.hero.hp -= damage;
|
||||
Mota.Plugin.require('pop').addPop(
|
||||
Mota.Plugin.require('pop_r').addPop(
|
||||
x * 32 + 16,
|
||||
y * 32 + 16,
|
||||
-damage
|
||||
@@ -1587,9 +1587,3 @@ function lineDamage(x1, y1, x2, y2, damage) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.towerBoss = {
|
||||
initTowerBoss
|
||||
};
|
||||
|
||||
export {};
|
||||
@@ -1,29 +1,8 @@
|
||||
///<reference path="../../../src/types/core.d.ts" />
|
||||
export {};
|
||||
// @ts-nocheck
|
||||
|
||||
(function () {
|
||||
export function init() {
|
||||
const { mainUi, fixedUi } = Mota.requireAll('var');
|
||||
|
||||
if (main.replayChecking)
|
||||
return (core.plugin.gameUi = {
|
||||
openItemShop: () => 0,
|
||||
openSkill: () => 0
|
||||
});
|
||||
|
||||
function openItemShop(itemShopId) {
|
||||
if (!core.isReplaying()) {
|
||||
Mota.require('var', 'mainUi').open('shop', {
|
||||
shopId: itemShopId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateVueStatusBar() {
|
||||
if (main.replayChecking) return;
|
||||
const status = Mota.Plugin.require('status');
|
||||
status.statusBarStatus.value = !status.statusBarStatus.value;
|
||||
}
|
||||
|
||||
ui.prototype.drawBook = function () {
|
||||
if (!core.isReplaying()) return mainUi.open('book');
|
||||
};
|
||||
@@ -86,14 +65,11 @@ export {};
|
||||
core.dom.toolBar.style.display = 'none';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function openSkill() {
|
||||
if (core.isReplaying()) return;
|
||||
mainUi.open('skill');
|
||||
}
|
||||
|
||||
core.plugin.gameUi = {
|
||||
openItemShop,
|
||||
openSkill
|
||||
};
|
||||
})();
|
||||
function updateVueStatusBar() {
|
||||
Mota.r(() => {
|
||||
const status = Mota.require('var', 'status');
|
||||
status.value = !status.value;
|
||||
});
|
||||
}
|
||||
@@ -169,18 +169,3 @@ export function findDir(from: Loc, to: Loc): Dir2 | 'none' {
|
||||
})?.[0] as Dir2) ?? 'none'
|
||||
);
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface GamePluginUtils {
|
||||
ofDir: typeof ofDir;
|
||||
}
|
||||
}
|
||||
|
||||
core.plugin.utils = {
|
||||
slide,
|
||||
backDir,
|
||||
has,
|
||||
maxGameScale,
|
||||
ofDir
|
||||
};
|
||||
core.has = has;
|
||||
+5
-4
@@ -35,8 +35,8 @@ const marked: MarkInfo<EnemyIds>[] = [];
|
||||
*/
|
||||
export function markEnemy(id: EnemyIds) {
|
||||
if (hasMarkedEnemy(id)) return;
|
||||
const { Enemy } = core.plugin.damage;
|
||||
const enemy = new Enemy(core.material.enemys[id]);
|
||||
const { DamageEnemy } = Mota.Plugin.require('damage_g');
|
||||
const enemy = new DamageEnemy(core.material.enemys[id]);
|
||||
enemy.calAttribute();
|
||||
enemy.getRealInfo();
|
||||
|
||||
@@ -44,7 +44,7 @@ export function markEnemy(id: EnemyIds) {
|
||||
id,
|
||||
enemy,
|
||||
mode: 0b011111,
|
||||
lastAtk: core.plugin.hero.getHeroStatusOn('atk', 'empty'),
|
||||
lastAtk: Mota.Plugin.require('hero_g').getHeroStatusOn('atk', 'empty'),
|
||||
lastDamage: enemy.calDamage().damage,
|
||||
status: 0b0,
|
||||
update: ref(true)
|
||||
@@ -66,9 +66,10 @@ export function unmarkEnemy(id: EnemyIds) {
|
||||
}
|
||||
|
||||
export function checkMarkedEnemy() {
|
||||
const { getHeroStatusOn } = Mota.Plugin.require('hero_g');
|
||||
marked.forEach(v => {
|
||||
const { id, enemy, mode, lastAtk, lastDamage, markDamage } = v;
|
||||
const atk = core.plugin.hero.getHeroStatusOn('atk', 'empty');
|
||||
const atk = getHeroStatusOn('atk', 'empty');
|
||||
let tip = 0;
|
||||
if (mode & 0b11110) {
|
||||
const damage = enemy.calDamage().damage;
|
||||
|
||||
@@ -36,26 +36,11 @@ export interface Light {
|
||||
_offset?: Loc;
|
||||
}
|
||||
|
||||
export default function init() {
|
||||
export function init() {
|
||||
core.registerAnimationFrame('shadow', true, () => {
|
||||
if (!needRefresh) return;
|
||||
drawShadow();
|
||||
});
|
||||
|
||||
return {
|
||||
initShadowCanvas,
|
||||
drawShadow,
|
||||
addLight,
|
||||
removeLight,
|
||||
setLight,
|
||||
setShadowNodes,
|
||||
setBackground,
|
||||
animateLight,
|
||||
transitionLight,
|
||||
moveLightAs,
|
||||
getAllLights,
|
||||
refreshLight
|
||||
};
|
||||
}
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
|
||||
@@ -59,13 +59,14 @@ export function getNowStatus(nowEquip?: Equip, onCol: boolean = false) {
|
||||
'hpmax',
|
||||
'money'
|
||||
] as (keyof SelectType<HeroStatus, number>)[];
|
||||
const { getHeroStatusOn } = Mota.Plugin.require('hero_g');
|
||||
|
||||
return (
|
||||
<div id="hero-status">
|
||||
{toShow.map(v => {
|
||||
let status: string;
|
||||
if (v === 'lv') status = core.getLvName() ?? '';
|
||||
else status = core.plugin.hero.getHeroStatusOn(v)?.toString();
|
||||
else status = getHeroStatusOn(v)?.toString();
|
||||
|
||||
let add = 0;
|
||||
if (has(nowEquip)) {
|
||||
|
||||
@@ -29,7 +29,7 @@ export function getDetailedEnemy(
|
||||
return typeof func === 'string' ? func : func(enemy);
|
||||
};
|
||||
const special: [string, string, string][] = enemy.enemy.special.map(vv => {
|
||||
const s = core.plugin.special[vv];
|
||||
const s = Mota.Plugin.require('special_g').special[vv];
|
||||
return [
|
||||
fromFunc(s.name, enemy.enemy),
|
||||
fromFunc(s.desc, enemy.enemy),
|
||||
|
||||
+3
-1
@@ -225,6 +225,7 @@ export async function doByInterval(
|
||||
|
||||
/**
|
||||
* 更改一个本地存储
|
||||
* @deprecated
|
||||
* @param name 要更改的信息
|
||||
* @param fn 更改时执行的函数
|
||||
* @param defaultValue 如果不存在时获取的默认值
|
||||
@@ -287,7 +288,8 @@ export function spliceBy<T>(arr: T[], from: T): T[] {
|
||||
}
|
||||
|
||||
export async function triggerFullscreen(full: boolean) {
|
||||
const { maxGameScale } = core.plugin.utils;
|
||||
if (!Mota.Plugin.inited) return;
|
||||
const { maxGameScale } = Mota.Plugin.require('utils_g');
|
||||
if (!!document.fullscreenElement && !full) {
|
||||
await document.exitFullscreen();
|
||||
requestAnimationFrame(() => {
|
||||
|
||||
Reference in new issue
Block a user