use bevy::prelude::*;
use bevy_gauge::prelude::*;
#[derive(Resource)]
struct Entities {
crown: Entity,
necromancer: Entity,
warlock: Entity,
skeleton: Entity,
}
fn main() {
App::new()
.add_plugins(MinimalPlugins)
.add_plugins(AttributesPlugin)
.add_systems(
Startup,
(
spawn,
demo.after(spawn),
),
)
.run();
}
fn spawn(mut commands: Commands) {
let crown = commands
.spawn((
Name::new("Necromancer's Crown"),
attributes! {
"IncreasedMinionLife" => 0.25,
},
))
.id();
let necromancer = commands
.spawn((
Name::new("Necromancer"),
attributes! {
"Intelligence" => 30.0,
},
))
.id();
let warlock = commands
.spawn((
Name::new("Warlock"),
attributes! {
"Intelligence" => 50.0,
},
))
.id();
let skeleton = commands
.spawn((
Name::new("Skeleton"),
attributes! {
"Life.base" => 100.0,
@complex "Life" => [("base", ReduceFn::Sum), ("increased", ReduceFn::Sum)] => "base * (1 + increased)",
},
))
.id();
commands.insert_resource(Entities {
crown,
necromancer,
warlock,
skeleton,
});
println!("--- Entities spawned ---\n");
}
fn demo(handles: Res<Entities>, mut attributes: AttributesMut) {
let crown = handles.crown;
let necro = handles.necromancer;
let warlock = handles.warlock;
let skeleton = handles.skeleton;
println!("=== Initial state ===\n");
print_skeleton_life("Skeleton", skeleton, &mut attributes);
println!("=== Necromancer equips Crown ===\n");
attributes.register_source(necro, "Equipment", crown);
attributes
.add_expr_modifier(necro, "IncreasedMinionLife", "IncreasedMinionLife@Equipment")
.expect("valid expression");
let necro_bonus = attributes.evaluate(necro, "IncreasedMinionLife");
println!(" Necromancer's IncreasedMinionLife: {necro_bonus:.2} (from Crown's 0.25)");
println!("\n=== Skeleton linked to Necromancer as Owner ===\n");
attributes.register_source(skeleton, "Owner", necro);
attributes
.add_expr_modifier(skeleton, "Life.increased", "IncreasedMinionLife@Owner")
.expect("valid expression");
let skel_life = attributes.evaluate(skeleton, "Life");
println!(" Skeleton Life: {skel_life:.1}");
println!(" Expected: 100 * (1 + 0.25) = 125.0");
println!("\n=== Upgrading Crown: IncreasedMinionLife 0.25 → 0.50 ===\n");
attributes.set_base(crown, "IncreasedMinionLife", 0.50);
let necro_bonus = attributes.evaluate(necro, "IncreasedMinionLife");
let skel_life = attributes.evaluate(skeleton, "Life");
println!(" Necromancer's IncreasedMinionLife: {necro_bonus:.2}");
println!(" Skeleton Life: {skel_life:.1}");
println!(" Expected: 100 * (1 + 0.50) = 150.0");
println!("\n=== Warlock takes the Crown from Necromancer ===\n");
attributes.set_base(necro, "IncreasedMinionLife", 0.0);
attributes.unregister_source(necro, "Equipment");
attributes.register_source(warlock, "Equipment", crown);
attributes
.add_expr_modifier(warlock, "IncreasedMinionLife", "IncreasedMinionLife@Equipment")
.expect("valid expression");
attributes.register_source(skeleton, "Owner", warlock);
let warlock_bonus = attributes.evaluate(warlock, "IncreasedMinionLife");
let skel_life = attributes.evaluate(skeleton, "Life");
println!(" Warlock's IncreasedMinionLife: {warlock_bonus:.2}");
println!(" Skeleton Life: {skel_life:.1}");
println!(" Expected: 100 * (1 + 0.50) = 150.0 (same crown, different owner)");
println!("\n=== Upgrading Crown again: 0.50 → 1.00 ===\n");
attributes.set_base(crown, "IncreasedMinionLife", 1.00);
let warlock_bonus = attributes.evaluate(warlock, "IncreasedMinionLife");
let skel_life = attributes.evaluate(skeleton, "Life");
println!(" Warlock's IncreasedMinionLife: {warlock_bonus:.2}");
println!(" Skeleton Life: {skel_life:.1}");
println!(" Expected: 100 * (1 + 1.00) = 200.0");
println!("\n=== Warlock unequips Crown ===\n");
attributes.set_base(warlock, "IncreasedMinionLife", 0.0);
attributes.unregister_source(warlock, "Equipment");
let warlock_bonus = attributes.evaluate(warlock, "IncreasedMinionLife");
let skel_life = attributes.evaluate(skeleton, "Life");
println!(" Warlock's IncreasedMinionLife: {warlock_bonus:.2}");
println!(" Skeleton Life: {skel_life:.1}");
println!(" Expected: 100 * (1 + 0.00) = 100.0 (no crown equipped)");
println!("\n--- Done ---");
std::process::exit(0);
}
fn print_skeleton_life(label: &str, entity: Entity, attributes: &mut AttributesMut) {
let life = attributes.evaluate(entity, "Life");
println!(" {label} Life: {life:.1}");
println!();
}