# Summary - 2026-02-04

## Current Task
Complete rewrite of the mass action system using direct effects approach, eliminating complex transpilers.

## Changes Made

### Architecture Refactor: MassActionEffects Direct Effects
Replaced the coroutine-based approach (calling game routines for each follower) with direct effect application. This eliminates the need for transpilers that NOPed out HUD/camera/conversation calls.

**Key insight:** With the old approach, multiple routines would fight over camera position, HUD state, and depth of field. The transpilers prevented this. With direct effects, only the original follower runs a routine - other followers get instant state changes + animations.

### Files Modified

#### CultOfQoL/Patches/Followers/MassActionEffects.cs
- **ApplyBribe**: Added `spawnCoins` parameter, now spawns coin VFX flying from player to follower
- **ApplyIntimidate**: Added `allowScaredTrait` parameter, controlled by `Plugin.MassIntimidateScareAll` config
- **ApplyExtort**: Changed from instant gold add to callback-based (gold added when coin animation reaches player)
- **ApplyLevelUp** (new):
  - Increments XP level, resets adoration
  - Plays devotion → bow → idle animation
  - Spawns souls/gold/magma stones based on progression and traits
  - Invokes `OnGivenRewards` callback to match vanilla
  - **Includes doctrine stone drop logic** (every 3rd level-up if conditions met)
  - Completes current task, handles wake-up day reset

#### CultOfQoL/Patches/Followers/FollowerPatches.cs
- Commented out `using CultOfQoL.Core.Routines` (no longer needed)
- **MassLevelUpAll**: Now uses `MassActionEffects.ApplyLevelUp()` directly instead of calling `LevelUpRoutine`
- **Added filtering to mass actions** (Dance, Intimidate, Bless):
  - `!FollowerManager.FollowerLocked(f.Brain.Info.ID)` - skip locked followers
  - `!f.Brain.HasTrait(FollowerTrait.TraitType.Mutated)` - skip mutated followers
  - For Dance: `f.Brain.CurrentTaskType != FollowerTaskType.GetPlayerAttention`
- **Mass Intimidate**: Now passes `allowScaredTrait: Plugin.MassIntimidateScareAll.Value`
- Commented out legacy `Close` prefix code that checked `MassActionCurrentlyRunning`
- Commented out legacy `LevelUpRoutine` prefix (never triggered with direct effects)

#### CultOfQoL/Core/Routines/RoutineTranspilers.cs
- **Entire file commented out** - transpilers no longer needed
- Transpilers were NOPing out:
  - `HUD_Manager.Hide()`
  - `GameManager.OnConversationNew/Next()`
  - `GameManager.AddPlayerToCamera()`
  - `GameManager.CameraSetOffset()`
  - `BiomeConstants.DepthOfFieldTween()`
- `MassActionCurrentlyRunning` and `ActiveMassRoutineCount` properties also commented out (never set)
- Kept as reference with explanatory header comment

## Key Decisions
- **Direct effects over routines**: Simpler, more predictable, eliminates ~200 lines of IL manipulation
- **Callback-based rewards**: Extort gold added when collected, matching vanilla behavior
- **Doctrine stone parity**: Mass level-up now drops doctrine stones like vanilla
- **Defensive filtering**: Skip locked/mutated followers to prevent edge case issues

## Testing Needed
- Mass level-up with doctrine stone unlocked (verify stones drop)
- Mass intimidate with `MassIntimidateScareAll` on/off
- Mass actions on followers that are locked or mutated (should be skipped)
- Verify no UI/camera issues with mass actions

---

## MysticAssistantRedux - New Mod Added

### Overview
Adopted and updated Ciarenni's abandoned [Mystic Assistant](https://github.com/Ciarenni/COTL_MysticAssistant) mod (v2.1.0). Allows players to purchase specific rewards from the Mystic Shop instead of spinning the random wheel.

### Files Created
- `MysticAssistantRedux/MysticAssistantRedux.csproj`
- `MysticAssistantRedux/GlobalUsings.cs`
- `MysticAssistantRedux/Plugin.cs`
- `MysticAssistantRedux/InventoryInfo.cs`
- `MysticAssistantRedux/InventoryManager.cs`
- `MysticAssistantRedux/Patches/MysticShopPatches.cs`
- `Thunderstore/mysticassistantredux/` (manifest, README, CHANGELOG, nexusmods_description)

