resources

package module
v0.0.0-...-c99ed1f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 30, 2025 License: GPL-3.0 Imports: 4 Imported by: 1

README

Resources System

The resources package provides infrastructure for managing consumable game resources such as spell slots, ability uses, hit dice, and action economy.

Overview

Resources are consumable values that track current and maximum amounts, with rules for consumption and restoration. This package provides generic infrastructure that game systems can use to implement their specific resource mechanics.

Core Components

Resource Interface

The base interface for all resources:

type Resource interface {
    core.Entity
    Owner() core.Entity
    Key() string
    Current() int
    Maximum() int
    Consume(amount int) error
    Restore(amount int)
    RestoreOnShortRest() int
    RestoreOnLongRest() int
    IsAvailable() bool
}
SimpleResource

Basic implementation with configurable restoration:

resource := resources.NewSimpleResource(resources.SimpleResourceConfig{
    ID:       "rage-uses",
    Type:     resources.ResourceTypeAbilityUse,
    Owner:    barbarian,
    Key:      "rage_uses",
    Current:  3,
    Maximum:  3,
    RestoreType: resources.RestoreLongRest,
    LongRestRestore: -1, // Full restore
})
Resource Pool

Manages collections of resources for an entity:

pool := resources.NewSimplePool(character)

// Add resources
pool.Add(resources.CreateSpellSlots(character, map[int]int{
    1: 4,  // 4 first level slots
    2: 3,  // 3 second level slots
    3: 2,  // 2 third level slots
}))

// Consume resources
err := pool.Consume("spell_slots_1", 1, eventBus)

// Process rests
pool.ProcessShortRest(eventBus)
pool.ProcessLongRest(eventBus)

Resource Types

  • Spell Slots: Level-based spell casting resources
  • Ability Uses: Limited-use class features
  • Hit Dice: Rest and recovery resources
  • Action Economy: Actions, bonus actions, reactions
  • Custom: Any game-specific resource

Restoration Types

  • Never: Resource doesn't automatically restore
  • Turn: Restores at start of turn
  • Short Rest: Restores on short rest
  • Long Rest: Restores on long rest
  • Custom: Game-specific restoration rules

Helper Functions

Spell Slots
slots := resources.CreateSpellSlots(wizard, map[int]int{
    1: 4,
    2: 3,
    3: 2,
})
Ability Uses
rage := resources.CreateAbilityUse(barbarian, "rage", 3, resources.RestoreLongRest)
secondWind := resources.CreateAbilityUse(fighter, "second_wind", 1, resources.RestoreShortRest)
Hit Dice
hitDice := resources.CreateHitDice(fighter, "d10", 10) // 10d10 hit dice
Action Economy
actions := resources.CreateActionEconomy(character)
// Creates action, bonus_action, and reaction resources

Event Integration

Resources publish events when consumed or restored:

// Listen for resource consumption
bus.Subscribe(resources.EventResourceConsumed, func(e events.Event) error {
    event := e.(*resources.ResourceConsumedEvent)
    fmt.Printf("%s consumed %d %s\n", 
        event.Source().GetID(), 
        event.Amount, 
        event.Resource.Key())
    return nil
})

Usage Examples

Wizard Spell Management
wizard := &Character{id: "wizard-1"}
pool := resources.NewSimplePool(wizard)

// Add spell slots
for _, slot := range resources.CreateSpellSlots(wizard, map[int]int{
    1: 4, 2: 3, 3: 2,
}) {
    pool.Add(slot)
}

// Cast a spell
err := pool.ConsumeSpellSlot(2, bus) // Cast 2nd level spell

// Long rest restores all slots
pool.ProcessLongRest(bus)
Fighter Abilities
fighter := &Character{id: "fighter-1"}
pool := resources.NewSimplePool(fighter)

// Add abilities
pool.Add(resources.CreateAbilityUse(fighter, "second_wind", 1, resources.RestoreShortRest))
pool.Add(resources.CreateAbilityUse(fighter, "action_surge", 1, resources.RestoreLongRest))
pool.Add(resources.CreateHitDice(fighter, "d10", 10))

// Use Second Wind
pool.Consume("second_wind_uses", 1, bus)

// Short rest restores Second Wind
pool.ProcessShortRest(bus)
Combat Action Economy
// At start of combat, create action resources
for _, action := range resources.CreateActionEconomy(character) {
    pool.Add(action)
}

