diff --git a/public/libs/control.js b/public/libs/control.js
index 5f517ea..fbc8bf4 100644
--- a/public/libs/control.js
+++ b/public/libs/control.js
@@ -2933,6 +2933,11 @@ control.prototype.getBuff = function (name) {
     return core.getFlag('__' + name + '_buff__', 1);
 };
 
+////// 获得或移除毒衰咒效果 //////
+control.prototype.triggerDebuff = function (action, type) {
+    return this.controldata.triggerDebuff(action, type);
+};
+
 ////// 设置勇士的位置 //////
 control.prototype.setHeroLoc = function (name, value, noGather) {
     if (!core.status.hero) return;
diff --git a/public/project/enemys.js b/public/project/enemys.js
index a1964c1..4ee75dd 100644
--- a/public/project/enemys.js
+++ b/public/project/enemys.js
@@ -16,7 +16,7 @@ var enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80 =
 	"bluePriest": {"name":"初级法师","hp":100,"atk":120,"def":0,"money":3,"exp":0,"point":1,"special":[9]},
 	"redPriest": {"name":"高级法师","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
 	"brownWizard": {"name":"初级巫师","hp":100,"atk":120,"def":0,"money":16,"exp":0,"point":0,"special":[15],"value":100,"range":2},
-	"redWizard": {"name":"高级巫师","hp":1000,"atk":1200,"def":0,"money":160,"exp":0,"point":0,"special":[15,28],"value":200,"zoneSquare":true,"specialHalo":[6,16],"n":9,"haloRange":2,"haloSquare":true},
+	"redWizard": {"name":"高级巫师","hp":1000,"atk":1200,"def":0,"money":160,"exp":0,"point":0,"special":[15,28],"value":200,"zoneSquare":true,"specialHalo":[6,16],"n":9,"haloRange":2,"haloSquare":true,"zone":200},
 	"swordsman": {"name":"双手剑士","hp":100,"atk":120,"def":0,"money":6,"exp":0,"point":0,"special":[4]},
 	"soldier": {"name":"冥战士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
 	"yellowKnight": {"name":"金骑士","hp":0,"atk":0,"def":0,"money":0,"exp":0,"point":0,"special":[]},
diff --git a/public/project/functions.js b/public/project/functions.js
index 3af2b28..5865e54 100644
--- a/public/project/functions.js
+++ b/public/project/functions.js
@@ -365,6 +365,63 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = {
                 if (callback) callback();
             });
         },
+        triggerDebuff: function (action, type) {
+            // 毒衰咒效果的获得与解除
+            // action:获得还是解除;'get'表示获得,'remove'表示解除
+            // type:一个数组表示获得了哪些毒衰咒效果;poison, weak,curse
+            if (!(type instanceof Array)) type = [type];
+
+            if (action == 'get') {
+                if (core.inArray(type, 'poison') && !core.hasFlag('poison')) {
+                    // 获得毒效果
+                    core.setFlag('poison', true);
+                }
+                if (core.inArray(type, 'weak') && !core.hasFlag('weak')) {
+                    // 获得衰效果
+                    core.setFlag('weak', true);
+                    if (core.values.weakValue >= 1) {
+                        // >=1,直接扣数值
+                        core.addStatus('atk', -core.values.weakValue);
+                        core.addStatus('def', -core.values.weakValue);
+                    } else {
+                        // <1,扣比例
+                        core.addBuff('atk', -core.values.weakValue);
+                        core.addBuff('def', -core.values.weakValue);
+                    }
+                }
+                if (core.inArray(type, 'curse') && !core.hasFlag('curse')) {
+                    // 获得咒效果
+                    core.setFlag('curse', true);
+                }
+            } else if (action == 'remove') {
+                var success = false;
+                if (core.inArray(type, 'poison') && core.hasFlag('poison')) {
+                    success = true;
+                    // 移除毒效果
+                    core.setFlag('poison', false);
+                }
+                if (core.inArray(type, 'weak') && core.hasFlag('weak')) {
+                    success = true;
+                    // 移除衰效果
+                    core.setFlag('weak', false);
+                    if (core.values.weakValue >= 1) {
+                        // >=1,直接扣数值
+                        core.addStatus('atk', core.values.weakValue);
+                        core.addStatus('def', core.values.weakValue);
+                    } else {
+                        // <1,扣比例
+                        core.addBuff('atk', core.values.weakValue);
+                        core.addBuff('def', core.values.weakValue);
+                    }
+                }
+                if (core.inArray(type, 'curse') && core.hasFlag('curse')) {
+                    success = true;
+                    // 移除咒效果
+                    core.setFlag('curse', false);
+                }
+                if (success) core.playSound('回血');
+            }
+        },
         updateStatusBar: function () {
             // 更新状态栏
 
diff --git a/public/project/plugins.js b/public/project/plugins.js
index 9cd2730..5b53240 100644
--- a/public/project/plugins.js
+++ b/public/project/plugins.js
@@ -361,7 +361,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
                 name: '破甲',
                 desc: enemy =>
                     `战斗前,怪物附加角色防御的${Math.floor(
-                        100 * (enemy.breakArmor || core.values.breakArmor)
+                        100 * (enemy.breakArmor ?? core.values.breakArmor)
                     )}%作为伤害"`,
                 color: '#b67'
             },
@@ -370,7 +370,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
                 name: '反击',
                 desc: enemy =>
                     `战斗时,怪物每回合附加角色攻击的${Math.floor(
-                        100 * (enemy.counterAttack || core.values.counterAttack)
+                        100 * (enemy.counterAttack ?? core.values.counterAttack)
                     )}%作为伤害,无视角色防御`,
                 color: '#fa4'
             },
@@ -379,7 +379,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
                 name: '净化',
                 desc: enemy =>
                     `战斗前,怪物附加角色护盾的${
-                        enemy.purify || core.values.purify
+                        enemy.purify ?? core.values.purify
                     }倍作为伤害`,
                 color: '#80eed6'
             },
