Skip to content

Commit a37a693

Browse files
SnoopLawgclaude
andcommitted
mod: emit Observatory area_bonus column in /hero-computed-stats (+ cb_run COLS)
The damage calibration's static +5.9% C.DMG missing from every hero is the in-game Total-Stats "Area Bonuses" (_areaBonus) column = the OBSERVATORY, NOT the Great Hall (the Great Hall / Capitol affinity bonus is already captured as affinity_bonus). Observatory bonuses are per-LOCATION, so every hero gets the same AllianceBoss-location bonus regardless of affinity — matching the empirical signature (static, uniform, present from tick 0). Grounded via the dump: EffectContext-free static calc BuildingSetup.BuildObservatoryBonus(villageData, ObservatoryLocationId.AllianceBoss=7) -> HeroExtensions.CalcBuildingsBonus. Added the area_bonus column to /hero-computed-stats (mirrors the affinity_bonus block) + area_bonus to cb_run.py COLS so future build snapshots sum it. Deployed. This is the area-bonus half of the blocked joint un-stack (lands WITH the WM-over fix — adding +C.DMG alone pushes the over-predictors further over). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SCKiWFsFcWRBkL4kWf1q6b
1 parent 8690ad3 commit a37a693

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

mod/bepinex/RaidAutomationPlugin.LiveData.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1586,6 +1586,41 @@ private string GetHeroComputedStats(string minGradeStr)
15861586
{
15871587
sb.Append(",\"_gh_err\":\"villageData=" + (villageData != null) + " element=" + heroElement + "\"");
15881588
}
1589+
// Observatory "Area Bonuses" column (in-game Total
1590+
// Stats _areaBonus). Per-LOCATION (not per-element),
1591+
// so uniform across heroes for a given area. CB =
1592+
// ObservatoryLocationId.AllianceBoss (=7). This is the
1593+
// static +C.DMG the damage calibration found missing
1594+
// from every hero (grounded 2026-06-29).
1595+
try
1596+
{
1597+
if (villageData != null)
1598+
{
1599+
var obsMethod = buildSetupType.GetMethod("BuildObservatoryBonus");
1600+
if (obsMethod != null)
1601+
{
1602+
var locType = FindType("SharedModel.Meta.Village.ObservatoryLocationId");
1603+
object locEnum = 7; // AllianceBoss
1604+
if (locType != null)
1605+
try { locEnum = Enum.ToObject(locType, 7); } catch { }
1606+
var obsSetup = obsMethod.Invoke(null, new object[] { villageData, locEnum });
1607+
if (obsSetup != null)
1608+
{
1609+
var obsBuildMethod = heroExtType.GetMethod("CalcBuildingsBonus");
1610+
var obsFormType = FindType("SharedModel.Meta.Heroes.HeroMetamorphForm");
1611+
object obsForm = 0;
1612+
if (obsFormType != null) try { obsForm = Enum.ToObject(obsFormType, 0); } catch { }
1613+
var obsStats = obsBuildMethod.Invoke(null, new object[] { hero, obsSetup, obsForm });
1614+
if (obsStats != null)
1615+
{
1616+
sb.Append(",\"area_bonus\":");
1617+
AppendAllStats(sb, obsStats);
1618+
}
1619+
}
1620+
}
1621+
}
1622+
}
1623+
catch (Exception aex) { sb.Append(",\"_area_err\":\"" + Esc(aex.InnerException != null ? aex.InnerException.Message : aex.Message) + "\""); }
15891624
}
15901625
}
15911626
}

tools/cb_run.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,7 @@ def _snapshot_run_build(log_filename, entries, boss_turns):
494494
BOSS_SPD = 190.0 # UNM CB boss SPD (cb_constants CB_SPEED_BY_DIFFICULTY) — for the
495495
# effective-speed estimate only; the `stats` below are exact.
496496
COLS = ["blessing_bonus", "empower_bonus", "affinity_bonus", "artifact_bonus",
497-
"relic_bonus", "mastery_bonus", "faction_guardians_bonus"]
497+
"relic_bonus", "mastery_bonus", "faction_guardians_bonus", "area_bonus"]
498498
SLOT = {1: "Helmet", 2: "Chest", 3: "Gloves", 4: "Boots", 5: "Weapon",
499499
6: "Shield", 7: "Ring", 8: "Amulet", 9: "Banner"}
500500
team_out = []

0 commit comments

Comments
 (0)