// Use action
pool.Consume("action", 1, bus)

// Actions restore at start of turn (handled by combat system)

Design Philosophy

This package follows rpg-toolkit principles:

  • Infrastructure, not rules: We provide resource tracking, games define what resources mean
  • Event-driven: Resources interact through events
  • Entity-based: Resources are entities for persistence
  • Flexible restoration: Games define when and how resources restore

Documentation

Overview

Package resources provides infrastructure for managing consumable and regenerating resources without defining what those resources represent.

Purpose: This package handles resource pools that can be consumed, restored, and regenerated over time, supporting game mechanics like health, mana, stamina, or any other depleting/restoring values.

Scope:

  • Resource pool management with current/maximum values
  • Consumption and restoration operations
  • Regeneration over time with configurable rates
  • Resource modification triggers and events
  • Overflow and underflow handling
  • Resource dependencies and relationships
  • Temporary maximum adjustments

Non-Goals:

  • Specific resource types: HP, MP, stamina are game-specific
  • Resource costs: What actions cost resources is game logic
  • Recovery rules: When/how resources regenerate is game-specific
  • Resource UI: Bars and displays are presentation layer
  • Balance values: Resource amounts and rates are game design
  • Death/exhaustion: What happens at zero is game-specific

Integration: This package integrates with:

  • events: Publishes resource change events
  • effects: Effects may consume or restore resources
  • conditions: Conditions may affect resource regeneration

Games define what resources mean and how they're used, while this package provides the numerical tracking infrastructure.

Example:

// Create a resource pool
health := resources.NewPool(resources.PoolConfig{
    Name:     "health",
    Current:  50,
    Maximum:  50,
    Minimum:  0,
    RegenRate: 1, // per interval
})

// Consume resources
err := health.Consume(10) // Take 10 damage
if err == resources.ErrInsufficientResources {
    // Not enough health
}

// Restore resources
restored := health.Restore(20) // Heal 20 HP
// restored = actual amount restored (capped by maximum)

// Check if depleted
if health.IsDepleted() {
    // Game-specific death/unconscious logic
}

// Regeneration (called by game loop)
health.Regenerate(deltaTime)

// Listen for changes
bus.Subscribe("resource.consumed", func(e events.Event) {
    data := e.Data.(ResourceEventData)
    fmt.Printf("%s consumed %d %s\n",
        data.EntityID, data.Amount, data.ResourceName)
})

Package resources provides infrastructure for managing consumable game resources such as spell slots, ability uses, hit dice, and action economy.

Example

Example demonstrates using custom restoration triggers instead of hardcoded rest mechanics.

// Create a character
character := &MockEntity{id: "paladin-1", typ: "character"}
pool := resources.NewSimplePool(character)
bus := events.NewBus()

// Create resources with game-specific triggers

// Divine resources that restore at dawn
layOnHands := resources.NewSimpleResource(resources.SimpleResourceConfig{
	ID:      "lay-on-hands",
	Type:    resources.ResourceTypeCustom,
	Owner:   character,
	Key:     "lay_on_hands_hp",
	Current: 25,
	Maximum: 50, // Level 10 paladin
	RestoreTriggers: map[string]int{
		"my.game.dawn":      -1, // Full restore at dawn
		"my.game.long_rest": -1, // Also on long rest
	},
})

// Ability that restores on any rest
divineSense := resources.NewSimpleResource(resources.SimpleResourceConfig{
	ID:      "divine-sense",
	Type:    resources.ResourceTypeAbilityUse,
	Owner:   character,
	Key:     "divine_sense_uses",
	Current: 3,
	Maximum: 6, // 1 + CHA modifier (5)
	RestoreTriggers: map[string]int{
		"my.game.short_rest": -1,
		"my.game.long_rest":  -1,
		"my.game.dawn":       -1, // Paladins regain at dawn too
	},
})

// Custom restoration from game events
inspiration := resources.NewSimpleResource(resources.SimpleResourceConfig{
	ID:      "divine-inspiration",
	Type:    resources.ResourceTypeCustom,
	Owner:   character,
	Key:     "inspiration_points",
	Current: 0,
	Maximum: 3,
	RestoreTriggers: map[string]int{
		"my.game.heroic_deed":     1,  // +1 for heroic acts
		"my.game.prayer_answered": 2,  // +2 when deity responds
		"my.game.milestone":       -1, // Full at story milestones
	},
})

