Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/FNScence/CSAFAP-config-package/llms.txt

Use this file to discover all available pages before exploring further.

The CSAFAP Config Package uses AveYo’s ticker system to execute alias chains every frame, enabling binds that require frame-perfect timing. This system is critical for jumpthrow binds, null movement, and rapid-fire mechanics.

What is the Ticker?

The ticker is a .vtest script file that runs every frame, calling specific aliases at precise intervals. It leverages CS2’s -testscript launch option to execute code outside the normal command queue.

Launch Option Requirement

From README.md installation (csafap/addons/.vtest:2):
-testscript "../../csgo/cfg/CSAFAP/addons/.vtest"
This tells CS2 to execute .vtest file continuously during gameplay.

The .vtest File

From csafap/addons/.vtest:
/// Credit and thanks to AveYo
/// use launch option: -testscript "../../csgo/cfg/CSAFAP/addons/.vtest"

Test_WaitForCheckPoint frame_end

W!
W!
A!
A!
S!
S!
D!
D!

M1!
M2!

CJ!
CJ!

JT!
JT!
JT!
JT!

J!

/// AveYo: add one or more to reduce fps impact at the cost of responsiveness
//Test_RunFrame

/// AveYo: loop each frame; repeated entries above are chaining multiple alias substitutions
Test_Run

How It Works

  1. Test_WaitForCheckPoint frame_end: Synchronizes to frame end
  2. Alias calls (e.g., W!, M1!, JT!): Execute in order
  3. Repeated calls: Chain multiple alias substitutions in single frame
  4. Test_Run: Loops back to beginning, running every frame
Key insight: Each alias (like W!) is called twice because a single alias substitution can only change one level deep per frame. Calling twice allows chained state transitions.

Jumpthrow Implementation

Basic Jumpthrow

From csafap/addons/AveYo.cfg:4-7:
alias +JumpThrow alias JT! JT+1; 
alias -JumpThrow alias JT! JT-1; 
alias JT! ""

alias JT+1 "M1>; alias JT! JT+2"; 
alias JT+2 "M2>; alias JT! JT+3"; 
alias JT+3 "alias JT!; +jump"

alias JT-1 "jump -9999 f u; alias JT!"
State Machine Flow: On key press (+JumpThrow):
  1. Set JT! to JT+1
  2. Next frame: Ticker calls JT! → executes JT+1 → calls M1> (release attack1), sets JT! to JT+2
  3. Next frame: Ticker calls JT! → executes JT+2 → calls M2> (release attack2), sets JT! to JT+3
  4. Next frame: Ticker calls JT! → executes JT+3 → activates +jump, clears JT!
On key release (-JumpThrow):
  1. Set JT! to JT-1
  2. Next frame: Ticker calls JT! → executes JT-1 → deactivates jump with jump -9999 f u, clears JT!
Result: The grenade releases exactly when jump activates, replicating CS:GO’s jumpthrow timing.

W-Jumpthrow

From csafap/addons/AveYo.cfg:9-13:
alias +WJumpThrow alias JT! WT+1; 
alias -WJumpThrow alias JT! WT-1; 
alias JT! ""

alias WT+1 "+forward; alias JT! WT+2"; 
alias WT+2 "M1>; alias JT! WT+3"; 
alias WT+3 "M2>;alias JT! WT+4"
alias WT+4 "alias JT!;+jump"

alias WT-1 "forward -9999 f u; alias JT! WT-2"; 
alias WT-2 "alias JT!; jump -9999 f u"
Adds forward movement before jump:
  1. Frame 1: +forward
  2. Frame 2: Release M1>
  3. Frame 3: Release M2>
  4. Frame 4: +jump
On release:
  1. Frame 1: Cancel forward movement
  2. Frame 2: Cancel jump

Mouse Button Ticker Integration

Jumpthrow requires special mouse binds (csafap/addons/AveYo.cfg:15-20):
// Jumpthrow bind requirements: bind MOUSE1 +M1; bind MOUSE2 +M2

alias +M1 alias M1! M1+; 
alias -M1 alias M1! M1-; 
alias M1! ""; 
alias M1> ""

alias M1+ "alias M1!; alias M1> -attack; +attack"; 
alias M1- "alias M1!; alias M1>; attack -9999 f u; spec_next"

alias +M2 alias M2! M2+; 
alias -M2 alias M2! M2-; 
alias M2! ""; 
alias M2> ""

alias M2+ "alias M2!; alias M2> -attack2; +attack2"; 
alias M2- "alias M2!; alias M2>; attack2 -9999 f u; spec_prev"
How M1> and M2> work:
  • When you click mouse1, +M1 sets M1> to -attack
  • When jumpthrow calls M1>, it executes -attack (releases grenade)
  • After release, M1> is cleared back to empty
Important: spec_next and spec_prev preserve spectator functionality when mouse buttons are released.

Null Movement Binds

From csafap/addons/AveYo.cfg:27-42:
// Null binds: bind W +nullW; bind A +nullA; bind S +nullS; bind D +nullD

alias +nullW alias W! W+1; 
alias -nullW alias W! W-1; 
alias W! ""; 
alias W< ""; 
alias W> ""

