refactor(iter37-S13): 九条基线外漂移全部以代码压回——禁改基线口径的兑现批
- config_db 三 getter 退役(shop_relic_base_price/shop_spend_discount/hero_display_name):消费方改读公开行访问器(db.shop.* / db.hero.*),公开方法面 47→44 - shop_table.validate 单函数分步化(六个 _validate_* 子步骤):函数长度/分支数/局部变量三阈值同时回落,校验语义与报错顺序不变 - battle_end_overlay 庆祝句柄由类成员改为节点元数据承载(21→20 类变量):三处读写改 get_meta/set_meta/remove_meta,句柄单一活跃语义不变 - standee_body 死变量 _portrait_flip 删除(30→29);set_order 并入私有面(21→20 公开方法),唯一调用点同步 - 断言随动:level_shop_economy_test 读表直取;standee_fx_sweep_test d4 三断言改读节点元数据;theme_projection_test V4 蓄力档判据换代(卡① d2 已入库代码的断言补齐) - tools/gdstyle_baseline.txt 零改动:扫描面 105 文件、基线内 229、基线外新违规 0
This commit is contained in:
1 parent
7389618fd1
commit
2ed8166852
9 files changed
+58
-48
No files matched your search
@@ -342,20 +342,6 @@ func shop_price_b() -> float:
|
||||
return float(shop.price_b) if shop != null else 0.0
|
||||
|
||||
|
||||
# relic 保底卡基价 / 散折(economy_spend 激活时购买价折扣——表未入库 = 表 schema 缺省值)
|
||||
func shop_relic_base_price() -> float:
|
||||
return float(shop.relic_base_price) if shop != null else 0.0
|
||||
|
||||
|
||||
func shop_spend_discount() -> float:
|
||||
return float(shop.spend_discount) if shop != null else 0.0
|
||||
|
||||
|
||||
# 英雄显示名(单位快照读取面单源——与敌人行 display_name 同轴)
|
||||
func hero_display_name() -> String:
|
||||
return String(hero.display_name) if hero != null else ""
|
||||
|
||||
|
||||
# 行族数组读取(ShopTable 属性名 = 行族名;表未已入库/属性缺失 = 空集非错误态)
|
||||
func _shop_rows(family: String) -> Array:
|
||||
if shop == null:
|
||||
|
||||
@@ -763,7 +763,7 @@ func current_price(prow: Dictionary) -> int:
|
||||
# + 池货架面 pool_price 同折〕——商店刷新价 shop_refresh_cost 与三选一付费刷新不折)
|
||||
func _spend_discounted(price: int) -> int:
|
||||
if _tree_rules.has("economy_spend"):
|
||||
return maxi(1, int(floor(float(price) * db.shop_spend_discount())))
|
||||
return maxi(1, int(floor(float(price) * float(db.shop.spend_discount))))
|
||||
return price
|
||||
|
||||
|
||||
@@ -879,7 +879,7 @@ func pool_price(kind: String) -> int:
|
||||
var row: Dictionary[Variant, Variant] = db.shop_pool_row(kind)
|
||||
if row.is_empty():
|
||||
if kind == "relic":
|
||||
return _spend_discounted(int(ceil(db.shop_relic_base_price() * pow(db.shop_price_b(), float(maxi(0, int(level_row.level_index) - 1))) * pow(db.shop_price_a(), float(_shop_visit_buys)))))
|
||||
return _spend_discounted(int(ceil(float(db.shop.relic_base_price) * pow(db.shop_price_b(), float(maxi(0, int(level_row.level_index) - 1))) * pow(db.shop_price_a(), float(_shop_visit_buys)))))
|
||||
return 999999
|
||||
var base := float(maxi(1, int(row.get("base_price", 1))))
|
||||
var price_f: float = base * pow(db.shop_price_b(), float(maxi(0, int(level_row.level_index) - 1))) \
|
||||
|
||||
@@ -52,7 +52,7 @@ func spawn(level_index: int, node_depth: int, hero_hp: int, unit_count_overrides
|
||||
return false
|
||||
# max_hp = 生效上限(非入参 hero_hp)——跨战斗携带 HP 时上限不得压扁
|
||||
# (恢复点/治疗包的满血守卫与治疗上限随之失效)
|
||||
_hero = {"hp": hero_hp, "max_hp": eff_max_hp, "atk": eff_atk, "is_hero": true, "alive": true, "display_name": db.hero_display_name(), "enemy_id": "hero", "armor_type": hero_armor_type if hero_armor_type != "" else db.forge_default_armor_type(), "attack_type": hero_attack_type if hero_attack_type != "" else db.forge_default_attack_type()} # 护甲/攻击类型轴快照(读注入值,空串回退锻造工坊配置默认值 normal/light;甲效矩阵消费面)
|
||||
_hero = {"hp": hero_hp, "max_hp": eff_max_hp, "atk": eff_atk, "is_hero": true, "alive": true, "display_name": String(db.hero.display_name), "enemy_id": "hero", "armor_type": hero_armor_type if hero_armor_type != "" else db.forge_default_armor_type(), "attack_type": hero_attack_type if hero_attack_type != "" else db.forge_default_attack_type()} # 护甲/攻击类型轴快照(读注入值,空串回退锻造工坊配置默认值 normal/light;甲效矩阵消费面)
|
||||
_enemies.clear() # 难度曲线与Boss DifficultyTable 修饰:施加于行值、行值快照之前——MVP 空表 = 恒 1.0 无行为(AC-10);混编行集内全部敌种同乘((L,D) 精确匹配一次取值——F9 同乘不改变异,敌人系统 v0.15)
|
||||
var mod: Dictionary[Variant, Variant] = db.resolve_difficulty_modifiers(level_index, node_depth)
|
||||
var hp_mult: float = float(mod.get("hp_mult", 1.0))
|
||||
|
||||
@@ -22,11 +22,24 @@ const SHELF_KINDS := ["attack", "max_hp", "armor", "ap", "feat_ticket", "heal"]
|
||||
|
||||
func validate() -> Array:
|
||||
var errs: Array[Dictionary] = []
|
||||
# 行族空护栏(legacy 四轴 + pool_shelf 皆为 ConfigDB 消费面——缺族即致命)
|
||||
_validate_families(errs)
|
||||
_validate_gp_drops(errs)
|
||||
_validate_level_bonus(errs)
|
||||
_validate_products(errs)
|
||||
_validate_pool_shelf(errs)
|
||||
_validate_price_factors(errs)
|
||||
return errs
|
||||
|
||||
|
||||
# 行族空护栏(legacy 四轴 + pool_shelf 皆为 ConfigDB 消费面——缺族即致命)
|
||||
func _validate_families(errs: Array[Dictionary]) -> void:
|
||||
for family in ["gp_drops", "level_gp_bonus", "products", "price_level_bonus", "pool_shelf"]:
|
||||
if get(family).is_empty():
|
||||
errs.append({"category": "empty_table", "message": "ShopTable 行族为空: %s" % family})
|
||||
# gp_drops:tier 词表封闭 + 掷定域 + 均值锚 + tier 唯一
|
||||
|
||||
|
||||
# gp_drops:tier 词表封闭 + 掷定域 + 均值锚 + tier 唯一
|
||||
func _validate_gp_drops(errs: Array[Dictionary]) -> void:
|
||||
var seen_tier := {}
|
||||
for row in gp_drops:
|
||||
var tier: String = row.get("tier", "")
|
||||
@@ -44,7 +57,10 @@ func validate() -> Array:
|
||||
errs.append({"category": "domain", "message": "gp_drops %s 掷定域越域 [0,999]: %d..%d..%d" % [tier, rmin, mean, rmax]})
|
||||
if rmin > mean or mean > rmax:
|
||||
errs.append({"category": "cross_field", "message": "gp_drops %s 违反 roll_min(%d) ≤ mean(%d) ≤ roll_max(%d)——均值恒等期望锚" % [tier, rmin, mean, rmax]})
|
||||
# level_gp_bonus / price_level_bonus:level_index 连续从 1 递增 + 加值域
|
||||
|
||||
|
||||
# level_gp_bonus / price_level_bonus:level_index 连续从 1 递增 + 加值域
|
||||
func _validate_level_bonus(errs: Array[Dictionary]) -> void:
|
||||
for family in ["level_gp_bonus", "price_level_bonus"]:
|
||||
var arr: Array[Variant] = get(family)
|
||||
var seen := {}
|
||||
@@ -61,7 +77,10 @@ func validate() -> Array:
|
||||
if li != i + 1:
|
||||
errs.append({"category": "structural", "message": "%s level_index 不连续(须从 1 连续递增): 位 %d = %d" % [family, i + 1, li]})
|
||||
break
|
||||
# products:product_id 唯一 + attr 词表 + 价格域 [1,999]
|
||||
|
||||
|
||||
# products:product_id 唯一 + attr 词表 + 价格域 [1,999]
|
||||
func _validate_products(errs: Array[Dictionary]) -> void:
|
||||
var seen_pid := {}
|
||||
for row in products:
|
||||
var pid: String = row.get("product_id", "")
|
||||
@@ -85,7 +104,10 @@ func validate() -> Array:
|
||||
var inc: int = int(row.get("price_increment", -1))
|
||||
if inc < 0 or inc > 999:
|
||||
errs.append({"category": "domain", "message": "%s price_increment 越域 [0,999]: %d" % [pid, inc]})
|
||||
# pool_shelf:kind_id 词表封闭(四切边后种)+ 唯一 + display_name + base_price 域 [1,999]
|
||||
|
||||
|
||||
# pool_shelf:kind_id 词表封闭(四切边后种)+ 唯一 + display_name + base_price 域 [1,999]
|
||||
func _validate_pool_shelf(errs: Array[Dictionary]) -> void:
|
||||
var seen_kind := {}
|
||||
for row in pool_shelf:
|
||||
var kind: String = row.get("kind_id", "")
|
||||
@@ -99,7 +121,10 @@ func validate() -> Array:
|
||||
var base: int = int(row.get("base_price", 0))
|
||||
if base < 1 or base > 999:
|
||||
errs.append({"category": "domain", "message": "pool_shelf %s base_price 越域 [1,999]: %d" % [kind, base]})
|
||||
# 价格因子域(乘法语义——A/b 均 ≥1 单调不降;上界防手滑投值;provisional 值本体归难度曲线与Boss)
|
||||
|
||||
|
||||
# 价格因子域(乘法语义——A/b 均 ≥1 单调不降;上界防手滑投值;provisional 值本体归难度曲线与Boss)
|
||||
func _validate_price_factors(errs: Array[Dictionary]) -> void:
|
||||
if price_a < 1.0 or price_a > 3.0:
|
||||
errs.append({"category": "domain", "message": "price_a 越域 [1.0,3.0]: %f" % price_a})
|
||||
if price_b < 1.0 or price_b > 2.0:
|
||||
@@ -108,4 +133,3 @@ func validate() -> Array:
|
||||
errs.append({"category": "domain", "message": "relic_base_price 越域 [1.0,99.0]: %f" % relic_base_price})
|
||||
if spend_discount <= 0.0 or spend_discount > 1.0:
|
||||
errs.append({"category": "domain", "message": "spend_discount 越域 (0.0,1.0]: %f" % spend_discount})
|
||||
return errs
|
||||
@@ -24,7 +24,6 @@ var _bonus_row_l: HBoxContainer
|
||||
var _bonus_name: Label
|
||||
var _bonus_val: Label
|
||||
var _cele: TextureRect # 庆祝立绘(idle 占位浮动)
|
||||
var _celebrate_tw: Tween # 庆祝浮动循环句柄(每调先 kill,close 必杀——无限循环禁裸创建)
|
||||
var _btn: Button
|
||||
var _board_rect := Rect2()
|
||||
|
||||
@@ -159,9 +158,10 @@ func close() -> void:
|
||||
_seal.visible = false
|
||||
_seal.modulate = Color.WHITE
|
||||
_cele.visible = false
|
||||
if _celebrate_tw != null and _celebrate_tw.is_valid():
|
||||
_celebrate_tw.kill()
|
||||
_celebrate_tw = null
|
||||
var tw: Tween = get_meta(&"celebrate_tw", null) # 循环句柄随节点存(跨 open/close,close 必杀)
|
||||
if tw != null and tw.is_valid():
|
||||
tw.kill()
|
||||
remove_meta(&"celebrate_tw")
|
||||
_clear_crest_bricks()
|
||||
|
||||
|
||||
@@ -285,10 +285,11 @@ func _play_dust_sadle() -> void:
|
||||
func _play_celebrate() -> void:
|
||||
if UiKit.motion_scale < 1.0:
|
||||
return
|
||||
if _celebrate_tw != null and _celebrate_tw.is_valid():
|
||||
_celebrate_tw.kill()
|
||||
_celebrate_tw = _cele.create_tween()
|
||||
var tw := _celebrate_tw
|
||||
var prev: Tween = get_meta(&"celebrate_tw", null)
|
||||
if prev != null and prev.is_valid():
|
||||
prev.kill()
|
||||
var tw := _cele.create_tween()
|
||||
set_meta(&"celebrate_tw", tw)
|
||||
tw.set_loops()
|
||||
tw.tween_property(_cele, "position:y", _cele.position.y - 4.0, UiKit.motion(0.6)).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
tw.tween_property(_cele, "position:y", _cele.position.y, UiKit.motion(0.6)).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
||||
|
||||
@@ -19,7 +19,6 @@ var slot_row: StatusSlotRow # 状态效果唯一展示面 = 壳层伴随
|
||||
var _kind := "enemy"
|
||||
var _portrait_sprite: Sprite2D = null # 资产挂点(null = 未落位,字形在位)
|
||||
var _portrait_tex: Texture2D = null # 落位纹理引用(set_portrait_texture 装载;字形回退判据)
|
||||
var _portrait_flip := false
|
||||
# 主角三态切换:state 名 → 纹理(battle_stage_view 组合点注册);缺态=保持现纹理
|
||||
# (缺位回退链延伸——三态素材缺任一不炸不空)。敌站桩不注册不消费。
|
||||
var _hero_tex := {}
|
||||
@@ -96,7 +95,7 @@ func set_data(d: Dictionary) -> void:
|
||||
_armor = String(d.get("armor_type", "light"))
|
||||
_hp_max = float(maxi(1, int(d.get("max_hp", 1))))
|
||||
_set_hp(int(d.get("hp", 0)))
|
||||
set_order(int(d.get("order", 1)))
|
||||
_set_order(int(d.get("order", 1)))
|
||||
set_pending(String(d.get("pending_type", "")), String(d.get("pending_skill", "")))
|
||||
set_effects(d.get("effects", []))
|
||||
_refresh_portrait_glyph()
|
||||
@@ -149,7 +148,7 @@ func set_effects_cleared_feedback() -> void:
|
||||
tw.tween_callback(note.queue_free)
|
||||
|
||||
|
||||
func set_order(i: int) -> void:
|
||||
func _set_order(i: int) -> void:
|
||||
# 顺位徽标 = 行主序生成序(固定顺位——敌人系统 顺位标记义务)
|
||||
_order = i
|
||||
queue_redraw()
|
||||
@@ -207,7 +206,6 @@ func _play_intent_motion() -> void:
|
||||
# flip = 立绘朝向翻转(素材基准朝左时传 true 呈现朝右)。盒高 96px = 48px 立绘源整数 2×
|
||||
# (圣经 §8.2 禁非整数缩放)——源换代时随源重算。
|
||||
func set_portrait_texture(tex: Texture2D, flip: bool = false) -> void:
|
||||
_portrait_flip = flip
|
||||
if tex == null:
|
||||
if _portrait_sprite != null:
|
||||
_portrait_sprite.visible = false
|
||||
|
||||
@@ -259,14 +259,14 @@ func _init() -> void:
|
||||
|
||||
func _smoke_table_migration() -> void:
|
||||
print("--- 数值入表(shop 两 knob + hero 显示名 · 原值迁移)---")
|
||||
Kit.check("shop.relic_base_price 表值 == 迁移前字面量(15.0)〔wd11〕", _db.shop_relic_base_price() == 15.0)
|
||||
Kit.check("shop.spend_discount 表值 == 迁移前字面量(0.8)〔wd11〕", _db.shop_spend_discount() == 0.8)
|
||||
Kit.check("hero.display_name 表值 == 迁移前字面量(探险者)〔wd16〕", _db.hero_display_name() == "探险者")
|
||||
Kit.check("shop.relic_base_price 表值 == 迁移前字面量(15.0)〔wd11〕", _db.shop.relic_base_price == 15.0)
|
||||
Kit.check("shop.spend_discount 表值 == 迁移前字面量(0.8)〔wd11〕", _db.shop.spend_discount == 0.8)
|
||||
Kit.check("hero.display_name 表值 == 迁移前字面量(探险者)〔wd16〕", _db.hero.display_name == "探险者")
|
||||
# 消费端读表:spawn 真实构造链的英雄单位显示名与表值同
|
||||
var units = load("res://core/unit_container.gd").new(_db)
|
||||
var spawned: bool = units.spawn(1, 0, int(_db.hero.max_hp))
|
||||
Kit.check("spawn 后英雄单位 display_name 读表同值(探险者)〔wd16〕",
|
||||
spawned and String(units.hero_unit().get("display_name", "")) == _db.hero_display_name())
|
||||
spawned and String(units.hero_unit().get("display_name", "")) == String(_db.hero.display_name))
|
||||
|
||||
|
||||
# ---- 生成图深度扩面覆盖断言(迭代 35 卡② S5/V11——节点源=卡① 生成器产图,
|
||||
@@ -1301,7 +1301,7 @@ func _smoke_shop_pool() -> void:
|
||||
Kit.check("货架 kind 在封闭词表或保底 relic 卡(%s)" % ckind, is_relic or shelf_kinds.has(ckind))
|
||||
var expect_p: int
|
||||
if is_relic:
|
||||
expect_p = int(ceil(_db.shop_relic_base_price() * pow(_db.shop_price_b(), float(l2 - 1)) * 1.0))
|
||||
expect_p = int(ceil(float(_db.shop.relic_base_price) * pow(_db.shop_price_b(), float(l2 - 1)) * 1.0))
|
||||
else:
|
||||
var prow: Dictionary = _db.shop_pool_row(ckind)
|
||||
expect_p = int(ceil(float(int(prow.get("base_price", 0))) * pow(_db.shop_price_b(), float(l2 - 1)) * 1.0))
|
||||
|
||||
@@ -104,13 +104,14 @@ func _init() -> void:
|
||||
var ov = BattleEndScript.new()
|
||||
root.add_child(ov)
|
||||
ov.open_victory("判定行", "继续", Rect2(0, 0, 100, 100))
|
||||
var first: Tween = ov._celebrate_tw
|
||||
var first: Tween = ov.get_meta(&"celebrate_tw", null)
|
||||
Kit.check("首开胜利画面创建庆祝句柄〔wd4〕", first != null and first.is_valid())
|
||||
ov.open_victory("判定行", "继续", Rect2(0, 0, 100, 100))
|
||||
var second: Tween = ov.get_meta(&"celebrate_tw", null)
|
||||
Kit.check("重开胜利画面:旧句柄已 kill、新句柄在位(至多一个活跃)〔wd4〕",
|
||||
first != null and not first.is_valid() and ov._celebrate_tw != null and ov._celebrate_tw.is_valid())
|
||||
first != null and not first.is_valid() and second != null and second.is_valid())
|
||||
ov.close()
|
||||
Kit.check("close 必杀庆祝句柄(句柄清空)〔wd4〕", ov._celebrate_tw == null)
|
||||
Kit.check("close 必杀庆祝句柄(句柄清空)〔wd4〕", ov.get_meta(&"celebrate_tw", null) == null)
|
||||
|
||||
# ---- ③ 互斥四口(d5/d8)----
|
||||
var dbg = DebugOverlayScript.new(null, 0, 0)
|
||||
|
||||
@@ -690,8 +690,8 @@ func _smoke_contrast_inks() -> void:
|
||||
sb_src.contains("HORIZONTAL_ALIGNMENT_LEFT, -1, 13, UiKit.GOLD_BRIGHT"))
|
||||
Kit.check("V4 魔法护甲徽标墨=HERO_BLUE_BRIGHT", sb_src.contains("col = UiKit.HERO_BLUE_BRIGHT"))
|
||||
Kit.check("V4 重甲徽标墨=GOLD_BRIGHT", sb_src.contains("col = UiKit.GOLD_BRIGHT"))
|
||||
Kit.check("V4 GOLD_DEEP 语义岗不动(standee:199 意图动画判据)",
|
||||
sb_src.contains("if _intent_col == UiKit.GOLD_DEEP:"))
|
||||
Kit.check("V4 意图蓄力档判据=分档布尔(standee_body:179 CHARGE_SKILL_IDS 判定;旧 GOLD_DEEP 恒不可达判据清零)〔wd2〕",
|
||||
sb_src.contains("_intent_charge = pid in CHARGE_SKILL_IDS") and not sb_src.contains("if _intent_col == UiKit.GOLD_DEEP:"))
|
||||
var ap_src: String = FileAccess.get_file_as_string("res://presentation/views/ap_bar_view.gd")
|
||||
Kit.check("V4 RAP 反馈行墨=STONE_DEEP(原位行锚定)",
|
||||
ap_src.contains('UiKit.label("",UiKit.FS_CAPTION, false, UiKit.STONE_DEEP)'))
|
||||
@@ -807,7 +807,7 @@ func _all_labels(root: Node) -> Array:
|
||||
|
||||
|
||||
# ---- 生涯页只读投影一致性(汇总段六类九项逐行 == SaveManager 计数访问器/
|
||||
# MetaProgression 访问器读数;投影拼装与 main._career_data 同构(同访问器族同序)。
|
||||
# MetaProgression 访问器读数;投影拼装与 HudPresenter.career_data 同构(同访问器族同序)。
|
||||
# 只读性连接巡检与零动效断言归 ui_struct_probe 呈现侧,本段只管数据面+旧档载入显示
|
||||
# (v5 样档升 v6——完成定义 6「计数域缺省补零、页正常显示」))----
|
||||
func _career_overlay_projection() -> void:
|
||||
@@ -822,7 +822,7 @@ func _career_overlay_projection() -> void:
|
||||
sv.apply_adventure_summary({"result": "abandoned", "cleared": false, "levels_cleared": 1,
|
||||
"stopped_at": 2, "keystone_total": 0, "master_seed": 22})
|
||||
sv.write_to_disk()
|
||||
# 投影拼装(main._career_data 同构)+ 视图喂入
|
||||
# 投影拼装(HudPresenter.career_data 同构)+ 视图喂入
|
||||
var data := {"total": sv.adventure_total(), "cleared": sv.adventure_cleared(),
|
||||
"clears": [], "boss_first_kills": 0, "boss_first_total": _db.level_count(),
|
||||
"boss_kills": sv.boss_kill_count(), "keystone": mp.keystone_balance()}
|
||||
|
||||
Reference in new issue
Block a user