Files
mtgodot-poc/project/test_lucky_lottery_fortune_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

143 lines
5.5 KiB
GDScript

# test_lucky_lottery_fortune_parity.gd —— Metin2 40250 幸运乐透与老妪占卜转运系统 1:1 测试套件
extends SceneTree
const LuckyLotteryFortuneSystem = preload("res://lucky_lottery_fortune_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_lucky_lottery_fortune_parity (Direction 4: Lucky Lottery & Fortune Telling 1:1) ===")
test_fortune_telling_rules()
test_bad_luck_and_talisman()
test_lottery_scratch_tickets()
test_fortune_update_and_expiry()
test_history_and_serialization()
print("\n=======================================================")
print("Lucky Lottery Parity Tests: %d Passed, %d Failed" % [_passed, _failed])
print("=======================================================\n")
if _failed > 0:
quit(1)
else:
quit(0)
func test_fortune_telling_rules() -> void:
print("\n--- Test 1: Old Woman Fortune Telling (40250 1:1) ---")
var system = LuckyLotteryFortuneSystem.new()
# 等级不足 20 级拦截
var res = system.tell_fortune(18, 50000)
_assert(res["ok"] == false, "Rejected Lv 18 character")
_assert(res["reason"] == "LEVEL_TOO_LOW", "Reason is LEVEL_TOO_LOW")
# 金币不足 7777 拦截
res = system.tell_fortune(25, 3000)
_assert(res["ok"] == false, "Rejected insufficient gold")
_assert(res["reason"] == "NOT_ENOUGH_GOLD", "Reason is NOT_ENOUGH_GOLD")
# 占卜成功:大吉
res = system.tell_fortune(25, 10000, "great_luck")
_assert(res["ok"] == true, "Fortune told successfully")
_assert(res["tier"] == "great_luck", "Tier is great_luck")
_assert(res["exp_bonus"] == 0.10, "+10% EXP bonus")
_assert(res["gold_bonus"] == 0.10, "+10% Gold drop bonus")
_assert(res["remaining_gold"] == 2223, "Deducted 7777 gold (10000 - 7777 = 2223)")
func test_bad_luck_and_talisman() -> void:
print("\n--- Test 2: Bad Luck & Karma Talisman (40250 1:1) ---")
var system = LuckyLotteryFortuneSystem.new()
# 占卜得到大凶
var res = system.tell_fortune(30, 20000, "bad_luck")
_assert(res["ok"] == true, "Told bad luck")
_assert(res["tier"] == "bad_luck", "Current tier is bad_luck")
_assert(res["can_buy_talisman"] == true, "Old woman offers talisman")
# 购买辟邪转运符 (70052)
var inv: Array = []
var buy_res = system.buy_karma_talisman(inv, 20000)
_assert(buy_res["ok"] == true, "Purchased talisman")
_assert(buy_res["talisman_vnum"] == 70052, "Talisman item vnum is 70052")
_assert(inv.size() == 1 and inv[0]["vnum"] == 70052, "Talisman added to inventory")
# 运势转危为安,大凶转化为中吉
var active = system.get_active_fortune_bonus()
_assert(active["tier"] == "good_luck", "Tier converted to good_luck")
_assert(active["gold_bonus"] > 0.0, "Gold penalty cleared into positive bonus")
func test_lottery_scratch_tickets() -> void:
print("\n--- Test 3: Scratch Lottery Tickets (40250 1:1) ---")
var system = LuckyLotteryFortuneSystem.new()
var inv: Array = [
{"vnum": 50027, "count": 2}, # 彩票 x2 (slot 0)
{"vnum": 50027, "count": 1}, # 彩票 x1 (slot 1)
{"vnum": 50027, "count": 1} # 彩票 x1 (slot 2)
]
# 1. 刮出三同号 [7, 7, 7] -> 特等大奖 (1,000,000 金币 + 祝福卷轴 25040)
var res = system.play_scratch_lottery(inv, 0, [7, 7, 7])
_assert(res["ok"] == true, "Scratched lottery ticket")
_assert(res["prize_tier"] == "grand_jackpot", "Won grand jackpot!")
_assert(res["prize_gold"] == 1000000, "Prize gold is 1,000,000")
_assert(res["prize_item"] == 25040, "Prize item is Blessing Scroll (25040)")
_assert(inv[0]["count"] == 1, "Count decremented from 2 to 1")
# 检查背包是否发放了祝福卷轴
var has_scroll := false
for it in inv:
if it != null and it.get("vnum", 0) == 25040:
has_scroll = true
_assert(has_scroll == true, "Blessing Scroll awarded into inventory")
# 2. 刮出二同号 [8, 8, 3] -> 二等奖 (200,000 金币)
res = system.play_scratch_lottery(inv, 1, [8, 8, 3])
_assert(res["prize_tier"] == "second_prize", "Won second prize")
_assert(res["prize_gold"] == 200000, "Prize gold is 200,000")
# 3. 刮出单号 [1, 5, 9] -> 安慰奖 (30,000 金币)
res = system.play_scratch_lottery(inv, 2, [1, 5, 9])
_assert(res["prize_tier"] == "consolation_prize", "Won consolation prize")
_assert(res["prize_gold"] == 30000, "Prize gold is 30,000")
func test_fortune_update_and_expiry() -> void:
print("\n--- Test 4: Fortune Duration & Expiry ---")
var system = LuckyLotteryFortuneSystem.new()
system.tell_fortune(30, 10000, "great_luck")
var active = system.get_active_fortune_bonus()
_assert(active["tier"] == "great_luck", "Active fortune exists")
# 时间流逝 20000 秒
system.update(20000.0)
_assert(system.fortune_time_remaining <= 8800.0, "Time remaining decremented")
# 时间流逝剩余时间 (到期)
system.update(10000.0)
active = system.get_active_fortune_bonus()
_assert(active["tier"] == "", "Fortune expired and cleared")
func test_history_and_serialization() -> void:
print("\n--- Test 5: History & Serialization ---")
var system = LuckyLotteryFortuneSystem.new()
var inv: Array = [{"vnum": 50027, "count": 1}]
system.play_scratch_lottery(inv, 0, [3, 3, 3])
_assert(system.lotto_history.size() == 1, "Recorded 1 lotto history")
var data = system.serialize()
var restored = LuckyLotteryFortuneSystem.new()
restored.deserialize(data)
_assert(restored.lotto_history.size() == 1, "Restored 1 lotto history")
_assert(restored.lotto_history[0]["prize_tier"] == "grand_jackpot", "Restored grand jackpot tier")