Split smart interact shortcut from single Alt+J send
bind: "interact" now resolves to game_binds.interact (Alt+J) only — a single keystroke. The full ISBoxer-style chain (CTM on -> Alt+J -> sleep walk_delay_ms -> CTM off) lives at bind: "smart_interact". Fixes the doubling bug Grok flagged: bind: "interact" previously expanded into the full chain unconditionally, so the loot_manual and interact_hold example maps fired ctm_on/ctm_off twice and produced unwanted sleep delays. - engine.rs: rename shortcut trigger (was: "interact") - examples/profile.yaml: loot now uses smart_interact; loot_manual and interact_hold keep "interact" as a single Alt+J send - docs/MACROS.md: heading + shortcut comment - docs/NOTES.md: trigger name - Add new test: interact_simple_sends_only_alt_j (1-line single-send) - Existing smart shortcut tests renamed to bind: smart_interact - CHANGELOG.md: trigger split note 93/93 cargo test pass; clippy clean.
This commit is contained in:
parent
1ec8d78f71
commit
8eb5346d92
@ -48,3 +48,6 @@
|
||||
clippy clean.
|
||||
- Docs: `docs/MACROS.md` "Smart interact shortcut" section, `docs/NOTES.md`
|
||||
callout, `examples/profile.yaml` updated with comments.
|
||||
|
||||
> Note: After this change, `bind: "interact"` is a single Alt+J send (game_binds.interact).
|
||||
> The full chain trigger is now `bind: "smart_interact"`. Examples and tests updated.
|
||||
|
||||
@ -78,11 +78,11 @@ Do not mash. A second interact while they are still pathing is how characters ru
|
||||
|
||||
If they stop short, raise `walk_delay_ms` (2500–4000), or use `interact.style: auto` (CTM stays on), or `interact.style: hold`.
|
||||
|
||||
## Smart interact shortcut (`bind: interact`)
|
||||
## Smart interact shortcut (`bind: smart_interact`)
|
||||
|
||||
The example profile's `loot` map (Alt+G) and `interact` map (Alt+I) both use a **smart shortcut**: a single user keypress fires the full chain (CTM on → Interact with Target → sleep `walk_delay_ms` → CTM off). It is what ISBoxer did with a "Mapped Key" — you press one key, the multibox software sends the whole chain.
|
||||
|
||||
In enBoxer the shortcut is `bind: interact` in a step:
|
||||
In enBoxer the shortcut is `bind: smart_interact` in a step:
|
||||
|
||||
```yaml
|
||||
- name: loot
|
||||
@ -90,7 +90,7 @@ In enBoxer the shortcut is `bind: interact` in a step:
|
||||
steps:
|
||||
- bind: assist
|
||||
target: others
|
||||
- bind: interact # <-- smart shortcut
|
||||
- bind: smart_interact # <-- smart shortcut
|
||||
target: others
|
||||
```
|
||||
|
||||
|
||||
@ -40,7 +40,7 @@ Visible-pixel capture: `grim` (default). Overlay: `mpv --wayland-app-id=enboxer-
|
||||
|
||||
## Smart interact shortcut
|
||||
|
||||
`bind: interact` in any map step expands at compile time into the full chain
|
||||
`bind: smart_interact` in any map step expands at compile time into the full chain
|
||||
(CTM on → Interact with Target → walk delay → CTM off), driven by
|
||||
`profile.interact` (`style` + `walk_delay_ms`). This is the ISBoxer Mapped
|
||||
Key analog — one user keypress, four keystrokes dispatched to every captured
|
||||
|
||||
@ -114,7 +114,7 @@ maps:
|
||||
steps:
|
||||
- bind: assist
|
||||
target: others
|
||||
- bind: interact
|
||||
- bind: smart_interact # full chain (use "interact" for a single Alt+J send)
|
||||
target: others
|
||||
- name: loot_manual
|
||||
# Same idea as `loot` but composed by hand. Pick this form if you want to
|
||||
@ -127,7 +127,7 @@ maps:
|
||||
target: others
|
||||
- bind: ctm_on
|
||||
target: others
|
||||
- bind: interact
|
||||
- bind: interact # single Alt+J send (NOT the smart shortcut)
|
||||
target: others
|
||||
- delay_ms: 5000
|
||||
- bind: ctm_off
|
||||
@ -140,7 +140,7 @@ maps:
|
||||
steps:
|
||||
- bind: ctm_on
|
||||
target: others
|
||||
- bind: interact
|
||||
- bind: interact # single Alt+J send (NOT the smart shortcut)
|
||||
target: others
|
||||
release_steps:
|
||||
- bind: ctm_off
|
||||
|
||||
@ -205,11 +205,14 @@ impl Engine {
|
||||
out.push(Action::Sleep(Duration::from_millis(ms)));
|
||||
continue;
|
||||
}
|
||||
// ISBoxer-style Mapped Key shortcut: `bind: "interact"` fires the
|
||||
// full CTM-toggle + Interact-with-Target + (optional) wait + CTM-off
|
||||
// chain driven by profile.interact (style + walk_delay_ms).
|
||||
// ISBoxer-style Mapped Key shortcut: `bind: "smart_interact"` fires
|
||||
// the full CTM-toggle + Interact-with-Target + (optional) wait +
|
||||
// CTM-off chain driven by profile.interact (style + walk_delay_ms).
|
||||
// The user only pressed the map hotkey; the daemon composes the chain.
|
||||
if step.bind.as_deref() == Some("interact") {
|
||||
// For per-step control, use `bind: "interact"` to send a single
|
||||
// Interact-with-Target keystroke (game_binds.interact = Alt+J) and
|
||||
// compose ctm_on / ctm_off / walk_delay_ms yourself.
|
||||
if step.bind.as_deref() == Some("smart_interact") {
|
||||
let slots = self.resolve_targets(&step.target, &map_name)?;
|
||||
let interact_key = self
|
||||
.profile
|
||||
@ -352,7 +355,7 @@ mod tests {
|
||||
target: "others".into(),
|
||||
},
|
||||
Step {
|
||||
bind: Some("interact".into()),
|
||||
bind: Some("smart_interact".into()),
|
||||
key: None,
|
||||
delay_ms: None,
|
||||
target: "others".into(),
|
||||
@ -505,6 +508,37 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interact_simple_sends_only_alt_j() {
|
||||
// After the smart_interact split, `bind: "interact"` is a single
|
||||
// Alt+J send (game_binds.interact = "g"). No CTM toggle, no sleep,
|
||||
// no second send. Use this from manual chains or release_steps.
|
||||
let mut e = sample();
|
||||
let map = crate::profile::Map {
|
||||
name: "interact_simple".into(),
|
||||
hotkey: Hotkey("Alt+U".into()),
|
||||
hold: false,
|
||||
steps: vec![crate::profile::Step {
|
||||
key: None,
|
||||
bind: Some("interact".into()),
|
||||
delay_ms: None,
|
||||
target: "others".into(),
|
||||
}],
|
||||
release_steps: vec![],
|
||||
};
|
||||
e.profile.maps.push(map);
|
||||
let acts = e.fire("Alt+U", Hold::Tap).unwrap();
|
||||
assert_eq!(acts.len(), 1, "exactly one action: {acts:?}");
|
||||
match &acts[0] {
|
||||
Action::Send { key, slots, hold } => {
|
||||
assert_eq!(key, "g");
|
||||
assert_eq!(*hold, Hold::Tap);
|
||||
assert_eq!(slots, &vec![2, 3]);
|
||||
}
|
||||
other => panic!("expected Send, got {other:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interact_smart_shortcut_standard_emits_full_sequence() {
|
||||
// bind: "interact" should fire CTM-on, Interact with Target,
|
||||
@ -518,7 +552,7 @@ mod tests {
|
||||
hold: false,
|
||||
steps: vec![crate::profile::Step {
|
||||
key: None,
|
||||
bind: Some("interact".into()),
|
||||
bind: Some("smart_interact".into()),
|
||||
delay_ms: None,
|
||||
target: "others".into(),
|
||||
}],
|
||||
@ -555,7 +589,7 @@ mod tests {
|
||||
hold: false,
|
||||
steps: vec![crate::profile::Step {
|
||||
key: None,
|
||||
bind: Some("interact".into()),
|
||||
bind: Some("smart_interact".into()),
|
||||
delay_ms: None,
|
||||
target: "others".into(),
|
||||
}],
|
||||
@ -585,7 +619,7 @@ mod tests {
|
||||
hold: true,
|
||||
steps: vec![crate::profile::Step {
|
||||
key: None,
|
||||
bind: Some("interact".into()),
|
||||
bind: Some("smart_interact".into()),
|
||||
delay_ms: None,
|
||||
target: "others".into(),
|
||||
}],
|
||||
|
||||
Loading…
Reference in New Issue
Block a user