Warframe Spam Macros (including Slide-Attack)

Post gaming related scripts
Arsonistic
Posts: 20
Joined: 10 Oct 2019, 13:51

Warframe Spam Macros (including Slide-Attack)

17 Oct 2019, 20:41

I rarely update the code or respond to comments here, refer to the Gist for that: gist.github.com/KarlRamstedt/758553272a042c4a94bef02ab5bdec2c

Contagion: Alt+Q to throw an Exodia Contagion projectile. FPS-dependent, look at code for details.
Slide-Attack: Shift+LeftAlt(+movement in any direction) to trigger. Hold for spam. Shift+PageUp/Down to change delay between attacks (Warframe uses a queue-system for melee attacks; if spammed too quick you can get normal attacks in between slide-attacks).
Attack-Spam: Ctrl+L to toggle On/Off. When on, just hold Melee or Primary-Fire to spam these up to 20 times per second (semi-auto weapons are limited to ~10/sec by the game).
Ability-Spam: AltGr+AbilityButton(1-4) to toggle On/Off. Win+AbilityButton to select ability for modification. AltGr+PageUp/Down to adjust spam delay. Win+PageUp/Down to change increment for delay changes. Example use-case: Rest Equinox Adaro. Press Win+2, hold down AltGr+PgDn until delay is 500ms, then press AltGr+2 to activate it.
NW-Skip: Alt+X to skip transmission dialogue. Requires Windowed/"Borderless Fullscreen" for mouse movement.

Additional utility hotkeys (toggles):
Disable Hotkeys: Ctrl+P
Pause Script Execution: Win+P

