Browse Source

修复模拟游玩发现的 3 个 bug

- 开垦后草 overlay 残留:clearGrass 清除世界高草,clearTile 还原时恢复草
- 背包满时购买扣款不退款:buyItem 先检查容量再扣款
- 连续升级天赋点丢失:_pendingTalent 改为待选点数计数

Co-Authored-By: Claude <noreply@anthropic.com>
nonvioce 2 months ago
parent
commit
08787fb278

+ 1 - 1
app/src/embed/assets/engine/save.lua

@@ -207,7 +207,7 @@ function Save.apply(data, gameState, farmSystem, playerSystem, weatherSystem, bl
     gameState.level          = data.level  or 1
     gameState.level          = data.level  or 1
     gameState.exp            = data.exp    or 0
     gameState.exp            = data.exp    or 0
     gameState.talents        = data.talents or {}
     gameState.talents        = data.talents or {}
-    gameState._pendingTalent = false
+    gameState._pendingTalent = 0
     gameState.race           = data.race
     gameState.race           = data.race
     gameState.class          = data.class
     gameState.class          = data.class
     gameState.stamina        = data.stamina or 50
     gameState.stamina        = data.stamina or 50

+ 2 - 2
app/src/embed/assets/game.lua

@@ -363,7 +363,7 @@ function Game:_bindEvents()
     -- 经验获得
     -- 经验获得
     Bus.on("gain_exp", function(d)
     Bus.on("gain_exp", function(d)
         local leveled = State.addExp(self.gameState, d.amount or 0)
         local leveled = State.addExp(self.gameState, d.amount or 0)
-        if leveled and self.gameState._pendingTalent then
+        if leveled and (self.gameState._pendingTalent or 0) > 0 then
             -- 弹出天赋选择面板
             -- 弹出天赋选择面板
             local choices = State.rollTalentChoices(self.gameState)
             local choices = State.rollTalentChoices(self.gameState)
             if #choices > 0 then
             if #choices > 0 then
@@ -829,7 +829,7 @@ function Game:onTap(x, y)
             State.pickTalent(self.gameState, talentId)
             State.pickTalent(self.gameState, talentId)
             self.talentRender:closePick()
             self.talentRender:closePick()
             -- 若还有待选(连续升多级),继续弹
             -- 若还有待选(连续升多级),继续弹
-            if self.gameState._pendingTalent then
+            if (self.gameState._pendingTalent or 0) > 0 then
                 local choices = State.rollTalentChoices(self.gameState)
                 local choices = State.rollTalentChoices(self.gameState)
                 if #choices > 0 then
                 if #choices > 0 then
                     self.talentRender:openPick(choices)
                     self.talentRender:openPick(choices)

+ 11 - 0
app/src/embed/assets/systems/farm.lua

@@ -2,6 +2,10 @@
 local Registry = require("engine/registry")
 local Registry = require("engine/registry")
 local Bus      = require("engine/eventbus")
 local Bus      = require("engine/eventbus")
 local Genetics = require("systems/genetics")
 local Genetics = require("systems/genetics")
+local WorldSystem = require("systems/world_system")
+
+-- 还原草地时恢复的高草 overlay ID(grass_tall,与常见野外高草一致)
+local GRASS_OVERLAY_ID = 17
 
 
 -- 冬季节气名集合(立冬~大寒,立春之前)
 -- 冬季节气名集合(立冬~大寒,立春之前)
 local WINTER_TERMS = {
 local WINTER_TERMS = {
@@ -45,6 +49,11 @@ end
 
 
 function FarmSystem:clearTile(row, col)
 function FarmSystem:clearTile(row, col)
     if self.farmData[row] then self.farmData[row][col] = nil end
     if self.farmData[row] then self.farmData[row][col] = nil end
+    -- 还原为草地:恢复高草 overlay(与开垦前视觉一致)
+    local ov = WorldSystem.getOverlayData()
+    if ov and ov[row] and ov[row][col] == 0 then
+        ov[row][col] = GRASS_OVERLAY_ID
+    end
 end
 end
 
 
 function FarmSystem:clearGrass(row, col)
 function FarmSystem:clearGrass(row, col)
@@ -53,6 +62,8 @@ function FarmSystem:clearGrass(row, col)
         self.farmData[row][col] = {
         self.farmData[row][col] = {
             state=STATE.EMPTY, cropId=nil, plantedAt=nil, watered=false, gene=nil,
             state=STATE.EMPTY, cropId=nil, plantedAt=nil, watered=false, gene=nil,
         }
         }
+        -- 清除世界上的高草 overlay,避免草地残留盖住农田
+        WorldSystem.removeGrass(row, col)
         Bus.emit("land_cleared", { row=row, col=col })
         Bus.emit("land_cleared", { row=row, col=col })
         return true
         return true
     end
     end

+ 9 - 5
app/src/embed/assets/systems/state.lua

@@ -29,7 +29,7 @@ function State.new()
         level          = 1,
         level          = 1,
         exp            = 0,
         exp            = 0,
         talents        = {},
         talents        = {},
-        _pendingTalent = false,
+        _pendingTalent = 0,          -- 待选天赋点数(连续升级累加)
         race           = nil,          -- 种族 id
         race           = nil,          -- 种族 id
         class          = nil,          -- 职业 id
         class          = nil,          -- 职业 id
         stamina        = 50,           -- 当前精力
         stamina        = 50,           -- 当前精力
@@ -134,9 +134,12 @@ function State.buyItem(state, itemId)
     local stats = TalentStats.fromState(state)
     local stats = TalentStats.fromState(state)
     local price = math.ceil(item.price * (stats.shopBuyDiscount or 1))
     local price = math.ceil(item.price * (stats.shopBuyDiscount or 1))
     if state.money < price then return false, "金币不足" end
     if state.money < price then return false, "金币不足" end
+    -- 先确认背包能容纳(同类可堆叠或存在空位),避免扣款后放不下
+    local inv = state.inventory
+    local canAdd = inv:findSlot("item", itemId) ~= nil or inv:findEmpty() ~= nil
+    if not canAdd then return false, "背包已满" end
     state.money = state.money - price
     state.money = state.money - price
-    local idx = state.inventory:addItem(itemId, 1)
-    if not idx then return false, "背包已满" end
+    inv:addItem(itemId, 1)
     Bus.emit("item_bought", { itemId=itemId })
     Bus.emit("item_bought", { itemId=itemId })
     return true
     return true
 end
 end
@@ -230,7 +233,7 @@ function State.addExp(state, amount)
         if state.exp >= nextExp then
         if state.exp >= nextExp then
             state.exp   = state.exp - nextExp
             state.exp   = state.exp - nextExp
             state.level = lv + 1
             state.level = lv + 1
-            state._pendingTalent = true
+            state._pendingTalent = (state._pendingTalent or 0) + 1
             leveled = true
             leveled = true
             Bus.emit("player_levelup", { level = state.level })
             Bus.emit("player_levelup", { level = state.level })
         else
         else
@@ -276,7 +279,8 @@ function State.pickTalent(state, talentId)
     local maxS  = def.maxStack or 99
     local maxS  = def.maxStack or 99
     if stack >= maxS then return false end
     if stack >= maxS then return false end
     state.talents[talentId] = stack + 1
     state.talents[talentId] = stack + 1
-    state._pendingTalent = false
+    -- 消耗一个待选点数;剩余点数由 game.lua 继续弹面板
+    state._pendingTalent = math.max(0, (state._pendingTalent or 0) - 1)
     Bus.emit("talent_picked", { talentId = talentId })
     Bus.emit("talent_picked", { talentId = talentId })
     return true
     return true
 end
 end