diff --git a/game/core/unit_container.gd b/game/core/unit_container.gd index ae00ed95..f438f036 100644 --- a/game/core/unit_container.gd +++ b/game/core/unit_container.gd @@ -10,7 +10,8 @@ # (pattern 环数组 + steps 指针 + heavy_multiplier)随技能池整体退役——拍结构保留(每结算每存活敌恰行动一次、 # 行序、先作用后推进),"轮到什么"改由开轮摇号决定(死亡即不动手:摇定后兑现前死亡 → 本拍作废、不 commit)。 # 切片登记接口漂移:heal() 为切片新增(战斗结算 治疗 clamp 需要写入口);spawn 签名 +3 参数(E4/区间批/ -# 遭遇骰——正式侧 GDD/registry 修订随对应批)。 +# 遭遇骰——正式侧 GDD/registry 修订随对应批);迭代 23 T2 +2 参数(hero_attack_type/hero_armor_type—— +# 两根类型轴注入面:hero.tres 静态表两轴删除〔契约 2 所有权移交〕,空串=锻造工坊配置默认值回退)。 # 实现 GDD:design/gdd/systems/战斗循环/敌人系统.md(registry 追溯锚,命名规范见 CLAUDE.md) class_name UnitContainer extends RefCounted @@ -44,7 +45,8 @@ func _init(db_ref: ConfigDb) -> void: # 逐行实例化、生成序 = 文件行序(行序即契约,敌人系统 v0.15);行集实例总数(各行传入数量求和) # ≤ ENEMY_ROWSET_INSTANCE_MAX 守卫 fail-fast。 func spawn(level_index: int, node_depth: int, hero_hp: int, unit_count_overrides: Array = [], - atk_override: int = -1, max_hp_override: int = -1, enemy_atk_overrides: Array = []) -> bool: + atk_override: int = -1, max_hp_override: int = -1, enemy_atk_overrides: Array = [], + hero_attack_type: String = "", hero_armor_type: String = "") -> bool: if _spawned: push_warning("[敌人系统] Alive 相位重复 spawn(相位守卫)") return false @@ -61,7 +63,7 @@ func spawn(level_index: int, node_depth: int, hero_hp: int, unit_count_overrides return false # max_hp = 生效上限(非入参 hero_hp)——2026-09-11 关卡扩展批修复:跨战斗携带 HP 时上限不得压扁 # (恢复点/治疗包的满血守卫与治疗上限随之失效——切片登记接口语义澄清) - _hero = {"hp": hero_hp, "max_hp": eff_max_hp, "atk": eff_atk, "is_hero": true, "alive": true, "display_name": "探险者", "enemy_id": "hero", "armor_type": String(db.hero.get("armor_type")) if db.hero.get("armor_type") else "light", "attack_type": String(db.hero.get("attack_type")) if db.hero.get("attack_type") else "normal"} # 护甲/攻击类型轴快照(2026-09-18 营地扩展前置批——可配置;甲效矩阵消费面) + _hero = {"hp": hero_hp, "max_hp": eff_max_hp, "atk": eff_atk, "is_hero": true, "alive": true, "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()} # 护甲/攻击类型轴快照(迭代 23 T2——hero.tres 两轴删除后改读注入值,空串回退锻造工坊配置默认值 normal/light=行为连续;甲效矩阵消费面) _enemies.clear() # 难度曲线与Boss DifficultyTable 修饰(2026-09-12 结构位兑现):施加于行值、行值快照之前——MVP 空表 = 恒 1.0 无行为(AC-10);混编行集内全部敌种同乘((L,D) 精确匹配一次取值——F9 同乘不改变异,敌人系统 v0.15) var mod: Dictionary = db.resolve_difficulty_modifiers(level_index, node_depth) var hp_mult: float = float(mod.get("hp_mult", 1.0)) diff --git a/game/data/schemas/hero_table.gd b/game/data/schemas/hero_table.gd index 0c953498..11ad18c3 100644 --- a/game/data/schemas/hero_table.gd +++ b/game/data/schemas/hero_table.gd @@ -3,14 +3,15 @@ # Date: 2026-09-10 # 数据配置 HeroTable schema(敌人系统 接口漂移新增;单行全局,Rule 4 豁免)。 # atk = 基础攻击恒存在(2026-09-11 用户裁决):域 [1,999]、0 = 加载拒绝——零基线死锁 schema 层杜绝。 +# 〔2026-10-12 迭代 23 锻造工坊实装批 T2:armor_type/attack_type 两根类型轴字段删除——契约 2 +# 所有权移交,默认值归锻造工坊配置(forge.tres)常驻持有、选中态写存档经参数面注入;本表只剩 +# 三数值轴 max_hp/atk/armor_class(armor_class=甲路线缺失时兜底基准,甲型基础 AC 归 forge.tres 行)。〕 class_name HeroTable extends Resource @export var max_hp: int = 50 # [1,999] knob(provisional,溯源 = 原型锚) @export var atk: int = 6 # [1,999] knob——基础攻击(溯源 = 概念原型 HERO_BASE_ATK,provisional 归 难度曲线与Boss);消费面 = 战斗结算·战斗段先手攻击 @export var armor_class: int = 10 # [0,999] knob——防守方护甲等级基准(2026-09-16 护甲等级掷点批,暂定 10 归 难度曲线与Boss);消费面 = 战斗结算掷点判定阈值基数(ac_up 效果加算其上) -@export var armor_type: String = "light" # enum {light, ward, heavy}——主角护甲类型轴(2026-09-18 营地扩展前置批:可配置可修改;缺省 light 向后兼容);消费面 = 战斗结算甲效矩阵(现行敌方攻击恒 normal 档 = 数值中性的结构位) -@export var attack_type: String = "normal" # enum {normal, pierce, magic}——主角基础攻击类型轴(2026-09-18 营地扩展前置批:基础攻击量(atk)与攻击类型抽象分离——营地永久强化换攻击类型 = 改此字段,量轴不动);消费面 = 战斗结算·战斗段基础分量查甲效矩阵 func validate() -> Array: @@ -21,8 +22,4 @@ func validate() -> Array: errs.append({"category": "domain", "message": "atk 越域 [1,999]: %d" % atk}) if armor_class < 0 or armor_class > 999: errs.append({"category": "domain", "message": "armor_class 越域 [0,999]: %d" % armor_class}) - if not ["light", "ward", "heavy"].has(armor_type): - errs.append({"category": "enum", "message": "armor_type 出域 {light, ward, heavy}: %s" % armor_type}) - if not ["normal", "pierce", "magic"].has(attack_type): - errs.append({"category": "enum", "message": "attack_type 出域 {normal, pierce, magic}: %s" % attack_type}) return errs diff --git a/game/data/tables/hero.tres b/game/data/tables/hero.tres index c78839f4..b7889025 100644 --- a/game/data/tables/hero.tres +++ b/game/data/tables/hero.tres @@ -7,8 +7,12 @@ script = ExtResource("1") max_hp = 26 atk = 2 armor_class = 10 -armor_type = "light" -attack_type = "normal" + +; 〔2026-10-12 迭代 23 锻造工坊实装批 T2——两根类型轴删除(契约 2 所有权移交):armor_type/ +; attack_type 两字段随本批从静态表删除,默认值归锻造工坊配置常驻持有(forge.tres +; default_attack_type=normal/default_armor_type=light),选中态写存档域 forge_routes、冒险开始 +; 经参数面注入;单位快照读取面改读注入值(缺省回退锻造配置默认值——行为连续)。原 2026-09-18 +; 营地扩展前置批「两根可配置轴」登记随字段删除退役,历史记载归 git 考古。〕 ; 数值压缩批(2026-09-17 用户拍板暂定——整体绝对值轴 ÷3): ; max_hp 50→17(16.67 四舍五入)、atk 6→2。armor_class 10 不动(掷点阈值轴,相对量纲不压缩—— @@ -18,13 +22,9 @@ attack_type = "normal" ; 护甲等级掷点批(2026-09-16 用户拍板):armor_class = 10(暂定基准,归 难度曲线与Boss; ; EV 参考数按判定式复算 = 期望减免 21.25%);ac_up 增益 +1 AC/层(×2 层 = AC+2)在其上加算。 ; -; 营地扩展前置批(2026-09-18 用户指令):新增两根可配置轴—— -; armor_type = 主角护甲类型(light/ward/heavy,缺省 light):轴现行休眠——甲效矩阵消费面 = 主角侧, -; 敌方攻击不查矩阵(2026-09-18 甲效矩阵调参批归因改述,原「恒 normal 档故三甲全 100% 中性」随旧三档 -; 结构退役),类型轴生效待敌方技能攻击类型批; -; attack_type = 主角基础攻击类型(normal/pierce/magic,缺省 normal):基础攻击量(atk)与攻击类型抽象分离—— -; 营地永久强化"换成魔法/穿刺攻击"= 改此字段(atk 量轴零改动),战斗段基础分量即按此查甲效矩阵。 -; 两轴全部 provisional,营地建设批(元进度侧)拍板正式投值。 +; 〔营地扩展前置批(2026-09-18 用户指令)两根可配置轴 armor_type/attack_type 已于 2026-10-12 +; 迭代 23 锻造工坊实装批 T2 删除——所有权移交锻造工坊配置(见顶部注记);甲型基础 AC 随甲路线 +; 行承载(轻 10/重 12/魔法护甲 9),本表 armor_class=10 保留为甲路线缺失时的兜底基准。〕 ; ; Package B 迭代·第 2 轮(2026-09-22——计划书 §6.2,用户拍板一B):max_hp 17→20。第 1 轮读数 ; 触发 §6.2(L1 精英承伤 43-55% vs 靶 ≤20%、L1 净消耗 17.7/17=104% 破产、normal L1 通过率 diff --git a/game/smoke/smoke_all.gd b/game/smoke/smoke_all.gd index 13034700..23ff8106 100644 --- a/game/smoke/smoke_all.gd +++ b/game/smoke/smoke_all.gd @@ -1462,8 +1462,8 @@ func _ac11_tier_samples() -> Array: # 同种子停手轮恒同掷点(效果只改乘区、不动掷点流)→ 落地伤害精确关系: # 增伤 = 基线 ×1.5、乏力 = ×0.75(hero_offense 池乘攻击合计——2026-09-19 充能退役后 = 单分量,直乘旁路退役); # 硬化 = 基线 ×0.5 且 < 基线(enemy_defense 池负值折半——+100 翻倍符号 bug 随批纠正)。 -# 基线构成(加法核 2026-09-18 + 充能退役 2026-09-19):基线 100——hero attack_type=normal 对轻甲中性 0 修正 -# (目标 = L1 地精轻甲;AC 0 恒全额非暴击种子)。 +# 基线构成(加法核 2026-09-18 + 充能退役 2026-09-19):基线 100——hero 攻击类型=normal(锻造工坊配置默认值, +# 迭代 23 T2 起 hero.tres 两轴删除)对轻甲中性 0 修正(目标 = L1 地精轻甲;AC 0 恒全额非暴击种子)。 func _smoke_pool_wiring() -> void: print("--- 主角乘区接线 + 硬化折半方向 ---") var base_row := _hero_attack_row_with({}, 100, 20260918) @@ -1898,7 +1898,8 @@ func _smoke_full_battle(L: int, D: int, label: String) -> void: if row.get("source_class", "") == "hero_attack": hero_attacks += 1 # 单分量伤害构成行(2026-09-19 充能退役批):hero_attack 行必须携带实际攻击类型键 + 掷点读数(P2 归因) - var atk_t: String = String(_db.hero.attack_type) + # 迭代 23 T2:类型键主语换代——hero.tres 两轴删除,实际攻击类型=锻造工坊配置默认值(本夹具零注入) + var atk_t: String = String(_db.forge_default_attack_type()) if not (row.has(atk_t) and row.has("roll") and row.has("ac") and row.has("tier")): hero_breakdown_ok = false check(has_verdict, "%s 步骤流含判定行" % label) @@ -4408,10 +4409,29 @@ func _smoke_meta() -> void: _meta_pricing_and_buy() _meta_settle_and_workshop() _meta_injection() + _smoke_forge_axes() _pause_overlay_projection() _career_overlay_projection() +# ---- 锻造工坊·两根类型轴所有权移交(迭代 23 T2——V5 前半:hero.tres 两轴删除+锻造配置默认值)---- +# 后半(build_adventure_params 注入默认值/选中覆盖)随 T4 注入接线同批断言;写口/解锁面归 T3。 +func _smoke_forge_axes() -> void: + print("--- 锻造工坊·类型轴所有权移交(T2)---") + # V5:hero.tres 静态表两轴已删(全表加载零违例——config_db_test 同款闸;此处钉字段不在位) + check(not ("attack_type" in _db.hero) and not ("armor_type" in _db.hero), + "hero.tres 无 attack_type/armor_type 字段(契约 2——静态表两轴删除)〔锻造工坊批 V5〕") + # 锻造配置默认值 = normal/light(常驻持有——与柜台解锁状态解耦,未点亮也照常可读) + check(_db.forge_default_attack_type() == "normal" and _db.forge_default_armor_type() == "light", + "锻造配置默认值 attack_type=normal / armor_type=light(常驻持有)〔锻造工坊批 V5〕") + # 单位快照回退面:spawn 三参形态(零注入)= 锻造配置默认值(行为连续——原 hero.tres normal/light) + var uc = load("res://core/unit_container.gd").new(_db) + check(uc.spawn(1, 0, int(_db.hero.max_hp)), "spawn 受理(三参形态——两轴缺省回退面)") + check(String(uc.hero_unit().get("attack_type", "")) == "normal" + and String(uc.hero_unit().get("armor_type", "")) == "light", + "主角单位快照两轴 = 锻造配置默认值 normal/light(零注入回退——行为连续)〔锻造工坊批 V5〕") + + # ---- 暂停层只读投影一致性(迭代 17 卡③——R4 数据只读同源:暂停层展示值逐项 == MetaProgression # 访问器读数;投影拼装与 main._pause_data 同构(同访问器族同序)。只读性连接巡检与零动效 # 断言归 ui_struct_probe 呈现侧,本段只管数据面)----