### Key Transformations from Original
1. **Target framework**: `netstandard2.0` → `net481`
2. **Harmony patching**: Manual `harmony.Patch()` → attribute-based `[HarmonyPatch]`
3. **Reflection removal**: `Traverse.Create().Field().GetValue()` → direct field access (publicized assemblies)
4. **Logging**: `Console.WriteLine` → `ManualLogSource`
5. **Plugin GUID**: `ciarenni.cultofthelamb.mysticassistant` → `p1xel8ted.cotl.mysticassistant`

### Bug Fixes
1. **OnSecondaryInteract patch target**: Original patched `Interaction_MysticShop.OnSecondaryInteract` which doesn't exist - must patch base `Interaction.OnSecondaryInteract` with type check
2. **Random.Range off-by-one**: Original used `Random.Range(0, shopStock - 1)` which never selected last item - fixed to `Random.Range(0, shopStock)`
3. **Static field access**: `maxAmountOfCrystalDoctrines` and `maxAmountOfTalismanPieces` are `const` fields - must access via type name, not instance

### Game Code Verification
Thoroughly verified all game API usage against `libs/game_code/`:
- `Interaction` base class has `HasSecondaryInteraction`, `SecondaryLabel`, `OnSecondaryInteract`
- `DataManager.MysticShopKeeperSkins` (15 entries), `MysticShopKeeperDecorations` (17 entries)
- `TarotCards.MysticCards` (8 entries)
- All UI controller `Show()` methods verified
- `TraderTrackerItems` structure confirmed

### Version
- `0.1.0` - Initial release under new maintainer

### Commit
`05fe0568` - Add MysticAssistantRedux - continuation of Ciarenni's Mystic Assistant

### Logging Added (later session)
Added comprehensive logging to help debug shop inventory issues:

**MysticAssistantRedux/Patches/MysticShopPatches.cs:**
- `[MysticShop] Opening assistant shop` - when shop opens
- `[MysticShop] Player purchased: {type} (cost: X God Tear)` - purchase logging
- Item-specific logs showing what was given (gold, necklace, skin, decoration, tarot card, relic)
- `[MysticShop] Shop closed, X post-shop actions queued` - shop close
- `[MysticShop] Overbuy warning triggered for {type}` - overbuy warnings
- `[MysticShop] Post-shop actions complete` - when screens finish

**MysticAssistantRedux/InventoryManager.cs:**
- Detailed logging for each populate method showing:
  - How many items are being checked from source arrays
  - Each individual item's unlock status
- Example: `[InventoryManager] Skin 'Penguin': unlocked=true`
- Final stock summary: `[InventoryManager] Shop stock: Skins=X, Decorations=X, TarotCards=X, Relics=X`

---

## TraitControl - Bug Fixes (0.1.5)

### Bug Reports Investigated
Two user bug reports for v0.1.4:
1. "Guarantee Don't Starve" not working (Immortal works fine)
2. Negative traits still appearing with "Enable Trait Replacement" on

### Root Causes Found

**Bug 1: Multiple Guaranteed Traits**
- `GetGuaranteedTrait()` returned the **first** available guaranteed trait and set `_guaranteedTraitGivenThisSession = true`
- Subsequent trait rolls saw the flag as true and skipped the guarantee check
- Result: Only Immortal given, DontStarve never assigned

**Bug 2: Negative Traits with Replacement**
- `GetFilteredTraits()` only filtered negative **event** traits when `NoNegativeTraits.Value` was true
- All other negative traits remained in the selection pool
- `FollowerBrain_Constructor_Postfix` could select negative traits that wouldn't be replaced

### Fixes Implemented

**TraitControl/Patches/TraitWeights.cs:**
1. Replaced single-use `_guaranteedTraitGivenThisSession` flag with `_pendingGuaranteedTraits` list
2. `PopulateGuaranteedTraits()` now queues ALL enabled guaranteed traits at session start
3. `GetGuaranteedTrait()` consumes one trait per call until list is empty
4. Added negative trait filtering to `GetFilteredTraits()` when `NoNegativeTraits.Value` is true

### Files Modified
- `TraitControl/Patches/TraitWeights.cs` - Multiple guaranteed traits support, negative trait filtering
- `Thunderstore/traitcontrol/CHANGELOG.md` - Added fix notes to 0.1.5