@@ -578,6 +578,166 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
     battle: function () {
         // 这个插件负责战斗相关内容
 
+        // --------------- 战后脚本
+        // enemy: DamageEnemy实例,也就是怪物本身
+        // x, y: 怪物坐标
+        Mota.rewrite(core.events, 'afterBattle', 'full', (enemy, x, y) => {
+            const { has } = Mota.Plugin.require('utils_g');
+
+            const floorId = core.status.floorId;
+            const special = enemy.info.special;
+
+            // 播放战斗动画
+            let animate = '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++;
+
+            // 获得金币
+            let money = enemy.enemy.money;
+            let exp = enemy.enemy.exp;
+            if (enemy.info.guard) {
+                enemy.info.guard.forEach(v => {
+                    money += v.enemy.money;
+                    exp += v.enemy.exp;
+                });
+            }
+            core.status.hero.money += money;
+            core.status.hero.statistics.money += money;
+
+            // 获得经验
+            core.status.hero.exp += exp;
+            core.status.hero.statistics.exp += exp;
+
+            const hint =
+                '打败 ' +
+                enemy.enemy.name +
+                ',金币+' +
+                money +
+                ',经验+' +
+                exp;
+            core.drawTip(hint, enemy.id);
+
+            // 中毒
+            if (special.includes(12)) {
+                core.triggerDebuff('get', 'poison');
+            }
+            // 衰弱
+            if (special.includes(13)) {
+                core.triggerDebuff('get', 'weak');
+            }
+            // 诅咒
+            if (special.includes(14)) {
+                core.triggerDebuff('get', 'curse');
+            }
+            // 仇恨怪物将仇恨值减半
+            if (special.includes(17)) {
+                core.setFlag(
+                    'hatred',
+                    Math.floor(core.getFlag('hatred', 0) / 2)
+                );
+            }
+            // 自爆
+            if (special.includes(19)) {
+                core.status.hero.statistics.battleDamage +=
+                    core.status.hero.hp - 1;
+                core.status.hero.hp = 1;
+            }
+            // 退化
+            if (special.includes(21)) {
+                core.status.hero.atk -= enemy.atkValue || 0;
+                core.status.hero.def -= enemy.defValue || 0;
+                if (core.status.hero.atk < 0) core.status.hero.atk = 0;
+                if (core.status.hero.def < 0) core.status.hero.def = 0;
+            }
+            // 增加仇恨值
+            core.setFlag(
+                'hatred',
+                core.getFlag('hatred', 0) + core.values.hatred
+            );
+
+            // 事件的处理
+            const todo = [];
+
+            // 战后事件
+            if (has(core.status.floorId)) {
+                const loc = `${x},${y}`;
+                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);
+                if (special.includes(23)) core.hideBlock(x, y);
+                else core.removeBlock(x, y);
+            } else core.drawHeroAnimate(animate);
+
+            // 如果已有事件正在处理中
+            if (core.status.event.id == null) core.continueAutomaticRoute();
+            else core.clearContinueAutomaticRoute();
+
+            // 打怪特效
+            Mota.r(() => {
+                const setting = Mota.require('var', 'mainSetting');
+                const { applyFragWith } = Mota.Plugin.require('frag_r');
+                if (setting.getValue('fx.frag') && has(x) && has(y)) {
+                    const frame = core.status.globalAnimateStatus % 2;
+                    const canvas = document.createElement('canvas');
+                    canvas.width = 32;
+                    canvas.height = 32;
+                    core.drawIcon(canvas, enemy.id, 0, 0, 32, 32, frame);
+                    const manager = applyFragWith(canvas);
+                    const frag = manager.canvas;
+                    frag.style.imageRendering = 'pixelated';
+                    frag.style.width = `${frag.width * core.domStyle.scale}px`;
+                    frag.style.height = `${
+                        frag.height * core.domStyle.scale
+                    }px`;
+                    const left =
+                        (x * 32 + 16 - frag.width / 2 - core.bigmap.offsetX) *
+                        core.domStyle.scale;
+                    const top =
+                        (y * 32 + 16 - frag.height / 2 - core.bigmap.offsetY) *
+                        core.domStyle.scale;
+                    frag.style.left = `${left}px`;
+                    frag.style.top = `${top}px`;
+                    frag.style.zIndex = '45';
+                    frag.style.position = 'absolute';
+                    frag.style.filter = 'sepia(20%)brightness(120%)';
+                    core.dom.gameDraw.appendChild(frag);
+                    manager.onEnd.then(() => {
+                        frag.remove();
+                    });
+                }
+            });
+        });
+
         // --------------- 战斗伤害
 
         const Damage = Mota.require('module', 'Damage');
