zzstat - Hardcode-Free MMORPG Stat Engine
A highly optimized, completely data-driven, and deterministic stat calculation engine designed specifically for RPG and MMORPG servers.
zzstat provides everything you need to build complex game mechanics without writing a single line of hardcoded game logic. With zero I/O, no async primitives, and an incredibly fast O(1) copy-on-write fork() architecture, you can evaluate thousands of combat formulas and buffs concurrently with maximum performance.
🚀 Features at a Glance
- JSON Data-Driven: Define your stat formulas, buffs, combat skills, and conditional abilities entirely in JSON. Let Game Designers balance the game without touching Rust code.
- Dependency Graph Resolution: Automatically resolves complex dependency chains (
ATK = STR * 2,DAMAGE = ATK - DEF) with topological sorting and cycle detection. - Resource Pools & DoT/HoT: Track stateful values like Current HP/MP, apply Damage over Time (Poison), and trigger custom Events (like
DEATH). - Temporary Status Effects (Buffs & Debuffs): A
StatusEffectManagerthat seamlessly applies temporary buffs usingfork(), ensuring the character's base stats are never mutated. Supports stacking behaviors (Refresh,Accumulate,Independent). - Combat Engine (AST): A fully JSON-driven Combat Abstract Syntax Tree (AST). Calculate complex damages involving
Chancenodes (Crit, Dodge, Block) deterministically. - AI-Ready Guidelines: Includes
AI_PROMPT.mdout-of-the-box so you can instantly generate perfectly valid JSON files using AI assistants like ChatGPT, Claude, or Copilot. - Modular & High Performance: Fully decoupled
StatRegistryandStatResolverusingrustc_hash::FxHashMapfor blazingly fastO(1)operations.
🛠️ Core Modules
1. StatTemplate (Data-Driven Architecture)
Forget writing manual transforms in Rust. Load your entire class, monster, or item stat logic directly from a JSON string.
2. ResourcePool (State Management)
RPG games need to track current states. ResourcePool handles Current HP/MP, bounds it to a StatResolver stat (like MAX_HP), processes ticks for DoTs, and emits events when thresholds are hit.
// Poison DoT (-20 HP/tick for 3 ticks)
hp_pool.add_effect;
// Emits "DEATH" event if HP falls to 0
hp_pool.add_trigger;
3. StatusEffectManager (Temporary Buffs/Debuffs)
Adding a temporary buff shouldn't permanently alter the base stats. zzstat uses an O(1) copy-on-write fork() method to overlay stats dynamically.
let buff = StatusEffect ;
// Add 50 ATK for 3 ticks
status_manager.add_status_effect;
// Use the active resolver safely
let current_atk = status_manager.get_active_resolver.resolve;
4. CombatEngine (AST Formula Evaluation)
Evaluate complex attack commands defined entirely in JSON. The CombatEngine reads the AST and calculates the damage based on the Attacker and Defender's stats. Random chances (Crit/Dodge) rely on a closure, making tests 100% deterministic!
5. Graph Visualization (Mermaid.js)
Export your entire stat dependency tree, including all active bonuses and active transforms, into a graph TD Mermaid string natively. Perfect for generating live documentation for your game's mechanics!
let mermaid_code = resolver.export_mermaid;
Generates output that renders directly in GitHub, Notion, and Mermaid Live Editor:
graph TD
WEAPON_MAX[("WEAPON_MAX")]
WEAPON_MAX_src_b0>"ConstantSource(181.0)"]
WEAPON_MAX_src_b0 -.-> WEAPON_MAX
WEAPON_MIN[("WEAPON_MIN")]
WEAPON_MIN_src_b0>"ConstantSource(159.0)"]
WEAPON_MIN_src_b0 -.-> WEAPON_MIN
MAIN_ATTACK[("MAIN_ATTACK")]
MAIN_ATTACK_tr_b0[/"scale(LEVEL, 2.00)"/]
MAIN_ATTACK_tr_b0 -.-> MAIN_ATTACK
MAIN_ATTACK_tr_b1[/"scale(STR, 2.00)"/]
MAIN_ATTACK_tr_b1 -.-> MAIN_ATTACK
MONSTER_DEFENSE[("MONSTER_DEFENSE")]
MONSTER_DEFENSE_src_b0>"ConstantSource(146.0)"]
MONSTER_DEFENSE_src_b0 -.-> MONSTER_DEFENSE
RAW_DAMAGE[("RAW_DAMAGE")]
RAW_DAMAGE_tr_b0[/"scale(MAIN_ATTACK, 1.00)"/]
RAW_DAMAGE_tr_b0 -.-> RAW_DAMAGE
RAW_DAMAGE_tr_b1[/"scale(WEAPON_AVG, 2.00)"/]
RAW_DAMAGE_tr_b1 -.-> RAW_DAMAGE
BASE_DAMAGE[("BASE_DAMAGE")]
BASE_DAMAGE_tr_b0[/"scale(RAW_DAMAGE, 1.00)"/]
BASE_DAMAGE_tr_b0 -.-> BASE_DAMAGE
BASE_DAMAGE_tr_b1[/"scale(MONSTER_DEFENSE, -1.00)"/]
BASE_DAMAGE_tr_b1 -.-> BASE_DAMAGE
LEVEL[("LEVEL")]
LEVEL_src_b0>"ConstantSource(105.0)"]
LEVEL_src_b0 -.-> LEVEL
STR[("STR")]
STR_src_b0>"ConstantSource(90.0)"]
STR_src_b0 -.-> STR
WEAPON_AVG[("WEAPON_AVG")]
WEAPON_AVG_tr_b0[/"scale(WEAPON_MIN, 0.50)"/]
WEAPON_AVG_tr_b0 -.-> WEAPON_AVG
WEAPON_AVG_tr_b1[/"scale(WEAPON_MAX, 0.50)"/]
WEAPON_AVG_tr_b1 -.-> WEAPON_AVG
LEVEL ==> MAIN_ATTACK
STR ==> MAIN_ATTACK
MAIN_ATTACK ==> RAW_DAMAGE
WEAPON_AVG ==> RAW_DAMAGE
RAW_DAMAGE ==> BASE_DAMAGE
MONSTER_DEFENSE ==> BASE_DAMAGE
WEAPON_MIN ==> WEAPON_AVG
WEAPON_MAX ==> WEAPON_AVG
⚡ Performance & Determinism
In MMORPG architecture, backend loops calculate stats for thousands of entities per second.
- Zero Allocations on Runtime Graph: Calculations trace predefined paths using robust caching (
FxHashMap). - Copy-on-Write Forks: Applying a buff creates an
Arcoverlay in nanoseconds. - Fixed-Point Arithmetic (Optional): Ensure cross-platform floating-point precision issues never desync your lockstep gameplay.
📚 Examples
Explore the /examples directory for comprehensive guides on how to use zzstat:
01_template_loader.rs02_resource_pool.rs03_status_effects.rs04_combat_engine.rs05_graph_export.rsmetin2/(Full MMORPG Damage Simulator)
Run them with:
🤝 Using AI to Create Content
You can use ChatGPT, Claude, or any LLM to generate perfectly formatted stat and combat JSONs for zzstat. Simply copy the contents of AI_PROMPT.md and give it to your AI assistant.
📖 API Documentation
For comprehensive API documentation including all structs, methods, and types, you can generate and open the Rustdoc HTML directly on your machine:
Additionally, check out the docs/ folder in the repository for detailed guides and architectural walkthroughs in both English and Turkish.
License
This project is licensed under the MIT License.