# Captivity Events Repair Patch — full changelog Seven change sets applied to a CE 1.4.5 install running BC Captor, Boukensha's Binder, SadSuns, Advanced Slavery and Bandit Expansion. XML only; the CE assembly is untouched (md5 `55a160776dfa61474c701fc03e19283d`, byte-identical to the official 1.4.5.1400 archive). Findings come from static analysis of an installed copy: Mono.Cecil for CE's IL, `System.Xml` schema validation against CE's own XSDs, and XML parsing for the event graph. Counts are reproducible against the same module set. --- ## Summary | # | Change | Scope | |----|---------------------------------------------------------------|-------------------| | 01 | `Ref="Hero"` → `Ref="Captive"` on captive-state skill checks | 171 checks, 17 files | | 02 | Duplicate event names and reference typos | 7 fixes, 6 files | | 03 | `Overwritable` restored on stray defaults | 7 events, 3 files | | 04 | Missing `Leave.` option restored to brothel menu 3 | 1 option, 1 file | | 05 | SadSuns weight element misspelling | 203 elements, 4 files | | 06 | Tokens absent from the CE schema removed | 75 lines, 9 files | | 07 | Background references repointed to existing art | 27 refs, 8 files | 43 distinct files (the sets overlap). | Measure | Before | After | |--------------------------------------------|-------------|-----------| | Event files passing `CEEventsModal.xsd` | 144 / 155 | 155 / 155 | | Events actually reaching the game | −436 | all | | Options that dead-end | 20 | 13 | | Trigger groups partly dead | 18 | 13 | | Event names with two live definitions | 6 | 3 | | Background references with no image | 64 | 43 | **The headline number is 436.** CE discards an *entire event file* when any single token in it fails XSD validation. Eleven files were failing, holding 436 events that had never loaded — 233 from zCEDefaults, all 203 from SadSuns. Changes 05 and 06 are what brought them back. --- ## 01 — Captive-state skill checks read the player instead of the captive CE writes custom captive-state skills (`CaptiveLust*`, `CaptiveEsteem`, `SocialEnergy`, `Devoted`, …) to the captive, but `CEEventChecker::SkillsCheck` resolves `Ref="Hero"` to `CharacterObject.PlayerCharacter` unconditionally: ``` IL_008D ldloc.s V_4 IL_008F callvirt SkillRequired::get_Ref() IL_0094 ldstr "Hero" IL_0099 call String::op_Equality IL_009E brtrue.s IL_00A3 IL_00A0 ldarg.1 <- else: the passed-in character IL_00A3 call CharacterObject::get_PlayerCharacter <- "Hero" => always PLAYER ``` The write path does not agree. In `SharedCallBackHelper::ConsequenceChangeSkill`, the target depends on the event's captor flag — so a skill written to the captive is read back from the player, whose value is always 0. The circulating community build converts 606 of these. This converts a further 171: inside `` only, and only where the `Id` is a custom captive-state flag. Vanilla Bannerlord skills keep `Ref="Hero"` — those genuinely do mean the player. `` writes are never touched. Split by direction: 45 `Min` checks (content that was locked out entirely) and 127 `Max` checks (content that fired regardless of state). Skill breakdown: CaptiveLustV 37, CaptiveLustO 32, CaptiveLustA 23, CaptiveEsteem 18, CaptiveLustC 17, CaptiveLustT 14, CaptiveAffection 9, FlowerGirlFavor 5, CaptiveEquus 4, CaptiveCanis 4, Concubine 3, Fame 2, Blackmailed 2, MindBroken 1. **Deliberately skipped:** 153 further checks in `a_BCCaptorConditions.xml`. 136 of them sit in condition blocks that no event references via `UseConditions`, and that file is where over-conversion breaks everything at once. Files: `zCEzBCCaptorGear/Events/` — BCCompanionDating 52, BCOverrideRandomEvents 38, BCOverrideCaptivityEvents 23, BCCaptorTTF 22, plus 13 files with fewer. --- ## 02 — Three duplicate event names and four reference typos Three of these were not typos but *collisions* — two different events sharing one name, so one of the pair was unreachable and a chain pointing at the intended name dead-ended. **`BB_UngenderedGaySoldiersRefusal` was defined twice.** The second copy sits in the middle of the femboy chain, its `BackgroundName` is `BB_FemboyCumFloor`, and its text ("You kick the pathetic twink out of your tent") answers the femboy options word for word. Three options pointed at `BB_UngenderedfemboyExposedRefused`, a name nothing defined. Renamed. **One paste error was killing all three refusal options.** **`BB_CagedCarousingEmbaressedWatchingInvited`** in `BoukieFemaleCarousing.xml` lost the `Fem` prefix that every sibling in that chain carries, dead-ending the female branch and colliding with the male file's event of the same name. Renamed to `BB_FemCagedCarousingEmbaressedWatchingInvited`. **`AdvancedSlavery_pussygrab2continue` was defined twice** with different scenes; the calling option lists `continue` and `continueb` at 50/50 weight. Second copy renamed to `…continueb`. The other four are plain reference typos: | was | now | why | |---|---|---| | `VoluntaryProstituteKnowurplaceDash**F**uckEveryone` | `…Dash**f**uckEveryone` | case only; defined lowercase | | `VoluntaryProstituteMaleKnowurplaceDash**F**uckEveryone` | `…Dash**f**uckEveryone` | case only | | `SlaveTownProstitute_10RapedFight**Lose**` | `…Fight**Loss**` | defined as Loss | | `SlaveTownProstitute_**13**Fucked` | `…_**15**Fucked` | option of _15; siblings point at _15Fucked | --- ## 03 — Seven zCEDefaults events were missing `Overwritable` The flag reads backwards. In CE, `Overwritable` does **not** mean "others may replace me". It means **"discard me if my name is already taken"** — a yield flag: ``` CEHelper::GetModulePaths paths.Insert(0, path) // walking launcher order CESubModule::OnBefore…SetAsRoot skip = incoming.Flags.Contains(Overwritable) && nameAlreadyClaimed ``` Because the path list is built with `Insert(0, …)` rather than `Add`, modules are parsed in **reverse launcher order** — the module lowest in your load order is parsed first and wins. An override pack must therefore sit *below* what it overrides, and the loser must carry `Overwritable` or it stays in the list as a live duplicate with selection left to chance. 217 of zCEDefaults' 224 events carry the flag. Seven did not. Two of the seven were being overridden by BC Captor, so both copies stayed live and the player got one at random. Flag added to all seven. Files: `zCEDefaults/Events/` — DefaultSpouseEventsFemale (2), DefaultSpouseEventsMale (2), DefaultRandomEventsFemale (3). --- ## 04 — Brothel waiting menu 3 has no usable exit `CE_prostitution_waiting_menu_3` is capped at `ReqHeroProstituteLevelBelow=200`, but its payout option requires `ReqHeroProstituteLevelAbove=200`. Both bounds are inclusive (`clt`/`cgt` in `CEEventChecker::ProstitutionLevelCheck`), so the option is live at *exactly* level 200 and nowhere else. Option gates disable rather than hide, so it sits in the menu greyed out with CE's tooltip `{=CEEVENTS1120}` — *"Your prostitution level is too low"* — advising the player to raise a level that, once past 200, stops the event appearing at all. **It is the only free-track menu with no working way out.** CE splits the two tracks cleanly: | track | exit | |---|---| | free (`HeroIsNotSlave`) | a free `Leave.` in all five menus — `_3`, `_4`, `_5`, `siege_2`, `siege_3` | | slave (`HeroIsSlave`) | the only paid exit — "Request your freedom", 300g, level > 110 | BC Captor replaced the free exits with a paid buyout at level 200 — slave-track economics applied to the voluntary track. In `menu_4`, `menu_5`, `siege_menu_2` and `siege_menu_3` that still leaves a usable exit. In `menu_3` it does not, because the threshold sits on the event's own ceiling. CE's original option is restored verbatim, localisation key included, in `menu_3` only. The other four menus are left exactly as BC Captor ships them — they work, and changing them would be a balance preference rather than a fix. The dead payout option is also left in place; that one is the author's call. **Known side effect if you also run Boukensha's Binder.** A duplicated menu name takes its text from whichever event wins the draw, but every same-named event contributes its options to the one game menu — they accumulate. Boukensha's `_3` covers level 50–100 with its own `Leave.` gated above 75, so at level 75–100 you will see **two "Leave." entries**. Both work. It is cosmetic, and no gate removes it without reopening a real gap: Boukensha's `_3` ends at 100, so without the restored option there is no exit at 50–75 or 100–199. File: `zCEzBCCaptorGear/Events/BCOverrideBrothelEvents.xml`, one `