Flexible race system with slot-based equipment and dragon race

- Expand race TOML schema: 7 stats, body shape (size/weight/custom slots),
  natural armor and attacks with damage types, resistances, traits/disadvantages,
  regen multipliers, vision types, XP rate, guild compatibility
- Replace equipped_weapon/equipped_armor with slot-based HashMap<String, Object>
- Each race defines available equipment slots; default humanoid slots as fallback
- Combat uses natural weapons/armor from race when no gear equipped
- DB migration from old weapon/armor columns to equipped_json
- Add Dragon race: huge body, custom slots (forelegs/wings/tail), fire breath,
  natural armor 8, fire immune, slow XP rate for balance
- Update all existing races with expanded fields (traits, resistances, vision, regen)
- Objects gain optional slot field; kind=weapon/armor still works as fallback
- Update chargen to display race traits, size, natural attacks, vision
- Update stats display to show equipment and natural bonuses separately
- Update TESTING.md and AGENTS.md with race/slot system documentation

Made-with: Cursor
This commit is contained in:
AI Agent
2026-03-14 15:37:20 -06:00
parent 3f164e4697
commit 005c4faf08
18 changed files with 586 additions and 139 deletions

View File

@@ -470,17 +470,15 @@ async fn admin_info(target: &str, state: &SharedState) -> CommandResult {
s.hp, s.max_hp, s.attack, s.defense, s.level, s.xp, s.xp_to_next
));
out.push_str(&format!(" Room: {}\r\n", p.room_id));
let equipped_str = if p.equipped.is_empty() {
"none".to_string()
} else {
p.equipped.iter().map(|(s, o)| format!("{}={}", s, o.name)).collect::<Vec<_>>().join(", ")
};
out.push_str(&format!(
" Inventory: {} item(s) | Weapon: {} | Armor: {}\r\n",
" Inventory: {} item(s) | Equipped: {}\r\n",
p.inventory.len(),
p.equipped_weapon
.as_ref()
.map(|w| w.name.as_str())
.unwrap_or("none"),
p.equipped_armor
.as_ref()
.map(|a| a.name.as_str())
.unwrap_or("none"),
equipped_str,
));
let attitudes = st.db.load_attitudes(&p.name);
if !attitudes.is_empty() {