// Add to pool
_ = pool.Add(layOnHands)
_ = pool.Add(divineSense)
_ = pool.Add(inspiration)

// Track restoration events (sorted for deterministic output)
restorations := []string{}
handler := func(_ context.Context, e events.Event) error {
	event := e.(*resources.ResourceRestoredEvent)
	restorations = append(restorations, fmt.Sprintf("  %s restored %d points (trigger: %s)",
		event.Resource.Key(), event.Amount, event.Reason))
	return nil
}
bus.SubscribeFunc(resources.EventResourceRestored, 0, events.HandlerFunc(handler))

// Helper to print sorted restoration messages
printRestorations := func() {
	sort.Strings(restorations)
	for _, msg := range restorations {
		fmt.Println(msg)
	}
	restorations = restorations[:0] // Clear for next batch
}

// Use some resources to see restoration
layOnHands.SetCurrent(10)
divineSense.SetCurrent(1)

// Simulate game events

// Dawn breaks - divine resources restore
fmt.Println("Dawn breaks...")
pool.ProcessRestoration("my.game.dawn", bus)
printRestorations()

// Character performs a heroic deed
fmt.Println("Paladin saves innocent - heroic deed!")
pool.ProcessRestoration("my.game.heroic_deed", bus)
printRestorations()

// Party reaches a milestone
fmt.Println("Major story milestone reached!")
pool.ProcessRestoration("my.game.milestone", bus)
printRestorations()

// Game-specific rest (not D&D's short/long rest)
fmt.Println("Party takes shelter in temple - blessed rest")
pool.ProcessRestoration("my.game.blessed_rest", bus)
printRestorations()
Output:

Dawn breaks...
  divine_sense_uses restored 5 points (trigger: my.game.dawn)
  lay_on_hands_hp restored 40 points (trigger: my.game.dawn)
Paladin saves innocent - heroic deed!
  inspiration_points restored 1 points (trigger: my.game.heroic_deed)
Major story milestone reached!
  inspiration_points restored 2 points (trigger: my.game.milestone)
Party takes shelter in temple - blessed rest

Index

Examples

Constants

View Source
const (
	EventResourceConsumed = "resource.consumed"
	EventResourceRestored = "resource.restored"
	EventShortRest        = "rest.short"
	EventLongRest         = "rest.long"
)

Event types for resource management

Variables

This section is empty.

Functions

This section is empty.

Types

type Pool

type Pool interface {
	// Owner returns the entity that owns this resource pool.
	Owner() core.Entity

	// Add adds a resource to the pool.
	Add(resource Resource) error

	// Remove removes a resource from the pool by key.
	Remove(key string) error

	// Get retrieves a resource by key.
	Get(key string) (Resource, bool)

	// GetByType retrieves all resources of a specific type.
	GetByType(resourceType ResourceType) []Resource

	// Consume attempts to consume from a specific resource.
	Consume(key string, amount int, bus events.EventBus) error

	// Restore restores a specific resource.
	Restore(key string, amount int, reason string, bus events.EventBus) error

	// ProcessShortRest processes a short rest for all resources.
	// Deprecated: Use ProcessRestoration("short_rest", bus) instead
	ProcessShortRest(bus events.EventBus)

	// ProcessLongRest processes a long rest for all resources.
	// Deprecated: Use ProcessRestoration("long_rest", bus) instead
	ProcessLongRest(bus events.EventBus)

	// ProcessRestoration processes a restoration trigger for all resources.
	// The trigger is a game-specific string that resources may respond to.
	// Examples: "short_rest", "long_rest", "dawn", "milestone", "prayer_cast"
	ProcessRestoration(trigger string, bus events.EventBus)

	// GetSpellSlots returns spell slots organized by level.
	GetSpellSlots() map[int]Resource

	// ConsumeSpellSlot attempts to consume a spell slot of the specified level or higher.
	ConsumeSpellSlot(level int, bus events.EventBus) error
}

Pool manages a collection of resources for an entity.

type Resource

