Vampire-Act-Mono/design/gdd/blood-energy-economy.md

10 KiB
Raw Permalink Blame History

Blood Energy Economy

Status: In Design Author: SepComet + Claude Last Updated: 2026-04-27 Implements Pillar: 操作优于数值 (Skill Over Stats), 切换即承诺 (Switch is Commitment)

Overview

Blood Energy Economy 是夜裔的核心资源系统——管理玩家用于切换形态的"血能"资源。血能通过攻击敌人和承受伤害两种方式获取,仅用于支付形态切换的消耗。它不是"攒大招"的能量槽,而是一个强制性的战术节奏控制器:你必须在前线积极战斗来赚取血能,然后在正确的时机消费它来切换形态。没有血能系统,形态切换退化为"CD好了就切",失去"切换即承诺"的战术重量。

Player Fantasy

此系统是纯基础设施——玩家感知的是它赋能的操作(切形态),而非血能数字本身。不展开独立幻想章节。

Detailed Design

Core Rules

1. Blood Energy Gain

Blood energy is earned through aggressive play:

  • Attack Hit: baseAttackGain × enemyTypeMultiplier per hit
  • Enemy Kill: baseKillGain × enemyTypeMultiplier per kill
  • Taking Damage: baseHurtGain × (damageTaken / maxHealth) — compensation ensures the player is never fully locked out of switching
  • Wave Clear: fixedBonus × waveNumber — reward for completing a wave

2. Blood Energy Spending

Blood energy has exactly one use: form switching.

  • Switch Cost: baseSwitchCost × (1.0 - skillDiscount)
  • Interrupted Switch: Blood energy is consumed on switch request (at Windup start). If the switch is interrupted, the energy is NOT refunded. This is the core punishment for switching at the wrong time.

3. Constraints

Rule Value
Valid range [0.0, maxEnergy]
Initial value (game start) 0
On death Reset to 0
Maximum value baseMax × (1.0 + upgradeBonus)
Cannot exceed max Add() clamps to max
Cannot go below 0 Spend() returns false if insufficient

States and Transitions

Blood Energy Economy has no complex states — it is a single float value with three meaningful thresholds:

Threshold Event Significance
Current == 0 OnEnergyEmpty Player is locked out of switching — must attack or take damage
Current >= switchCost (check via CanSpend()) Switching is possible
Current == Max OnEnergyFull Further gains are wasted — signals "you should switch now"

Every value change fires OnEnergyChanged(current, max) for HUD/L1 consumption.

Interactions with Other Systems

System Direction Interface
Form Switch SM Consumes Calls CanSpend(cost) before switching, Spend(cost) on switch start
HUD (L2) Reads Subscribes to OnEnergyChanged for display
Skill Tree Modifies Can set GainRate, baseSwitchCost, baseMax, skillDiscount
Death/Respawn Resets Calls Reset() on player death

Formulas

Attack Gain

energyGain_attack = baseAttackGain × enemyTypeMultiplier
Variable Symbol Type Range Description
Base attack gain baseAttackGain float 28 Energy gained per hit
Enemy type multiplier enemyTypeMultiplier float 0.52.0 Riskier enemies reward more

Output: 116 per hit | Extreme: Swarm enemies low (0.5x), Brute/Stalker high (1.52.0x)

Kill Gain

energyGain_kill = baseKillGain × enemyTypeMultiplier
Variable Symbol Type Range Description
Base kill gain baseKillGain float 1025 Kill reward significantly higher than hit
Enemy type multiplier enemyTypeMultiplier float 0.52.0 Same as attack formula

Output: 550 | Example: Brute kill (2.0x) = 25 × 2.0 = 50 energy

Hurt Gain

energyGain_hurt = baseHurtGain × (damageTaken / maxHealth)
Variable Symbol Type Range Description
Base hurt gain baseHurtGain float 820 Compensation to prevent deadlock
Damage ratio damageTaken / maxHealth float 0.01.0 Bigger hits give more energy

Intent: Ensures pressured players can earn a switch-out resource.

Switch Cost

switchCost = baseSwitchCost × (1.0 - skillDiscount)
Variable Symbol Type Range Description
Base switch cost baseSwitchCost float 2560 ~5-12 attack hits to earn one switch (at default ratio ≈8)
Skill discount skillDiscount float 0.00.4 Skill Tree cost reduction

Output: 1850 | Example: baseSwitchCost=40, no discount → cost=40

Wave Clear Bonus

waveClearBonus = min(fixedBonus × waveNumber, 2 × fixedBonus)
Variable Symbol Type Range Description
Fixed bonus fixedBonus float 2040 Base reward per cleared wave
Wave number waveNumber int 1N Caps at 2× fixedBonus to prevent late-wave overflow

Output: 2080 | Cap ensures wave bonuses don't exceed ~80% of maxEnergy in one reward

