Commit c99601c
fix(combat-trainer): regression when all weapon skills mindlocked (elanthia-online#7345)
## Summary
Fixes regression from elanthia-online#7341 where `all_weapons_locked` disabled attacks
when all weapon skills reached 34/34 mid-hunt, breaking FA and skinning
training. Also fixes a pre-existing bug where
`combat_trainer_ignore_weapon_mindstate: true` caused rapid weapon
cycling instead of action-count-based rotation.
### Root cause
PR elanthia-online#7341 added an `all_weapons_locked` flag that disabled attacks in
`AttackProcess` when every weapon skill hit 34/34. This was intended to
prevent bare-fisted jab spam at script startup, but it also disabled
attacks **mid-hunt** when a weapon was already equipped -- breaking FA,
skinning, and any other non-weapon training that requires killing.
Users who tried `combat_trainer_ignore_weapon_mindstate: true` as a
workaround hit a second bug: `skill_done?` returns `true` immediately at
exp==34 (line 5131), triggering `determine_next_to_train` to switch
weapons every cycle -- resulting in an infinite load/aim/unload/swap
loop without ever firing.
### What changed
#### 1. Removed `all_weapons_locked` entirely
- Removed the flag from `attr_accessor`, `initialize`, and the
`AttackProcess` condition
- A weapon is now always selected (see 5a/5b below), so attacks are
never disabled by this flag
#### 2. All weapons at 34 with weapon equipped (scenario 5a)
- The all-locked guard in `determine_next_to_train` returns early
**without switching weapons**
- Attacks continue with the current weapon so the player can train FA,
skinning, etc.
- One-time user message:
```
*** combat-trainer: All weapon skills are at 34/34 mindstate.
*** combat-trainer: Continuing to attack with Bow for FA/skinning
training.
*** combat-trainer: Set combat_trainer_ignore_weapon_mindstate: true to
cycle weapons by action count instead.
```
#### 3. All weapons at 34 with no weapon equipped at startup (scenario
5b)
- Previously returned early from the all-locked guard, leaving
`weapon_skill` nil -- causing bare-fisted jab spam (the original
pre-elanthia-online#7341 bug)
- Now falls through to weapon selection, picks the first available
weapon, then behaves as 5a
- One-time user message:
```
*** combat-trainer: All weapon skills are at 34/34 mindstate.
*** combat-trainer: Selecting initial weapon to begin attacking.
*** combat-trainer: Set combat_trainer_ignore_weapon_mindstate: true to
cycle weapons by action count instead.
```
#### 4. `ignore_weapon_mindstate: true` now works correctly
- Passed `ignore_weapon_mindstate` into `GameState` so `skill_done?` can
check it directly (SRP -- the decision about whether training is
complete belongs in the method making that decision)
- When the flag is true, `skill_done?` skips **all** mindstate-driven
logic:
- No gain_check blacklisting
- No early return at exp==34
- No focus_threshold adjustments
- No `target_increment` comparison
- Only evaluates: `action_count >= target_action_count`
- Weapons cycle indefinitely by action count regardless of mindstate
- One-time user message when all weapons reach 34:
```
*** combat-trainer: All weapon skills at 34/34 mindstate --
ignore_weapon_mindstate is active.
*** combat-trainer: Cycling weapons by combat_trainer_action_count only.
```
#### 5. Blank/nil `weapon_training` guard
- New guard at the top of `determine_next_to_train`: `unless
weapon_training&.any?`
- If no weapons are configured, attacks are disabled and the character
dances (bob/weave/circle) for defensive skills only
- Added `weapon_skill.nil?` check to `AttackProcess` so a missing weapon
falls into the dance path instead of attempting bare-fisted attacks
- One-time user message:
```
*** combat-trainer: No weapons configured in weapon_training.
*** combat-trainer: Attacks are disabled. Only defensive dance actions
(bob/weave/circle) will be used.
*** combat-trainer: Add entries to weapon_training in your YAML if you
want to train weapon skills.
```
#### 6. Spec file consolidation
- Renamed `combat_trainer_bundle_spec.rb` to `combat_trainer_spec.rb`
(one spec file per script convention)
- Added `GameState` and `SetupProcess` specs covering:
- `skill_done?` with `ignore_weapon_mindstate` true/false at exp values
0, 17, and 34
- `determine_next_to_train` for 5a, 5b, mixed exp, fresh start,
ignore_mindstate, skill_done? false
- Blank and nil `weapon_training` guard
- One-time messaging for all scenarios (5a, 5b, ignore_mindstate, blank
weapon_training)
- Adversarial: messaging does NOT fire when not all weapons are at 34
## Test plan
- [x] 53 specs pass (`rspec spec/combat_trainer_spec.rb`)
- [x] `rubocop -A` clean on both files
- [ ] In-game: all weapons capped, no `ignore_weapon_mindstate` --
verify attacks continue with current weapon (5a), verify message appears
once
- [ ] In-game: script start with all weapons already capped -- verify a
weapon is selected and attacks proceed (5b), verify message appears once
- [ ] In-game: `ignore_weapon_mindstate: true` with all weapons capped
-- verify cycling by action count with no rapid swap loop, verify
message appears once
- [ ] In-game: `ignore_weapon_mindstate: true` with one weapon
configured -- verify attacks continue indefinitely
- [ ] In-game: blank `weapon_training` -- verify dance-only behavior
with message
- [ ] In-game: normal multi-weapon cycling unaffected when skills are
not all at 34
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 4f5827e commit c99601c
2 files changed
Lines changed: 432 additions & 14 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
163 | 163 | | |
164 | 164 | | |
165 | 165 | | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
166 | 178 | | |
167 | 179 | | |
168 | 180 | | |
169 | 181 | | |
170 | 182 | | |
171 | | - | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
172 | 186 | | |
173 | | - | |
174 | | - | |
175 | | - | |
176 | | - | |
177 | | - | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
178 | 202 | | |
179 | | - | |
180 | 203 | | |
181 | 204 | | |
182 | | - | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
183 | 215 | | |
184 | 216 | | |
185 | 217 | | |
| |||
3703 | 3735 | | |
3704 | 3736 | | |
3705 | 3737 | | |
3706 | | - | |
| 3738 | + | |
3707 | 3739 | | |
3708 | 3740 | | |
3709 | 3741 | | |
| |||
4364 | 4396 | | |
4365 | 4397 | | |
4366 | 4398 | | |
4367 | | - | |
| 4399 | + | |
4368 | 4400 | | |
4369 | 4401 | | |
4370 | 4402 | | |
| |||
4422 | 4454 | | |
4423 | 4455 | | |
4424 | 4456 | | |
4425 | | - | |
4426 | 4457 | | |
4427 | 4458 | | |
4428 | 4459 | | |
| |||
4475 | 4506 | | |
4476 | 4507 | | |
4477 | 4508 | | |
| 4509 | + | |
| 4510 | + | |
| 4511 | + | |
4478 | 4512 | | |
4479 | 4513 | | |
4480 | 4514 | | |
| |||
5108 | 5142 | | |
5109 | 5143 | | |
5110 | 5144 | | |
| 5145 | + | |
| 5146 | + | |
| 5147 | + | |
| 5148 | + | |
| 5149 | + | |
| 5150 | + | |
| 5151 | + | |
5111 | 5152 | | |
5112 | 5153 | | |
5113 | 5154 | | |
| |||
0 commit comments