From 39f38cd7036541aa5efaa06506f3a394c110836a Mon Sep 17 00:00:00 2001
From: unanmed <1319491857@qq.com>
Date: Mon, 30 Sep 2024 10:35:25 +0800
Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=89=B9=E6=AE=8A=E5=B1=9E?=
 =?UTF-8?q?=E6=80=A7=E6=94=B9=E6=88=90=E9=9B=86=E5=90=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/core/render/preset/damage.ts |   4 +-
 src/game/enemy/battle.ts         |   8 +--
 src/game/enemy/damage.ts         | 103 +++++++++++++------------------
 src/plugin/game/replay.ts        |  19 ------
 src/plugin/ui/fixed.ts           |   2 +-
 src/ui/fixed.vue                 |   2 +-
 6 files changed, 51 insertions(+), 87 deletions(-)

diff --git a/src/core/render/preset/damage.ts b/src/core/render/preset/damage.ts
index e94cc10..d54ecdf 100644
--- a/src/core/render/preset/damage.ts
+++ b/src/core/render/preset/damage.ts
@@ -340,7 +340,7 @@ export class Damage extends Sprite<EDamageEvent> {
         };
         block.add(dam1).add(dam2);
 
-        if (real.special.includes(8) && real.togetherNum) {
+        if (real.special.has(8) && real.togetherNum) {
             const dam3: DamageRenderable = {
                 align: 'right',
                 baseline: 'top',
@@ -352,7 +352,7 @@ export class Damage extends Sprite<EDamageEvent> {
             };
             block.add(dam3);
         }
-        if (real.special.includes(30)) {
+        if (real.special.has(30)) {
             const dam4: DamageRenderable = {
                 align: 'left',
                 baseline: 'top',
diff --git a/src/game/enemy/battle.ts b/src/game/enemy/battle.ts
index d530361..ccc51a1 100644
--- a/src/game/enemy/battle.ts
+++ b/src/game/enemy/battle.ts
@@ -192,7 +192,7 @@ function init() {
         core.status.hero.statistics.battle++;
 
         // 智慧之源
-        if (special.includes(14) && flags.hard === 2) {
+        if (special.has(14) && flags.hard === 2) {
             core.addFlag(
                 'inte_' + floorId,
                 Math.ceil((core.status.hero.mdef / 10) * 0.3) * 10
@@ -202,11 +202,11 @@ function init() {
         }
 
         // 极昼永夜
-        if (special.includes(22)) {
+        if (special.has(22)) {
             flags[`night_${floorId}`] ??= 0;
             flags[`night_${floorId}`] -= enemy.info.night!;
         }
-        if (special.includes(23)) {
+        if (special.has(23)) {
             flags[`night_${floorId}`] ??= 0;
             flags[`night_${floorId}`] += enemy.info.day;
         }
@@ -216,7 +216,7 @@ function init() {
         // }
 
         // 如果是融化怪,需要特殊标记一下
-        if (special.includes(25) && has(x) && has(y)) {
+        if (special.has(25) && has(x) && has(y)) {
             flags[`melt_${floorId}`] ??= {};
             flags[`melt_${floorId}`][`${x},${y}`] = enemy.info.melt;
         }
diff --git a/src/game/enemy/damage.ts b/src/game/enemy/damage.ts
index 891a365..8adafce 100644
--- a/src/game/enemy/damage.ts
+++ b/src/game/enemy/damage.ts
@@ -1,12 +1,6 @@
 import { getHeroStatusOf, getHeroStatusOn } from '@/game/state/hero';
 import { Range, RangeCollection } from '@/plugin/game/range';
-import {
-    checkV2,
-    ensureArray,
-    formatDamage,
-    has,
-    manhattan
-} from '@/plugin/game/utils';
+import { ensureArray, has, manhattan } from '@/plugin/game/utils';
 import EventEmitter from 'eventemitter3';
 
 // todo: 光环划分优先级,从而可以实现光环的多级运算
@@ -24,11 +18,11 @@ interface HaloType {
     };
 }
 
-export interface EnemyInfo extends Partial<Enemy> {
+export interface EnemyInfo extends Partial<Omit<Enemy, 'special'>> {
     atk: number;
     def: number;
     hp: number;
-    special: number[];
+    special: Set<number>;
     damageDecline: number;
     atkBuff_: number;
     defBuff_: number;
@@ -280,7 +274,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
             hp: enemy.hp,
             atk: enemy.atk,
             def: enemy.def,
-            special: enemy.special.slice(),
+            special: new Set(enemy.special),
             damageDecline: 0,
             atkBuff_: 0,
             defBuff_: 0,
@@ -323,7 +317,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         }
 
         // 智慧之源
-        if (flags.hard === 2 && special.includes(14)) {
+        if (flags.hard === 2 && special.has(14)) {
             info.atk += flags[`inte_${floorId}`] ?? 0;
         }
 
@@ -368,21 +362,17 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         return this.info;
     }
 
-    getHaloSpecials(): number[] {
-        if (!this.floorId) return [];
-        if (!has(this.x) || !has(this.y)) return [];
+    getHaloSpecials(): Set<number> {
+        if (!this.floorId) return new Set();
+        if (!has(this.x) || !has(this.y)) return new Set();
         const special = this.info.special ?? this.enemy.special;
-        const filter = special.filter(v => {
-            return haloSpecials.has(v) && !this.providedHalo.has(v);
+        const res = new Set<number>();
+        special.forEach(v => {
+            if (haloSpecials.has(v) && !this.providedHalo.has(v)) {
+                res.add(v);
+            }
         });
-        if (filter.length === 0) return [];
-        const collection = this.col ?? core.status.maps[this.floorId].enemy;
-        if (!collection) {
-            throw new Error(
-                `Unexpected undefined of enemy collection in floor ${this.floorId}.`
-            );
-        }
-        return filter;
+        return res;
     }
 
     /**
@@ -421,9 +411,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
                             const s = enemy.specialHalo!;
 
                             for (const spe of s) {
-                                // 防止重复
-                                if (!e.special.includes(spe))
-                                    e.special.push(spe);
+                                e.special.add(spe);
                             }
                             // 如果是自身,就不进行特殊属性数值处理了
                             if (e === this.info) return;
@@ -476,14 +464,14 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         // e 是被加成怪的属性,enemy 是施加光环的怪
 
         // 抱团
-        if (special.includes(8)) {
+        if (special.has(8)) {
             col.applyHalo(
                 'square',
                 { x: this.x, y: this.y, d: 5 },
                 this,
                 (e, enemy) => {
                     if (
-                        e.special.includes(8) &&
+                        e.special.has(8) &&
                         (e.x !== this.x || this.y !== e.y)
                     ) {
                         e.atkBuff_ += enemy.together ?? 0;
@@ -497,7 +485,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         }
 
         // 冰封光环
-        if (special.includes(21)) {
+        if (special.has(21)) {
             square7.push(e => {
                 e.damageDecline += this.info.iceHalo ?? 0;
             });
@@ -511,7 +499,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         }
 
         // 冰封之核
-        if (special.includes(26)) {
+        if (special.has(26)) {
             square5.push(e => {
                 e.defBuff_ += this.info.iceCore ?? 0;
             });
@@ -525,7 +513,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         }
 
         // 火焰之核
-        if (special.includes(27)) {
+        if (special.has(27)) {
             square5.push(e => {
                 e.atkBuff_ += this.info.fireCore ?? 0;
             });
@@ -539,7 +527,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         }
 
         // 再生光环
-        if (special.includes(31)) {
+        if (special.has(31)) {
             square7.push(e => {
                 e.hpBuff_ += this.info.hpHalo ?? 0;
             });
@@ -553,7 +541,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         }
 
         // 同化,它不会被光环类属性影响,因此放到这
-        if (special.includes(32)) {
+        if (special.has(32)) {
             const e = this.info;
             const type = 'square';
             const r = Math.floor(e.assimilateRange!);
@@ -567,10 +555,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
 
                 for (const spe of s) {
                     if (unassimilatable.has(spe)) continue;
-                    // 防止重复
-                    if (!enemy.special.includes(spe)) {
-                        enemy.special.push(spe);
-                    }
+                    enemy.special.add(spe);
                 }
                 // 然后计算特殊属性数值
                 for (const spec of s) {
@@ -643,7 +628,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         const h = floor.height;
 
         // 突刺
-        if (this.info.special.includes(15)) {
+        if (this.info.special.has(15)) {
             const range = enemy.range ?? 1;
             const startX = Math.max(0, this.x - range);
             const startY = Math.max(0, this.y - range);
@@ -666,7 +651,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         }
 
         // 射击
-        if (this.info.special.includes(24)) {
+        if (this.info.special.has(24)) {
             const dirs: Dir[] = ['left', 'down', 'up', 'right'];
             const dam = Math.max((enemy.atk ?? 0) - hero.def!, 0);
             const objs = core.getMapBlocksObj(this.floorId);
@@ -683,8 +668,6 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
                     if (
                         block &&
                         block.event.noPass &&
-                        block.event.cls !== 'enemys' &&
-                        block.event.cls !== 'enemy48' &&
                         block.id !== 141 &&
                         block.id !== 151
                     ) {
@@ -696,7 +679,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         }
 
         // 电摇嘲讽
-        if (this.info.special.includes(19)) {
+        if (this.info.special.has(19)) {
             const objs = core.getMapBlocksObj(this.floorId);
             for (let nx = 0; nx < w; nx++) {
                 const loc = `${nx},${this.y}` as LocString;
@@ -719,7 +702,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         }
 
         // 追猎
-        if (this.info.special.includes(12)) {
+        if (this.info.special.has(12)) {
             const objs = core.getMapBlocksObj(this.floorId);
             for (let nx = 0; nx < w; nx++) {
                 const loc = `${nx},${this.y}` as LocString;
@@ -922,13 +905,13 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         const add = info.def + info.hp - core.status.hero.mana;
 
         // 坚固,不可能通过攻击秒杀
-        if (info.special.includes(3)) {
+        if (info.special.has(3)) {
             return Infinity;
         }
 
         // 列方程求解,拿笔算一下就知道了
         // 饥渴,会偷取勇士攻击
-        if (info.special.includes(7)) {
+        if (info.special.has(7)) {
             if (info.damageDecline === 0) {
                 return add / (1 - this.enemy.hungry! / 100);
             } else {
@@ -942,7 +925,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         }
 
         // 霜冻
-        if (info.special.includes(20) && !core.hasEquip('I589')) {
+        if (info.special.has(20) && !core.hasEquip('I589')) {
             return (
                 info.def +
                 info.hp / (1 - this.enemy.ice! / 100) -
@@ -998,7 +981,7 @@ export function calDamageWith(
     let damage = 0;
 
     // 饥渴
-    if (special.includes(7)) {
+    if (special.has(7)) {
         const delta = Math.floor((atk * info.hungry!) / 100);
         atk -= delta;
         monAtk += delta;
@@ -1007,10 +990,10 @@ export function calDamageWith(
     let heroPerDamage: number;
 
     // 绝对防御
-    if (special.includes(9)) {
+    if (special.has(9)) {
         heroPerDamage = atk + mana - monDef;
         if (heroPerDamage <= 0) return null;
-    } else if (special.includes(3)) {
+    } else if (special.has(3)) {
         // 由于坚固的特性,只能放到这来计算了
         if (atk > enemy.def) heroPerDamage = 1 + mana;
         else return null;
@@ -1021,7 +1004,7 @@ export function calDamageWith(
     }
 
     // 霜冻
-    if (special.includes(20) && !core.hasEquip('I589')) {
+    if (special.has(20) && !core.hasEquip('I589')) {
         heroPerDamage *= 1 - info.ice! / 100;
     }
 
@@ -1030,7 +1013,7 @@ export function calDamageWith(
     let enemyPerDamage: number;
 
     // 魔攻
-    if (special.includes(2) || special.includes(13)) {
+    if (special.has(2) || special.has(13)) {
         enemyPerDamage = monAtk;
         enemyPerDamage -= magicDef;
     } else {
@@ -1038,38 +1021,38 @@ export function calDamageWith(
     }
 
     // 连击
-    if (special.includes(4)) enemyPerDamage *= 2;
-    if (special.includes(5)) enemyPerDamage *= 3;
-    if (special.includes(6)) enemyPerDamage *= info.n!;
+    if (special.has(4)) enemyPerDamage *= 2;
+    if (special.has(5)) enemyPerDamage *= 3;
+    if (special.has(6)) enemyPerDamage *= info.n!;
 
     if (enemyPerDamage < 0) enemyPerDamage = 0;
 
     // 苍蓝刻
-    if (special.includes(28)) {
+    if (special.has(28)) {
         heroPerDamage *= 1 - info.paleShield! / 100;
     }
 
     let turn = Math.ceil(monHp / heroPerDamage);
 
     // 致命一击
-    if (special.includes(1)) {
+    if (special.has(1)) {
         const times = Math.floor(turn / 5);
         damage += ((times * (info.crit! - 100)) / 100) * enemyPerDamage;
     }
 
     // 勇气之刃
-    if (turn > 1 && special.includes(10)) {
+    if (turn > 1 && special.has(10)) {
         damage += (info.courage! / 100 - 1) * enemyPerDamage;
     }
 
     // 勇气冲锋
-    if (special.includes(11)) {
+    if (special.has(11)) {
         damage += (info.charge! / 100) * enemyPerDamage;
         turn += 5;
     }
 
     // 先攻
-    if (special.includes(17)) {
+    if (special.has(17)) {
         damage += enemyPerDamage;
     }
 
diff --git a/src/plugin/game/replay.ts b/src/plugin/game/replay.ts
index 3ef5f68..b86bce9 100644
--- a/src/plugin/game/replay.ts
+++ b/src/plugin/game/replay.ts
@@ -45,25 +45,6 @@ export function init() {
         return true;
     });
 
-    core.registerReplayAction('study', name => {
-        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);
-        ensureFloorDamage(core.status.floorId);
-        const col = core.status.thisMap.enemy;
-        col.calRealAttribute();
-        const enemy = col.list.find(v => v.x === x && v.y === y)!.info;
-        if (!enemy.special.includes(num)) return false;
-        studySkill(enemy, num);
-        core.status.route.push(name);
-        core.replay();
-        return true;
-    });
-
     // 商店
     let shopOpened = false;
     let openedShopId = '';
diff --git a/src/plugin/ui/fixed.ts b/src/plugin/ui/fixed.ts
index 1bb60ea..8e68a84 100644
--- a/src/plugin/ui/fixed.ts
+++ b/src/plugin/ui/fixed.ts
@@ -28,7 +28,7 @@ export function getDetailedEnemy(
     ) => {
         return typeof func === 'string' ? func : func(enemy);
     };
-    const special: [string, string, string][] = enemy.info.special
+    const special: [string, string, string][] = [...enemy.info.special]
         .filter(v => !enemy.info.specialHalo?.includes(v))
         .map(vv => {
             const s = Mota.require('var', 'enemySpecials')[vv];
diff --git a/src/ui/fixed.vue b/src/ui/fixed.vue
index 8499e8f..80b93be 100644
--- a/src/ui/fixed.vue
+++ b/src/ui/fixed.vue
@@ -73,7 +73,7 @@ const detail = ((): [number, string, string][] => {
     ];
 })();
 const special = (() => {
-    const s = enemy.info.special;
+    const s = [...enemy.info.special];
 
     const fromFunc = (
         func: string | ((enemy: EnemyInfo) => string),