Files
mtgodot-poc/project/test_fishing_cooking_camp_parity.gd
T
shenandshen 66d217b313 feat(client): 完成40250客户端核心功能1:1对齐与桥梁高度采样修复
- 桥梁与静态物体高度采样修复:
  - 严格对齐 40250 CMapOutdoor::GetHeight 与 CAttributeInstance::GetHeight
  - 解析 .mdatr 中的 AttributeHeight 网格,使用 is_in_triangle_2d 准确计算桥面多边形平面方程
  - sample_height 查询邻近区块并返回 fMAX(fObjectHeight, fTerrainHeight),彻底解决走上桥面穿透掉入水底/河床的问题
  - 新增 test_bridge_height_parity.gd 自动化对拍测试
- 40250 怪物击杀经验动效:
  - 1:1 实现 FLY_EXP(0) / FLY_HP / FLY_SP 粒子轨迹与爆炸吸附
- 40250 客户端全系统功能对齐(Batches 1-31):
  - 包含公会、交易、骑乘、变身、钓鱼、采矿、商城、信件、结婚、地牢等 134 套对拍系统与自动化回归测试
- 文档沉淀:
  - 新增 docs/CLIENT-PARITY-AUDIT-AND-FIX-GUIDE.md 客户端对拍缺陷发现与修复工程指南
2026-09-19 08:51:25 -07:00

163 lines
5.5 KiB
GDScript