Notes
- Tooltips will tab out if in Fullscreen (but not in Windowed/"Borderless Fullscreen"), so remove them if you need to use Fullscreen (Find&Replace all CenteredToolTip(" with ;CenteredToolTip(" should work).
- The script uses the front thumb-button on the mouse for melee by default. To change key to (for example) E, just replace all instances of XButton2 with e (letters need to be small, see below for why).
- Sending large letters (like E instead of e) will make AHK send Shift+Letter to make the letter large, potentially triggering a roll if you're using a combined Roll/Sprint key.
- Non-EU keyboard layouts may lack an AltGr key, for most of these the Right Alt key should work. If that doesn't work try replacing all instances of <^>!(AltGr modifier) with >!(Right Alt modifier) or !(Alt modifier).
- You can easily add and remove "Spam" keys by adding/removing keys to/from the spamHotkeys array.

Disclaimer
DE's stance on third-party software is (paraphrasing)"Use external software at your own risk", but that said, many players(including prominent Warframe Partners) have been using macros for years without issues.
DE Support on their stance on macros (this exact statement has been the standard copy-paste for most support responses):
What we do not tolerate[...] is complete automation, such as auto aiming, targeting, leaving your Warframe farming for kills or any action that could remove the human element from the game.
References:
forums.warframe.com/topic/1105960-third-party-software-and-you-a-psa/
forums.warframe.com/topic/607708-about-using-macros/

Basically, as long as the macro doesn't play the game for you(essentially a bot), it should be fine.
I will never add functionality that goes clearly against those guidelines.
This script is made to help you play the game, not to play the game for you.

Code: Select all

#NoEnv ; For performance and compatibility with future AutoHotkey releases
SendMode Input ; For speed and reliability
SetBatchLines -1 ; No script sleep, for more consistent timing behavior. Default behavior is 10ms execution then 10ms sleep
ListLines Off ; Increase performance by a few percent by not logging the lines of code that are executed

; Modifiers: [+ = Shift] [^ = Ctrl] [# = Win] [! = Alt] [* = Ignores modifiers] [~ = Also uses original function] [$ = Forces hook, preventing hotkey from triggering itself] More info here: https://www.autohotkey.com/docs/KeyList.htm
; All time values listed are in ms(MilliSeconds), which are 1/1000 of a second. 1000/delay = activationsPerSecond. I.e: 50ms delay -> 1000/50 = 20 per sec
; Time values are typically rounded up to a multiple of 10ms by the Windows time-keeping system. So there's no point to Timer/Sleep values that aren't multiples of 10. Higher precision may be achieved via Loop+DllCall, but is rarely relevant and certainly doesn't matter for this script

global slideDelay := 110 ; 110 achieves max movement speed with Balla (with extremely high attack speed). Use higher delay for slower attack speeds. Too low a delay can yield normal, non-slide attacks. To find out the sweetspot for your weapon, see if you execute any non-slide attacks, then increase delay incrementally until they stop

global crouchDelay := 250 ; 125ms between notes for Octavia tracks

global abilitySpam := [false, false, false, false]
global abilityDelay := [500, 9000, 15000, 2000] ; Delay between activations for ability 1, 2, 3 and 4, respectively
global delayToModify := 4
global incrementIncrement := 50
global abilityDelayIncrement := 500
global abilityKeys := ["1", "2", "3", "4"] ; Keybind for each respective ability key. Change these to be the same as your ingame keybinds

#IfWinActive ahk_exe Warframe.x64.exe ; Only trigger hotkeys when Warframe is the active window
Hotkey, IfWinActive, ahk_exe Warframe.x64.exe ; Same, but for dynamically created hotkeys

global BoundFuncCache := {} ; A collection of bound functions for use in Timer stopping. Func(f).Bind(k) seems to create an object and return a reference to it, without caching the result, so manual caching is required to reference the same object

for i, key in abilityKeys {
	toggleAbilityBF := Func("ToggleAbilitySpam").Bind(key)
	Hotkey, % "*<^>!" . key, % toggleAbilityBF ; AltGr+AbilityKey to toggle spam for that ability
	selectBF := Func("SelectAbilityToModify").Bind(key)
	Hotkey, % "#" . key, % selectBF ; Win+AbilityKey to select ability for modification of delay
	BoundFuncCache[key] := Func("CastAbility").Bind(key)
}

SelectAbilityToModify(key){
	delayToModify := IndexOf(abilityKeys, key)
	DisplayAbilityDelay()
}

ToggleAbilitySpam(key){
	i := IndexOf(abilityKeys, key)
	abilitySpam[i] := !abilitySpam[i]
	if (abilitySpam[i]){
		CenteredToolTip("Ability " . i . " Spam On (Delay: " . abilityDelay[i] . "ms)") ; Periods concatenate strings
		Send, % "{Blind}{" . key . "}"
		tmp := BoundFuncCache[key] ; SetTimer doesn't support function references in expression mode, requiring a temporary variable and regular variable dereferencing
		SetTimer, %tmp%, % abilityDelay[i]
	} else {
		CenteredToolTip("Ability " . i . " Spam Off")
		tmp := BoundFuncCache[key]
		SetTimer, %tmp%, Off
	}
}
CastAbility(key){
	if (WinActive("ahk_exe Warframe.x64.exe"))
		Send, % "{Blind}{" . key . "}" ; {Blind} fixes issues with a combined Sprint+Roll key; Without {Blind}, holding down Shift during a Send command will send {Shift Up}, then the key and then {Shift Down}, causing unintentional rolling
}

global spam := false
spamHotkeys := ["LButton", "XButton2", "MButton"] ; Hold one of these to spam that key. Just add a key to the array to automatically make it a new spam hotkey (same goes for removing)

for i, key in spamHotkeys { ; Creates hotkeys for each key in the array above
	BoundFuncCache[key] := Func("SendBlind").Bind(key)
	Hotkey, IfWinActive ; Make StopSpam work outside of Warframe to avoid button getting stuck when clicking on a different window
	stopSpamBF := Func("StopSpam").Bind(BoundFuncCache[key])
	Hotkey, % "~*" . key . " Up", % stopSpamBF
	Hotkey, IfWinActive, ahk_exe Warframe.x64.exe ; Re-enable condition
	spamBF := Func("Spam").Bind(key) ; Bind(BoundFunc) the Key to the Spam function to use it as input for the Hotkey Command
	Hotkey, % "$*" . key, % spamBF ; $ to ensure Hotkeys can't trigger themselves
}

Spam(key){
	Send, % "{Blind}{" . key . " Down}" ; Required because ~ can't be used with KeyWait for blocking Auto-Repeat
	if (spam){
		tmp := BoundFuncCache[key] ; SetTimer doesn't support function references in expression mode, requiring a temporary variable and regular variable dereferencing
		SetTimer, %tmp%, 50 ; Delay between activations in ms. 50ms = 20 times per second. Should be good for most use-cases
		KeyWait, % key
	}
}
StopSpam(boundFunc){
	SetTimer, %boundFunc%, Off
}
SendBlind(key){ ; Function-wrapper for the Send Command
	Send, % "{Blind}{" . key . "}"
}

^L:: ; Ctrl+L toggles Spam On/Off
	spam := !spam
	if (spam)
		CenteredToolTip("Spam On")
	else
		CenteredToolTip("Spam Off")
return

MeleeAttack(){
	Send, {Blind}{XButton2} ; Melee key. Replace with the key you use
}
*!Q:: ; Alt+Q to throw Contagion. Most of the delays(Sleep) need to be longer than 2 frames, which at 60FPS is 2/60 = 33.33ms, i.e: 40 delay. Increase delay to 70 if you can't keep FPS above 60
	Send, {Blind}{Space}
	Sleep, 40 ; Too short delay = throw fizzles (no throw)
	Send, {Blind}{Space}
	Sleep, 1 ; Without a minimal delay here the throw fizzles if you don't have your melee out
	Send, {Blind}{RButton Down}
	Sleep, 40 ; Too short delay = aim-glide gets stuck
	MeleeAttack()
	Sleep, 40 ; ONLY NEEDED AS CLIENT. Too short delay = throw fizzles
	Send, {Blind}{RButton Up}
return

; Shift+PageUp/Down to adjust delay between Slide-Attacks. Warframe uses a queue system for melee inputs; too low a delay can yield normal, non-slide attacks
+PgUp::
	slideDelay := slideDelay+10
	CenteredToolTip("SlideDelay: " . slideDelay . "ms")
return
+PgDn::
	if (slideDelay > 10) ; Avoid 0 and negative values
		slideDelay := slideDelay-10
	CenteredToolTip("SlideDelay: " . slideDelay . "ms")
return

*+LAlt:: ; Triggers with Shift+LeftAlt, then keeps attacking while LeftAlt is held down
	SlideAttack()
	SetTimer, SlideAttack, %slideDelay%
	KeyWait, LAlt
return
~*LAlt Up::
	SetTimer, SlideAttack, Off
return
SlideAttack(){
	Send, {LCtrl Down} ; Crouch key. {Blind} is not used because it causes Alt to sometimes get stuck logically down
	MeleeAttack()
	Send, {LCtrl Up} ; No delay needed between Crouch down and up. Has the bonus of removing the "shake" of spam-crouching
}

; Alt+PageUp/Down to adjust delay between crouches
!PgUp::
	crouchDelay := crouchDelay+10
	CenteredToolTip("CrouchDelay: " . crouchDelay . "ms")
return
!PgDn::
	if (crouchDelay > 10)
		crouchDelay := crouchDelay-10
	CenteredToolTip("CrouchDelay: " . crouchDelay . "ms")
return

*!C:: ; Alt+C to spam crouch
	Send, {Blind}{LCtrl Down}
	SetTimer, CrouchSpam, %crouchDelay%
	KeyWait, C
return
~*C Up::
	Send, {Blind}{LCtrl Up}
	SetTimer, CrouchSpam, Off
return
CrouchSpam(){
	Send, {Blind}{LCtrl Up}
	Sleep, 1
	Send, {Blind}{LCtrl Down}
}

DisplayAbilityDelay(){
	CenteredToolTip("Ability " . delayToModify . " Delay: " . abilityDelay[delayToModify] . "ms")
}

; AltGr+PageUp/Down to adjust delay between ability activations
<^>!PgUp::
	abilityDelay[delayToModify] := abilityDelay[delayToModify]+abilityDelayIncrement
	DisplayAbilityDelay()
	if (abilitySpam[delayToModify]){
		tmp := BoundFuncCache[abilityKeys[delayToModify]]
		SetTimer, %tmp%, % abilityDelay[delayToModify] ; Update running timers
	}
return
<^>!PgDn::
	if (abilityDelay[delayToModify] > abilityDelayIncrement) ; Avoid 0 and negative values
		abilityDelay[delayToModify] := abilityDelay[delayToModify]-abilityDelayIncrement
	DisplayAbilityDelay()
	if (abilitySpam[delayToModify]){
		tmp := BoundFuncCache[abilityKeys[delayToModify]]
		SetTimer, %tmp%, % abilityDelay[delayToModify]
	}
return

; Win+PageUp/Down to adjust increment for adjusting delay between ability activations
#PgUp::
	abilityDelayIncrement := abilityDelayIncrement+incrementIncrement
	CenteredToolTip("Ability Delay Increment: " . abilityDelayIncrement . "ms")
return
#PgDn::
	if (abilityDelayIncrement > incrementIncrement)
		abilityDelayIncrement := abilityDelayIncrement-incrementIncrement
	CenteredToolTip("Ability Delay Increment: " . abilityDelayIncrement . "ms")
return

!X:: ; Alt+X to skip transmission dialogue (AKA "Nightwave skip"). Made for 16:9 aspect ratios, change the MouseMove if your screen isn't 16:9 so the cursor lands on the Nightwave banner
	Send, {Esc}
	Sleep, 444 ; Wait for transition animation
	MouseMove, % A_ScreenWidth*0.85, % A_ScreenHeight*0.87, 0 ; Use relative location rather than absolute so that it works with any 16:9 resolution. NOTE: Mouse Movement doesn't work in fullscreen mode
	Sleep, 1 ; Needs delay between movement and Click
	Click, down
	Sleep, 1 ; Needs separate up and down events, otherwise the UI doesn't register the click
	Click, up ; Essentially: Send, {Blind}{LButton Up}
	Sleep, 444 ; Wait for transition animation
	Send, {Esc}
return

CapsLock::5 ; Remaps CapsLock to 5. I'm using CapsLock as Transference key

#IfWinActive ; The next hotkeys work outside of Warframe too

^P::Suspend ; Ctrl+P toggles hotkeys On/Off
*#P::Pause ; Win+P toggles execution Pause
<^>!R::Reload ; AltGr+R reloads script

CenteredToolTip(text, duration = 999){ ; Duration in ms (MilliSeconds). Default value can be optionally overridden
	ToolTip, %text%, A_ScreenWidth/2, A_ScreenHeight/2
	SetTimer, RemoveToolTip, -%duration% ; Negative to only trigger once
}
RemoveToolTip(){
	ToolTip
}

IndexOf(array, item){ ; Returns the index of the first item matching the input item
	for i in array
		if (array[i] == item)
			return i
}
Last edited by Arsonistic on 08 Mar 2021, 20:17, edited 1 time in total.
WhiskeyJack_98
Posts: 2
Joined: 03 Nov 2019, 06:23

Re: Warframe Macros (including Slide-Attack Macro)

03 Nov 2019, 06:31

hi, since slide attack was nerfed this past update, i was wondering if you can help me. I was hoping you can create a simple script for spam "e" for melee. The action im referring to is I wanted to Hold E in order for continous melee... thank you
jensenbeach
Posts: 1
Joined: 15 Dec 2018, 22:33

Re: Warframe Macros (including Slide-Attack Macro)

15 Nov 2019, 04:33

yes i would love a script for spamming "e" for melee for orthos prime :)
Arsonistic
Posts: 20
Joined: 10 Oct 2019, 13:51

Re: Warframe Spam Macros (including Slide-Attack)

09 Mar 2021, 10:39

@jensenbeach @WhiskeyJack_98
That functionality is now included in the script here. But that has already been on the Gist page for over a year :P
Let me reiterate: I rarely update the code or respond to comments here, refer to the Gist for that: gist.github.com/KarlRamstedt/758553272a042c4a94bef02ab5bdec2c

Return to “Gaming Scripts (v1)”

Who is online

Users browsing this forum: No registered users and 103 guests