type Resource interface {
	core.Entity // Resources are entities with ID and Type

	// Owner returns the entity that owns this resource.
	Owner() core.Entity

	// Key returns the resource identifier (e.g., "spell_slots_1", "rage_uses").
	Key() string

	// Current returns the current amount of this resource.
	Current() int

	// Maximum returns the maximum amount of this resource.
	Maximum() int

	// Consume attempts to use the specified amount of resource.
	// Returns an error if insufficient resources are available.
	Consume(amount int) error

	// Restore adds the specified amount to the resource, up to maximum.
	Restore(amount int)

	// SetCurrent sets the current value directly.
	SetCurrent(value int)

	// SetMaximum sets the maximum value.
	SetMaximum(value int)

	// RestoreOnShortRest returns the amount restored on a short rest.
	// Deprecated: Use RestoreOnTrigger with game-specific triggers instead
	RestoreOnShortRest() int

	// RestoreOnLongRest returns the amount restored on a long rest.
	// Deprecated: Use RestoreOnTrigger with game-specific triggers instead
	RestoreOnLongRest() int

	// RestoreOnTrigger returns the amount to restore for a given trigger.
	// Triggers are game-specific strings like "my.game.short_rest" or "dawn".
	// Returns 0 if the resource doesn't respond to the trigger.
	// Special return values:
	//   -1: Restore to full (maximum - current)
	RestoreOnTrigger(trigger string) int

	// IsAvailable returns true if any resource is available.
	IsAvailable() bool
}

Resource represents a consumable game resource with current and maximum values.

func CreateAbilityUse

func CreateAbilityUse(owner core.Entity, abilityName string, maxUses int, restoreType RestorationType) Resource

CreateAbilityUse creates a resource for tracking ability uses.

func CreateActionEconomy

func CreateActionEconomy(owner core.Entity) []Resource

CreateActionEconomy creates action economy resources for combat.

func CreateHitDice

func CreateHitDice(owner core.Entity, hitDieType string, level int) Resource

CreateHitDice creates hit dice resources for a character.

func CreateKiPoints

func CreateKiPoints(owner core.Entity, level int) Resource

CreateKiPoints creates a resource for monk ki points.

func CreateRageUses

func CreateRageUses(owner core.Entity, level int) Resource

CreateRageUses creates a resource for barbarian rage uses.

func CreateSpellSlots

func CreateSpellSlots(owner core.Entity, slots map[int]int) []Resource

CreateSpellSlots creates a set of spell slot resources for a caster. The slots map should have level (1-9) as keys and max slots as values.

type ResourceConsumedEvent

type ResourceConsumedEvent struct {
	*events.GameEvent
	Resource Resource
	Amount   int
}

ResourceConsumedEvent is published when a resource is consumed.

type ResourceRestoredEvent

type ResourceRestoredEvent struct {
	*events.GameEvent
	Resource Resource
	Amount   int
	Reason   string // "short_rest", "long_rest", "ability", etc.
}

ResourceRestoredEvent is published when a resource is restored.

type ResourceType

type ResourceType string

ResourceType represents the category of resource.

const (
	ResourceTypeSpellSlot   ResourceType = "spell_slot"
	ResourceTypeAbilityUse  ResourceType = "ability_use"
	ResourceTypeHitDice     ResourceType = "hit_dice"
	ResourceTypeAction      ResourceType = "action"
	ResourceTypeBonusAction ResourceType = "bonus_action"
	ResourceTypeReaction    ResourceType = "reaction"
	ResourceTypeCustom      ResourceType = "custom"
)

Resource type constants

type RestorationType

type RestorationType string

RestorationType indicates when a resource is restored.

const (
	RestoreNever     RestorationType = "never"
	RestoreShortRest RestorationType = "short_rest"
	RestoreLongRest  RestorationType = "long_rest"
	RestoreTurn      RestorationType = "turn"
	RestoreCustom    RestorationType = "custom"
)

Restoration type constants

type SimplePool

type SimplePool struct {
	// contains filtered or unexported fields
}

SimplePool provides a basic implementation of the Pool interface.

func NewSimplePool

func NewSimplePool(owner core.Entity) *SimplePool

NewSimplePool creates a new resource pool for an entity.

func (*SimplePool) Add

func (p *SimplePool) Add(resource Resource) error

Add adds a resource to the pool

func (*SimplePool) Consume

func (p *SimplePool) Consume(key string, amount int, bus events.EventBus) error

Consume attempts to consume from a specific resource

func (*SimplePool) ConsumeSpellSlot

func (p *SimplePool) ConsumeSpellSlot(level int, bus events.EventBus) error

ConsumeSpellSlot attempts to consume a spell slot of the specified level or higher

func (*SimplePool) Get

func (p *SimplePool) Get(key string) (Resource, bool)

Get retrieves a resource by key

