diff --git a/public/libs/control.js b/public/libs/control.js
index c4890c6..ab0bcca 100644
--- a/public/libs/control.js
+++ b/public/libs/control.js
@@ -979,11 +979,10 @@ control.prototype.tryMoveDirectly = function (destX, destY) {
     ];
     var canMoveDirectlyArray = core.canMoveDirectlyArray(dirs, canMoveArray);
 
-    for (var i = 0; i < dirs.length; ++i) {
-        var d = dirs[i],
-            dx = d[0],
-            dy = d[1],
-            dir = d[2];
+    for (let i = 0; i < dirs.length; ++i) {
+        var d = dirs[i];
+        const [dx, dy, dir] = d;
+
         if (
             dx < 0 ||
             dx >= core.bigmap.width ||
@@ -1461,20 +1460,7 @@ control.prototype._checkBlock_disableQuickShop = function () {
 
 ////// 阻击 //////
 control.prototype._checkBlock_repulse = function (repulse) {
-    if (!repulse || repulse.length == 0) return;
-    var actions = [];
-    repulse.forEach(function (t) {
-        actions.push({
-            type: 'move',
-            loc: [t[0], t[1]],
-            steps: [t[3]],
-            time: 250,
-            keep: true,
-            async: true
-        });
-    });
-    actions.push({ type: 'waitAsync' });
-    core.insertAction(actions);
+    // Deprecated.
 };
 
 ////// 更新全地图显伤 //////
diff --git a/public/libs/maps.js b/public/libs/maps.js
index 990eeff..8ae2f57 100644
--- a/public/libs/maps.js
+++ b/public/libs/maps.js
@@ -793,6 +793,7 @@ maps.prototype._canMoveHero_checkPoint = function (
     floorId = floorId || core.status.floorId;
     if (!floorId) return false;
     arrays = arrays || this._generateMovableArray_arrays(floorId);
+    const floor = core.status.maps[floorId];
 
     // 1. 检查该点 cannotMove
     if (
@@ -845,13 +846,12 @@ maps.prototype._canMoveHero_checkPoint = function (
         return false;
 
     // 4. 检查是否能进将死的领域
-    // todo: 不使用 core.status.checkBlock
     if (
         floorId == core.status.floorId &&
         !core.flags.canGoDeadZone &&
         !core.status.lockControl &&
         Math.max(core.status.hero.hp, 1) <=
-            ((core.status.checkBlock.damage || {})[nx + ',' + ny] || 0) &&
+            (floor.enemy.mapDamage[`${nx},${ny}`]?.damage ?? 0) &&
         arrays.eventArray[ny][nx] == 0
     )
         return false;
@@ -1023,10 +1023,11 @@ maps.prototype._canMoveDirectly_checkNextPoint = function (blocksObj, x, y) {
         if (!ignore) return false;
     }
     // 是否存在阻激夹域伤害
-    // todo: 不使用 core.status.checkBlock
-    // if (core.status.checkBlock.damage[index]) return false;
-    // if (core.status.checkBlock.repulse[index]) return false;
-    // if (core.status.checkBlock.mockery[index]) return false;
+    const damage = core.status.thisMap.enemy.mapDamage[index];
+    if (damage) {
+        if (damage.damage !== 0) return false;
+        if (damage.mockery) return false;
+    }
 
     return true;
 };
@@ -1107,24 +1108,21 @@ maps.prototype._automaticRoute_deepAdd = function (x, y, blocks) {
     var block = blocks[x + ',' + y];
     if (block && !block.disable) {
         var id = block.event.id;
-        // 绕过亮灯
-        if (id == 'light') deepAdd += 100;
-        // 绕过路障
-        if (id.endsWith('Net') && !core.hasFlag(id.substring(0, id.length - 3)))
-            deepAdd += 100;
+
         // 绕过血瓶和绿宝石
         if (
             core.hasFlag('__potionNoRouting__') &&
             (id.endsWith('Potion') || id == 'greenGem')
         )
             deepAdd += 100;
-        // 绕过传送点
-        // if (block.event.trigger == 'changeFloor') deepAdd+=10;
     }
     // 绕过存在伤害的地方
-    // todo: 不使用 core.status.checkBlock
-    // deepAdd += (core.status.checkBlock.damage[x + ',' + y] || 0) * 100;
-    // deepAdd += core.status.checkBlock.mockery[`${x},${y}`] ? 1000 : 0;
+    const damage = core.status.thisMap.enemy.mapDamage[`${x},${y}`];
+    if (damage) {
+        deepAdd += damage.damage * 100;
+        deepAdd += !!damage.mockery ? 1e5 : 0;
+    }
+
     return deepAdd;
 };
 
diff --git a/src/plugin/fx/smoothView.ts b/src/plugin/fx/smoothView.ts
index 4999c21..b663c7c 100644
--- a/src/plugin/fx/smoothView.ts
+++ b/src/plugin/fx/smoothView.ts
@@ -36,8 +36,12 @@ export default function init() {
 
         tran.transition('x', ox).transition('y', oy);
 
-        needSmooth = true;
-        func();
+        if (tran.easeTime > 0) {
+            needSmooth = true;
+            func();
+        } else {
+            core.setViewport(tran.value.x, tran.value.y);
+        }
     };
 
     let time2 = Date.now();
@@ -45,19 +49,19 @@ export default function init() {
     control.prototype._moveAction_moving = function (...params: any[]) {
         if (Date.now() - time2 > 20)
             tran.mode(hyper('sin', 'out')).time(200).absolute();
-        origin1.call(this, ...params);
+        return origin1.call(this, ...params);
     };
 
     const origin2 = control.prototype.moveDirectly;
     control.prototype.moveDirectly = function (...params: any[]) {
         time2 = Date.now();
         tran.mode(hyper('sin', 'out')).time(600).absolute();
-        origin2.call(this, ...params);
+        return origin2.call(this, ...params);
     };
 
     const origin3 = events.prototype._changeFloor_beforeChange;
     events.prototype._changeFloor_beforeChange = function (...params: any[]) {
         tran.time(1).absolute();
-        origin3.call(this, ...params);
+        return origin3.call(this, ...params);
     };
 }
diff --git a/src/plugin/game/damage.ts b/src/plugin/game/damage.ts
index 2120b73..98d1b6c 100644
--- a/src/plugin/game/damage.ts
+++ b/src/plugin/game/damage.ts
@@ -138,7 +138,6 @@ export class EnemyCollection implements RangeCollection<DamageEnemy> {
 
     /**
      * 计算地图伤害
-     * @param noCache 是否不使用缓存
      */
     calMapDamage() {
         this.mapDamage = {};
diff --git a/src/plugin/game/popup.js b/src/plugin/game/popup.ts
similarity index 84%
rename from src/plugin/game/popup.js
rename to src/plugin/game/popup.ts
index 95e9c4a..f929789 100644
--- a/src/plugin/game/popup.js
+++ b/src/plugin/game/popup.ts
@@ -3,23 +3,24 @@ import { drawHalo } from './halo';
 
 // 伤害弹出
 // 复写阻激夹域检测
-control.prototype.checkBlock = function (forceMockery) {
-    // todo: 不使用 core.status.checkBlock
+control.prototype.checkBlock = function (forceMockery: boolean = false) {
     var x = core.getHeroLoc('x'),
         y = core.getHeroLoc('y'),
         loc = x + ',' + y;
-    var damage = 0;
+    const floor = core.status.floorId;
+    const info = core.status.maps[floor].enemy.mapDamage[loc];
+    var damage = info.damage;
     if (damage) {
-        if (!main.replayChecking)
+        if (!main.replayChecking) {
             core.addPop(
                 (x - core.bigmap.offsetX / 32) * 32 + 12,
                 (y - core.bigmap.offsetY / 32) * 32 + 20,
-                -damage.toString()
+                (-damage).toString()
             );
+        }
         core.status.hero.hp -= damage;
-        var text =
-            Object.keys(core.status.checkBlock.type[loc] || {}).join(',') ||
-            '伤害';
+        const type = Array.from(info.type.keys());
+        var text = type.join(',') || '伤害';
         core.drawTip('受到' + text + damage + '点');
         core.drawHeroAnimate('zone');
         this._checkBlock_disableQuickShop();
@@ -33,14 +34,14 @@ control.prototype.checkBlock = function (forceMockery) {
             core.updateStatusBar();
         }
     }
-    // this._checkBlock_repulse(core.status.checkBlock.repulse[loc]);
-    // checkMockery(loc, forceMockery);
+    checkMockery(loc, forceMockery);
 };
 
-/**
- * @param {CanvasRenderingContext2D} ctx
- */
-control.prototype._drawDamage_draw = function (ctx, onMap, floorId) {
+control.prototype._drawDamage_draw = function (
+    ctx: CanvasRenderingContext2D,
+    onMap: boolean,
+    floorId: FloorIds
+) {
     if (!core.hasItem('book')) return;
     drawHalo(ctx, onMap, floorId);
 
@@ -62,7 +63,7 @@ control.prototype._drawDamage_draw = function (ctx, onMap, floorId) {
                 return;
         }
         var alpha = core.setAlpha(ctx, one.alpha);
-        core.fillBoldText(ctx, one.text, px, py, one.color);
+        core.fillBoldText(ctx, one.text, px, py, one.color as string);
         core.setAlpha(ctx, alpha);
     });
 
@@ -82,7 +83,7 @@ control.prototype._drawDamage_draw = function (ctx, onMap, floorId) {
             )
                 return;
         }
-        core.fillBoldText(ctx, one.text, px, py, one.color);
+        core.fillBoldText(ctx, one.text, px, py, one.color as string);
     });
 
     ctx.save();
@@ -132,38 +133,31 @@ control.prototype._drawDamage_draw = function (ctx, onMap, floorId) {
         ctx.strokeStyle = 'black';
         ctx.lineWidth = 2.5;
         ctx.stroke();
-        ctx.strokeStyle = v.color;
+        ctx.strokeStyle = v.color as string;
         ctx.lineWidth = 1;
         ctx.stroke();
     });
     ctx.restore();
 };
 
-control.prototype.moveHero = function (direction, callback) {
-    // todo: 不使用 core.status.checkBlock
+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.checkBlock.mockery[`${nx},${ny}`]) {
-    //     core.autosave();
-    // }
+    if (core.status.thisMap.enemy.mapDamage[`${nx},${ny}`]?.mockery) {
+        core.autosave();
+    }
 
     if (callback) return this.moveAction(callback);
     this._moveHero_moving();
 };
 
-/**
- * 电摇嘲讽
- * @param {LocString} loc
- * @param {boolean} force
- */
-function checkMockery(loc, force) {
-    // todo: 不使用 core.status.checkBlock
+function checkMockery(loc: string, force: boolean = false) {
     if (core.status.lockControl && !force) return;
-    const mockery = core.status.checkBlock.mockery[loc];
+    const mockery = core.status.thisMap.enemy.mapDamage[loc]?.mockery;
     if (mockery) {
         mockery.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]));
         const action = [];
@@ -179,7 +173,6 @@ function checkMockery(loc, force) {
             y += dy;
             const block = blocks[`${x},${y}`];
             if (block) {
-                block.event.cls === '';
                 if (
                     [
                         'animates',
diff --git a/src/plugin/pop.ts b/src/plugin/pop.ts
index 2c40c0e..9678751 100644
--- a/src/plugin/pop.ts
+++ b/src/plugin/pop.ts
@@ -1,4 +1,5 @@
 // 示例插件:文字弹出
+// todo: 重写
 
 let pop: any[] = [];
 
diff --git a/src/types/function.d.ts b/src/types/function.d.ts
index 507c077..808a317 100644
--- a/src/types/function.d.ts
+++ b/src/types/function.d.ts
@@ -145,7 +145,7 @@ interface EventData {
      * 游戏失败
      * @param reason 失败原因
      */
-    lose(reason: string): void;
+    lose(reason?: string): void;
 
     /**
      * 切换楼层中,即屏幕完全变黑的那一刻
diff --git a/src/types/status.d.ts b/src/types/status.d.ts
index 434c082..c0077b9 100644
--- a/src/types/status.d.ts
+++ b/src/types/status.d.ts
@@ -774,7 +774,7 @@ interface GameStatus extends InitGameStatus {
     /**
      * 获得当前楼层信息,等价于core.status.maps[core.status.floorId]
      */
-    thisMap: ResolvedFloor;
+    thisMap: Floor;
 
     /**
      * 地图伤害
@@ -950,6 +950,8 @@ interface HeroStatus {
      */
     followers: Follower[];
 
+    statistics: HeroStatistics;
+
     /**
      * 勇士拥有的道具
      */