Devlog10: Implement Missions (Story) feature


Plan developed with chat with Claude.io.

I like using Guthub Projects for updates for this sprint - Click here

Reflection:

- my apprentice (Claude.io) was overly enthusiastic and created a system that was too complex for me and didn't work. 

Some progress here with version 2 of above, this commit gives me confidence we are making progress:

- Trouble shooting getting UI to work when transitioning from Main Menu to Story mode. Devlog10 video

- Perseverance pays off - basic version of story mode works - commit feature: Story Mode - basic story complete with polish needed

- Demo4 uploaded to itch.io - tutorial system needs fixing: story mode panel gets in the way. 

- I like using spreadsheets for UML style diagrams - see screen shot



First few hours

7Bridges Story System - SOLID Design Architecture

SOLID Principles Application

1. Single Responsibility Principle (SRP)

Each class has one reason to change:

  • StoryManager → Story progression logic only
  • DialogueSystem → Dialogue display only
  • HistoricalContext → Historical facts only
  • EulerNPC → Euler character behavior only

2. Open/Closed Principle (OCP)

Open for extension, closed for modification:

  • IStoryElement interface allows new story types without changing existing code
  • StoryMissionFactory can create new mission types
  • Abstract StoryMission base class for common behavior

3. Liskov Substitution Principle (LSP)

Derived classes must be substitutable:

  • Any StoryMission can replace MissionDefinition
  • Any IStoryElement can be used interchangeably
  • KonigsbergMission is-a StoryMission

4. Interface Segregation Principle (ISP)

Clients don't depend on unused interfaces:

  • IDialogueProvider separate from IStoryProgression
  • IHistoricalNarrator separate from INPCBehavior
  • Small, focused interfaces

5. Dependency Inversion Principle (DIP)

Depend on abstractions, not concretions:

  • StoryManager depends on IStoryElement, not concrete classes
  • DialogueSystem depends on IDialogueProvider
  • Dependency injection through constructors/properties

UML Class Diagram

classDiagram     %% Existing System (Simplified)     class LearningMissionsManager {         -MissionDefinition[] missions         +StartMission(int index)         +GetCurrentMissionIndex()     }          class MissionDefinition {         +string missionName         +JourneyType targetType         +string learningObjective     }          %% New Story System     class IStoryElement {         <<interface>>         +string StoryId         +bool IsComplete         +void Initialize()         +void Execute()         +void Complete()     }          class StoryManager {         -IStoryElement[] storyElements         -IDialogueSystem dialogueSystem         -IHistoricalContext historicalContext         +void StartStory()         +void ProgressStory()         +void ShowDialogue(string text)     }          class DialogueSystem {         -TextMeshProUGUI dialogueText         -Button continueButton         +void ShowDialogue(string text)         +void HideDialogue()         +event Action OnDialogueComplete     }          class IDialogueProvider {         <<interface>>         +string[] GetDialogue(string context)         +string GetIntroduction()         +string GetConclusion()     }          class EulerNPC {         -Vector3 position         -Animator animator         +void Appear()         +void Speak(string dialogue)         +void Disappear()     }          class StoryMission {         <<abstract>>         -string storyIntroduction         -string historicalContext         -EulerNPC euler         +abstract void ExecuteStoryPhase()         +void ShowIntroduction()         +void ShowConclusion()     }          class KonigsbergMission {         -int bridgesCrossed         -bool puzzleAttempted         +void ExecuteStoryPhase()         +void ShowKonigsbergHistory()         +void DemonstrateImpossibility()     }          class HistoricalContextProvider {         -Dictionary~string, HistoricalFact~ facts         +string GetHistoricalContext(string period)         +string GetMathematicalExplanation(string concept)         +HistoricalFact GetEulerBiography()     }          %% Relationships     LearningMissionsManager --> MissionDefinition : contains     StoryManager --> IStoryElement : manages     StoryManager --> DialogueSystem : uses     StoryManager --> HistoricalContextProvider : uses     StoryMission ..|> IStoryElement : implements     StoryMission ..|> IDialogueProvider : implements     KonigsbergMission --|> StoryMission : extends     EulerNPC ..|> IDialogueProvider : implements     DialogueSystem --> IDialogueProvider : uses          %% Integration with existing     LearningMissionsManager --> StoryManager : delegates to     StoryMission --> MissionDefinition : extends 

UML Sequence Diagram - Mission Flow

