Accept negative --at coordinates; probe the pick at given points
`--at -8445,320,135` failed: clap read the leading minus of the separate values as a flag. It is now one x,y,z value that may start with a minus. EDITOR_PROBES casts the cursor's walkable-surface ray down at WoW points beside EDITOR_SHOT. Run at 11 Stormwind spawns on WMO floors (the Keep, the Mage Quarter tower's top storey, the Trade District), it hits 0 to 0.21 yd under the z the server stores, on the spawn's own storey. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -32,10 +32,21 @@ struct Args {
|
||||
/// Map id; defaults to the first spawn's, else 0 (Eastern Kingdoms).
|
||||
#[arg(long)]
|
||||
map: Option<u32>,
|
||||
/// Where the camera opens, WoW `x,y,z`; defaults to the first spawn on the map, else
|
||||
/// Northshire.
|
||||
#[arg(long, value_delimiter = ',', num_args = 3)]
|
||||
at: Option<Vec<f32>>,
|
||||
/// Where the camera opens, WoW `x,y,z` (`--at -8445,320,135`); defaults to the first spawn on
|
||||
/// the map, else Northshire.
|
||||
#[arg(long, allow_hyphen_values = true, value_parser = parse_point)]
|
||||
at: Option<[f32; 3]>,
|
||||
}
|
||||
|
||||
/// `x,y,z` as three floats. One value, not three: WoW coordinates are mostly negative, and clap
|
||||
/// reads a leading `-` in a separate value as a flag.
|
||||
fn parse_point(s: &str) -> Result<[f32; 3], String> {
|
||||
let v: Vec<f32> = s
|
||||
.split(',')
|
||||
.map(|p| p.trim().parse::<f32>().map_err(|e| format!("`{p}`: {e}")))
|
||||
.collect::<Result<_, _>>()?;
|
||||
v.try_into()
|
||||
.map_err(|v: Vec<f32>| format!("want x,y,z, got {} value(s)", v.len()))
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
@@ -55,9 +66,9 @@ fn main() -> anyhow::Result<()> {
|
||||
.map
|
||||
.or_else(|| project.creatures.values().next().map(|c| c.map))
|
||||
.unwrap_or(0);
|
||||
let start = match args.at.as_deref() {
|
||||
Some([x, y, z]) => [*x, *y, *z],
|
||||
_ => project
|
||||
let start = match args.at {
|
||||
Some(at) => at,
|
||||
None => project
|
||||
.creatures
|
||||
.values()
|
||||
.find(|c| c.map == map)
|
||||
@@ -186,6 +197,30 @@ fn shoot_and_exit(
|
||||
benilla_assets::coords::bevy_to_wow(c.translation() + *dir * h.distance)
|
||||
})
|
||||
});
|
||||
// `EDITOR_PROBES=x,y,z;…`: the cursor's cast straight down from 3 yd above each WoW
|
||||
// point, e.g. a server spawn on a WMO floor, so the pick is measured against the
|
||||
// height the server stores.
|
||||
for probe in std::env::var("EDITOR_PROBES")
|
||||
.unwrap_or_default()
|
||||
.split(';')
|
||||
{
|
||||
let p: Vec<f32> = probe
|
||||
.split(',')
|
||||
.filter_map(|v| v.trim().parse().ok())
|
||||
.collect();
|
||||
let [x, y, z] = p[..] else { continue };
|
||||
let hit = collision
|
||||
.ray_body(
|
||||
benilla_assets::coords::wow_to_bevy([x, y, z + 3.0]),
|
||||
Dir3::NEG_Y,
|
||||
50.0,
|
||||
)
|
||||
.map(|h| z + 3.0 - h.distance);
|
||||
info!(
|
||||
"EDITOR_PROBE at=[{x}, {y}, {z}] hit_z={hit:?} dz={:?}",
|
||||
hit.map(|h| h - z)
|
||||
);
|
||||
}
|
||||
let cam = cam
|
||||
.single()
|
||||
.map(|c| benilla_assets::coords::bevy_to_wow(c.translation()));
|
||||
@@ -208,3 +243,20 @@ fn shoot_and_exit(
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn at_takes_negative_coordinates() {
|
||||
for argv in [
|
||||
["e", "p.json", "--at", "-8445,320,135"],
|
||||
["e", "p.json", "--at=-8445,320,135", "--map=0"],
|
||||
] {
|
||||
let args = Args::try_parse_from(argv.iter().filter(|a| !a.is_empty())).unwrap();
|
||||
assert_eq!(args.at, Some([-8445.0, 320.0, 135.0]));
|
||||
}
|
||||
assert!(Args::try_parse_from(["e", "p.json", "--at", "1,2"]).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user