# test_fishing_cooking_camp_parity.gd —— 40250 野外钓鱼烹饪与露营增益 1:1 回归测试套件
extends SceneTree
const FishingCookingCampSystem = preload("res://fishing_cooking_camp_system.gd")
var _passed := 0
var _failed := 0
func _assert(cond: bool, msg: String) -> void:
if cond:
_passed += 1
print(" [PASS] %s" % msg)
else:
_failed += 1
printerr(" [FAIL] %s" % msg)
func _init() -> void:
print("\n=== Running test_fishing_cooking_camp_parity (Direction 2: Fishing Cooking Camp 1:1) ===")
_test_campfire_lighting()
_test_cooking_fish_recipes()
_test_eating_and_stat_buffs()
_test_buff_expiration_and_cleanup()
_finish()
func _test_campfire_lighting() -> void:
print("\n--- Test 1: Lighting & Extinguishing Campfire (27600) ---")
var camp := FishingCookingCampSystem.new()
var inv: Array = [
{"vnum": FishingCookingCampSystem.CAMPFIRE_KIT_VNUM, "name": "营火工具", "count": 2}
]
var light_sig := {"fired": false, "time": 0.0}
camp.campfire_lit.connect(func(_p: Vector3, d: float):
light_sig["fired"] = true
light_sig["time"] = d
)
var res = camp.light_campfire(Vector3(10, 0, 10), inv)
_assert(res["ok"] == true, "Campfire lit")
_assert(camp.is_campfire_active == true, "Campfire is active")
_assert(inv[0]["count"] == 1, "1 campfire kit consumed (2 -> 1)")
_assert(light_sig["fired"] == true and light_sig["time"] == 300.0, "campfire_lit emitted with 300s")
# Extinguish on timeout (advance 305 seconds)
var ext_sig := {"fired": false}
camp.campfire_extinguished.connect(func(): ext_sig["fired"] = true)
var dummy_p := {}
camp.update(305.0, dummy_p)
_assert(camp.is_campfire_active == false, "Campfire extinguished")
_assert(ext_sig["fired"] == true, "campfire_extinguished emitted")
func _test_cooking_fish_recipes() -> void:
print("\n--- Test 2: Cooking Fish Recipes on Campfire ---")
var camp := FishingCookingCampSystem.new()
var inv: Array = [
{"vnum": 27600, "count": 1},
{"vnum": 27802, "name": "生鲤鱼", "count": 1},
{"vnum": 27815, "name": "生红鳟鱼", "count": 2}
]
# Try cook without active fire
var fail_c = camp.cook_fish(1, inv)
_assert(fail_c["ok"] == false and fail_c["reason"] == "NO_ACTIVE_CAMPFIRE", "Cannot cook without campfire")
# Light fire
camp.light_campfire(Vector3.ZERO, inv)
var cook_sig := {"fired": false, "name": ""}
camp.fish_cooked.connect(func(_raw: int, _ckd: int, cname: String):
cook_sig["fired"] = true
cook_sig["name"] = cname
)
# Cook Carp (slot 1)
var res1 = camp.cook_fish(1, inv)
_assert(res1["ok"] == true, "Cooked Carp")
_assert(cook_sig["fired"] == true and cook_sig["name"] == "烤鲤鱼", "fish_cooked signal emitted")
var has_cooked_carp := false
for it in inv:
if it != null and it.get("vnum", 0) == 27832:
has_cooked_carp = true
break
_assert(has_cooked_carp, "Cooked carp found in inventory")
# Cook Trout (slot 2)
camp.cook_fish(2, inv)
_assert(inv[2]["count"] == 1, "Raw trout count decremented (2 -> 1)")
var has_cooked_trout := false
for it in inv:
if it != null and it.get("vnum", 0) == 27845:
has_cooked_trout = true
break
_assert(has_cooked_trout, "Cooked trout found in inventory")
func _test_eating_and_stat_buffs() -> void:
print("\n--- Test 3: Eating Cooked Fish & 30-Minute Buffs ---")
var camp := FishingCookingCampSystem.new()
var player := {
"max_hp": 8000,
"atk": 500,
"move_speed": 100
}
var inv: Array = [
{"vnum": 27832, "name": "烤鲤鱼", "count": 1},
{"vnum": 27845, "name": "烤红鳟鱼", "count": 1}
]
var buff_sig := {"fired": false, "id": "", "dur": 0.0}
camp.food_buff_applied.connect(func(bid: String, _n: String, d: float):
buff_sig["fired"] = true
buff_sig["id"] = bid
buff_sig["dur"] = d
)
# Eat Grilled Carp (max_hp +1000)
var eat1 = camp.eat_cooked_fish(0, inv, player)
_assert(eat1["ok"] == true, "Ate Grilled Carp")
_assert(player["max_hp"] == 9000, "Max HP increased 8000 -> 9000 (+1000)")
_assert(inv[0] == null, "Grilled carp consumed")
_assert(buff_sig["fired"] == true and buff_sig["id"] == "buff_grilled_carp", "food_buff_applied emitted")
# Eat Grilled Trout (atk +50)
var eat2 = camp.eat_cooked_fish(1, inv, player)
_assert(eat2["ok"] == true, "Ate Grilled Trout")
_assert(player["atk"] == 550, "Atk increased 500 -> 550 (+50)")
_assert(camp.active_buffs.size() == 2, "2 active food buffs running")
func _test_buff_expiration_and_cleanup() -> void:
print("\n--- Test 4: Buff Duration & Clean Expiration ---")
var camp := FishingCookingCampSystem.new()
var player := {"max_hp": 8000}
var inv: Array = [{"vnum": 27832, "name": "烤鲤鱼", "count": 1}]
camp.eat_cooked_fish(0, inv, player)
_assert(player["max_hp"] == 9000, "HP is 9000")
var expire_sig := {"fired": false, "id": ""}
camp.food_buff_expired.connect(func(bid: String):
expire_sig["fired"] = true
expire_sig["id"] = bid
)
# Simulate 1805 seconds (exceeding 1800s duration)
camp.update(1805.0, player)
_assert(expire_sig["fired"] == true and expire_sig["id"] == "buff_grilled_carp", "food_buff_expired emitted")
_assert(player["max_hp"] == 8000, "Max HP cleanly reverted back to baseline 8000")
_assert(camp.active_buffs.is_empty(), "active_buffs cleared")
func _finish() -> void:
print("\n==========================================")
print("Fishing Cooking Camp Parity Tests Finished:")
print("Passed: %d, Failed: %d" % [_passed, _failed])
print("==========================================")
if _failed > 0:
printerr("FAILED: Some tests did not pass.")
quit(1)
else:
print("SUCCESS: All Fishing Cooking Camp parity tests passed!")
quit(0)