sequenceDiagram     participant Player     participant UI as LearningMissionsManager       participant SM as StoryManager     participant DS as DialogueSystem     participant Euler as EulerNPC     participant JT as JourneyTracker          Player->>UI: Start Mission 1     UI->>SM: StartStory("KonigsbergIntro")     SM->>DS: ShowDialogue("Welcome to 1736...")     DS->>Player: Display introduction          Player->>DS: Click Continue     DS->>SM: OnDialogueComplete     SM->>Euler: Appear()     Euler->>DS: ShowDialogue("I am Leonhard Euler...")          Player->>DS: Click Continue       DS->>SM: OnDialogueComplete     SM->>JT: SetMissionType(Walk)     SM->>UI: BeginGameplay()          loop Gameplay Phase         Player->>JT: Move/Cross Bridges         JT->>SM: OnProgressUpdate         alt Mission Complete             SM->>Euler: Speak("Interesting approach...")             SM->>DS: ShowConclusion()         end     end          SM->>UI: MissionComplete()     UI->>SM: StartStory("NextMission") 

Integration Strategy

Extending Existing Classes

// Extend existing MissionDefinition public class StoryMissionDefinition : MissionDefinition {     public string storyIntroduction;     public string[] eulerDialogue;     public string historicalContext;     public string conclusionText; }  // Extend LearningMissionsManager public partial class LearningMissionsManager {     [SerializeField] private StoryManager storyManager;          // Override existing method     public override void StartMission(int missionIndex)     {         if (missions[missionIndex] is StoryMissionDefinition storyMission)         {             storyManager?.StartStoryMission(storyMission);         }         else         {             base.StartMission(missionIndex); // Original behavior         }     } } 

Dependency Injection Pattern

public class StoryManager : MonoBehaviour {     // Dependencies injected via inspector or constructor     [SerializeField] private DialogueSystem dialogueSystem;     [SerializeField] private EulerNPC eulerNPC;     [SerializeField] private HistoricalContextProvider contextProvider;          // Constructor injection for testing     public StoryManager(IDialogueSystem dialogue = null,                         IHistoricalContext context = null)     {         this.dialogueSystem = dialogue ?? GetComponent<DialogueSystem>();         this.contextProvider = context ?? GetComponent<HistoricalContextProvider>();     } } 

Component Diagram

graph TB     subgraph "Existing Game Systems"         LMM[LearningMissionsManager]         JT[JourneyTracker]          BS[Bridge System]         UI[MinimalModeUI]     end          subgraph "New Story System"         SM[StoryManager]         DS[DialogueSystem]         HCP[HistoricalContextProvider]         ENPC[EulerNPC]     end          subgraph "Story Content"         SMD[StoryMissionDefinition]         KM[KonigsbergMission]         HC[HistoricalContext]     end          %% Dependencies     LMM --> SM : delegates story missions     SM --> DS : displays dialogue     SM --> HCP : gets historical facts     SM --> ENPC : controls NPC     SM --> JT : monitors progress          %% Content     SM --> SMD : loads story data     KM -.-> SMD : implements     HCP --> HC : provides facts          %% UI Integration       DS --> UI : reuses text components     SM --> UI : triggers updates          style SM fill:#e1f5fe     style DS fill:#e8f5e8     style HCP fill:#fff3e0     style ENPC fill:#fce4ec 

Implementation Benefits

1. Maintainability (SRP)

  • Story logic separated from gameplay logic
  • Easy to modify dialogue without affecting game mechanics
  • Historical content can be updated independently

2. Extensibility (OCP)

  • New story elements can be added without modifying existing code
  • Different dialogue providers (Euler, other NPCs, narration)
  • New mission types just implement IStoryElement

3. Testability (DIP)

  • Mock interfaces for unit testing
  • Story progression can be tested without UI
  • Historical content can be validated separately

4. Reusability

  • Dialogue system can be used for other educational content
  • Historical context provider works for any mathematical history
  • Story structure supports other mathematical topics

Quick Implementation Steps

  1. Create interfaces first (IStoryElement, IDialogueProvider)
  2. Implement simple DialogueSystem (reuse existing UI components)
  3. Create StoryManager with dependency injection
  4. Build KonigsbergMission extending existing mission system
  5. Add EulerNPC with basic dialogue functionality
  6. Integrate with LearningMissionsManager using composition

This design leverages your existing architecture while adding story capabilities through clean, maintainable OOP principles.

Get 7Bridges

Leave a comment

Log in with itch.io to leave a comment.