@@ -590,7 +750,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
         // 返回null表示不能战斗,返回Infinity也可以
         Mota.rewrite(Damage, 'calDamageWith', 'full', (info, hero) => {
             // 获取勇士属性,这几个属性直接从core.status.hero获取
-            const { hp, mana } = core.status.hero;
+            const { hp, mana, manamax } = core.status.hero;
             // 获取勇士属性,这几个属性从勇士真实属性获取
             // 分开获取是因为获取勇士真实属性会对性能造成一定影响
             let { atk, def, mdef, hpmax } = hero;
@@ -601,21 +761,40 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
             let damage = 0;
             /** 勇士单回合伤害 */
             let heroPerDamage;
+            /** 战斗回合 */
+            let turn = 0;
+
+            // 无敌
+            if (special.includes(20) && !core.hasItem('cross')) {
+                return null;
+            }
 
             if (special.includes(3)) {
                 // 由于坚固的特性,只能放到这来计算了
                 if (atk > enemy.def) heroPerDamage = 1;
                 else return null;
             } else {
+                // 模仿
+                if (special.includes(10)) {
+                    monAtk = atk;
+                    monDef = def;
+                }
                 heroPerDamage = atk - monDef;
                 if (heroPerDamage <= 0) return null;
             }
 
+            // 吸血
+            if (special.includes(11)) {
+                const vampire = hp * (info.vampire ?? 0);
+                if (info.add) monHp += vampire;
+                damage += vampire;
+            }
+
             /** 怪物单回合伤害 */
             let enemyPerDamage;
 
             // 魔攻
-            if (special.includes(2) || special.includes(13)) {
+            if (special.includes(2)) {
                 enemyPerDamage = monAtk;
             } else {
                 enemyPerDamage = monAtk - def;
@@ -623,22 +802,69 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
             }
 
             // 先攻
-            if (special.includes(17)) {
+            if (special.includes(1)) {
                 damage += enemyPerDamage;
             }
 
             // 连击
             if (special.includes(4)) enemyPerDamage *= 2;
             if (special.includes(5)) enemyPerDamage *= 3;
-            if (special.includes(6)) enemyPerDamage *= enemy.n;
+            if (special.includes(6)) enemyPerDamage *= info.n;
 
-            /** 战斗回合 */
-            let turn = Math.ceil(monHp / heroPerDamage);
+            // 破甲
+            if (special.includes(7)) {
+                damage += def * (info.breakArmor ?? core.values.breakArmor);
+            }
 
+            // 反击
+            if (special.includes(8)) {
+                enemyPerDamage +=
+                    atk * (info.counterAttack ?? core.values.counterAttack);
+            }
+
+            // 净化
+            if (special.includes(9)) {
+                damage += mdef * (info.purify ?? core.values.purify);
+            }
+
+            turn = Math.ceil(monHp / heroPerDamage);
+
+            // 支援,支援信息由光环计算而得,直接使用即可
+            if (info.guard) {
+                const guardFirst = false;
+                const inGuard = core.getFlag('__inGuard__');
+                if (!inGuard)
+                    core.setFlag('__extraTurn__', guardFirst ? 0 : turn);
+                core.setFlag('__inGuard__', true);
+                for (const enemy of info.guard) {
+                    const info = enemy.getRealInfo();
+                    damage +=
+                        Damage.calDamageWith(info, {
+                            ...hero,
+                            mdef: 0
+                        }) ?? Infinity;
+                    if (!isFinite(damage)) return null;
+                }
+                if (!inGuard) core.removeFlag('__inGuard__');
+                turn += core.getFlag('__extraTurn__', 0);
+                core.removeFlag('__extraTurn__');
+            }
+
+            // 计算最终伤害
             damage += (turn - 1) * enemyPerDamage;
             damage -= mdef;
             if (!core.flags.enableNegativeDamage) damage = Math.max(0, damage);
 
+            // 仇恨
+            if (special.includes(17)) {
+                damage += core.getFlag('hatred', 0);
+            }
+
+            // 固伤
+            if (special.includes(22)) {
+                damage += info.damage;
+            }
+
             return damage;
         });
 
@@ -660,13 +886,33 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
                 if (info.special.includes(3)) {
                     return Infinity;
                 }
+                // 模仿,不计算临界
+                if (info.special.includes(10)) {
+                    return Infinity;
+                }
 
                 return add;
             }
         );
 
         // --------------- 地图伤害
-        // 全量复写地图伤害的计算函数,注意此处不能使用箭头函数,因为这是在原型上的函数,其this指向实例,也即怪物(DamageEnemy实例)
+        const { getHeroStatusOn } = Mota.requireAll('fn');
+        const caledBetween = new Set();
+        // 全量复写地图伤害计算,这个计算会调用所有的 DamageEnemy 的地图伤害计算
+        Mota.rewrite(
+            Mota.require('class', 'EnemyCollection').prototype,
+            'calMapDamage',
+            'full',
+            function () {
+                this.mapDamage = {};
+                caledBetween.clear();
+                const hero = getHeroStatusOn(Damage.realStatus, this.floorId);
+                this.list.forEach(v => {
+                    v.calMapDamage(this.mapDamage, hero);
+                });
+            }
+        );
+        // 全量复写单个怪物地图伤害的计算函数,注意此处不能使用箭头函数,因为这是在原型上的函数,其this指向实例,也即怪物(DamageEnemy实例)
         // 函数接收两个参数,damage和hero,前者表示要将结果存入的对象,后者是勇士真实属性
         // 直接将damage返回即可,返回其他值有可能会引起出错
         // 计算出伤害后直接调用this.setMapDamage即可将伤害传到对象中
@@ -678,21 +924,27 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
                 // 功能函数,计算曼哈顿距离,和判断一个值是否存在
                 const { manhattan, has } = Mota.Plugin.require('utils_g');
                 // 判断这个怪物是不是在地图上
-                if (!has(this.x) || !has(this.y) || !has(this.floorId))
+                if (
+                    !has(this.x) ||
+                    !has(this.y) ||
+                    !has(this.floorId) ||
+                    !has(this.col)
+                ) {
                     return damage;
-                const enemy = this.enemy;
+                }
+                const enemy = this.info;
                 const floor = core.status.maps[this.floorId];
                 const w = floor.width;
                 const h = floor.height;
 
-                // 突刺
+                // 领域
                 if (this.info.special.includes(15)) {
                     const range = enemy.range ?? 1;
                     const startX = Math.max(0, this.x - range);
                     const startY = Math.max(0, this.y - range);
                     const endX = Math.min(floor.width - 1, this.x + range);
                     const endY = Math.min(floor.height - 1, this.y + range);
-                    const dam = Math.max((enemy.value ?? 0) - hero.def, 0);
+                    const dam = Math.max(enemy.zone ?? 0, 0);
 
                     for (let x = startX; x <= endX; x++) {
                         for (let y = startY; y <= endY; y++) {
@@ -703,16 +955,15 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
                                 continue;
                             }
                             const loc = `${x},${y}`;
-                            this.setMapDamage(damage, loc, dam, '突刺');
+                            this.setMapDamage(damage, loc, dam, '领域');
                         }
                     }
                 }
 
-                // 射击
+                // 激光
                 if (this.info.special.includes(24)) {
                     const dirs = ['left', 'down', 'up', 'right'];
-                    const dam = Math.max((enemy.atk ?? 0) - hero.def, 0);
-                    const objs = core.getMapBlocksObj(this.floorId);
+                    const dam = Math.max(enemy.laser ?? 0, 0);
 
                     for (const dir of dirs) {
                         let x = this.x;
@@ -722,22 +973,75 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
                             x += dx;
                             y += dy;
                             const loc = `${x},${y}`;
-                            const block = objs[loc];
-                            if (
-                                block &&
-                                block.event.noPass &&
-                                block.event.cls !== 'enemys' &&
-                                block.event.cls !== 'enemy48' &&
-                                block.id !== 141 &&
-                                block.id !== 151
-                            ) {
-                                break;
-                            }
-                            this.setMapDamage(damage, loc, dam, '射击');
+                            this.setMapDamage(damage, loc, dam, '激光');
                         }
                     }
                 }
 
