Difference between revisions of "SAR"

From P2SR Wiki

(bugfix is out)
m
 
(101 intermediate revisions by 7 users not shown)
Line 1: Line 1:
 
{{P2_Infobox|Source Auto Record (SAR)|NeKz.jpg|
 
{{P2_Infobox|Source Auto Record (SAR)|NeKz.jpg|
*''Blenderiste09's SAR'' [https://github.com/Blenderiste09/SourceAutoRecord/releases/latest Latest Version]
+
*''GitHub Repo'' [https://s.portal2.sr/sar Latest Stable Release]
*''Latest Console Variables'' [https://github.com/Blenderiste09/SourceAutoRecord/blob/pre-release/doc/cvars.md Latest cvars.md]
+
*''Latest Console Variables'' [https://github.com/p2sr/SourceAutoRecord/blob/master/docs/cvars.md Latest cvars.md]
*''NeKz Official Release'' [https://github.com/NeKzor/SourceAutoRecord/releases  OUTDATED]
 
 
}}
 
}}
  
Source Auto Record is a Portal 2 Plugin developed by [[NeKz]]. The plugin is widely used by most if not all Portal 2 speedrunners across all different categories. It adds a wide variety of useful commands, and quality of life improvements that make running the game easier, and at times, more accurate.  
+
Source Auto Record is a Portal 2 plugin originally developed by [[NeKz]]. The plugin is used by almost all Portal 2 speedrunners, and is highly recommended if you want to speedrun the game. It adds a wide variety of useful commands, and Quality of Life improvements that make running the game easier, and at times, more accurate.  
  
 
==How to install==
 
==How to install==
 +
''Main Article: [[Plugins#How to install plugins|How to install plugins]]''
  
SAR is very easy to install and use. To install, start by downloading your desired version from github (Linked in the info box at the top).  
+
# Download either <code>sar.dll</code> or <code>sar.so</code> depending on whether you're on Windows or Linux respectively.
 +
# It is also recommended to download the <code>sar.pdb</code> file on Windows, as it expands on crash logs if Portal 2 were to crash.
 +
# Place the downloaded files into <code>(steam installation)\steamapps\common\Portal 2</code>.
  
===Windows Firewall Issues===
+
Note: [[Portal 2 Speedrun Mod]] (P2SM) and other Sourcemods use SAR for timing as well, but these mods read from your base game install, so you do not need any special installation for SAR with P2SM. Just install SAR normally for Portal 2. However, full mods like Portal Stories: Mel require SAR to be installed manually.
  
It's important to note that Windows often doesn't trust .dll files from github. There is a chance that downloads of this plugin will result in windows defender or other anti-virus programs automatically deleting the file. You will need to go and manually add exceptions for the file in any directory you keep it in (more than likely the downloads folder, and your portal2 folder).
+
== Speedrun Timer ==
  
===Loading SAR in Portal 2===
+
One of SAR's main uses is for timing runs. SAR will interface with LiveSplit (or other speedrun timing programs that support it), and automatically start/split/stop runs. This is done through the <code>sar_speedrun</code> category of commands. Most these commands are fairly self explanatory; the most important ones are below.
  
Portal 2 can load .dll (Windows) or .so (Linux) plugins through the console command <code>plugin_load pluginname</code>. This command will search the default directory of <code>\steamapps\common\Portal 2</code> and <code>\steamapps\common\Portal 2\portal2</code>, so your <code>\Portal 2</code> folder, or <code>\portal2</code> folder is where you will want to place SAR.
+
* <code>sar_speedrun_category <name></code> - sets the category being run (affects how the run timing starts and stops). '''This only applies once you load a map.'''
  
====Notes====
+
* <code>sar_speedrun_offset <ticks></code> - offsets the timer by a certain amount at the start of the run. Used, for instance, with Vault Save.
*Ensure that SAR is installed in your actual install location. Be sure to check this by browsing local files through the steam properties of the game.
 
*All plugins are unloaded after the game is closed. Every time you reopen Portal 2, the plugin will be unloaded, it is recommended you add the <code>plugin_load sar</code> line to your [[autoexec]] so that you will not need to reload the plugin every time you launch the game.
 
*[[Portal 2 Speedrun Mod]] (P2SM) uses SAR for timing as well. But the mod reads from your base game install, so you do not need any special installation for SAR with p2sm. Just install SAR normally for portal 2.
 
  
===Configuring with Livesplit===
+
* <code>sar_speedrun_time_pauses <0|1></code> - affects whether pauses are timed. You are allowed to omit pauses if you do not use them to gain an advantage.
  
.asl files are used to interface with livesplit, so using sar with livesplit is fairly simple following these steps.
+
* <code>sar_speedrun_smartsplit <0|1></code> - enabled by default. Will prevent SAR from splitting on maps which you have previously entered in this run. Should be disabled in coop runs!
  
1. Create a new file called sar.asl (the folder does not matter as long as you can find it), or alternatively, download the already made file from the Resources page on [https://www.speedrun.com/portal_2/resources Speedrun.com]
+
* <code>sar_speedrun_reset</code> - resets a run in preparation for another.
  
2. Copy and Paste the information from [https://raw.githubusercontent.com/NeKzor/SourceAutoRecord/livesplit/SAR.asl this link] into the file, and save it.
+
=== Custom Categories ===
  
3. Open Livesplit with Portal 2 splits (splits can be found at [https://www.speedrun.com/portal_2/resources here]).
+
SAR allows the creation of custom categories for speedruns based on entity inputs.
  
4. Right-click and select '''Edit Layout'''
+
sar_speedrun_category_create <categoryname>
 +
sar_speedrun_category_remove <categoryname>
 +
sar_speedrun_category_rule_create <rulename> <type> [option=value]... <map=map> <action=action>
 +
sar_speedrun_category_add_rule <categoryname> <rulename>
 +
sar_speedrun_category_remove_rule <categoryname> <rulename>
  
5. Select the large '''+''' icon at the top left.
+
There is a shorthand version of these commands used for creating MTriggers, which is
  
6. Go to '''Control'''
+
sar_speedrun_cc_start <categoryname> [map=map] [action=action]
 +
sar_speedrun_cc_rule <rulename> <type> [option=value]... [action=action]
 +
sar_speedrun_cc_finish
  
7. Select '''Scriptable Auto Splitter''' and enter the file directory (Ex: C:\Livesplit\Components\sar.asl)
+
SAR comes packed with some default speedrun categories, and for Portal 2, [https://github.com/p2sr/portal2-mtriggers this GitHub repository] contains custom categories for every map in the game, for use in CM.
  
8. Right click on Livesplit, and hover "'''Compare Against'''", and select "'''Game Time'''"
+
==== Rule Creation ====
 +
Rule types:
  
 +
* <code>load</code> - Rule triggers at the start of the level.
  
====Trouble Shooting====
+
* <code>zone <center=x,y,z> <size=x,y,z> <angle=degrees></code> - Rule triggers when any player enters the area specified by the center, size, and angle given. Size is on BOTH sides of the center, so the distance from the center to an edge is 1/2 of the given size.
  
*Livesplit sometimes needs to be ran as an admin on your machine to work. If Livesplit isn't updating, run Livesplit as an admin.
+
* <code>portal <center=x,y,z> <size=x,y,z> <angle=degrees> [portal=blue|orange]</code> - Like a zone, except for portals instead of players.
  
*Attempting to run Livesplit while Livesplit is still located in it's original ZIP file will cause issues, be sure to extract.
+
* <code>entity <targetname|classname=target> <inputname=input> [parameter=param]</code> - Rule triggers on the input of a specified 'target' entity. ''See also: [[#Entity Inputs|Entity inputs]]''. Note that if the name, input, or parameter includes any of these characters <code>(){}:'</code>, quotes must be put around the argument e.g. <code>targetname=@glados inputname=RunScriptCode "parameter=Success()"</code>
  
*Be sure to disable the Autosplitter built into to Livesplit through the <code>Edit Splits...</code> tab. This will interfere with SAR's autosplitter
+
* <code>fly</code> - Rule triggers when a player leaves a funnel with the [[Crouch Flying Glitch]].
  
*Ensure you haven't accidentally unchecked any of the options boxes in the settings for the Scriptable Autosplitter. (Start, Split & Reset)
+
* <code>flags</code> - Rule triggers when any player activates the CM flags.
  
*Make sure your livesplit '''SAR.asl''' file is an .asl file, and not a text file, and try remaking the file to ensure there are no issues.
+
* <code>end</code> - Rule ends when the map transitions to the next.
  
*On fresh windows installs, there can often be dependencies that aren't installed. If all steps have been followed, and SAR is still not loading, check your device drivers, and install other applications that are common on Windows machines (can include other games). Try installing these dependencies:
+
For any rule, the following options can be added:
  
*[https://www.microsoft.com/net/download/dotnet-framework-runtime DotNet Framework Runtime]
+
* <code>map</code> - Specifies that this rule must occur on the map specified.
  
*[https://aka.ms/vs/15/release/vc_redist.x86.exe VC_redist]
+
* <code>action</code> - Can be used to modify the timer. (<code>start</code>, <code>force_start</code>, <code>stop</code>, <code>split</code>, <code>pause</code>, <code>resume</code>)
  
<gallery widths=300px>
+
* <code>player</code> - Specifies a certain player must trigger the rule. Player 0 is blue.
File:AutoSplitterOptions.png|thumb|The options for the Scriptable Autosplitter (Should all be enabled)
 
File:DisableAuto.png|thumb|The default Livesplit Autosplitter (Should be disabled)
 
</gallery>
 
  
== Speedrun Timer ==
+
* <code>after</code> - Specifies that this rule must occur after the rule specified.
  
'''Note: as of SAR 1.12, the speedrun timer is now accurate in coop!'''
+
* <code>ccafter</code> - Same as <code>after</code>, except adds the category name to the beginning of the rule name. For use in the shorthand. e.g. <code>"ccafter=Flags 1"</code> in the category creation for Laser Crusher becomes <code>"after=Laser Crusher - Flags 1"</code>
  
One of SAR's main uses is for timing runs. SAR will interface with
+
When using the shorthand and a rule's map or action is not specified, it is inherited from the category. Every rule requires an action and a map.
LiveSplit (or other speedrun timing programs that support it), and
 
automatically start/split/stop runs. This is done through the
 
<code>sar_speedrun</code> category of commands. Most these commands are
 
fairly self explanatory; the most important ones are below.
 
  
* <code>sar_speedrun_category [name]</code>: sets the category being run (affects how the run timing starts and stops). '''This only applies once you load a map.'''
+
e.g. (Laser Crusher)
 +
sar_speedrun_cc_start "Laser Crusher" map=mp_coop_laser_crusher action=split
 +
sar_speedrun_cc_rule "Start" load action=force_start
 +
sar_speedrun_cc_rule "End Hop" zone center=2630.95,-1135.87,80.33 size=77.85,287.33,161.4 angle=0
 +
sar_speedrun_cc_rule "End Trigger Blue" entity targetname=team_door-team_proxy inputname=OnProxyRelay1
 +
sar_speedrun_cc_rule "End Trigger Orange" entity targetname=team_door-team_proxy inputname=OnProxyRelay3
 +
sar_speedrun_cc_rule "Flags 1" flags
 +
sar_speedrun_cc_rule "Flags 2" flags "ccafter=Flags 1" action=stop
 +
sar_speedrun_cc_finish
  
* <code>sar_speedrun_offset [ticks]</code>: offsets the timer by a certain amount at the start of the run. Used, for instance, with the Container Ride save.
+
In this example, all rules except <code>Start</code> and <code>Flags 2</code> inherit the action <code>split</code> from the category, and all rules inherit the map.
  
* <code>sar_speedrun_time_pauses [0/1]</code>: affects whether pauses are timed. You are allowed to omit pauses if you do not use them to gain an advantage.
+
=== Entity Inputs ===
  
* <code>sar_speedrun_smartsplit [0/1]</code>: enabled by default. Will prevent SAR from splitting on maps which you have previously entered in this run. Should be disabled in coop runs!
+
'''Note: This command exists for category creation purposes. It is not allowed in runs, and is therefore cheat protected.'''
  
* <code>sar_speedrun_reset</code>: resets a run in preparation for another.
+
Almost all events that occur in Source games are dictated by certain 'inputs' to entities in the map. For example, whenever the Blue robot gets near an exit door, the door receives the entity input <code>OnProxyRelay1</code>, which triggers a sound and lights up Blue's side of the indicator above the door. Many speedrun categories make use of these entity inputs as rules. In order to assist creation of these categories, you can toggle <code>sar_show_entinp <0|1></code>. This will show the entity inputs, and the tick they occurred on, in the developer console.
  
In fullgame runs, the timer offset used for the Container Ride save is '''16868''', so <code>sar_speedrun_offset 16868</code>.
+
== Demo Recording ==
 
 
=== Custom Categories ===
 
 
 
SAR 1.12 allows the creation of custom categories for sar_speedrun based
 
on entity inputs.
 
 
 
<code>sar_speedrun_category_create [name] [map] [entity] [input] [map] [entity] [input]</code>
 
 
 
<code>sar_speedrun_category_remove [name]</code>
 
 
 
To create a category, you give:
 
* The map in which the speedrun starts
 
 
 
* The entity and input which trigger the start of the run
 
 
 
* The map in which the speedrun ends
 
 
 
* The entity and input which trigger the end of the run
 
 
 
Entity names are targetnames by default, but a leading ! will cause it
 
to be treated as a classname instead. For instance, this is a small
 
custom category that times within Wakeup; from the start of the map to
 
placing Wheatley in his receptacle.
 
 
 
<code>sar_speedrun_category_create Wakeup sp_a1_wakeup !portal_stats_controller OnLevelStart sp_a1_wakeup socket_powered_rl Trigger</code>
 
 
 
This is a custom category named "Wakeup" which:
 
  
* Starts in Wakeup
+
If you are recording demos (for run verification or analysis), the command <code>sar_autorecord 1</code> will automatically begin recording a new demo every level load or restart. Make sure to start recording demos at the start of your run with <code>record demoname</code>, and stop recording '''after the timer stops''' with <code>stop</code>.
  
* Looks at the entity with classname <code>portal_stats_controller</code>
+
===== Demo Prefix =====
 
+
The command <code>sar_record_prefix</code> can be used to timestamp or prepend text to recorded demo names.
* Watches for its <code>OnLevelStart</code> input to start the timer
+
e.g. <code>sar_record_prefix "demo/%Y-%m-%d_%H-%M-%S_"</code> will put demos in the <code>demo</code> folder, and have Year, Month, Day, Hour, Minute, Second prefixed to it. e.g. <code>demo/2021-06-01_19-23-50_fullgame.dem</code><ref>https://cplusplus.com/reference/ctime/strftime/</ref> (fun trivia, that's the build time of SAR 1.12.3)
 
 
* Ends in Wakeup
 
 
 
* Looks at the entity with targetname <code>socket_powered_rl</code>
 
 
 
* Watches for its <code>Trigger</code> input to end the timer
 
 
 
== Demo Recording ==
 
 
 
If you are recording demos (for run verification or analysis), the command <code>sar_autorecord 1</code> will automatically begin recording a new demo every level load or restart. Make sure to start recording demos at the start of your run with <code>record demoname</code>, and stop recording after the timer stops with <code>stop</code>.
 
  
 
== Loading Fixes ==
 
== Loading Fixes ==
Line 137: Line 108:
 
SAR contains several commands to improve loading times:
 
SAR contains several commands to improve loading times:
  
* <code>ui_loadingscreen_transition_time</code>
+
ui_loadingscreen_transition_time <0|1>
 
+
ui_loadingscreen_fadein_time <0|1>
* <code>ui_loadingscreen_fadein_time</code>
+
ui_loadingscreen_mintransition_time <0|0.5>
 
+
sar_disable_mat_snapshot_recompute <0|1>
* <code>ui_loadingscreen_mintransition_time</code>
+
sar_disable_progress_bar_update <0|1>
 
+
sar_loads_uncap <0|1>
* <code>sar_disable_mat_snapshot_recompute</code>
+
sar_loads_norender <0|1>
 
 
* <code>sar_prevent_peti_materials_loading</code>
 
 
 
* <code>sar_disable_progress_bar_update</code>
 
 
 
* <code>sar_loads_uncap</code>
 
 
 
* <code>sar_loads_norender</code>
 
  
 
To make using these easier, there is one unified command to set all of them to preset values.
 
To make using these easier, there is one unified command to set all of them to preset values.
  
<code>sar_fast_load_preset [preset]</code>
+
<code>sar_fast_load_preset <preset></code>
  
 
The following presets exist:
 
The following presets exist:
Line 170: Line 133:
 
== CM Leaderboard ==
 
== CM Leaderboard ==
  
SAR can disable the leaderboard popup at the start of the map in challenge mode. It is allowed in all single player CM levels.
+
SAR can disable the leaderboard popup at the start of the map in challenge mode. It is allowed in all singleplayer CM levels.
  
 
'''Note: Not recommended for use in coop, as it can cause issues with the start of the level, and potentially invalidate your run.'''
 
'''Note: Not recommended for use in coop, as it can cause issues with the start of the level, and potentially invalidate your run.'''
  
<code>sar_disable_challenge_stats_hud 1</code>
+
<code>sar_disable_challenge_stats_hud <0|1></code>
  
 
== HUDs ==
 
== HUDs ==
Line 182: Line 145:
 
=== SAR HUD ===
 
=== SAR HUD ===
  
SAR's main HUD is effectively a more extensible version of <code>cl_showpos</code>, displaying useful information in a simple text form somewhere on your scren. It allows for displaying arbitrary text; higher precision on position and angle values; demo and session times; customizable fonts and position; and more. Elements of this HUD are enabled and tweaked through the <code>sar_hud_xxxx</code> commands. For instance, <code>sar_hud_position</code> and <code>sar_hud_angles</code> will display your position and angle like <code>cl_showpos</code> does. To replicate the behaviour of <code>cl_showpos 1</code>, run the following commands:
+
SAR's main HUD is effectively a more extensible version of <code>cl_showpos</code>, displaying useful information in a simple text form somewhere on your screen. It allows for displaying arbitrary text; higher precision on position and angle values; demo and session timers; customizable fonts and position; and more. Elements of this HUD are enabled and tweaked through the <code>sar_hud_xxxx</code> commands. For instance, <code>sar_hud_position</code> and <code>sar_hud_angles</code> will display your position and angle like <code>cl_showpos</code> does. To replicate the behaviour of <code>cl_showpos 1</code>, run the following commands:
  
* <code>sar_hud_velocity 1</code>
+
sar_hud_velocity 4
 +
sar_hud_position 2
 +
sar_hud_angles 2
 +
sar_hud_precision 2
  
* <code>sar_hud_position 2</code>
+
You can customize the color, font, and spacing of the SAR HUD using these commands:
  
* <code>sar_hud_angles 2</code>
+
* <code>sar_hud_font_index</code>
  
* <code>sar_hud_precision 2</code>
+
* <code>sar_hud_font_color</code>
  
You can customize the color, font, and spacing of the SAR HUD using these commands:
+
* <code>sar_hud_spacing</code>
  
* <code>sar_hud_default_font_index</code>
+
* <code>sar_hud_x</code>
  
* <code>sar_hud_default_font_color</code>
+
* <code>sar_hud_y</code>
  
* <code>sar_hud_default_spacing</code>
+
You can reorder HUD elements using <code>sar_hud_order_top</code> and <code>sar_hud_order_bottom</code>.
  
* <code>sar_hud_default_padding_x</code>
+
The SAR HUD also allows you to write arbitrary text on the screen. A line of text is added with <code>sar_hud_set_text <id> <text></code>; for example, <code>sar_hud_set_text 0 "Portal Funneling: ON"</code> will set the piece of text with ID 0 to "Portal Funneling: ON". Pieces of text can then be shown or hidden from the HUD using <code>sar_hud_show_text <id></code> and <code>sar_hud_hide_text <id></code>. For instance, this config provides a portal funneling toggle alias named "funnelingChange" which displays this text when funneling is enabled:
  
* <code>sar_hud_default_padding_y</code>
+
<pre style="color:red>
 +
Changing the value of portal funneling is banned in all categories other than CM.
 +
</pre>
  
You can reorder HUD elements using <code>sar_hud_default_order_top</code> and <code>sar_hud_default_order_bottom</code>.
+
sar_hud_set_text 0  "Portal Funneling: ON"
 +
sar_hud_set_text 1  "Portal Funneling: OFF"
 +
alias "funnelingOff" "sv_player_funnel_into_portals 0; sar_hud_hide_text 0; sar_hud_show_text 1; alias funnelingChange funnelingOn"
 +
alias "funnelingOn"  "sv_player_funnel_into_portals 1; sar_hud_show_text 0; sar_hud_hide_text 1; alias funnelingChange funnelingOff"
 +
funnelingOn
 +
bind <key> funnelingChange
  
The SAR HUD also allows you to write arbitrary text on the screen. A line of text is added with <code>sar_hud_set_text [id] [text]</code>; for example, <code>sar_hud_set_text 0 "flyin into portals"</code> will set the piece of text with ID 0 to "flyin into portals". Pieces of text can then be shown or hidden from the HUD using <code>sar_hud_show_text [id]</code> and <code>sar_hud_hide_text [id]</code>. For instance, this config provides a portal funneling toggle alias named "funneling_change" which displays this text when funneling is enabled:
+
The command <code>sar_hud_set_text_color <id> <hex color></code> can be used to change the color of the arbitrary text values. Furthermore, the color can be changed inline by using <code>#<hex code></code>. e.g:
  
<code>
+
alias "funnelingOff" "sv_player_funnel_into_portals 0; sar_hud_set_text 0 Portal Funneling: #55FF55ON;  alias funnelingChange funnelingOn"
sar_hud_set_text 0 "flyin into portals"
+
alias "funnelingOn"  "sv_player_funnel_into_portals 1; sar_hud_set_text 0 Portal Funneling: #FF5555OFF; alias funnelingChange funnelingOff"
 +
funnelingOn
 +
bind <key> funnelingChange
  
alias "funneling_off" "sv_player_funnel_into_portals 0; sar_hud_hide_text 0; alias funneling_change funneling_on"
+
You can also add a grey background to the SAR HUD using <code>sar_hud_bg <0|1></code>.
 
 
alias "funneling_on" "sv_player_funnel_into_portals 1; sar_hud_show_text 0; alias funneling_change funneling_off"
 
 
 
funneling_on
 
</code>
 
  
 
=== Input HUD ===
 
=== Input HUD ===
  
Another commonly used HUD is the input HUD (ihud). This is a HUD element which displays a subset of your inputs to the game on a keyboard overlay. It is enabled using the <code>sar_ihud</code> variable, which can be given one of several values:
+
Another commonly used HUD is the input HUD (ihud). This is a HUD element which displays a subset of your inputs to the game on a keyboard overlay. It is made up of 3 presets:
  
* <code>sar_ihud 0</code> - disable the HUD entirely
+
*<code>sar_ihud_preset normal</code> - Displays WASD movement as well as jump, duck, use, and the portal shots.
  
* <code>sar_ihud 1</code> - show WASD movement
+
*<code>sar_ihud_preset normal_mouse</code> - Same as above, but also has a display of your mouse movement.
  
* <code>sar_ihud 2</code> - show all of the above, as well as duck, jump, and use
+
*<code>sar_ihud_preset tas</code> - Displays two analog displays of your current move direction and look direction, as well as jump, duck, use, and the portal shots. This is helpful when TASing <span style="font-size:0.5em">or when playing with controller</span>.
  
* <code>sar_ihud 3</code> - show all of the above, as well as attack and attack2 (portal shots)
+
Once set up with a preset, the ihud can be extensively modified using the command <code>sar_ihud_modify <element|all> [property=value]...</code>.
  
* <code>sar_ihud 4</code> - show all of the above, as well as speed and reload (not generally used in Portal 2)
+
This HUD can be used to see inputs in demos, which can be useful when learning movement.
 
 
This HUD can be used to see inputs in demos, which can be useful when, for instance, learning movement.
 
  
 
=== Portal HUD ===
 
=== Portal HUD ===
 
+
The Least Portals HUD shows how many portals you've shot in total across a play session. It is toggled using <code>sar_lphud <0|1></code>, and its portal count can be reset using <code>sar_lphud_set 0</code>. The LP HUD accurately accounts for save loads and other level changes, so is useful in category extensions like 100 Portals.
The Least Portals HUD (lphud) shows how many portals you've shot in total across a play session. It is enabled through <code>sar_lphud</code>, and its portal count can be reset using <code>sar_lphud_set 0</code>. The LP HUD accurately accounts for save loads and other level changes, so is useful in category extensions like 100 Portals.
 
  
 
=== Vphys HUD ===
 
=== Vphys HUD ===
Line 242: Line 209:
 
'''Note: This HUD exists for routing purposes. It is not allowed in runs, and is therefore cheat protected.'''
 
'''Note: This HUD exists for routing purposes. It is not allowed in runs, and is therefore cheat protected.'''
  
The vphys HUD displays some physics information on-screen. It is useful for routers and those trying to understand various glitches in the game; it shows the states of your physics hitboxes, your current funnel handle and count, etc. It can be enabled using <code>sar_vphys_hud 1</code>.
+
The vphys HUD displays some physics information on-screen. It is useful for routers and those trying to understand various glitches in the game; it shows the states of your physics hitboxes, your current funnel handle and count, etc. It can be toggled using <code>sar_vphys_hud <0|1></code>.
  
 
== Ghosts ==
 
== Ghosts ==
  
SAR 1.12 includes support for ghosts: models that appear in-game to represent the position of another player. There are two kinds of ghosts: demo ghosts and network ghosts. Demo ghosts follow the path of a player defined by a demo file, whereas network ghosts represent the real-time position of another player on the same map, and are generally best suited to longer races (e.g. fullgame).
+
SAR includes support for ghosts: models that appear in-game to represent the position of another player. There are two kinds of ghosts: demo ghosts and network ghosts. Demo ghosts follow the path of a player defined by a demo file, whereas network ghosts represent the real-time position of another player on the same map, and are generally best suited to longer races (e.g. fullgame).
  
 
=== Setting Up ===
 
=== Setting Up ===
Line 256: Line 223:
 
=== Other Ghost Commands ===
 
=== Other Ghost Commands ===
  
There are many more commands affecting the appearance and behaviour of ghosts.
+
There are many more commands affecting the appearance and behavior of ghosts.
  
* <code>ghost_delete_by_ID [id]</code> - delete the demo ghost with the given ID.
+
* <code>ghost_delete_by_ID <id></code> - delete the demo ghost with the given ID.
  
 
* <code>ghost_delete_all</code> - delete all demo ghosts.
 
* <code>ghost_delete_all</code> - delete all demo ghosts.
Line 266: Line 233:
 
* <code>ghost_reset</code> - reset all demo ghosts ready for restarting.
 
* <code>ghost_reset</code> - reset all demo ghosts ready for restarting.
  
* <code>ghost_TCP_only [0/1]</code> - for network ghosts, send all position data over TCP rather than UDP. This is slower, but more reliable, so may be useful if you have an unreliable Internet connection
+
* <code>ghost_TCP_only <0|1></code> - for network ghosts, send all position data over TCP rather than UDP. This is slower, but more reliable, so may be useful if you have an unreliable Internet connection.
  
* <code>ghost_update_rate [ms]</code> - the number of milliseconds between sending out position updates to the ghost server. The default value, 50, is generally recommended, but can be tweaked if necessary.  
+
* <code>ghost_update_rate <ms></code> - the number of milliseconds between sending out position updates to the ghost server. The default value, 50, is generally recommended, but can be tweaked if necessary.  
  
 
* <code>ghost_disconnect</code> - disconnect from the current ghost server.
 
* <code>ghost_disconnect</code> - disconnect from the current ghost server.
  
* <code>ghost_name [name]</code> - change what your name appears as to others on the ghost server.
+
* <code>ghost_name <name></code> - change what your name appears as to others on the ghost server.
  
* <code>ghost_message [msg]</code> - send a chat message to the ghost server.
+
* <code>ghost_message <msg></code> - send a chat message to the ghost server.
  
* <code>ghost_height [height]</code> - set the amount to vertically offset ghosts by.
+
* <code>ghost_height <height></code> - set the amount to vertically offset ghosts by.
  
* <code>ghost_transparency [0-255]</code> - set the opacity of ghost models, where 0 is completely transparent and 255 is completely opaque.
+
* <code>ghost_transparency <0-255></code> - set the opacity of ghost models, where 0 is completely transparent and 255 is completely opaque.
  
* <code>ghost_text_offset [height]</code> - set the amount to vertically offset ghost names by.
+
* <code>ghost_text_offset <height></code> - set the amount to vertically offset ghost names by.
  
* <code>ghost_show_advancement [0/1]</code> - set whether to display a message in chat when ghosts move between levels.
+
* <code>ghost_show_advancement <0|1></code> - set whether to display a message in chat when ghosts move between levels.
  
* <code>ghost_proximity_fade [0-2000]</code> - how far you need to be from ghost models before they start fading out, to prevent them from blocking your view. The default is 200.
+
* <code>ghost_proximity_fade <0-2000></code> - how far you need to be from ghost models before they start fading out, to prevent them from blocking your view. The default is 200.
  
* <code>ghost_show_name [0/1]</code> - set whether to display ghosts' names about their models.
+
* <code>ghost_show_name <0|1></code> - set whether to display ghosts' names above their models.
  
* <code>ghost_type [0/1/2]</code> - sets how ghosts render for you. In type 0, ghosts simply render as plain red triangles. In type 1, ghosts render as entities with models (see <code>ghost_prop_model</code>). In type 2, ghosts render as red triangles, with small portal guns. NOTE: for a run to be legitimate, you must use ghost type 0; see the "Run Legitimacy" section below.
+
* <code>ghost_type <0|1|2></code> - sets how ghosts render for you. In type 0, ghosts simply render as plain red triangles. In type 1, ghosts render as entities with models (see <code>ghost_prop_model</code>). In type 2, ghosts render as red triangles, with small portal guns. ''See also: [[#Run_Legitimacy|Run Legitimacy]].''
  
* <code>ghost_prop_model [model]</code> - for demo ghosts, sets the model that all ghosts use (if ghost_type is 1). For network ghosts, set the model you appear as to other people (if their ghost_type is 1). Contains autocompletions for some common models.
+
* <code>ghost_prop_model <model></code> - for demo ghosts, sets the model that all ghosts use (if ghost_type is 1). For network ghosts, set the model you appear as to other people (if their ghost_type is 1). Contains autocompletions for some common models.
  
 
=== Run Legitimacy ===
 
=== Run Legitimacy ===
Line 296: Line 263:
 
Ghosts themselves are not banned from runs. However, some aspects and uses of them are considered illegitimate.
 
Ghosts themselves are not banned from runs. However, some aspects and uses of them are considered illegitimate.
  
For a run to be legitimate, <code>ghost_type</code> must be set to 0, because of the fact that ghosts otherwise affect demos. Additionally, you may not use a ghost to gain '''any''' advantage. This includes, but is not limited to, using the positions of other ghosts for lineups, or using <code>ghost_sync</code> to perform pause abuse (e.g. checking coordinates). Any runs submitted to speedrun.com or iVerb which in any way abuse ghosts can and will be rejected or removed.
+
* <code>ghost_type</code> 0 and 1 are legal in runs. Type 2 is not allowed because it adversely effects demos.
 +
 
 +
* You may not use a ghost to gain '''any''' advantage. This includes, but is not limited to, using the positions of other ghosts for lineups, or using <code>ghost_sync</code> to perform pause abuse (e.g. checking coordinates). Any runs submitted to speedrun.com or the CM leaderboards which in any way abuse ghosts can and will be rejected or removed.
  
 
=== Server ===
 
=== Server ===
  
To use network ghosts, a "ghost server" must be hosted. The server is cross-platform (working on both Windows and Linux); it can be found on [https://github.com/Blenderiste09/GhostServer Blenderiste's GitHub]. To use it, set a port in the settings (the default is 53000) and, if neccesary (behind NAT), forward this port on TCP '''and''' UDP.
+
To use network ghosts, a "ghost server" must be hosted. The server is cross-platform (works on both Windows and Linux); it can be found on [https://github.com/p2sr/GhostServer GitHub]. To use it, set a port in the settings (the default is 53000) and, if necessary (behind NAT), forward this port on TCP '''and''' UDP.
  
The server can trigger a countdown for all connected clients, and can run commands before and after the countdown (for instance, running <code>load containerridesave</code> after the countdown for a fullgame race). Note that the countdown will not work for clients in the menu; they must all be in-game.
+
Alternatively to setting up your own server, you can use [https://ghost.portal2.sr our website] which will host it for you.
 +
 
 +
The server can trigger a countdown for all connected clients, and can run commands before and after the countdown (for instance, running <code>load vault</code> after the countdown for a fullgame race). Note that the countdown will not work for clients in the menu; they must all be in-game.
  
 
== Config+ ==
 
== Config+ ==
  
Config+ is the name for three SAR commands allowing more complex configurations.
+
Config+ is the name for a number of SAR commands allowing more complex configurations. More advanced use of this functionality is often referred to as Config++ or C++.
  
 
=== seq ===
 
=== seq ===
Line 312: Line 283:
 
The <code>seq</code> command takes an arbitrary number of commands as arguments, and runs them all one tick after another. For instance:
 
The <code>seq</code> command takes an arbitrary number of commands as arguments, and runs them all one tick after another. For instance:
  
<code>seq "say 1" "say 2" "say 3"</code>
+
seq "say 1" "say 2" "say 3"
  
 
This will output 1 to the chat, then one tick later 2, then one tick later 3.
 
This will output 1 to the chat, then one tick later 2, then one tick later 3.
 +
 +
===hwait===
 +
 +
The <code>hwait <ticks> <command></code> command runs a command after a specified number of ticks. Unlike <code>seq</code>, these timers run even on the menus.
  
 
=== cond ===
 
=== cond ===
Line 320: Line 295:
 
The second command is <code>cond</code>. This command allows you to only run a command '''in certain conditions'''.
 
The second command is <code>cond</code>. This command allows you to only run a command '''in certain conditions'''.
  
<code>cond [condition] [command]</code>
+
cond [condition] [command]
 +
 
 +
This can be used, for instance, to automatically apply execs for different categories or levels; as an example, the condition "map=mp_coop_start & !orange" will succeed only when you run it in Calibration as blue. Conditions work as follows:
 +
 
 +
* <code>?<variable>=<value></code> checks whether the svar <variable> is equal to the value on the right side. (e.g. the condition <code>?yes=1</code> will run if the svar 'yes' is set to 1). You can also use <code>?<variable></code> on the right side (e.g. <code>?foo=?bar</code> will run if the svars 'foo' and 'bar' are the same). Originally, this syntax was <code>var:<variable>=<value></code>, but the newer syntax is favored because of the 'breakset.'
  
This can be used, for instance, to automatically apply execs for different categories or levels; as an example, the condition "map=mp_coop_start & !orange" will run only when you load into Calibration as blue. Conditions work as follows:
+
* <code>#<cvar>=<value></code> checks whether the cvar <cvar> is equal to the value on the right side. (e.g. the condition <code>#sv_cheats=1</code> will run if the cvar 'sv_cheats' is set to 1). You can also use <code>#<cvar></code> on the right side. Alternatively, you can also use <code>cvar:<cvar></code>.
  
* <code>map=map_name</code> checks whether you are in a certain map
+
* <code>%<string>=<value></code> checks whether the literal string <string> is equal to the value on the right side. (e.g. the condition <code>%map=?variable</code> will run if the svar 'variable' is equal to 'map'.
  
* <code>prev_map=map_name</code> checks the last map you were in
+
* <code>game=<game_name></code> checks whether you are playing a certain Source game. Currently supported games are Portal 2 (<code>portal2</code>), Aperture Tag (<code>aptag</code>), Portal Stories: Mel (<code>mel</code>), Thinking With Time Machine (<code>twtm</code>), Portal Reloaded (<code>reloaded</code>), and Portal 2 Speedrun Mod (<code>srm</code>). Any other game is recognized as <code>other</code>. You can also use <code>?<variable></code> on the right side here.
 +
 
 +
* <code>map=<map_name></code> checks whether you are in a certain map. You can also use <code>?<variable></code> on the right side here.
 +
 
 +
* <code>prev_map=<map_name></code> checks the last map you were in. You can also use <code>?<variable></code> on the right side here.
 +
 
 +
* <code>steamid=<steam32id></code> checks for specific partner Steam32 ID. You can also use <code>?<variable></code> on the right side here. Use <code>sar_get_partner_id</code> in Co-Op to retrieve your partner's Steam32 ID.
  
 
* <code>same_map</code> checks whether the current map is the same as the previous map
 
* <code>same_map</code> checks whether the current map is the same as the previous map
Line 334: Line 319:
 
* <code>orange</code> checks whether you are playing as orange (P-Body)
 
* <code>orange</code> checks whether you are playing as orange (P-Body)
  
* <code>cm</code> checks whether you are in challenge mode
+
* <code>cm</code> checks whether you are in Challenge Mode
 +
 
 +
* <code>workshop</code> checks whether you are currently in a map from the workshop
 +
 
 +
* <code>menu</code> checks whether you are currently in the menu
  
 
* <code>!</code> is logical NOT; if put before a condition, it inverts it (e.g. the condition <code>!orange</code> will run '''unless''' you are playing as orange)
 
* <code>!</code> is logical NOT; if put before a condition, it inverts it (e.g. the condition <code>!orange</code> will run '''unless''' you are playing as orange)
Line 342: Line 331:
 
* <code>|</code> is logical OR; it chains conditions, requiring at least one to be true (e.g. <code>map=sp_a1_intro1 | map=sp_a1_intro2</code> will run in both Container Ride and Portal Carousel)
 
* <code>|</code> is logical OR; it chains conditions, requiring at least one to be true (e.g. <code>map=sp_a1_intro1 | map=sp_a1_intro2</code> will run in both Container Ride and Portal Carousel)
  
* Parentheses can be used to group expressions
+
* Parentheses <code>()</code> can be used to group expressions
  
For example, the following condition would run a coop_orange exec when run in a coop map as orange:
+
For example, the following condition would run an exec when run in a coop map as orange:
  
 
<code>cond "coop & orange" "exec coop_orange"</code>
 
<code>cond "coop & orange" "exec coop_orange"</code>
  
=== sar_on_load ===
+
Another relevant command is <code>conds</code>, which does the same but in a sort of if-else manner. It will run the command for the first condition that is truthy.
  
The last command is <code>sar_on_load</code>. This is used to register a command to be run on every map load. This command will pass all successive arguments to the command given; this means you '''do not need to quote the command given'''. You can chain this with <code>cond</code> to make conditional execs as follows:
+
conds [<condition> <command>]... [else]
  
<code>sar_on_load cond "coop & orange" "exec coop_orange"</code>
+
For example, <code>conds "coop & orange" "exec coop_orange" "coop" "exec coop_blue" "exec singleplayer"</code> will exec the relevant file for your role. You can chain as many statements as you like.
  
== MTrigger ==
+
=== sar_on_ Events ===
  
MTrigger is a feature allowing you to make custom splits in a map, allowing you to track your times in runs or in demos.
+
The <code>sar_on_</code> family of commands are used to register commands to be run on certain events. These commands will pass all successive arguments to the command given; this means you '''do not need to quote the command given'''.
  
=== Adding/Removing triggers ===
+
* <code>load</code> - to be run on session start
 +
* <code>session_end</code> - to be run on session end
 +
* <code>exit</code> - to be run on game exit
 +
* <code>demo_start</code> - to be run when demo playback starts
 +
* <code>demo_stop</code> - to be run when demo playback stops
 +
* <code>flags</code> - to be run when CM flags are hit
 +
* <code>coop_reset_done</code> - to be run when coop reset is completed
 +
* <code>coop_reset_remote</code> - to be run when coop reset run remotely
 +
* <code>coop_spawn</code> - to be run on coop spawn
 +
* <code>config_exec</code> - to be run on config.cfg exec
 +
* <code>tas_start</code> - to be run when TAS script playback starts
 +
* <code>tas_end</code> - to be run when TAS script playback ends
 +
* <code>pb</code> - to be run when auto-submitter detects PB
 +
* <code>not_pb</code> - to be run when auto-submitter detects not PB
  
To make these splits, you have to create triggers by using one of the following two commands:
+
You can chain this with <code>cond</code> to make conditional execs as follows:
  
The first command is of the following form:
+
<code>sar_on_load cond "coop & orange" exec coop_orange</code>
  
<code>sar_mtrigger_add <id> <A.x> <A.y> <A.z> <B.x> <B.y> <B.z> [angle]</code>.
+
=== svars ===
 +
Configurable variables called 'svars,' or 'SAR variables,' allow you to read the values of cvars into variables. You can set an svar using <code>svar_set <svar> <value></code>, read the console output of a command with <code>svar_capture <svar> <command></code>, or read the value of a cvar with <code>svar_from_cvar <svar> <cvar></code>. You can then do arithmetic on these variables using the following commands:
  
This command will create a "zone" trigger; a cuboid which will trigger when the player passes through it. You can also place them by aiming at points in the map by using the <code>sar_mtrigger_place <id></code> command. Triggers can be rotated with <code>sar_mtrigger_rotate <id> <angle></code>.
+
*<code>svar_add <svar> <svar|value></code> - Adds the value of the right side to the svar.
  
The second command is of the following form:
+
*<code>svar_sub <svar> <svar|value></code> - Subtracts the value of the right side from the svar.
  
<code>sar_mtrigger_add <id> <entity> <input></code>
+
*<code>svar_mul <svar> <svar|value></code> - Multiplies the svar by the value of the right side.
  
This command will create an "entity" trigger, which triggers whenever the given input is executed for the entity with the given targetname.
+
*<code>svar_div <svar> <svar|value></code> - Divides the svar by the value of the right side.
  
Examples:
+
*<code>svar_mod <svar> <svar|value></code> - Returns the remainder when dividing the svar by the value of the right side.
  
<code>sar_mtrigger_add 1 38.2815 479.597 1104.03 49.7213 539.146 1195.38 45</code> will create a zone trigger with an ID of 1 at the specified coordinates and rotated by 45°.
+
For each of the above commands, there is an equivalent <code>svar_f<...></code> command that uses floating point arithmetic rather than integer, i.e. <code>svar_fadd <svar> <svar|value></code>. You can see what an svar is set to using <code>svar_get <svar></code>. There are also the following commands for operating on a single svar:
  
<code>sar_mtrigger_add podium_collapse_push_brush Enable</code> will create an entity trigger that will watch the <code>Enable</code> input of the <code>podium_collapse_push_brush</code> entity in Portal Gun.
+
*<code>svar_floor <svar></code> - Rounds ''down'' the value of the svar to the nearest integer.
  
You can delete the triggers by using the <code>sar_mtrigger_delete <id></code> or <code>sar_mtrigger_delete_all</code> commands.
+
*<code>svar_round <svar></code> - Rounds the value of the svar to the nearest integer.
  
Once the triggers are placed, you have to set the runner's name with <code>sar_mtrigger_name <name></code>.
+
*<code>svar_ceil <svar></code> - Rounds ''up'' the value of the svar to the nearest integer.
  
You can now play the map. As soon as you trigger an entity or zone trigger, the game will display your split time in the chat with the syntax <code><name> -> <split time> (time since last split)</code>. It also adds this time to a CSV file; we'll get to that in a bit.
+
*<code>svar_abs <svar></code> - Sets the value of the svar to its absolute value. e.g. -17.2 => 17.2, 31 => 31
  
Normal usage of this is to set your own name while you're grinding a chamber and change it to the corresponding runner's name when playing a demo.
+
*<code>svar_substr <svar> <from> [length]</code> - Sets the value of the svar to its substring. From starts at 0. A negative from value means from the end of the svar.
  
To reset the splits results, use the <code>sar_mtrigger_reset</code> command.
+
Note: If a cvar is set to 1.000000 (by <code>incrementvar</code> for example) and you use <code>svar_from_cvar</code> on it, you can coerce this value to be 1 by doing <code>svar_add <svar> 0</code>.
  
=== Exporting ===
+
=== SAR Functions ===
 +
<code>sar_function</code> is a command that allows you to make commands that can be dynamically filled with svars and passed arguments. The <code>$</code> character is used to get svars or args. <code>$1</code> will be replaced with the first argument given to the command, and this works up to <code>$63</code>. Similarly, <code>$+1</code> will be replaced by all arguments after and including argument 1. <code>$variable</code> will be replaced with the value of the svar <code>variable</code>. Additionally, <code>$-</code> will expand to nothing, to be used as a separator between substitutions and text e.g. <code>$variable$-hello</code>, and <code>$'</code> will expand to <code>"</code>, for use in nested quotes.  <code>$#</code> will be replaced with the number of arguments provided. Finally, <code>$$</code> will expand to <code>$</code>. This substitution (excluding <code>$1 - $63</code> and <code>$+1 - $+63</code>) can be done inline with the <code>sar_expand</code> command. <code>$#</code> will expand to -1 when using <code>sar_expand</code>.
  
Once you're done with grinding or with demo playback, you might want to export the results. Before doing that, you have to set the <code>sar_mtrigger_header</code> variable. <code>sar_mtrigger_header</code> will be the header of the CSV file; for instance, "Name,Ground trigger,Portal gun,Office".
+
Some examples:
  
Once these variables are set, you can export the file with <code>sar_mtrigger_export_stats <filename></code>, <code>filename</code> being the path to the file. It will export a .csv in your Portal 2 folder with the header you set, and all the times you recorded.
+
// pass arguments to the function
 +
sar_function print echo "$1"
 +
print "Hello World!"                // prints "Hello World!" to the console.
  
You can also export the triggers, either to save them or to share them to someone. To do that, use the command <code>sar_mtrigger_export_triggers <filename></code>. This will export a CFG file with all the commands to automatically generate the triggers. You can then place it in your <code>Portal2/portal2/cfg</code> folder and type <code>exec <filename></code> to re-create the triggers.
+
// the function can read svars
 +
sar_function print echo "$variable"
 +
svar_set variable "Hello World!"
 +
print                              // prints "Hello World!" to the console.
  
=== Miscellaneous ===
+
These functions are one of the main reasons [https://github.com/RainbowwPhoenixx/SARtris SARtris] is possible.
  
* <code>sar_mtrigger_show_chat <0/1></code> - display split times in the chat
+
=== Common Mistakes ===
  
* <code>sar_mtrigger_draw <0/1></code> - show the zone triggers (requires <code>sv_cheats 1</code>)
+
There are a few common mistakes that users make when writing Config+ commands.
  
== Freecam ==
+
* You must quote conditions that contain [[Command_Parsing#Break_set|breakset]] characters. <code>cond var:yes=1 echo hi</code> should be <code>cond "var:yes=1" echo hi</code> or <code>cond ?yes=1 echo hi</code>
  
SAR 1.12 allows you to freely control the in-game camera using commands, much like in demos. The camera can be separated from the player using <code>sar_cam_control 1</code> (only works if playing a demo OR with cheats enabled). Then, the camera can be manipulated using the following commands:
+
<pre style="color:red">What are more mistakes people make? I don't know because I'm so smart B)</pre>
  
* <code>sar_cam_setpos [x] [y] [z]</code>
+
== Freecam ==
 
 
* <code>sar_cam_setang [pitch] [yaw] <roll></code>
 
  
* <code>sar_cam_setfov [fov]</code>
+
SAR allows you to freely control the in-game camera using commands, much like in demos. The camera can be separated from the player using <code>sar_cam_control 1</code> (only works if playing a demo OR with cheats enabled). Then, the camera can be manipulated using the following commands:
  
* <code>sar_cam_reset</code>
+
sar_cam_setpos <x> <y> <z>
 +
sar_cam_setang <pitch> <yaw> [roll]
 +
sar_cam_setfov <fov>
 +
sar_cam_reset
  
 
=== Drive Mode ===
 
=== Drive Mode ===
Line 430: Line 440:
 
* Hold '''right click''' and move mouse '''up and down''' to change FOV.
 
* Hold '''right click''' and move mouse '''up and down''' to change FOV.
  
Drive mode can be disabled with <code>sar_cam_drive 0</code>, and re-enabled with <code>sar_cam_drive 1</code>.
+
Drive mode can be toggled using <code>sar_cam_drive <0|1></code>
  
 
=== Cinematic Mode ===
 
=== Cinematic Mode ===
Line 438: Line 448:
 
* <code>sar_cam_path_setkf <frame> <x> <y> <z> <pitch> <yaw> <roll> <fov></code> - adds a path keyframe. Parameters default to the current frame and position if not given.
 
* <code>sar_cam_path_setkf <frame> <x> <y> <z> <pitch> <yaw> <roll> <fov></code> - adds a path keyframe. Parameters default to the current frame and position if not given.
  
* <code>sar_cam_path_remkf [frame]</code> - removes the given keyframe.
+
* <code>sar_cam_path_remkf <frame></code> - removes the given keyframe.
  
 
* <code>sar_cam_path_showkfs</code> - list all the current keyframes.
 
* <code>sar_cam_path_showkfs</code> - list all the current keyframes.
Line 444: Line 454:
 
* <code>sar_camera_control 2</code> - puts the camera into cinematic mode to follow the set path.
 
* <code>sar_camera_control 2</code> - puts the camera into cinematic mode to follow the set path.
  
==Misc Commands==
+
== Misc. Commands ==
 +
 
 +
* <code>sar_about</code> - Gives information about the currently installed version of SAR. Make sure you're up to date!
 +
 
 +
* <code>sar_update [release|pre|canary] [exit|restart] [force]</code> - Checks if SAR is up-to-date, and if not, updates it. If force is given, it will always reinstall, even if it may be a downgrade.
  
===Remove Drawline===
+
* <code>sar_clear_lines</code> - Removes drawn <code>drawline</code> lines (like the ones used to practice moonshot).
Removing drawn <code>drawline</code> lines (like the ones used to practice moonshot).
 
  
* <code>sar_clear_lines</code>
+
== Credits ==
 +
* NeKz : Original creator of SAR
 +
* Krzyhau : TASTools developer and responsible for fixing a memory leak
 +
* Blenderiste09, Mlugg : Past maintainers of SAR
 +
* AMJ, Krzyhau : Current maintainers of SAR
 +
* A number of other people have helped contribute, find a list [https://github.com/p2sr/SourceAutoRecord/graphs/contributors here]
  
=== Credits ===
+
=== References===
* NeKz : Creator of SAR
+
<references />
* Blenderiste09, Krzyhau, mlugg : Random guys that modified the plugin :)
 
  
 
[[Category:Plugin]]
 
[[Category:Plugin]]

Latest revision as of 19:54, 29 August 2024

NeKz.jpg

Source Auto Record (SAR)


Source Auto Record is a Portal 2 plugin originally developed by NeKz. The plugin is used by almost all Portal 2 speedrunners, and is highly recommended if you want to speedrun the game. It adds a wide variety of useful commands, and Quality of Life improvements that make running the game easier, and at times, more accurate.

How to install

Main Article: How to install plugins

  1. Download either sar.dll or sar.so depending on whether you're on Windows or Linux respectively.
  2. It is also recommended to download the sar.pdb file on Windows, as it expands on crash logs if Portal 2 were to crash.
  3. Place the downloaded files into (steam installation)\steamapps\common\Portal 2.

Note: Portal 2 Speedrun Mod (P2SM) and other Sourcemods use SAR for timing as well, but these mods read from your base game install, so you do not need any special installation for SAR with P2SM. Just install SAR normally for Portal 2. However, full mods like Portal Stories: Mel require SAR to be installed manually.

Speedrun Timer

One of SAR's main uses is for timing runs. SAR will interface with LiveSplit (or other speedrun timing programs that support it), and automatically start/split/stop runs. This is done through the sar_speedrun category of commands. Most these commands are fairly self explanatory; the most important ones are below.

  • sar_speedrun_category <name> - sets the category being run (affects how the run timing starts and stops). This only applies once you load a map.
  • sar_speedrun_offset <ticks> - offsets the timer by a certain amount at the start of the run. Used, for instance, with Vault Save.
  • sar_speedrun_time_pauses <0|1> - affects whether pauses are timed. You are allowed to omit pauses if you do not use them to gain an advantage.
  • sar_speedrun_smartsplit <0|1> - enabled by default. Will prevent SAR from splitting on maps which you have previously entered in this run. Should be disabled in coop runs!
  • sar_speedrun_reset - resets a run in preparation for another.

Custom Categories

SAR allows the creation of custom categories for speedruns based on entity inputs.

sar_speedrun_category_create <categoryname>
sar_speedrun_category_remove <categoryname>
sar_speedrun_category_rule_create <rulename> <type> [option=value]... <map=map> <action=action>
sar_speedrun_category_add_rule <categoryname> <rulename>
sar_speedrun_category_remove_rule <categoryname> <rulename>

There is a shorthand version of these commands used for creating MTriggers, which is

sar_speedrun_cc_start <categoryname> [map=map] [action=action]
sar_speedrun_cc_rule <rulename> <type> [option=value]... [action=action]
sar_speedrun_cc_finish

SAR comes packed with some default speedrun categories, and for Portal 2, this GitHub repository contains custom categories for every map in the game, for use in CM.

Rule Creation

Rule types:

  • load - Rule triggers at the start of the level.
  • zone <center=x,y,z> <size=x,y,z> <angle=degrees> - Rule triggers when any player enters the area specified by the center, size, and angle given. Size is on BOTH sides of the center, so the distance from the center to an edge is 1/2 of the given size.
  • portal <center=x,y,z> <size=x,y,z> <angle=degrees> [portal=blue|orange] - Like a zone, except for portals instead of players.
  • entity <targetname|classname=target> <inputname=input> [parameter=param] - Rule triggers on the input of a specified 'target' entity. See also: Entity inputs. Note that if the name, input, or parameter includes any of these characters (){}:', quotes must be put around the argument e.g. targetname=@glados inputname=RunScriptCode "parameter=Success()"
  • flags - Rule triggers when any player activates the CM flags.
  • end - Rule ends when the map transitions to the next.

For any rule, the following options can be added:

  • map - Specifies that this rule must occur on the map specified.
  • action - Can be used to modify the timer. (start, force_start, stop, split, pause, resume)
  • player - Specifies a certain player must trigger the rule. Player 0 is blue.
  • after - Specifies that this rule must occur after the rule specified.
  • ccafter - Same as after, except adds the category name to the beginning of the rule name. For use in the shorthand. e.g. "ccafter=Flags 1" in the category creation for Laser Crusher becomes "after=Laser Crusher - Flags 1"

When using the shorthand and a rule's map or action is not specified, it is inherited from the category. Every rule requires an action and a map.

e.g. (Laser Crusher)

sar_speedrun_cc_start "Laser Crusher" map=mp_coop_laser_crusher action=split
sar_speedrun_cc_rule "Start" load action=force_start
sar_speedrun_cc_rule "End Hop" zone center=2630.95,-1135.87,80.33 size=77.85,287.33,161.4 angle=0
sar_speedrun_cc_rule "End Trigger Blue" entity targetname=team_door-team_proxy inputname=OnProxyRelay1
sar_speedrun_cc_rule "End Trigger Orange" entity targetname=team_door-team_proxy inputname=OnProxyRelay3
sar_speedrun_cc_rule "Flags 1" flags
sar_speedrun_cc_rule "Flags 2" flags "ccafter=Flags 1" action=stop
sar_speedrun_cc_finish

In this example, all rules except Start and Flags 2 inherit the action split from the category, and all rules inherit the map.

Entity Inputs

Note: This command exists for category creation purposes. It is not allowed in runs, and is therefore cheat protected.

Almost all events that occur in Source games are dictated by certain 'inputs' to entities in the map. For example, whenever the Blue robot gets near an exit door, the door receives the entity input OnProxyRelay1, which triggers a sound and lights up Blue's side of the indicator above the door. Many speedrun categories make use of these entity inputs as rules. In order to assist creation of these categories, you can toggle sar_show_entinp <0|1>. This will show the entity inputs, and the tick they occurred on, in the developer console.

Demo Recording

If you are recording demos (for run verification or analysis), the command sar_autorecord 1 will automatically begin recording a new demo every level load or restart. Make sure to start recording demos at the start of your run with record demoname, and stop recording after the timer stops with stop.

Demo Prefix

The command sar_record_prefix can be used to timestamp or prepend text to recorded demo names. e.g. sar_record_prefix "demo/%Y-%m-%d_%H-%M-%S_" will put demos in the demo folder, and have Year, Month, Day, Hour, Minute, Second prefixed to it. e.g. demo/2021-06-01_19-23-50_fullgame.dem[1] (fun trivia, that's the build time of SAR 1.12.3)

Loading Fixes

SAR contains several commands to improve loading times:

ui_loadingscreen_transition_time <0|1>
ui_loadingscreen_fadein_time <0|1>
ui_loadingscreen_mintransition_time <0|0.5>
sar_disable_mat_snapshot_recompute <0|1>
sar_disable_progress_bar_update <0|1>
sar_loads_uncap <0|1>
sar_loads_norender <0|1>

To make using these easier, there is one unified command to set all of them to preset values.

sar_fast_load_preset <preset>

The following presets exist:

  • none - disables all loading fixes
  • normal - enables most loading fixes, but retains loading screen and progress bar rendering
  • sla - enables all loading fixes which do not affect SLA
  • full - enables all loading fixes

The full preset is generally recommended for most runners.

CM Leaderboard

SAR can disable the leaderboard popup at the start of the map in challenge mode. It is allowed in all singleplayer CM levels.

Note: Not recommended for use in coop, as it can cause issues with the start of the level, and potentially invalidate your run.

sar_disable_challenge_stats_hud <0|1>

HUDs

SAR adds many optional HUDs on top of the base game, including the "SAR HUD", input HUD (ihud), portal HUD (lphud), vphysics HUD (vphys_hud), and more.

SAR HUD

SAR's main HUD is effectively a more extensible version of cl_showpos, displaying useful information in a simple text form somewhere on your screen. It allows for displaying arbitrary text; higher precision on position and angle values; demo and session timers; customizable fonts and position; and more. Elements of this HUD are enabled and tweaked through the sar_hud_xxxx commands. For instance, sar_hud_position and sar_hud_angles will display your position and angle like cl_showpos does. To replicate the behaviour of cl_showpos 1, run the following commands:

sar_hud_velocity 4
sar_hud_position 2
sar_hud_angles 2
sar_hud_precision 2

You can customize the color, font, and spacing of the SAR HUD using these commands:

  • sar_hud_font_index
  • sar_hud_font_color
  • sar_hud_spacing
  • sar_hud_x
  • sar_hud_y

You can reorder HUD elements using sar_hud_order_top and sar_hud_order_bottom.

The SAR HUD also allows you to write arbitrary text on the screen. A line of text is added with sar_hud_set_text <id> <text>; for example, sar_hud_set_text 0 "Portal Funneling: ON" will set the piece of text with ID 0 to "Portal Funneling: ON". Pieces of text can then be shown or hidden from the HUD using sar_hud_show_text <id> and sar_hud_hide_text <id>. For instance, this config provides a portal funneling toggle alias named "funnelingChange" which displays this text when funneling is enabled:

Changing the value of portal funneling is banned in all categories other than CM.
sar_hud_set_text 0   "Portal Funneling: ON"
sar_hud_set_text 1   "Portal Funneling: OFF"
alias "funnelingOff" "sv_player_funnel_into_portals 0; sar_hud_hide_text 0; sar_hud_show_text 1; alias funnelingChange funnelingOn"
alias "funnelingOn"  "sv_player_funnel_into_portals 1; sar_hud_show_text 0; sar_hud_hide_text 1; alias funnelingChange funnelingOff"
funnelingOn
bind <key> funnelingChange

The command sar_hud_set_text_color <id> <hex color> can be used to change the color of the arbitrary text values. Furthermore, the color can be changed inline by using #<hex code>. e.g:

alias "funnelingOff" "sv_player_funnel_into_portals 0; sar_hud_set_text 0 Portal Funneling: #55FF55ON;  alias funnelingChange funnelingOn"
alias "funnelingOn"  "sv_player_funnel_into_portals 1; sar_hud_set_text 0 Portal Funneling: #FF5555OFF; alias funnelingChange funnelingOff"
funnelingOn
bind <key> funnelingChange

You can also add a grey background to the SAR HUD using sar_hud_bg <0|1>.

Input HUD

Another commonly used HUD is the input HUD (ihud). This is a HUD element which displays a subset of your inputs to the game on a keyboard overlay. It is made up of 3 presets:

  • sar_ihud_preset normal - Displays WASD movement as well as jump, duck, use, and the portal shots.
  • sar_ihud_preset normal_mouse - Same as above, but also has a display of your mouse movement.
  • sar_ihud_preset tas - Displays two analog displays of your current move direction and look direction, as well as jump, duck, use, and the portal shots. This is helpful when TASing or when playing with controller.

Once set up with a preset, the ihud can be extensively modified using the command sar_ihud_modify <element|all> [property=value]....

This HUD can be used to see inputs in demos, which can be useful when learning movement.

Portal HUD

The Least Portals HUD shows how many portals you've shot in total across a play session. It is toggled using sar_lphud <0|1>, and its portal count can be reset using sar_lphud_set 0. The LP HUD accurately accounts for save loads and other level changes, so is useful in category extensions like 100 Portals.

Vphys HUD

Note: This HUD exists for routing purposes. It is not allowed in runs, and is therefore cheat protected.

The vphys HUD displays some physics information on-screen. It is useful for routers and those trying to understand various glitches in the game; it shows the states of your physics hitboxes, your current funnel handle and count, etc. It can be toggled using sar_vphys_hud <0|1>.

Ghosts

SAR includes support for ghosts: models that appear in-game to represent the position of another player. There are two kinds of ghosts: demo ghosts and network ghosts. Demo ghosts follow the path of a player defined by a demo file, whereas network ghosts represent the real-time position of another player on the same map, and are generally best suited to longer races (e.g. fullgame).

Setting Up

Demo ghosts are very simple to use. The command ghost_set_demo [demo] <id> will add a ghost using the given demo file. If specified, the ghost will be created with the given ID (replacing it if it already exists). There is also ghost_set_demos, which works similarly, but will automatically continue with successive demo files (demo_2, demo_3 etc). Once your ghosts are set up, you can start then with ghost_start. If you need to set a delay before ghosts start, you can set a per-ghost offset with ghost_offset [offset] [id].

Network ghosts are similarly simple. First, you should set a name with ghost_name [name]; this is the name you will be shown as to other people connected to the server. Then, run ghost_connect [server] [port] with the server address and port the host has given you.

Other Ghost Commands

There are many more commands affecting the appearance and behavior of ghosts.

  • ghost_delete_by_ID <id> - delete the demo ghost with the given ID.
  • ghost_delete_all - delete all demo ghosts.
  • ghost_recap - list all current demo ghosts.
  • ghost_reset - reset all demo ghosts ready for restarting.
  • ghost_TCP_only <0|1> - for network ghosts, send all position data over TCP rather than UDP. This is slower, but more reliable, so may be useful if you have an unreliable Internet connection.
  • ghost_update_rate <ms> - the number of milliseconds between sending out position updates to the ghost server. The default value, 50, is generally recommended, but can be tweaked if necessary.
  • ghost_disconnect - disconnect from the current ghost server.
  • ghost_name <name> - change what your name appears as to others on the ghost server.
  • ghost_message <msg> - send a chat message to the ghost server.
  • ghost_height <height> - set the amount to vertically offset ghosts by.
  • ghost_transparency <0-255> - set the opacity of ghost models, where 0 is completely transparent and 255 is completely opaque.
  • ghost_text_offset <height> - set the amount to vertically offset ghost names by.
  • ghost_show_advancement <0|1> - set whether to display a message in chat when ghosts move between levels.
  • ghost_proximity_fade <0-2000> - how far you need to be from ghost models before they start fading out, to prevent them from blocking your view. The default is 200.
  • ghost_show_name <0|1> - set whether to display ghosts' names above their models.
  • ghost_type <0|1|2> - sets how ghosts render for you. In type 0, ghosts simply render as plain red triangles. In type 1, ghosts render as entities with models (see ghost_prop_model). In type 2, ghosts render as red triangles, with small portal guns. See also: Run Legitimacy.
  • ghost_prop_model <model> - for demo ghosts, sets the model that all ghosts use (if ghost_type is 1). For network ghosts, set the model you appear as to other people (if their ghost_type is 1). Contains autocompletions for some common models.

Run Legitimacy

Ghosts themselves are not banned from runs. However, some aspects and uses of them are considered illegitimate.

  • ghost_type 0 and 1 are legal in runs. Type 2 is not allowed because it adversely effects demos.
  • You may not use a ghost to gain any advantage. This includes, but is not limited to, using the positions of other ghosts for lineups, or using ghost_sync to perform pause abuse (e.g. checking coordinates). Any runs submitted to speedrun.com or the CM leaderboards which in any way abuse ghosts can and will be rejected or removed.

Server

To use network ghosts, a "ghost server" must be hosted. The server is cross-platform (works on both Windows and Linux); it can be found on GitHub. To use it, set a port in the settings (the default is 53000) and, if necessary (behind NAT), forward this port on TCP and UDP.

Alternatively to setting up your own server, you can use our website which will host it for you.

The server can trigger a countdown for all connected clients, and can run commands before and after the countdown (for instance, running load vault after the countdown for a fullgame race). Note that the countdown will not work for clients in the menu; they must all be in-game.

Config+

Config+ is the name for a number of SAR commands allowing more complex configurations. More advanced use of this functionality is often referred to as Config++ or C++.

seq

The seq command takes an arbitrary number of commands as arguments, and runs them all one tick after another. For instance:

seq "say 1" "say 2" "say 3"

This will output 1 to the chat, then one tick later 2, then one tick later 3.

hwait

The hwait <ticks> <command> command runs a command after a specified number of ticks. Unlike seq, these timers run even on the menus.

cond

The second command is cond. This command allows you to only run a command in certain conditions.

cond [condition] [command]

This can be used, for instance, to automatically apply execs for different categories or levels; as an example, the condition "map=mp_coop_start & !orange" will succeed only when you run it in Calibration as blue. Conditions work as follows:

  • ?<variable>=<value> checks whether the svar <variable> is equal to the value on the right side. (e.g. the condition ?yes=1 will run if the svar 'yes' is set to 1). You can also use ?<variable> on the right side (e.g. ?foo=?bar will run if the svars 'foo' and 'bar' are the same). Originally, this syntax was var:<variable>=<value>, but the newer syntax is favored because of the 'breakset.'
  • #<cvar>=<value> checks whether the cvar <cvar> is equal to the value on the right side. (e.g. the condition #sv_cheats=1 will run if the cvar 'sv_cheats' is set to 1). You can also use #<cvar> on the right side. Alternatively, you can also use cvar:<cvar>.
  • %<string>=<value> checks whether the literal string <string> is equal to the value on the right side. (e.g. the condition %map=?variable will run if the svar 'variable' is equal to 'map'.
  • game=<game_name> checks whether you are playing a certain Source game. Currently supported games are Portal 2 (portal2), Aperture Tag (aptag), Portal Stories: Mel (mel), Thinking With Time Machine (twtm), Portal Reloaded (reloaded), and Portal 2 Speedrun Mod (srm). Any other game is recognized as other. You can also use ?<variable> on the right side here.
  • map=<map_name> checks whether you are in a certain map. You can also use ?<variable> on the right side here.
  • prev_map=<map_name> checks the last map you were in. You can also use ?<variable> on the right side here.
  • steamid=<steam32id> checks for specific partner Steam32 ID. You can also use ?<variable> on the right side here. Use sar_get_partner_id in Co-Op to retrieve your partner's Steam32 ID.
  • same_map checks whether the current map is the same as the previous map
  • coop checks whether you are in coop
  • orange checks whether you are playing as orange (P-Body)
  • cm checks whether you are in Challenge Mode
  • workshop checks whether you are currently in a map from the workshop
  • menu checks whether you are currently in the menu
  • ! is logical NOT; if put before a condition, it inverts it (e.g. the condition !orange will run unless you are playing as orange)
  • & is logical AND; it chains conditions, requiring both to be true (e.g. coop & !orange will only run if you are playing as blue in coop)
  • | is logical OR; it chains conditions, requiring at least one to be true (e.g. map=sp_a1_intro1 | map=sp_a1_intro2 will run in both Container Ride and Portal Carousel)
  • Parentheses () can be used to group expressions

For example, the following condition would run an exec when run in a coop map as orange:

cond "coop & orange" "exec coop_orange"

Another relevant command is conds, which does the same but in a sort of if-else manner. It will run the command for the first condition that is truthy.

conds [<condition> <command>]... [else]

For example, conds "coop & orange" "exec coop_orange" "coop" "exec coop_blue" "exec singleplayer" will exec the relevant file for your role. You can chain as many statements as you like.

sar_on_ Events

The sar_on_ family of commands are used to register commands to be run on certain events. These commands will pass all successive arguments to the command given; this means you do not need to quote the command given.

  • load - to be run on session start
  • session_end - to be run on session end
  • exit - to be run on game exit
  • demo_start - to be run when demo playback starts
  • demo_stop - to be run when demo playback stops
  • flags - to be run when CM flags are hit
  • coop_reset_done - to be run when coop reset is completed
  • coop_reset_remote - to be run when coop reset run remotely
  • coop_spawn - to be run on coop spawn
  • config_exec - to be run on config.cfg exec
  • tas_start - to be run when TAS script playback starts
  • tas_end - to be run when TAS script playback ends
  • pb - to be run when auto-submitter detects PB
  • not_pb - to be run when auto-submitter detects not PB

You can chain this with cond to make conditional execs as follows:

sar_on_load cond "coop & orange" exec coop_orange

svars

Configurable variables called 'svars,' or 'SAR variables,' allow you to read the values of cvars into variables. You can set an svar using svar_set <svar> <value>, read the console output of a command with svar_capture <svar> <command>, or read the value of a cvar with svar_from_cvar <svar> <cvar>. You can then do arithmetic on these variables using the following commands:

  • svar_add <svar> <svar|value> - Adds the value of the right side to the svar.
  • svar_sub <svar> <svar|value> - Subtracts the value of the right side from the svar.
  • svar_mul <svar> <svar|value> - Multiplies the svar by the value of the right side.
  • svar_div <svar> <svar|value> - Divides the svar by the value of the right side.
  • svar_mod <svar> <svar|value> - Returns the remainder when dividing the svar by the value of the right side.

For each of the above commands, there is an equivalent svar_f<...> command that uses floating point arithmetic rather than integer, i.e. svar_fadd <svar> <svar|value>. You can see what an svar is set to using svar_get <svar>. There are also the following commands for operating on a single svar:

  • svar_floor <svar> - Rounds down the value of the svar to the nearest integer.
  • svar_round <svar> - Rounds the value of the svar to the nearest integer.
  • svar_ceil <svar> - Rounds up the value of the svar to the nearest integer.
  • svar_abs <svar> - Sets the value of the svar to its absolute value. e.g. -17.2 => 17.2, 31 => 31
  • svar_substr <svar> <from> [length] - Sets the value of the svar to its substring. From starts at 0. A negative from value means from the end of the svar.

Note: If a cvar is set to 1.000000 (by incrementvar for example) and you use svar_from_cvar on it, you can coerce this value to be 1 by doing svar_add <svar> 0.

SAR Functions

sar_function is a command that allows you to make commands that can be dynamically filled with svars and passed arguments. The $ character is used to get svars or args. $1 will be replaced with the first argument given to the command, and this works up to $63. Similarly, $+1 will be replaced by all arguments after and including argument 1. $variable will be replaced with the value of the svar variable. Additionally, $- will expand to nothing, to be used as a separator between substitutions and text e.g. $variable$-hello, and $' will expand to ", for use in nested quotes. $# will be replaced with the number of arguments provided. Finally, $$ will expand to $. This substitution (excluding $1 - $63 and $+1 - $+63) can be done inline with the sar_expand command. $# will expand to -1 when using sar_expand.

Some examples:

// pass arguments to the function
sar_function print echo "$1"
print "Hello World!"                // prints "Hello World!" to the console.
// the function can read svars
sar_function print echo "$variable"
svar_set variable "Hello World!"
print                               // prints "Hello World!" to the console.

These functions are one of the main reasons SARtris is possible.

Common Mistakes

There are a few common mistakes that users make when writing Config+ commands.

  • You must quote conditions that contain breakset characters. cond var:yes=1 echo hi should be cond "var:yes=1" echo hi or cond ?yes=1 echo hi
What are more mistakes people make? I don't know because I'm so smart B)

Freecam

SAR allows you to freely control the in-game camera using commands, much like in demos. The camera can be separated from the player using sar_cam_control 1 (only works if playing a demo OR with cheats enabled). Then, the camera can be manipulated using the following commands:

sar_cam_setpos <x> <y> <z>
sar_cam_setang <pitch> <yaw> [roll]
sar_cam_setfov <fov>
sar_cam_reset

Drive Mode

As well as the above commands, the camera can also be controlled in drive mode. This is very similar to drive mode demos, but contains several extra features. Whilst holding left click, the camera can be controlled as follows:

  • Move the mouse to look around.
  • Use WASD to move around.
  • Hold left shift to speed up or left ctrl to slow down.
  • Hold right click and move mouse left and right to change camera roll.
  • Hold right click and move mouse up and down to change FOV.

Drive mode can be toggled using sar_cam_drive <0|1>

Cinematic Mode

In demos only, the camera can be given a specific path to follow for a cinematic view.

  • sar_cam_path_setkf <frame> <x> <y> <z> <pitch> <yaw> <roll> <fov> - adds a path keyframe. Parameters default to the current frame and position if not given.
  • sar_cam_path_remkf <frame> - removes the given keyframe.
  • sar_cam_path_showkfs - list all the current keyframes.
  • sar_camera_control 2 - puts the camera into cinematic mode to follow the set path.

Misc. Commands

  • sar_about - Gives information about the currently installed version of SAR. Make sure you're up to date!
  • sar_update [release|pre|canary] [exit|restart] [force] - Checks if SAR is up-to-date, and if not, updates it. If force is given, it will always reinstall, even if it may be a downgrade.
  • sar_clear_lines - Removes drawn drawline lines (like the ones used to practice moonshot).

Credits

  • NeKz : Original creator of SAR
  • Krzyhau : TASTools developer and responsible for fixing a memory leak
  • Blenderiste09, Mlugg : Past maintainers of SAR
  • AMJ, Krzyhau : Current maintainers of SAR
  • A number of other people have helped contribute, find a list here

References