func (*SimplePool) GetByType

func (p *SimplePool) GetByType(resourceType ResourceType) []Resource

GetByType retrieves all resources of a specific type

func (*SimplePool) GetSpellSlots

func (p *SimplePool) GetSpellSlots() map[int]Resource

GetSpellSlots returns spell slots organized by level

func (*SimplePool) Owner

func (p *SimplePool) Owner() core.Entity

Owner returns the entity that owns this pool

func (*SimplePool) ProcessLongRest

func (p *SimplePool) ProcessLongRest(bus events.EventBus)

ProcessLongRest processes a long rest for all resources Deprecated: Use ProcessRestoration("long_rest", bus) instead

func (*SimplePool) ProcessRestoration

func (p *SimplePool) ProcessRestoration(trigger string, bus events.EventBus)

ProcessRestoration processes a restoration trigger for all resources

func (*SimplePool) ProcessShortRest

func (p *SimplePool) ProcessShortRest(bus events.EventBus)

ProcessShortRest processes a short rest for all resources Deprecated: Use ProcessRestoration("short_rest", bus) instead

func (*SimplePool) Remove

func (p *SimplePool) Remove(key string) error

Remove removes a resource from the pool

func (*SimplePool) Restore

func (p *SimplePool) Restore(key string, amount int, reason string, bus events.EventBus) error

Restore restores a specific resource

type SimpleResource

type SimpleResource struct {
	// contains filtered or unexported fields
}

SimpleResource provides a basic implementation of the Resource interface.

func NewSimpleResource

func NewSimpleResource(cfg SimpleResourceConfig) *SimpleResource

NewSimpleResource creates a new simple resource from a config.

func (*SimpleResource) Consume

func (r *SimpleResource) Consume(amount int) error

Consume attempts to use the specified amount of resource

func (*SimpleResource) Current

func (r *SimpleResource) Current() int

Current returns the current amount

func (*SimpleResource) GetID

func (r *SimpleResource) GetID() string

GetID implements core.Entity

func (*SimpleResource) GetType

func (r *SimpleResource) GetType() string

GetType implements core.Entity

func (*SimpleResource) IsAvailable

func (r *SimpleResource) IsAvailable() bool

IsAvailable returns true if any resource is available

func (*SimpleResource) Key

func (r *SimpleResource) Key() string

Key returns the resource identifier

func (*SimpleResource) Maximum

func (r *SimpleResource) Maximum() int

Maximum returns the maximum amount

func (*SimpleResource) Owner

func (r *SimpleResource) Owner() core.Entity

Owner returns the entity that owns this resource

func (*SimpleResource) Restore

func (r *SimpleResource) Restore(amount int)

Restore adds the specified amount to the resource

func (*SimpleResource) RestoreOnLongRest

func (r *SimpleResource) RestoreOnLongRest() int

RestoreOnLongRest returns the amount restored on a long rest Deprecated: Use RestoreOnTrigger("long_rest") instead

func (*SimpleResource) RestoreOnShortRest

func (r *SimpleResource) RestoreOnShortRest() int

RestoreOnShortRest returns the amount restored on a short rest Deprecated: Use RestoreOnTrigger("short_rest") instead

func (*SimpleResource) RestoreOnTrigger

func (r *SimpleResource) RestoreOnTrigger(trigger string) int

RestoreOnTrigger returns the amount to restore for a given trigger

func (*SimpleResource) SetCurrent

func (r *SimpleResource) SetCurrent(value int)

SetCurrent sets the current value directly

func (*SimpleResource) SetMaximum

func (r *SimpleResource) SetMaximum(value int)

SetMaximum sets the maximum value

type SimpleResourceConfig

type SimpleResourceConfig struct {
	ID      string
	Type    ResourceType
	Owner   core.Entity
	Key     string
	Current int
	Maximum int

	// Restoration configuration (deprecated - use RestoreTriggers instead)
	ShortRestRestore int             // Amount restored on short rest
	LongRestRestore  int             // Amount restored on long rest (-1 for full)
	RestoreType      RestorationType // Primary restoration method

	// RestoreTriggers maps trigger strings to restoration amounts.
	// Special values:
	//   -1: Restore to full
	//    0: No restoration (or omit from map)
	//   >0: Restore specific amount
	RestoreTriggers map[string]int
}

SimpleResourceConfig holds the configuration for creating a SimpleResource.

Directories

Path Synopsis
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL