Browse/Narrative & Choice/Companion Death
Narrative & Choice

Companion Death

Structured approach to companion death that balances depth with accessibility, creating satisfying player experiences.

Medium complexity
2 examples
1 patterns

Overview

The companion death mechanic provides a framework that provides meaningful choices and consequences for player actions. The implementation varies significantly across genres, with each game adapting the core concept to fit its specific design goals and target audience. Understanding the design principles behind this mechanic helps developers create more engaging and balanced game experiences.

Game Examples

Social Deduction Games

Social Deduction Games use this mechanic where players manage resources carefully to collect all available items. Emergent gameplay arises from simple rules, resulting in satisfying progression.

Stealth Games

Stealth Games use this mechanic where players coordinate with teammates to support their team effectively. Resource scarcity drives interesting decisions, resulting in creative expression.

Pros & Cons

Advantages

  • Balances social against mechanical effectively
  • Rewards both creative problem-solving and pattern recognition
  • Scales well from beginner to advanced play
  • Creates meaningful tactical decisions for players
  • Creates meaningful narrative decisions for players

Disadvantages

  • Increases storage requirements significantly
  • Risk of balance issues in competitive environments
  • Can become overpowered in the late game
  • Can create exploitation if not carefully balanced
  • Creates potential for cheese strategies by experienced players

Implementation Patterns

Branching Engine

Core implementation pattern for handling companion death logic with clean state management.

class CompanionDeathSystem {
  currentNode: string = "intro";
  flags: Set<string> = new Set();

  getDialogue() {
    const node = DIALOGUE_TREE[this.currentNode];
    return {
      text: node.text,
      choices: node.choices.filter(c =>
        !c.requires || c.requires.every(f => this.flags.has(f))
      )
    };
  }

  choose(choiceIndex: number) {
    const node = DIALOGUE_TREE[this.currentNode];
    const choice = node.choices[choiceIndex];
    if (choice.setsFlag) this.flags.add(choice.setsFlag);
    this.currentNode = choice.next;
    return this.getDialogue();
  }
}