diff --git a/public/libs/control.js b/public/libs/control.js index f534556..a3cd94a 100644 --- a/public/libs/control.js +++ b/public/libs/control.js @@ -1587,25 +1587,8 @@ control.prototype._drawDamage_draw = function (ctx, onMap) { core.plugin.halo.drawHalo(ctx, onMap); core.setFont(ctx, "14px 'normal'"); - core.setTextAlign(ctx, 'left'); - core.status.damage.data.forEach(function (one) { - var px = one.px, - py = one.py; - if (onMap && core.bigmap.v2) { - px -= core.bigmap.posX * 32; - py -= core.bigmap.posY * 32; - if ( - px < -32 * 2 || - px > core._PX_ + 32 || - py < -32 || - py > core._PY_ + 32 - ) - return; - } - core.fillBoldText(ctx, one.text, px, py, one.color); - }); - core.setTextAlign(ctx, 'center'); + core.setTextBaseline(ctx, 'middle'); core.status.damage.extraData.forEach(function (one) { var px = one.px, py = one.py; @@ -1624,6 +1607,25 @@ control.prototype._drawDamage_draw = function (ctx, onMap) { core.fillBoldText(ctx, one.text, px, py, one.color); 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); + }); }; // ------ 录像相关 ------ // diff --git a/src/plugin/game/damage.ts b/src/plugin/game/damage.ts index f4a6345..4fd46da 100644 --- a/src/plugin/game/damage.ts +++ b/src/plugin/game/damage.ts @@ -1,3 +1,4 @@ +import { boundary, equal } from './utils'; import { getHeroStatusOf, getHeroStatusOn } from './hero'; import { Range, RangeCollection } from './range'; import { @@ -32,7 +33,7 @@ interface EnemyInfo { interface DamageInfo { damage: number; - /** 从勇士位置指向怪物的方向 */ + /** 从怪物位置指向勇士的方向 */ dir: Dir | 'none'; x?: number; y?: number; @@ -203,16 +204,55 @@ export class EnemyCollection implements RangeCollection { `Unexpected null of enemy's damage. Loc: '${v.x},${v.y}'. Floor: ${v.floorId}` ); } - for (const dam of v.damage) { - if (dam.dir === 'none') { - // 怪物本身所在位置 - const { damage, color } = formatDamage(dam.damage); - core.status.damage.data.push({ - text: damage, - px: 32 * v.x! + 1, - py: 32 * (v.y! + 1) - 1, - color: color - }); + if (equal(v.damage, 'damage')) { + // 伤害全部相等,绘制在怪物本身所在位置 + const { damage, color } = formatDamage(v.damage[0].damage); + core.status.damage.data.push({ + text: damage, + px: 32 * v.x! + 1, + py: 32 * (v.y! + 1) - 1, + color: color + }); + } else { + const [min, max] = boundary(v.damage, 'damage'); + const delta = max - min; + const { damage, color } = formatDamage(min); + // 在怪物位置绘制最低的伤害 + core.status.damage.data.push({ + text: damage, + px: 32 * v.x! + 1, + py: 32 * (v.y! + 1) - 1, + color: color + }); + // 然后根据位置依次绘制对应位置的伤害 + for (const dam of v.damage) { + const d = (dam.damage - min) / delta; + const color = core.arrayToRGB([d * 255, 255 - d * 255, 0]); + if (dam.dir === 'down' || dam.dir === 'up') { + const dir = dam.dir === 'down' ? '↑' : '↓'; + core.status.damage.extraData.push({ + text: dir, + px: 32 * v.x! + 16, + py: + 32 * v.y! + + 16 + + core.utils.scan[dam.dir].y * 16, + color: color, + alpha: 1 + }); + } else if (dam.dir === 'left' || dam.dir === 'right') { + const dir = dam.dir === 'left' ? '→' : '←'; + core.status.damage.extraData.push({ + text: dir, + px: + 32 * v.x! + + 16 + + core.utils.scan[dam.dir].x * 16, + py: 32 * v.y! + 16, + color: color, + alpha: 1 + }); + } } } }); @@ -259,7 +299,7 @@ export class EnemyCollection implements RangeCollection { core.status.damage.extraData.push({ text: damage, px: 32 * x + 16, - py: 32 * (y + 1) - 14, + py: 32 * y + 16, color, alpha: 1 }); @@ -435,10 +475,10 @@ export class DamageEnemy { * @param progress 期望进度 */ ensureCaled(progress: number) { - if (progress <= 1) this.preProvideHalo(); - if (progress <= 2) this.calAttribute(); - if (progress <= 3) this.provideHalo(); - if (progress <= 4) this.getRealInfo(); + if (progress >= 1) this.preProvideHalo(); + if (progress >= 2) this.calAttribute(); + if (progress >= 3) this.provideHalo(); + if (progress >= 4) this.getRealInfo(); } getHaloSpecials(): number[] { @@ -591,8 +631,7 @@ export class DamageEnemy { let x = this.x; let y = this.y; const { x: dx, y: dy } = core.utils.scan[dir]; - while (1) { - if (x < 0 || y < 0 || x >= w || y >= h) break; + while (x >= 0 && y >= 0 && x < w && y < h) { x += dx; y += dy; const loc = `${x},${y}` as LocString; @@ -707,7 +746,7 @@ export class DamageEnemy { /** * 计算怪物临界,计算临界时,根据当前方向计算临界,但也会输出与当前最少伤害的伤害差值 * @param num 要计算多少个临界 - * @param dir 从勇士位置指向怪物的方向 + * @param dir 从怪物位置指向勇士的方向 * @param hero 勇士属性,最终结果将会与由此属性计算出的伤害相减计算减伤 */ calCritical( @@ -767,6 +806,7 @@ export class DamageEnemy { let curr = hero.atk!; let start = curr; let end = seckill; + let ori = origin.damage; let i = 0; while (1) { @@ -798,11 +838,12 @@ export class DamageEnemy { for (let i = 0; i < d.length - 1; i++) { const [a, dam] = d[i]; const [na, ndam] = d[i + 1]; - if (na < damage) { + if (ndam < damage) { start = a; end = na; cal = true; } + ori = dam; } } }); @@ -813,7 +854,7 @@ export class DamageEnemy { const damage = calDamageWith(this.info, { atk: curr, def }) ?? Infinity; damageCache[curr] = damage; - if (damage < origin.damage) { + if (damage < ori) { end = curr; } else { start = curr; @@ -832,7 +873,7 @@ export class DamageEnemy { /** * 计算n防减伤 * @param num 要加多少防御 - * @param dir 从勇士位置指向怪物的方向 + * @param dir 从怪物位置指向勇士的方向 * @param hero 勇士属性,最终结果将会与由此属性计算出的伤害相减计算减伤 */ calDefDamage( @@ -915,6 +956,7 @@ const skills: [unlock: string, condition: string][] = [ * @param x 怪物横坐标 * @param y 怪物纵坐标 * @param floorId 怪物所在楼层 + * @returns 由怪物方向指向勇士的方向 */ export function getNeedCalDir( x?: number, @@ -941,7 +983,8 @@ export function getNeedCalDir( if (tx < 0 || ty < 0 || tx >= width || ty >= height) return false; const index = `${tx},${ty}` as LocString; const block = blocks[index]; - if (!block || block.event.noPass) return false; + if (!block) return true; + if (block.event.noPass) return false; if (!core.canMoveHero(tx, ty, backDir(v), floorId)) return false; return true; diff --git a/src/plugin/game/utils.ts b/src/plugin/game/utils.ts index 56a1dbb..3fb7f24 100644 --- a/src/plugin/game/utils.ts +++ b/src/plugin/game/utils.ts @@ -97,6 +97,45 @@ export function formatDamage(damage: number): DamageString { return { damage: dam, color: color as Color }; } +export function equal(arr: number[]): boolean; +export function equal(arr: T[], key: keyof T): boolean; +export function equal(arr: any, key?: any) { + if (has(key)) { + for (let i = 1; i < arr.length; i++) { + if (arr[i][key] !== arr[0][key]) return false; + } + return true; + } else { + for (let i = 1; i < arr.length; i++) { + if (arr[i] !== arr[0]) return false; + } + return true; + } +} + +export function boundary(arr: number[]): [number, number]; +export function boundary(arr: T[], key: keyof T): [number, number]; +export function boundary(arr: any, key?: any) { + if (has(key)) { + let min = arr[0][key]; + let max = arr[0][key]; + for (let i = 1; i < arr.length; i++) { + const ele = arr[i][key]; + if (ele < min) min = ele; + if (ele > max) max = ele; + } + return [min, max]; + } else { + let min = arr[0]; + let max = arr[0]; + for (let i = 1; i < arr.length; i++) { + const ele = arr[i]; + if (ele < min) min = ele; + if (ele > max) max = ele; + } + return [min, max]; + } +} declare global { interface GamePluginUtils { ofDir: typeof ofDir; diff --git a/src/types/util.d.ts b/src/types/util.d.ts index d0d6171..ff9ebe4 100644 --- a/src/types/util.d.ts +++ b/src/types/util.d.ts @@ -265,7 +265,7 @@ interface Utils { * @param color 一行三列的数组,各元素必须为不大于255的自然数 * @returns 该颜色的十六进制表示,使用小写字母 */ - arrayToRGB(color: RGBArray): string; + arrayToRGB(color: RGBArray): _RGBA; /** * 颜色数组转字符串