Implement devotee loyalty and morale mechanics with cap based on reputation tier #221

Open
opened 2026-03-16 01:39:32 +00:00 by freemo · 0 comments
Owner

Metadata

Field Value
Epic #203 — Devotee System
Legendary #199 — Reputation & Social Standing
Type Feature
Priority Medium
Points 8
MoSCoW Should Have
Branch feature/m4-devotee-loyalty-morale-mechanics
Commit Message Implement devotee loyalty and morale mechanics with cap based on reputation tier (#221)

Background and Context

Devotees are not mindless automatons — they have loyalty and morale that fluctuate based on player actions and conditions. Loyalty represents a devotee's commitment to the player, while morale represents their current emotional state and willingness to work.

Loyalty increases slowly when devotees successfully complete tasks (+1 per day of active work) and decreases when the player's reputation with the devotee's original faction drops. Morale decreases when devotees are left idle without assignments or when conditions are poor, and increases when assigned meaningful work.

If either loyalty or morale drops below 10, the devotee deserts — they leave the player's service permanently. This creates a management challenge and rewards attentive players.

The number of devotees a player can maintain is capped based on their highest relevant reputation tier:

  • Neutral (and below): 0 devotees
  • Friendly: 1 devotee
  • Respected: 3 devotees
  • Honored: 6 devotees
  • Exalted: 10 devotees

Expected Behavior

  1. Loyalty gain: +1 per game day when a devotee has an active assignment and completes work.
  2. Loyalty loss: When player's reputation with the devotee's faction drops, loyalty decreases proportionally (e.g., -5 rep = -2 loyalty).
  3. Morale loss: -1 per game day when a devotee is idle (no assignment). Additional -2 per day if player's faction reputation is Unfriendly or below.
  4. Morale gain: +1 per game day when assigned and working.
  5. Desertion: If loyalty < 10 OR morale < 10, the devotee deserts at the next game-day tick. The player receives a notification. The devotee is removed from player.info["devotees"].
  6. Devotee cap: Checked on recruitment and on each game-day tick. If a player's reputation drops and their cap decreases below their current count, the devotee with the lowest loyalty deserts.
  7. Both loyalty and morale are clamped to 0-100.

Acceptance Criteria

  • Loyalty increases by 1/day when devotee has an active assignment.
  • Loyalty decreases proportionally when faction reputation drops.
  • Morale decreases by 1/day when devotee is idle.
  • Morale decreases by additional 2/day when faction reputation is Unfriendly or below.
  • Morale increases by 1/day when assigned and working.
  • Devotees desert when loyalty drops below 10.
  • Devotees desert when morale drops below 10.
  • Player receives notification on desertion.
  • Devotee cap is enforced: Neutral=0, Friendly=1, Respected=3, Honored=6, Exalted=10.
  • If cap decreases below current count, lowest-loyalty devotee deserts.
  • All changes are processed on game-day tick.

Subtasks

  • Create lib/aethyr/core/reputation/devotee_mechanics.rb with the loyalty/morale engine.
  • Implement loyalty gain on active assignment (+1/day).
  • Implement loyalty loss on faction reputation drop.
  • Implement morale loss on idle (-1/day).
  • Implement morale loss on low faction reputation (-2/day additional).
  • Implement morale gain on active assignment (+1/day).
  • Implement desertion check (loyalty < 10 or morale < 10).
  • Implement desertion notification to player.
  • Implement devotee cap per reputation tier.
  • Implement cap enforcement on reputation tier drop.
  • Subscribe to game-day tick for daily processing.
  • Subscribe to :reputation_changed for dynamic loyalty/cap updates.
  • Docs: Update YARD comments on affected classes and methods. Update relevant Docusaurus documentation pages if applicable.
  • Tests (Cucumber): Add tests/unit/devotee_mechanics.feature covering loyalty gain/loss, morale gain/loss, desertion trigger, desertion notification, cap enforcement, and cap-drop desertion.
  • Tests (Cucumber Integration): Add integration feature in tests/integration/ for multi-day devotee lifecycle including loyalty/morale changes, desertion, and cap enforcement.
  • Tests (Profiling): Run bundle exec rake unit_profile and verify no performance regressions.
  • Quality: Verify coverage >=97% via bundle exec rake unit. If coverage is <97% then review the current unit test coverage report at build/tests/unit/coverage/ and use it to write new Cucumber based unit tests to improve code coverage. Specifically, write Cucumber/Gherkin style unit tests that are descriptively named and specifically improve coverage on whichever file has the most uncovered lines by writing tests that will target the uncovered lines in the report. Once that is done rerun bundle exec rake unit to verify all tests pass and coverage is above >=97%. Only mark this as complete once coverage is >=97%, if not repeat this task as many times as is needed until coverage reaches >=97%.
  • Quality: Run bundle exec rake (default task: unit tests with coverage) and bundle exec rake integration, fix any errors if needed ensuring both pass across entire code base, do not ignore any failure even if it seems unrelated to this commit, fix it.

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
## Metadata | Field | Value | |-------|-------| | **Epic** | #203 — Devotee System | | **Legendary** | #199 — Reputation & Social Standing | | **Type** | Feature | | **Priority** | Medium | | **Points** | 8 | | **MoSCoW** | Should Have | | **Branch** | `feature/m4-devotee-loyalty-morale-mechanics` | | **Commit Message** | `Implement devotee loyalty and morale mechanics with cap based on reputation tier (#221)` | ## Background and Context Devotees are not mindless automatons — they have loyalty and morale that fluctuate based on player actions and conditions. Loyalty represents a devotee's commitment to the player, while morale represents their current emotional state and willingness to work. Loyalty increases slowly when devotees successfully complete tasks (+1 per day of active work) and decreases when the player's reputation with the devotee's original faction drops. Morale decreases when devotees are left idle without assignments or when conditions are poor, and increases when assigned meaningful work. If either loyalty or morale drops below 10, the devotee deserts — they leave the player's service permanently. This creates a management challenge and rewards attentive players. The number of devotees a player can maintain is capped based on their highest relevant reputation tier: - Neutral (and below): 0 devotees - Friendly: 1 devotee - Respected: 3 devotees - Honored: 6 devotees - Exalted: 10 devotees ## Expected Behavior 1. **Loyalty gain**: +1 per game day when a devotee has an active assignment and completes work. 2. **Loyalty loss**: When player's reputation with the devotee's faction drops, loyalty decreases proportionally (e.g., -5 rep = -2 loyalty). 3. **Morale loss**: -1 per game day when a devotee is idle (no assignment). Additional -2 per day if player's faction reputation is Unfriendly or below. 4. **Morale gain**: +1 per game day when assigned and working. 5. **Desertion**: If loyalty < 10 OR morale < 10, the devotee deserts at the next game-day tick. The player receives a notification. The devotee is removed from `player.info["devotees"]`. 6. **Devotee cap**: Checked on recruitment and on each game-day tick. If a player's reputation drops and their cap decreases below their current count, the devotee with the lowest loyalty deserts. 7. Both loyalty and morale are clamped to 0-100. ## Acceptance Criteria - [ ] Loyalty increases by 1/day when devotee has an active assignment. - [ ] Loyalty decreases proportionally when faction reputation drops. - [ ] Morale decreases by 1/day when devotee is idle. - [ ] Morale decreases by additional 2/day when faction reputation is Unfriendly or below. - [ ] Morale increases by 1/day when assigned and working. - [ ] Devotees desert when loyalty drops below 10. - [ ] Devotees desert when morale drops below 10. - [ ] Player receives notification on desertion. - [ ] Devotee cap is enforced: Neutral=0, Friendly=1, Respected=3, Honored=6, Exalted=10. - [ ] If cap decreases below current count, lowest-loyalty devotee deserts. - [ ] All changes are processed on game-day tick. ## Subtasks - [ ] Create `lib/aethyr/core/reputation/devotee_mechanics.rb` with the loyalty/morale engine. - [ ] Implement loyalty gain on active assignment (+1/day). - [ ] Implement loyalty loss on faction reputation drop. - [ ] Implement morale loss on idle (-1/day). - [ ] Implement morale loss on low faction reputation (-2/day additional). - [ ] Implement morale gain on active assignment (+1/day). - [ ] Implement desertion check (loyalty < 10 or morale < 10). - [ ] Implement desertion notification to player. - [ ] Implement devotee cap per reputation tier. - [ ] Implement cap enforcement on reputation tier drop. - [ ] Subscribe to game-day tick for daily processing. - [ ] Subscribe to `:reputation_changed` for dynamic loyalty/cap updates. - [ ] Docs: Update YARD comments on affected classes and methods. Update relevant Docusaurus documentation pages if applicable. - [ ] Tests (Cucumber): Add `tests/unit/devotee_mechanics.feature` covering loyalty gain/loss, morale gain/loss, desertion trigger, desertion notification, cap enforcement, and cap-drop desertion. - [ ] Tests (Cucumber Integration): Add integration feature in `tests/integration/` for multi-day devotee lifecycle including loyalty/morale changes, desertion, and cap enforcement. - [ ] Tests (Profiling): Run `bundle exec rake unit_profile` and verify no performance regressions. - [ ] Quality: Verify coverage >=97% via `bundle exec rake unit`. If coverage is <97% then review the current unit test coverage report at `build/tests/unit/coverage/` and use it to write new Cucumber based unit tests to improve code coverage. Specifically, write Cucumber/Gherkin style unit tests that are descriptively named and specifically improve coverage on whichever file has the most uncovered lines by writing tests that will target the uncovered lines in the report. Once that is done rerun `bundle exec rake unit` to verify all tests pass and coverage is above >=97%. Only mark this as complete once coverage is >=97%, if not repeat this task as many times as is needed until coverage reaches >=97%. - [ ] Quality: Run `bundle exec rake` (default task: unit tests with coverage) and `bundle exec rake integration`, fix any errors if needed ensuring both pass across **entire** code base, do not ignore any failure even if it seems unrelated to this commit, fix it. ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done.
freemo added this to the v1.3.0 milestone 2026-03-16 01:39:32 +00:00
freemo self-assigned this 2026-03-16 01:39:32 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
Reference: aethyr/Aethyr#221
No description provided.