alias W+1 "W<; alias W! W+2"; 
alias W+2 "alias W!; alias S< forward -9999 f u; alias S> +forward; +forward"

alias W-1 "forward -9999 f u; alias W! W-2"; 
alias W-2 "alias W!; alias S< +back; alias S>; W>"
State Machine Logic: When W is pressed:
  1. +nullW sets W! to W+1
  2. Next frame: W+1 calls W< (empty initially), sets W! to W+2
  3. Next frame: W+2 activates +forward, and sets S< and S> aliases:
    • S< = cancel forward movement
    • S> = activate forward movement
When S is pressed while W is held:
  1. +nullS triggers similar chain
  2. Calls W< which now equals forward -9999 f u (from S’s setup)
  3. Cancels forward movement instantly
  4. Activates backward movement instead
Result: Pressing opposite direction keys cancels the first key’s action, enabling “Snap-Tap” null movement.

Why Dual Aliases (< and >)

  • W</S</A</D<: Called by opposite key to cancel current movement
  • W>/S>/A>/D>: Called on key release to restore previous movement state
This creates proper priority: last pressed key wins.

Crouch Jump

From csafap/addons/AveYo.cfg:22-25:
alias +CrouchJump alias CJ! CJ+; 
alias -CrouchJump alias CJ! CJ-; 
alias CJ! ""

alias CJ+ "+duck; alias CJ! CJ++"; 
alias CJ++ "+jump; alias CJ!"
alias CJ- "duck -9999 f u; alias CJ! CJ--"; 
alias CJ-- "alias CJ!; jump -9999 f u"
On press:
  1. Frame 1: +duck
  2. Frame 2: +jump
On release:
  1. Frame 1: Cancel duck
  2. Frame 2: Cancel jump
Ensures crouch activates one frame before jump for maximum height.

Performance Impact

From csafap/addons/.vtest:28-29:
/// AveYo: add one or more to reduce fps impact at the cost of responsiveness
//Test_RunFrame
Options:
  • No Test_RunFrame: Runs every frame (highest responsiveness, small FPS cost)
  • One Test_RunFrame: Runs every 2nd frame (lower responsiveness, better FPS)
  • Multiple Test_RunFrame: Further reduces frequency
Default configuration omits Test_RunFrame for maximum responsiveness.

Ticker vs. Radio Wheel Binds

The CSAFAP package uses two different bind systems:
FeatureTicker BindsRadio Wheel Binds
Implementation.vtest + AveYo.cfglogic.cfg alias chains
Use CaseFrame-perfect timingMulti-phase selection
ExamplesJumpthrow, null WASDLine-up selection, pro crosshairs
Frame Precision✅ Yes❌ No
State PersistenceCleared each framePersists across frames
Launch OptionRequiredNot required

Common Issues

Console Spam: Unknown command: W!...

From README.md Q20: Cause: The ticker aliases (W!, M1!, etc.) aren’t initialized before the .vtest script starts. Solution:
  1. Ensure +exec csafap/main is in launch options
  2. Check for long alias commands that might break the exec queue
  3. Verify .vtest file has correct name (literally .vtest, not vtest.vtest)

Movement/Mouse Buttons Don’t Work

From README.md Q21: Cause: Same as console spam - ticker initialized before binds loaded. Solution:
  1. Remove -testscript from launch options temporarily
  2. Check console for errors after exec csafap/main
  3. Fix any alias that’s too long or malformed
  4. Add -testscript back once all aliases load successfully

Rapid Fire/Follow Recoil Not Working

From README.md Q18: Framerate dependency:
  • Default config requires 150+ FPS
  • For <150 FPS: rename rapid_followrecoil_lessthan150FPS.cfg to rapid_followrecoil.cfg
Ticker timing is frame-dependent, so low FPS breaks frame-perfect sequences.

Technical Deep Dive

Why -9999 f u?

Commands like jump -9999 f u instantly deactivate the command:
  • The -9999 is an extreme negative value
  • f u are flags (exact meaning undocumented by Valve)
  • Together they force immediate deactivation, overriding any queued actions

Alias Substitution Depth Limit

CS2 only allows one level of alias substitution per frame. Example:
alias test1 "alias test2 new_value"
alias test2 "old_value"
test1  // Sets test2 to new_value
test2  // Still executes old_value in the same frame!
This is why .vtest calls each alias twice - the first call changes the alias, the second call executes the new value.

Frame Timing

  • frame_end: Ticker runs after game logic but before rendering
  • Render time: ~6-16ms at 60-165 FPS
  • Ticker overhead: <0.1ms per frame
This ensures ticker actions take effect before the next frame’s input processing.

Advantages Over Multi-Input Binds

Valve patched multi-input binds (Oct 28, 2024) where bind key "+action1; +action2" would only execute first action. Ticker system bypasses this by:
  1. Storing state in aliases (e.g., JT!)
  2. Ticker executing state machine steps across multiple frames
  3. Each frame issues only one +action, legal per Valve’s rules
This is why jumpthrow still works post-patch while old methods don’t.

Build docs developers (and LLMs) love