Max Energy

maxEnergy = baseMax × (1.0 + upgradeBonus)
Variable Symbol Type Range Description
Base max baseMax float 80150 Initial energy cap (default 100)
Upgrade bonus upgradeBonus float 0.00.5 Skill Tree capacity growth

Output: 100150

Edge Cases

# Condition Resolution Rationale
1 Add() would exceed MaxEnergy Clamp to Max, fire OnEnergyFull Overflow waste — incentivizes spending before full
2 Spend() amount exceeds current Return false, no side effects, no events Silent failure — UI should prevent this via CanSpend
3 Add() called while dead Ignore, return immediately Dead players don't accumulate resources
4 Switch interrupted (Interrupt()) Energy NOT refunded — deducted at Windup start Core punishment of "Switch is Commitment"
5 skillDiscount pushes cost near 0 Enforce minimum cost of 1.0 Switching always has a cost
6 Simultaneous Gain and Spend in same frame Process Gains first, then Spends Kill reward can enable immediate switch
7 Wave bonus causes overflow Clamp to Max (same as #1) Incentivize spending before wave end
8 skillTree undo reduces maxEnergy below current Force current = min(current, newMax) Cannot hold more than new cap

Dependencies

System Relationship Data Flow
Form Switch SM Downstream consumer Calls CanSpend() / Spend()
HUD (L2) Downstream display Subscribes to OnEnergyChanged
Skill Tree Upstream modifier Sets GainRate, baseMax, skillDiscount
Death/Respawn Upstream reset Calls Reset()

No upstream dependencies — this is a Foundation layer system.

Tuning Knobs

Parameter Default Safe Range Too Low Too High
baseAttackGain 5 28 Switching too slow, stuck in one form Switching too frequent, no tactical weight
baseKillGain 20 1030 Kills not worth prioritizing Kill-chasing replaces form strategy
baseHurtGain 12 820 Being pressured = no comeback Deliberate self-damage becomes optimal
baseSwitchCost 40 2560 Switching has almost no threshold Gap too long, player afraid to switch
baseMax 100 80150 Energy always capped → waste anxiety Decision window too large → no urgency
fixedBonus 30 2040 Wave bonus imperceptible Between-wave switching too lenient

Key tuning pair: baseSwitchCost / baseAttackGain ≈ 8 — roughly 8 attack hits to earn one switch. This ratio defines the core combat rhythm.

Visual/Audio Requirements

This system has no direct visual output. Its presentation is via:

  • HUD (L2): Blood energy bar with fill animation, drain animation on switch, color flash on value change
  • VFX Spawner (L1): Brief player glow on OnEnergyFull — visual cue "switch now"
  • Audio Player (L1): Warning sound on OnEnergyEmpty — audio cue "cannot switch"

UI Requirements

Element Position Content
Blood Energy Bar HUD bottom/side Amber Gold gradient, fill ratio current / max
Form Switch Buttons HUD corner One per form: grey = insufficient energy, bright = can switch, highlighted = current
Full Energy Indicator Next to bar Pulse effect when OnEnergyFull fires

Acceptance Criteria

# GIVEN WHEN THEN
1 Blood energy is 0 Player attacks and hits an enemy Energy increases by baseAttackGain × enemyTypeMultiplier
2 Blood energy is 50, cost is 40 Player requests a form switch CanSpend(40) returns true, Spend(40) succeeds, energy = 10
3 Blood energy is 10, cost is 40 Player requests a form switch CanSpend(40) returns false, Spend(40) returns false, energy stays 10
4 Blood energy is 95, gain is 10 Player gains energy Energy becomes 100 (clamped), OnEnergyFull fires
5 Energy was 60, 40 deducted on switch Player is hit during Windup Switch interrupted, energy stays at 20 (deducted cost not refunded, remainder preserved)
6 Player dies Reset() called Energy becomes 0
7 Energy reaches 0 Any cause OnEnergyEmpty fires
8 skillDiscount=0.4, baseSwitchCost=40 Player switches Cost = 24, energy decreased by 24
9 Energy changes (any cause) Per frame or event OnEnergyChanged(current, max) fires with correct values
10 baseMax changed from 100 to 50, current is 80 Skill tree update Current clamps to 50
11 skillDiscount set to 1.0, baseSwitchCost = 40 Player requests switch Cost = max(40 × 0.0, 1.0) = 1.0 (minimum cost enforced)
12 Player is dead, Add(10) called Energy gain event Gain ignored, energy unchanged

Open Questions

  • Final baseSwitchCost value (recommended 40) needs prototype validation — actual game feel will determine the right "attacks-per-switch" rhythm
  • Should there be a "low health → increased energy gain" comeback mechanic? Currently handled by hurt gain; revisit if playtest shows deadlock issues in low-health situations