+                // 夹击
+                if (this.info.special.includes(16)) {
+                    const dirs = ['left', 'down', 'up', 'right'];
+                    const dam = Math.floor(core.status.hero.hp / 2);
+
+                    for (const dir of dirs) {
+                        let x = this.x;
+                        let y = this.y;
+                        const { x: dx, y: dy } = core.utils.scan[dir];
+                        if (caledBetween.has(`${x + dx},${y + dy}`)) continue;
+                        const e = this.col.list.find(v => {
+                            return v.x === x + dx * 2 && v.y === y + dy * 2;
+                        });
+                        if (e) {
+                            const loc = `${x + dx},${y + dy}`;
+                            this.setMapDamage(damage, loc, dam, '夹击');
+                            caledBetween.add(loc);
+                        }
+                    }
+                }
+
+                // 阻击
+                if (this.info.special.includes(18)) {
+                    const range = 1;
+                    const startX = Math.max(0, this.x - range);
+                    const startY = Math.max(0, this.y - range);
+                    const endX = Math.min(floor.width - 1, this.x + range);
+                    const endY = Math.min(floor.height - 1, this.y + range);
+                    const dam = Math.max(enemy.repulse ?? 0, 0);
+
+                    for (let x = startX; x <= endX; x++) {
+                        for (let y = startY; y <= endY; y++) {
+                            if (
+                                !enemy.zoneSquare &&
+                                manhattan(x, y, this.x, this.y) > range
+                            ) {
+                                continue;
+                            }
+                            const loc = `${x},${y}`;
+                            this.setMapDamage(damage, loc, dam, '阻击');
+                            damage[loc].repulse = damage[loc].repulse ?? [];
+                            damage[loc].repulse.push([this.x, this.y]);
+                        }
+                    }
+                }
+
+                // 捕捉
+                if (this.info.special.includes(27)) {
+                    const dirs = ['left', 'down', 'up', 'right'];
+                    for (const dir of dirs) {
+                        let x = this.x;
+                        let y = this.y;
+                        const { x: dx, y: dy } = core.utils.scan[dir];
+                        this.col.list.forEach(v => {
+                            if (v.x === x + dx * 2 && v.y === y + dy * 2) {
+                                const loc = `${x + dx},${y + dy}`;
+                                this.setMapDamage(damage, loc, 0);
+                            }
+                            damage[loc].ambush = damage[loc].ambush ?? [];
+                            damage[loc].ambush.push(this);
+                        });
+                    }
+                }
+
                 return damage;
             }
         );
@@ -750,7 +1054,7 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
 
         // 光环属性列表,是一个集合Set,你可以在这里配置会被视为光环的属性
         const haloSpecials = Mota.require('module', 'Damage').haloSpecials;
-        haloSpecials.add(8).add(11);
+        haloSpecials.add(25).add(26).add(28);
 
         // ----- 计算第二类光环,即普通光环,这类光环更常见,因此放到前面了
         Mota.rewrite(
@@ -770,78 +1074,58 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
                 // 获取所有还没有计算的光环,注意这里不能直接获取haloSpecial
                 const special = this.getHaloSpecials();
 
-                const square7 = [];
-                const square5 = [];
-
                 // e 是被加成怪的属性,enemy 是施加光环的怪
 
                 for (const halo of special) {
                     switch (halo) {
-                        case 8:
-                            square5.push((e, enemy) => {
-                                if (
-                                    e.special.includes(8) &&
-                                    (e.x !== this.x || this.y !== e.y)
-                                ) {
-                                    e.atkBuff += enemy.together ?? 0;
-                                    e.defBuff += enemy.together ?? 0;
-                                }
+                        // 普通光环
+                        case 25: {
+                            const e = this.enemy;
+                            const type = e.haloSquare ? 'square' : 'manhattan';
+                            const r = Math.floor(e.haloRange);
+                            const d = type === 'square' ? r * 2 + 1 : r;
+                            const range = { x: this.x, y: this.y, d };
+
+                            // 施加光环
+                            col.applyHalo(type, range, this, (e, enemy) => {
+                                e.atkBuff += enemy.atkBuff ?? 0;
+                                e.defBuff += enemy.defBuff ?? 0;
+                                e.hpBuff += enemy.hpBuff ?? 0;
                             });
-                            this.providedHalo.add(8);
+                            // 向已施加的光环列表中添加
+                            this.providedHalo.add(25);
                             break;
-                        case 21:
-                            square7.push(e => {
-                                // e.damageDecline += this.enemy.iceHalo ?? 0;
-                            });
-                            col.haloList.push({
-                                type: 'square',
-                                data: { x: this.x, y: this.y, d: 7 },
-                                special: 21,
-                                from: this
-                            });
-                            this.providedHalo.add(21);
-                            break;
-                        case 26:
-                            square5.push(e => {
-                                e.defBuff += this.enemy.iceCore ?? 0;
-                            });
-                            col.haloList.push({
-                                type: 'square',
-                                data: { x: this.x, y: this.y, d: 5 },
-                                special: 26,
-                                from: this
+                        }
+                        case 26: {
+                            const range = { x: this.x, y: this.y, d: 1 };
+                            // 支援
+                            col.applyHalo('square', range, this, (e, enemy) => {
+                                e.guard = e.guard ?? [];
+                                e.guard.push(this);
                             });
                             this.providedHalo.add(26);
                             break;
-                        case 27:
-                            square5.push(e => {
-                                e.atkBuff += this.enemy.fireCore ?? 0;
-                            });
-                            col.haloList.push({
-                                type: 'square',
-                                data: { x: this.x, y: this.y, d: 5 },
-                                special: 27,
-                                from: this
-                            });
-                            this.providedHalo.add(27);
-                            break;
+                        }
                     }
                 }
-
-                col.applyHalo(
-                    'square',
-                    { x: this.x, y: this.y, d: 7 },
-                    square7
-                );
-                col.applyHalo(
-                    'square',
-                    { x: this.x, y: this.y, d: 5 },
-                    square5
-                );
             }
         );
 
         // ----- 计算第一类光环
+        const changeable = Mota.require('module', 'Damage').changeableHaloValue;
+        changeable
+            .set(21, ['atkValue', 'defValue'])
+            .set(7, ['breakArmor'])
+            .set(8, ['counterAttack'])
+            .set(22, ['damage'])
+            .set(25, ['haloRange'])
+            .set(24, ['laser'])
+            .set(6, ['n'])
+            .set(9, ['purify'])
+            .set(15, ['range'])
+            .set(18, ['repulse'])
+            .set(11, ['vampire'])
+            .set(15, ['zone']);
         Mota.rewrite(
             Mota.require('class', 'DamageEnemy').prototype,
             'preProvideHalo',
@@ -850,11 +1134,47 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
                 if (this.progress !== 0) return;
                 this.progress = 1;
                 const special = this.getHaloSpecials();
+                const col = this.col ?? core.status.maps[this.floorId].enemy;
 
                 for (const halo of special) {
                     switch (halo) {
-                        default:
-                            break;
+                        case 28: {
+                            // 特殊光环
+                            const e = this.enemy;
+                            const type = e.haloSquare ? 'square' : 'manhattan';
+                            const r = Math.floor(e.haloRange);
+                            const d = type === 'square' ? r * 2 + 1 : r;
+                            const range = { x: this.x, y: this.y, d };
+
+                            // 这一句必须放到applyHalo之前
+                            this.providedHalo.add(28);
+
+                            col.applyHalo(
+                                type,
+                                range,
+                                this,
+                                (e, enemy) => {
+                                    const s = enemy.specialHalo;
+                                    e.special.push(...s);
+                                    // 然后计算特殊属性数值
+                                    for (const spec of s) {
+                                        const toChange = changeable.get(spec);
+                                        if (!toChange) continue;
+                                        for (const key of toChange) {
+                                            if (enemy.specialMultiply) {
+                                                e[key] = s[key] ?? 1;
+                                                e[key] *= enemy[key];
+                                            } else {
+                                                e[key] = s[key] ?? 0;
+                                                e[key] += enemy[key];
+                                            }
+                                        }
+                                    }
+                                },
+                                // true表示递归计算,视为第一类光环
+                                true
+                            );
+                        }
                     }
                 }
             }
@@ -870,5 +1190,96 @@ var plugins_bb40132b_638b_4a9f_b028_d3fe47acc8d1 = {
                 halo(this.info, enemy);
             }
         );
+    },
+    checkBlock: function () {
+        Mota.rewrite(core.control, 'checkBlock', 'full', function () {
+            const x = core.getHeroLoc('x'),
+                y = core.getHeroLoc('y'),
+                loc = x + ',' + y;
+            const info = core.status.thisMap.enemy.mapDamage[loc];
+            const damage = info?.damage;
+            const floor = core.status.thisMap;
+            if (damage) {
+                // 伤害弹出,在渲染进程中执行
+                Mota.r(() => {
+                    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();
+                }
+            }
+            const { findDir, ofDir } = Mota.Plugin.require('utils_g');
+
+            // 阻击处理
+            if (info?.repulse) {
+                const actions = [];
+                for (const [ex, ey] of info.repulse) {
+                    const dir = findDir({ x, y }, { x: ex, y: ey });
+                    const [tx, ty] = ofDir(ex, ey, dir);
+                    if (
+                        tx < 0 ||
+                        ty < 0 ||
+                        tx >= floor.width ||
+                        ty >= floor.height ||
+                        core.getBlock(tx, ty)
+                    ) {
+                        continue;
+                    }
+                    actions.push({
+                        type: 'move',
+                        loc: [ex, ey],
+                        steps: [findDir({ x, y }, { x: ex, y: ey })],
+                        time: 250,
+                        keep: true,
+                        async: true
+                    });
+                }
+                actions.push({ type: 'waitAsync' });
+                core.insertAction(actions);
+            }
+            // 捕捉处理
+            if (info?.ambush) {
+                const actions = [];
+                for (const enemy of info.ambush) {
+                    actions.push({
+                        type: 'move',
+                        loc: [enemy.x, enemy.y],
+                        steps: [findDir(enemy, { x, y })],
+                        time: 250,
+                        keep: false,
+                        async: true
+                    });
+                }
+                actions.push({ type: 'waitAsync' });
+                // 强制战斗
+                for (const enemy of info.ambush) {
+                    actions.push({
+                        type: 'function',
+                        function:
+                            'function() { ' +
+                            `core.battle(${enemy.x}, ${enemy.y}, true, core.doAction); ` +
+                            '}',
+                        async: true
+                    });
+                }
+                core.insertAction(actions);
+            }
+        });
     }
 };
diff --git a/src/components/enemyOne.vue b/src/components/enemyOne.vue
index f04baf6..a81ca21 100644
--- a/src/components/enemyOne.vue
+++ b/src/components/enemyOne.vue
@@ -19,11 +19,14 @@
                     class="special-text"
                     v-if="has(enemy.special) && enemy.special.length > 0"
                 >
-                    <span
-                        v-for="(text, i) in enemy.showSpecial"
-                        :style="{ color: text[2] }"
-                        >&nbsp;{{ text[0] }}&nbsp;</span
-                    >
+                    <template v-for="(text, i) in enemy.showSpecial">
+                        <span
+                            v-if="i < (isMobile ? 1 : 2)"
+                            :style="{ color: text[2] }"
+                            >&nbsp;{{ text[0] }}&nbsp;</span
+                        >
+                        <span v-if="i === (isMobile ? 1 : 2)">...</span>
+                    </template>
                 </div>
                 <div class="special-text" v-else>无属性</div>
             </div>
diff --git a/src/game/enemy/battle.ts b/src/game/enemy/battle.ts
index 521d3f5..d24a9f5 100644
--- a/src/game/enemy/battle.ts
+++ b/src/game/enemy/battle.ts
@@ -58,116 +58,6 @@ function init() {
         callback?.();
     };
 
-    core.events.afterBattle = function afterBattle(
-        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) && 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.enemys.getCurrentEnemys = function getCurrentEnemys(
         floorId = core.status.floorId
     ) {
diff --git a/src/game/enemy/damage.ts b/src/game/enemy/damage.ts
index 927c9ab..e403d31 100644
--- a/src/game/enemy/damage.ts
+++ b/src/game/enemy/damage.ts
@@ -14,9 +14,14 @@ interface HaloType {
         y: number;
         d: number;
     };
+    manhattan: {
+        x: number;
+        y: number;
+        d: number;
+    };
 }
 
-interface EnemyInfo {
+interface EnemyInfo extends Partial<SelectType<Enemy, number | undefined>> {
     atk: number;
     def: number;
     hp: number;
@@ -25,6 +30,7 @@ interface EnemyInfo {
     defBuff: number;
     hpBuff: number;
     enemy: Enemy;
+    guard?: DamageEnemy[];
     x?: number;
     y?: number;
     floorId?: FloorIds;
@@ -39,7 +45,8 @@ interface DamageInfo {
 interface MapDamage {
     damage: number;
     type: Set<string>;
-    mockery?: LocArr[];
+    repulse?: LocArr[];
+    ambush?: DamageEnemy[];
 }
 
 interface HaloData<T extends keyof HaloType = keyof HaloType> {
@@ -103,6 +110,8 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
         this.haloList = [];
         this.list.forEach(v => {
             v.reset();
+        });
+        this.list.forEach(v => {
             v.preProvideHalo();
         });
         this.list.forEach(v => {
@@ -146,21 +155,22 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
     applyHalo<K extends keyof HaloType>(
         type: K,
         data: HaloType[K],
+        enemy: DamageEnemy,
         halo: HaloFn | HaloFn[],
         recursion: boolean = false
     ) {
         const arr = ensureArray(halo);
-        const enemy = this.range.scan(type, data);
+        const enemys = this.range.scan(type, data);
         if (!recursion) {
             arr.forEach(v => {
-                enemy.forEach(e => {
-                    e.injectHalo(v, e.enemy);
+                enemys.forEach(e => {
+                    e.injectHalo(v, enemy.enemy);
                 });
             });
         } else {
-            enemy.forEach(e => {
+            enemys.forEach(e => {
                 arr.forEach(v => {
-                    e.injectHalo(v, e.enemy);
+                    e.injectHalo(v, enemy.enemy);
                     e.preProvideHalo();
                 });
             });
@@ -260,6 +270,26 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
                         alpha: 1
                     });
                 }
+
+                if (dam.ambush) {
+                    core.status.damage.extraData.push({
+                        text: '!',
+                        px: 32 * x + 16,
+                        py: 32 * y + 16,
+                        color: '#fa3',
+                        alpha: 1
+                    });
+                }
+
+                if (dam.repulse) {
+                    core.status.damage.extraData.push({
+                        text: '阻',
+                        px: 32 * x + 16,
+                        py: 32 * y + 16,
+                        color: '#fa3',
+                        alpha: 1
+                    });
+                }
             }
         }
     }
@@ -320,8 +350,15 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
             y: this.y,
             floorId: this.floorId
         };
+
+        for (const [key, value] of Object.entries(enemy)) {
+            if (!(key in this.info) && has(value)) {
+                // @ts-ignore
+                this.info[key] = value;
+            }
+        }
         this.progress = 0;
-        this.providedHalo = new Set();
+        this.providedHalo.clear();
     }
 
     /**
@@ -381,6 +418,7 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         if (!this.floorId) return [];
         if (!has(this.x) || !has(this.y)) return [];
         const special = this.info.special ?? this.enemy.special;
+
         const filter = special.filter(v => {
             return Damage.haloSpecials.has(v) && !this.providedHalo.has(v);
         });
@@ -397,92 +435,12 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
     /**
      * 光环预提供,用于平衡所有怪的光环属性,避免出现不同情况下光环效果不一致的现象
      */
-    preProvideHalo() {
-        if (this.progress !== 0) return;
-        this.progress = 1;
-        const special = this.getHaloSpecials();
-
-        for (const halo of special) {
-            switch (halo) {
-                default:
-                    break;
-            }
-        }
-    }
+    preProvideHalo() {}
 
     /**
      * 向其他怪提供光环
      */
-    provideHalo() {
-        if (this.progress !== 2) return;
-        this.progress = 3;
-        if (!this.floorId) 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();
-
-        const square7: HaloFn[] = [];
-        const square5: HaloFn[] = [];
-
-        // e 是被加成怪的属性,enemy 是施加光环的怪
-
-        for (const halo of special) {
-            switch (halo) {
-                case 8:
-                    square5.push((e, enemy) => {
-                        if (
-                            e.special.includes(8) &&
-                            (e.x !== this.x || this.y !== e.y)
-                        ) {
-                            e.atkBuff += enemy.together ?? 0;
-                            e.defBuff += enemy.together ?? 0;
-                        }
-                    });
-                    this.providedHalo.add(8);
-                    break;
-                case 21:
-                    square7.push(e => {
-                        // e.damageDecline += this.enemy.iceHalo ?? 0;
-                    });
-                    col.haloList.push({
-                        type: 'square',
-                        data: { x: this.x, y: this.y, d: 7 },
-                        special: 21,
-                        from: this
-                    });
-                    this.providedHalo.add(21);
-                    break;
-                case 26:
-                    square5.push(e => {
-                        e.defBuff += this.enemy.iceCore ?? 0;
-                    });
-                    col.haloList.push({
-                        type: 'square',
-                        data: { x: this.x, y: this.y, d: 5 },
-                        special: 26,
-                        from: this
-                    });
-                    this.providedHalo.add(26);
-                    break;
-                case 27:
-                    square5.push(e => {
-                        e.atkBuff += this.enemy.fireCore ?? 0;
-                    });
-                    col.haloList.push({
-                        type: 'square',
-                        data: { x: this.x, y: this.y, d: 5 },
-                        special: 27,
-                        from: this
-                    });
-                    this.providedHalo.add(27);
-                    break;
-            }
-        }
-
-        col.applyHalo('square', { x: this.x, y: this.y, d: 7 }, square7);
-        col.applyHalo('square', { x: this.x, y: this.y, d: 5 }, square5);
-    }
+    provideHalo() {}
 
     /**
      * 接受其他怪的光环
@@ -507,64 +465,6 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         damage: Record<string, MapDamage> = {},
         hero: Partial<HeroStatus> = getHeroStatusOn(Damage.realStatus)
     ) {
-        if (!has(this.x) || !has(this.y) || !has(this.floorId)) return damage;
-        const enemy = this.enemy;
-        const floor = core.status.maps[this.floorId];
-        const w = floor.width;
-        const h = floor.height;
-
-        // 突刺
-        if (this.info.special.includes(15)) {
-            const range = enemy.range ?? 1;
-            const startX = Math.max(0, this.x - range);
-            const startY = Math.max(0, this.y - range);
-            const endX = Math.min(floor.width - 1, this.x + range);
-            const endY = Math.min(floor.height - 1, this.y + range);
-            const dam = Math.max((enemy.value ?? 0) - hero.def!, 0);
-
-            for (let x = startX; x <= endX; x++) {
-                for (let y = startY; y <= endY; y++) {
-                    if (
-                        !enemy.zoneSquare &&
-                        manhattan(x, y, this.x, this.y) > range
-                    ) {
-                        continue;
-                    }
-                    const loc = `${x},${y}`;
-                    this.setMapDamage(damage, loc, dam, '突刺');
-                }
-            }
-        }
-
-        // 射击
-        if (this.info.special.includes(24)) {
-            // const dirs: Dir[] = ['left', 'down', 'up', 'right'];
-            // const dam = Math.max((enemy.atk ?? 0) - hero.def!, 0);
-            // const objs = core.getMapBlocksObj(this.floorId);
-            // for (const dir of dirs) {
-            //     let x = this.x;
-            //     let y = this.y;
-            //     const { x: dx, y: dy } = core.utils.scan[dir];
-            //     while (x >= 0 && y >= 0 && x < w && y < h) {
-            //         x += dx;
-            //         y += dy;
-            //         const loc = `${x},${y}` as LocString;
-            //         const block = objs[loc];
-            //         if (
-            //             block &&
-            //             block.event.noPass &&
-            //             block.event.cls !== 'enemys' &&
-            //             block.event.cls !== 'enemy48' &&
-            //             block.id !== 141 &&
-            //             block.id !== 151
-            //         ) {
-            //             break;
-            //         }
-            //         this.setMapDamage(damage, loc, dam, '射击');
-            //     }
-            // }
-        }
-
         return damage;
     }
 
@@ -572,11 +472,11 @@ export class DamageEnemy<T extends EnemyIds = EnemyIds> {
         damage: Record<string, MapDamage>,
         loc: string,
         dam: number,
-        type: string
+        type?: string
     ) {
         damage[loc] ??= { damage: 0, type: new Set() };
         damage[loc].damage += dam;
-        damage[loc].type.add(type);
+        if (type) damage[loc].type.add(type);
     }
 
     private calEnemyDamageOf(hero: Partial<HeroStatus>, enemy: EnemyInfo) {
@@ -730,6 +630,12 @@ export namespace Damage {
     /** 光环属性 */
     export const haloSpecials: Set<number> = new Set();
 
+    /** 会被第一类光环修改的怪物特殊属性数值 */
+    export const changeableHaloValue: Map<
+        number,
+        SelectKey<Enemy, number | undefined>[]
+    > = new Map();
+
     /**
      * 计算伤害时会用到的勇士属性,攻击防御,其余的不会有buff加成,直接从core.status.hero取
      */
@@ -744,55 +650,7 @@ export namespace Damage {
         info: EnemyInfo,
         hero: Partial<HeroStatus>
     ): number | null {
-        const { hp, hpmax, mana, mdef } = core.status.hero;
-        let { atk, def } = hero as HeroStatus;
-        let { hp: monHp, atk: monAtk, def: monDef, special, enemy } = info;
-
-        let damage = 0;
-
-        // 饥渴
-        if (special.includes(7)) {
-            const delta = Math.floor((atk * enemy.hungry!) / 100);
-            atk -= delta;
-            monAtk += delta;
-        }
-
-        let heroPerDamage: number;
-
-        // 绝对防御
-        if (special.includes(3)) {
-            // 由于坚固的特性,只能放到这来计算了
-            if (atk > enemy.def) heroPerDamage = 1 + mana;
-            else return null;
-        } else {
-            heroPerDamage = atk - monDef;
-            if (heroPerDamage > 0) heroPerDamage += mana;
-            else return null;
-        }
-
-        let enemyPerDamage: number;
-
-        // 魔攻
-        if (special.includes(2) || special.includes(13)) {
-            enemyPerDamage = monAtk;
-        } else {
-            enemyPerDamage = monAtk - def;
-            if (enemyPerDamage < 0) enemyPerDamage = 0;
-        }
-
-        // 先攻
-        if (special.includes(17)) {
-            damage += enemyPerDamage;
-        }
-
-        // 连击
-        if (special.includes(4)) enemyPerDamage *= 2;
-        if (special.includes(5)) enemyPerDamage *= 3;
-        if (special.includes(6)) enemyPerDamage *= enemy.n!;
-
-        let turn = Math.ceil(monHp / heroPerDamage);
-
-        return damage;
+        return null;
     }
 
     export function ensureFloorDamage(floorId: FloorIds) {
diff --git a/src/game/system.ts b/src/game/system.ts
index fcc4c18..228b289 100644
--- a/src/game/system.ts
+++ b/src/game/system.ts
@@ -164,7 +164,6 @@ interface PluginInterface {
     heroFourFrames_g: typeof import('../plugin/game/fx/heroFourFrames');
     rewrite_g: typeof import('../plugin/game/fx/rewrite');
     itemDetail_g: typeof import('../plugin/game/fx/itemDetail');
-    checkBlock_g: typeof import('../plugin/game/enemy/checkblock');
 }
 
 interface PackageInterface {
diff --git a/src/plugin/fx/frag.ts b/src/plugin/fx/frag.ts
index fa5046d..9ae9559 100644
--- a/src/plugin/fx/frag.ts
+++ b/src/plugin/fx/frag.ts
@@ -24,40 +24,7 @@ const MAX_ROTATE = 0.5;
 /** 碎裂动画的速率曲线函数 */
 const FRAG_TIMING = linear();
 
-export function init() {
-    Mota.rewrite(core.events, 'afterBattle', 'add', (_, enemy, x, y) => {
-        // 打怪特效
-        const setting = Mota.require('var', 'mainSetting');
-
-        if (setting.getValue('fx.frag') && has(x) && has(y)) {
-            const frame = core.status.globalAnimateStatus % 2;
-            const canvas = document.createElement('canvas');
-            canvas.width = 32;
-            canvas.height = 32;
-            core.drawIcon(canvas, enemy.id, 0, 0, 32, 32, frame);
-            const manager = applyFragWith(canvas);
-            const frag = manager.canvas;
-            frag.style.imageRendering = 'pixelated';
-            frag.style.width = `${frag.width * core.domStyle.scale}px`;
-            frag.style.height = `${frag.height * core.domStyle.scale}px`;
-            const left =
-                (x * 32 + 16 - frag.width / 2 - core.bigmap.offsetX) *
-                core.domStyle.scale;
-            const top =
-                (y * 32 + 16 - frag.height / 2 - core.bigmap.offsetY) *
-                core.domStyle.scale;
-            frag.style.left = `${left}px`;
-            frag.style.top = `${top}px`;
-            frag.style.zIndex = '45';
-            frag.style.position = 'absolute';
-            frag.style.filter = 'sepia(20%)brightness(120%)';
-            core.dom.gameDraw.appendChild(frag);
-            manager.onEnd.then(() => {
-                frag.remove();
-            });
-        }
-    });
-}
+export function init() {}
 
 export function applyFragWith(
     canvas: HTMLCanvasElement,
diff --git a/src/plugin/game/enemy/checkblock.ts b/src/plugin/game/enemy/checkblock.ts
deleted file mode 100644
index 607b4a1..0000000
--- a/src/plugin/game/enemy/checkblock.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-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) {
-            Mota.r(() => {
-                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();
-            }
-        }
-    };
-}
diff --git a/src/plugin/game/index.ts b/src/plugin/game/index.ts
index e718b4e..e20a7f0 100644
--- a/src/plugin/game/index.ts
+++ b/src/plugin/game/index.ts
@@ -6,7 +6,6 @@ import * as removeMap from './removeMap';
 import * as shop from './shop';
 import * as utils from './utils';
 import * as remainEnemy from './enemy/remainEnemy';
-import * as checkBlock from './enemy/checkblock';
 
 Mota.Plugin.register('utils_g', utils);
 Mota.Plugin.register('shop_g', shop);
@@ -16,7 +15,6 @@ 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('remainEnemy_g', remainEnemy);
-Mota.Plugin.register('checkBlock_g', checkBlock, checkBlock.init);
 
 // export {
 //     halo,
diff --git a/src/plugin/game/range.ts b/src/plugin/game/range.ts
index 497d1f7..e66346f 100644
--- a/src/plugin/game/range.ts
+++ b/src/plugin/game/range.ts
@@ -96,3 +96,21 @@ Range.registerRangeType(
         );
     }
 );
+Range.registerRangeType(
+    'manhattan',
+    (col, { x, y, d }) => {
+        const list = col.collection.list;
+        return list.filter(v => {
+            if (!has(v.x) || !has(v.y)) return;
+            const dx = Math.abs(v.x - x);
+            const dy = Math.abs(v.y - y);
+            return dx + dy < d;
+        });
+    },
+    (col, { x, y, d }, item) => {
+        if (!has(item.x) || !has(item.y)) return false;
+        const dx = Math.abs(item.x - x);
+        const dy = Math.abs(item.y - y);
+        return dx + dy < d;
+    }
+);
diff --git a/src/plugin/game/utils.ts b/src/plugin/game/utils.ts
index 6a0d4bd..bee586d 100644
--- a/src/plugin/game/utils.ts
+++ b/src/plugin/game/utils.ts
@@ -160,9 +160,10 @@ export function boundary(arr: any, key?: any) {
 export function findDir(from: Loc, to: Loc): Dir2 | 'none' {
     const dx = to.x - from.x;
     const dy = to.y - from.y;
+
     return (
         (Object.entries(core.utils.scan2).find(v => {
-            v[1].x === dx && v[1].y === dy;
+            return v[1].x === dx && v[1].y === dy;
         })?.[0] as Dir2) ?? 'none'
     );
 }
diff --git a/src/plugin/ui/fixed.ts b/src/plugin/ui/fixed.ts
index f919c87..06ce1e5 100644
--- a/src/plugin/ui/fixed.ts
+++ b/src/plugin/ui/fixed.ts
@@ -28,19 +28,17 @@ export function getDetailedEnemy(
     ) => {
         return typeof func === 'string' ? func : func(enemy);
     };
-    const special: [string, string, string][] = enemy.enemy.special.map(vv => {
+    const special: [string, string, string][] = enemy.info.special.map(vv => {
         const s = Mota.require('var', 'enemySpecials')[vv];
+        const info = { ...enemy.enemy, ...enemy.info };
         return [
-            fromFunc(s.name, enemy.enemy),
-            fromFunc(s.desc, enemy.enemy),
+            fromFunc(s.name, info),
+            fromFunc(s.desc, info),
             s.color as string
         ];
     });
     const l = isMobile ? 1 : 2;
-    const showSpecial =
-        special.length > l
-            ? special.slice(0, l).concat([['...', '', '#fff']])
-            : special.slice();
+    const showSpecial = special;
 
     const damageColor = getDamageColor(dam) as string;
 
diff --git a/src/types/enemy.d.ts b/src/types/enemy.d.ts
index 5a61f7c..832b1fa 100644
--- a/src/types/enemy.d.ts
+++ b/src/types/enemy.d.ts
@@ -15,21 +15,7 @@ type PartialNumbericEnemyProperty =
     | 'purify'
     | 'atkValue'
     | 'defValue'
-    | 'damage'
-    | 'iceDecline'
-    | 'iceCore'
-    | 'fireCore'
-    | 'together'
-    | 'hungry'
-    | 'ice'
-    | 'crit'
-    | 'courage'
-    | 'charge'
-    | 'paleShield'
-    | 'iceHalo'
-    | 'day'
-    | 'night'
-    | 'melt';
+    | 'damage';
 
 type BooleanEnemyProperty =
     | 'zoneSquare'