use bevy::prelude::*;
use bevy_gauge::prelude::*;
#[derive(Resource)]
struct Entities {
archer: Entity,
target: Entity,
iron_arrow: Entity,
fire_arrow: Entity,
shortbow: Entity,
longbow: 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 archer = commands
.spawn((
Name::new("Archer"),
attributes! {
"Agility" => 30.0,
},
))
.id();
let target = commands
.spawn((
Name::new("Target Dummy"),
attributes! {
"Life" => 200.0,
"Life.current" => 200.0,
},
))
.id();
let iron_arrow = commands
.spawn((
Name::new("Iron Arrow"),
attributes! { "Damage" => 15.0 },
))
.id();
let fire_arrow = commands
.spawn((
Name::new("Fire Arrow"),
attributes! { "Damage" => 25.0 },
))
.id();
let shortbow = commands
.spawn((
Name::new("Shortbow"),
attributes! { "Damage" => 10.0 },
))
.id();
let longbow = commands
.spawn((
Name::new("Longbow"),
attributes! { "Damage" => 20.0 },
))
.id();
commands.insert_resource(Entities {
archer,
target,
iron_arrow,
fire_arrow,
shortbow,
longbow,
});
println!("--- Entities spawned ---\n");
}
fn demo(handles: Res<Entities>, mut attributes: AttributesMut) {
let on_hit = instant! {
"Life.current" -= "Damage@arrow + Damage@bow + (Agility@attacker * 0.1)",
};
println!("=== Shot 1: Iron Arrow + Shortbow ===\n");
let roles: &[(&str, Entity)] = &[
("arrow", handles.iron_arrow),
("bow", handles.shortbow),
("attacker", handles.archer),
];
let preview = attributes.evaluate_instant(&on_hit, roles, handles.target);
for entry in &preview {
println!(" Preview: {} {:?} {:.1}", entry.attribute, entry.op, entry.value);
}
println!(" Expected: 15 (arrow) + 10 (bow) + 30*0.1 (agility) = 28.0\n");
attributes.apply_evaluated_instant(&preview, handles.target);
let life = attributes.evaluate(handles.target, "Life.current");
println!(" Target life after shot 1: {life:.1} / 200\n");
println!("=== Shot 2: Fire Arrow + Longbow ===\n");
let roles: &[(&str, Entity)] = &[
("arrow", handles.fire_arrow),
("bow", handles.longbow),
("attacker", handles.archer),
];
let preview = attributes.evaluate_instant(&on_hit, roles, handles.target);
for entry in &preview {
println!(" Preview: {} {:?} {:.1}", entry.attribute, entry.op, entry.value);
}
println!(" Expected: 25 (arrow) + 20 (bow) + 30*0.1 (agility) = 48.0\n");
attributes.apply_evaluated_instant(&preview, handles.target);
let life = attributes.evaluate(handles.target, "Life.current");
println!(" Target life after shot 2: {life:.1} / 200\n");
println!("=== Shot 3: Iron Arrow + Longbow (direct apply) ===\n");
let roles: &[(&str, Entity)] = &[
("arrow", handles.iron_arrow),
("bow", handles.longbow),
("attacker", handles.archer),
];
attributes.apply_instant(&on_hit, roles, handles.target);
let life = attributes.evaluate(handles.target, "Life.current");
println!(" Expected damage: 15 + 20 + 3 = 38.0");
println!(" Target life after shot 3: {life:.1} / 200\n");
println!("=== Summary ===\n");
println!(" Total damage dealt: {:.1}", 200.0 - life);
println!(" Remaining life: {life:.1}");
println!("\n--- Done ---");
std::process::exit(0);
}