Xonotic Forums
Console Tips & Tricks - Printable Version

+- Xonotic Forums (https://forums.xonotic.org)
+-- Forum: Support (https://forums.xonotic.org/forumdisplay.php?fid=3)
+--- Forum: Xonotic - Configuration Tips (https://forums.xonotic.org/forumdisplay.php?fid=19)
+--- Thread: Console Tips & Tricks (/showthread.php?tid=2987)

Pages: 1 2


Console Tips & Tricks - BlaXpirit - 05-05-2012

Here I will be sharing some interesting things I've found about Xonotic console.

Basics

You can insert contents of any cvar anywhere: echo "ctf: ${g_ctf}""ctf: 1".
If the cvar doesn't exist, the character combination will be left unchanged and a warning will be shown. To avoid this: echo "test${unexisting_cvar ?}test""testtest".
It is possible to 'go deeper' and get a variable value by its name stored in another variable: set myvar 5; set myvarname "myvar"; ${$myvarname}5

Similar argument expansion exists for the alias command.
${1} means the first parameter passed to a command created with alias.
${3-} means all the parameters starting with the third one.
${*} means all the parameters, but I prefer ${1-}.
${4 ?} means the fourth parameter, or nothing if it wasn't passed.
${2 asis} means the second parameter, without escaping quotes (because by default they are escaped)
${* q}, ${1- q} means all the parameters as they were provided, escaped (spaces and quotes work)
alias test "echo ${3},${2-},${5 ?},${1 ?}"; test v1 v2 v3 v4"v3,v2 v3 v4,,v1"

These parentheses can be omitted ($g_dm or $1-), but not in all the cases. I like to always put them: it makes variable substitutions more noticeable.
It is possible to have 'nested' quotes by escaping them: alias go "say Wait for it...; defer 3 \"say GO!\""

If you bind a command with a plus in front of it to a key, the same command, only with minus, will be called when the key is released: +command, -command.

toggle is quite an interesting command. It switches a variable between 0 and 1 each call, or between the provided arguments: toggle some_var val1 val2 val3 val4.
defer executes the command you give to it after some seconds: defer 4.7 disconnect. And defer clear removes all pending actions.

???
PROFIT!

Advanced Console Usage

Conditionals

Let's start with making an if command. Yes, that's right, we will be able to execute commands depending on cvar values.
It will test if the value passed is a nonzero number and execute the following command only if it is so.
It can be used like this:
bx_if 5 echo "Yup""Yup"
bx_if 0 echo "Nope"×
bx_if ${g_ctf} echo "You are playing a CTF game now."

set bx_if_var_ "" // create a variable that will hold the value which is being tested
alias bx_if "bx_if_var_ ${1};············· // set our variable to the supplied value
·············toggle bx_if_var_;··········· // toggle it, so that all the nonzero values become zero
·············alias bx_if_action0_ ${2-};·· // make an action that will be executed if the value is zero (i. e. nonzero was supplied)
·············alias bx_if_action1_ bx_noop; // if the value is zero, nothing will be done (alias bx_noop "" was defined earlier)
·············bx_if_do_"··················· // call a "proxy" command, because cvars are expanded at the very beginning!
alias bx_if_do_ "bx_if_action${bx_if_var_}_" // bx_if_action0_ or bx_if_action1_ will be called depending on the variable

You may have noticed a naming convention I've used. An underscore in the end means that the command or variable is for internal use. And no, these newlines in between of a command are not allowed. This is just for presentation.

Key Combinations

set bx_shift_state 0
alias +bx_shift "+crouch; bx_shift_state 1"
alias -bx_shift "-crouch; bx_shift_state 0"
bind SHIFT "+bx_shift"

alias bx_announce_dropped "say_team Dropped %w.; g_waypointsprite_team_here"
bind G "bx_if ${bx_shift_state} bx_announce_dropped; wait; dropweapon"

If you press the G key, you will drop the current weapon. But an announcement about it to your team will be made only if Shift is down.

RPN
Before reading make sure you know what is Reverse Polish Notation.

Xonotic has a command named rpn. It allows to do various operations on a stack, such as math, but not only that.
A quick example: rpn 1 2 + 4 *"rpn: still on stack: 12".
rpn differentiates between 3 data types: float (numeric), string (text, which should be prepended with '/') and set (string of space-separated console tokens). To push these values onto the stack you just write them. If you write text without a '/' symbol before it, rpn interprets it as a variable name and replaces the name with the value of that variable.
set testvar 47; rpn 6.28 /sometext "1 2 3" testvar"rpn: still on stack: 47 \ rpn: still on stack: 1 2 3 \ rpn: still on stack: sometext \ rpn: still on stack: 6.28"

Now, for a reference of what rpn can do.
'x' will stand for any data type (plain text), 'n' for numbers, 's' for sets.
[x, pop]····[] // remove the top item.
[x, dup]····[x, x] // duplicate the top item.
[x1, x2, exch]····[x2, x1] // exchange the two top items.
[/cvar, load]····[x] // load a variable by name cvar onto the stack
[/cvar, x, (def|=)]····[] // save a value from the stack into the variable with name cvar
[n1, n2, (add|+ | sub|- | mul|* | div|/ | mod|% | max | min)]····[n] // binary operations
[n1, n2, (eq|== | ne|!= | gt|> | ge|>= | lt|< | le|<=)]····[n] // binary comparisons: 1 if true, 0 if false
[n, (neg, abs, sgn, floor, ceil)]····[n] // unary operations
[n1, n2, n3, bound]····[n] // limits n2 between n1 and n3
[n1, n2, n3, when]····[n] // if n3 is nonzero, the result is n1, else n2
[n, rand]····[n] // random integer between 0 and n-1
[time]····[n] // number of seconds (with fractional part) the game has been running for
[x, (/MD4 | /SHA256), digest]····[x] // hashing
[s, s, (union | intersection | difference)]····[s] // set operations
[s, shuffle]····[s] // shuffle elements of a sequence
There is also other functionality, even databases (which I don't quite understand). You can find more information in the "usage" text of rpn which is at the bottom of this file.

Some examples:
rpn 5 6 lt"rpn: still on stack: 1"
rpn 5 6 >="rpn: still on stack: 0"
alias bx_inc "rpn /${1} dup load 1 + =" // increase a cvar by 1: $1 = $1+1; load is used to avoid clashes with rpn commands (e.g. if $1 is intersection)
alias bx_random_range "rpn /bx_random_range_r ${2} ${1} - 1 + rand ${1} + =" // a random number between $1 and $2 inclusively: bx_random_range_r = rand($2-$1+1)+$1
rpn "/1 2 3" "/2 3 4" intersection"rpn: still on stack: 2 3".
rpn /test_string /MD4 digest"rpn: still on stack: 11e0c1ec8d9fbc76aa8fff26e44ce627"

Hash-Based String Comparison

alias bx_if_eq "rpn /bx_if_eq_var1_ \"/${1}\" /SHA256 digest =; // save the hash of the first var
················rpn /bx_if_eq_var2_ \"/${2}\" /SHA256 digest =; // save the hash of the second var
················alias bx_if_eq_action_ ${3- q};··························// save the action
················bx_if_eq_step2_"
alias bx_if_eq_step2_ "set bx_if_eq_resultvar_ \"bx_if_eq_var_${bx_if_eq_var1_}_\"; // save the name of the result var
·······················set bx_if_eq_var_${bx_if_eq_var1_}_ 0; // set the variable with the 1st hash in its name to 0
·······················set bx_if_eq_var_${bx_if_eq_var2_}_ 1; // if hashes are the same, this will change the same variable, so the result var will now hold 1
·······················bx_if_eq_step3_"
alias bx_if_eq_step3_ "bx_if ${$bx_if_eq_resultvar_} bx_if_eq_action_" // execute the action only if result is 1: hashes are equal
Hash collisions (if you know what I'm talking about) are possible in theory, but not in practice.

Miscellaneous

Weapons

Weapon Hook

When you change your active weapon, the game calls the alias cl_hook_activeweapon with a parameter that is the name of the selected weapon. Here's what I do with it:
set bx_weapon "shotgun" // default value
alias cl_hook_activeweapon "bx_weapon ${1}; bx_on_weapon_change" // now we have the current weapon name in a variable, and can execute an action, too!
alias bx_on_weapon_change "hud_panel_physics 3; bx_if_eq ${bx_weapon} laser hud_panel_physics 2" // show speed HUD panel only when laser is selected
I will show one more way to use this variable in the next section.

Weapon Switching

Don't you think that the current way to switch weapons – one, sometimes two per key – is somewhat inefficient? Well, there's a better way. Go to the console and type search cl_weapon* right now.
So, the cl_weaponpriorityN cvars can hold individual weapon cycling lists, to be used by impulse 20N, impulse 21N and impulse 22N. I'll just leave my binds here.

cl_weaponpriority1 "crylink shotgun"; cl_weaponpriority2 "hagar uzi hlac"; cl_weaponpriority3 "rocketlauncher electro grenadelauncher"; cl_weaponpriority4 "minstanex nex rifle"; cl_weaponpriority5 "fireball seeker minelayer porto"; cl_weaponpriority0 "laser hook"
bind 1 "impulse 221"; bind 2 "impulse 222"; bind 3 "impulse 223"; bind 4 "impulse 224"; bind 5 "impulse 225"; bind 6 "impulse 226"
bind Q "bx_if_not_eq ${bx_weapon} laser impulse 220; bx_if_eq ${bx_weapon} laser weaplast" // if not laser, switch to laser, else switch to previous weapon

Weapon Combos

Yes, weaplast command (Q button by default) is useful, but imagine this situation: you have a 2-weapon combo, you keep switching between those weapons, shoot your opponent... but then you need to use the laser, so your 'combo' is broken: now it is one of the weapons and laser. Well, I made a similar bx_invprev command that does just the same, but excludes laser! You can use the laser and then the command can switch back to your combo of 2 weapons.

alias bx_on_weapon_change "bx_save_last_weapon_ ${bx_weapon}" // save new weapon selection
set bx_last_weapons "" //this variable will hold 2 last weapons, separated with space
alias bx_save_last_weapon_ "rpn /bx_last_weapons_temp_ /${1} bx_last_weapons union /shotgun union \"/laser none\" difference =; // save ($1$bx_last_weaponsshotgun)–(lasernone)
····························bx_save_last_weapon_step2_"
alias bx_save_last_weapon_step2_ "bx_save_last_weapon_step3_ ${bx_last_weapons_temp_}" // a relay so we can cut off all arguments except the first 2
alias bx_save_last_weapon_step3_ "bx_last_weapons \"${1 ?} ${2 ?}\""·················· // save the first 2 weapons from the 'set'

alias bx_invprev "bx_switch_weapon2_ ${bx_last_weapons} shotgun shotgun" // shotgun is added in case the variable is empty
alias bx_switch_weapon2_ "weapon_${2}" // many arguments are passed, but we take only the 2nd
bind E "bx_invprev" // it is probably more usual to put Q here, but I use it for laser

Game Mode Hooks

When a round starts, the game calls cl_hook_gamestart_all. When it ends, the game calls cl_hook_gameend.
The game also calls cl_hook_gamestart_MODE at the beginning of every round, depending on the game mode: arena, as, ca, ctf, cts, dm, dom, ft, ka, kh, lms, nb, nop, ons, rc, rune or tdm.



Have fun using what you've learned. Make sure to tell me your interesting ideas about all of this.
And please, mention me if you want to 'retell' some of this information.

Thanks to Mr. Bougo for explaining or pointing to many of the game's secrets.

Change Log
  • 5 May 2012 - initial version
  • 11 May 2012 - added RPN, var value by name, nested quotes, string comparison, 'q' and 'asis' substitution, weapon hook, gamemode hooks; minor improvements
  • 12 May 2012 - fixed string comparison, intersection example, inc example
  • 10 Jun 2012 - added previous weapon without laser, syntax highlight; minor fixes and improvements



RE: Console Tips & Tricks - Mr. Bougo - 05-05-2012

Cool stuff! It's nice to see people interested in console tricks. There was a timespan back in the Nexuiz days where a few people (me included) got interested in this. I remember AceOfThumbs and Shaggy got pretty excited about this. And Blub blew us all out of the water by cooking up a set of aliases that emulated a basic set of x86 instructions. The config files still live in this directory and (what I guess is) the most up to date version lives in this git repo. Here's an archived thread on the nexuiz forums: link. I see Blub also made a basic lisp interpreter, that's crazy.

I also wrote some guide a while ago (now archived on the OUNS mirror -- I'm a bit embarrassed with the writing but that was long ago), it's not very complete but shows one thing that you missed: "as-is" expansion: ${foo asis}. You should talk about escaping in your guide! I personally didn't know about this "null if undefined" cvar expansion, wish I had known it back then! (Maybe it's new?)

You should make a page on the dev wiki (you'll need to sign in) for this guide! (for lack of a better place to store it currently)


Wow. That was four years ago. Time flies.

If you want to chat about the console (look up menu_cmd rpn!), hit me up on IRC. I'm on #xonotic on irc.quakenet.org.


RE: Console Tips & Tricks - Mr. Bougo - 05-12-2012

In your recent update: sets are strings of console tokens, not lists of numbers. Console tokens are arguments of console commands, i.e. with quoted strings counted as a single token. I guess this works:
rpn "/\"two words\" one \"foo bar\"" "/one two three \"foo bar\"" int
According to the source though, I think this would return the string "one foo bar" instead of "one \"foo bar\"". I can't test this now.

Also, in your bx_if_eq, ${1} isn't prefixed with a slash to make sure its contents are not considered a cvar. Isn't that needed? Same with your example of "intersection".

Lastly, I "explained" prio lists in this post. I'm not sure it belongs in console tricks, they are just a few undocumented cvars.


RE: Console Tips & Tricks - rocknroll237 - 05-12-2012

divVerent told me that I could set up custom fov settings per weapon, but is there not a feature to simply move a weapon's position without changing the fov?


RE: Console Tips & Tricks - Mr. Bougo - 05-12-2012

What "position" do you mean? Is there a cvar to change the weapon's position? If yes, then of course you can do it. Use the same trick as for fov, but replace the fov commands with position commands. The per-weapon settings system is explained in these posts: first post, shorthand


RE: Console Tips & Tricks - BlaXpirit - 05-12-2012

(05-12-2012, 06:32 AM)rocknroll237 Wrote: divVerent told me that I could set up custom fov settings per weapon, but is there not a feature to simply move a weapon's position without changing the fov?

You can always do something like
Code:
alias cl_hook_activeweapon "on_weapon_all; on_weapon_${1}"
alias on_weapon_all "fov 100; cl_gunalign 3"
alias on_weapon_rocketlauncher "fov 110; cl_gunalign 1"
... etc etc ...

Or if you have only a few special cases, you could use the conditionals as described in the original post.

Try this:
Code:
cvarlist cl_gunalign
to find out more about cl_gunalign


RE: Console Tips & Tricks - rocknroll237 - 05-12-2012

Thanks. Mr Bougo, I was asking if I could move the weapons forward without having to change the fov. So basically just being able to change how far forward the weapon is.


RE: Console Tips & Tricks - Mr. Bougo - 05-12-2012

I don't think that's possible currently. Why do you feel this is needed? Is it a question of personal preference or do you think the weapons are wrongly positioned?


RE: Console Tips & Tricks - rocknroll237 - 05-12-2012

Well for me, the machine gun is way too far back. You can hardly see the screen on it. That's all really. Big Grin


RE: Console Tips & Tricks - Mr. Bougo - 05-12-2012

What FOV do you use? If it's not a smaller fov than the default, it really should change. Please make a thread about this with screenshots.

Back on topic now, I guess.


RE: Console Tips & Tricks - zykure - 08-10-2012

Hey BlaXpirit, this is one of the most helpful posts on the forum imho (along with halogene's and fisume's guides)! Big Grin

Two remarks: Your post is missing the if_not_eq function, which is called in bx_invprev later on. It was not that hard to implement it myself from what you wrote (copy over if_eq and exchange 0 and 1 in the second part), but I think it's better to include that as well. Apart from that, I'm really impressed how good these two binds work (laserswitch + improved lastweapon).

The other thing is that I wondered if the laserswitch function is broken because it didn't switch back to the last weapon like I expected it, but to the second-last one instead. After spending some thoughts on how to solve this, it became clear to me that it makes more sense this way since you can always use the lastweapon bind to go back. Now it's even possible to switch from wpn A to wpn B to laser, then back to wpn A and repeat, without touching one of the direct weapon keys. Just plain awesome!


RE: Console Tips & Tricks - BlaXpirit - 08-10-2012

Thank you for the kind words.

I didn't include every possible combination of these `if` commands, because I want people to learn something from this and make their own stuff, not just copy. And the post is quite fat anyway.

As for the laser switch, it's just the way it works; laser is a special case in it, after all... I did change the bind in my own config to switch to the last weapon, not the second. I just put a conditional there: "if current weapon is laser, `weaplast`, else `bx_invprev`"


RE: Console Tips & Tricks - PillowPants - 06-15-2013

If I wanted to set up a custom bind where "g" (or any other key) is "impulse 220" except when playing minsta+hook, where it would be "+hook". How would I go about doing that? Smile


RE: Console Tips & Tricks - Mr. Bougo - 06-15-2013

(06-15-2013, 10:49 AM)PillowPants Wrote: If I wanted to set up a custom bind where "g" (or any other key) is "impulse 220" except when playing minsta+hook, where it would be "+hook". How would I go about doing that? Smile

You can't, sorry. There are config hooks* for game start events for each game type, but not for mutators (minsta is a mutator for deathmatch). Besides, there's no way to detect whether or not the hook is enabled on the server. What can be done however is CTF-specific binds, or TDM-specific binds, or race binds etc.

*Not grappling hooks, but a command that can be defined to intercept certain kinds of events.


You can however have a bind to toggle the g key's functionality. Here's how you do it, using p to toggle what g does:
Code:
alias +gkey "+gkey_mh${_gkey_mh}"
alias -gkey "-gkey_mh${_gkey_mh}"
alias +gkey_mh1 "+hook"
alias -gkey_mh1 "-hook"
alias +gkey_mh0 "impulse 220"
alias -gkey_mh0 ""

alias gkey_toggle "-gkey; toggle _gkey_mh; _gkey_toggle2"
alias _gkey_toggle2 "echo ^1g key minsta hook status set to ^3${_gkey_mh}"

bind p gkey_toggle
bind g +gkey
Untested, but should work fine. The -gkey_mh0 in gkey_toggle is to release the key when p is pressed, otherwise you might get stuck with +hook if you press p while hooking. It could have side effects if you have anything special in one of the - binds, but that's not the case here.


RE: Console Tips & Tricks - PillowPants - 09-14-2013

(06-15-2013, 01:16 PM)Mr. Bougo Wrote:
(06-15-2013, 10:49 AM)PillowPants Wrote: If I wanted to set up a custom bind where "g" (or any other key) is "impulse 220" except when playing minsta+hook, where it would be "+hook". How would I go about doing that? Smile

You can't, sorry. There are config hooks* for game start events for each game type, but not for mutators (minsta is a mutator for deathmatch). Besides, there's no way to detect whether or not the hook is enabled on the server. What can be done however is CTF-specific binds, or TDM-specific binds, or race binds etc.

*Not grappling hooks, but a command that can be defined to intercept certain kinds of events.


You can however have a bind to toggle the g key's functionality. Here's how you do it, using p to toggle what g does:
Code:
alias +gkey "+gkey_mh${_gkey_mh}"
alias -gkey "-gkey_mh${_gkey_mh}"
alias +gkey_mh1 "+hook"
alias -gkey_mh1 "-hook"
alias +gkey_mh0 "impulse 220"
alias -gkey_mh0 ""

alias gkey_toggle "-gkey; toggle _gkey_mh; _gkey_toggle2"
alias _gkey_toggle2 "echo ^1g key minsta hook status set to ^3${_gkey_mh}"

bind p gkey_toggle
bind g +gkey
Untested, but should work fine. The -gkey_mh0 in gkey_toggle is to release the key when p is pressed, otherwise you might get stuck with +hook if you press p while hooking. It could have side effects if you have anything special in one of the - binds, but that's not the case here.

Hi Mr Bouge,

Didn't know you had replied, so thank you first of all Smile Second, it doesn't work Sad I do get output to the console:

g key minsta hook status set to ${_gkey_mh}

but no change from laser (impulse 220) to hook and vice versa. Could you help me again?

Thanks!!


RE: Console Tips & Tricks - Mr. Bougo - 09-14-2013

Right. There's a line missing:
Code:
set _gkey_mh 0

Put it at the top.


RE: Console Tips & Tricks - PillowPants - 09-14-2013

(09-14-2013, 08:43 AM)Mr. Bougo Wrote: Right. There's a line missing:
Code:
set _gkey_mh 0

Put it at the top.

Thanks for the quick response but it still doesn't work Confused The output makes more sense though:

key minsta hook status set to 1

Thanks again Mr Bougo!


RE: Console Tips & Tricks - Mr. Bougo - 09-14-2013

Really? It works for me though... Hm.

What happens when you press g then?


RE: Console Tips & Tricks - PillowPants - 09-14-2013

This is printed to the console:

key minsta hook status set to 1

I did bind it to F12, but I'm guessing that doesn't matter Smile


RE: Console Tips & Tricks - Mr. Bougo - 09-14-2013

Huh. But my code above makes p do what you say.

Here p is supposed to toggle what the g key does.


RE: Console Tips & Tricks - PillowPants - 09-14-2013

(09-14-2013, 01:35 PM)Mr. Bougo Wrote: Huh. But my code above makes p do what you say.

Here p is supposed to toggle what the g key does.

This is verbatim what I have (I use p now):

set _gkey_mh 0
alias +gkey "+gkey_mh${_gkey_mh}"
alias -gkey "-gkey_mh${_gkey_mh}"
alias +gkey_mh1 "+hook"
alias -gkey_mh1 "-hook"
alias +gkey_mh0 "impulse 220"
alias -gkey_mh0 ""

alias gkey_toggle "-gkey; toggle _gkey_mh; _gkey_toggle2"
alias _gkey_toggle2 "echo ^1g key minsta hook status set to ^3${_gkey_mh}"

bind p gkey_toggle


I did put this in autoexec.cfg cause in config.cfg the code disappears after I start Xon (does this matter). I also bind p gkey_toggle in config.cfg. I missing something obvious but I don't know what Confused


RE: Console Tips & Tricks - Mr. Bougo - 09-14-2013

Um. You are supposed to bind the g key to +gkey:
Code:
bind g +gkey

EDIT: I suppose you didn't realize there was a scroll bar in the code box. Sorry about that!


RE: Console Tips & Tricks - PillowPants - 09-14-2013

(09-14-2013, 02:28 PM)Mr. Bougo Wrote: Um. You are supposed to bind the g key to +gkey:
Code:
bind g +gkey

EDIT: I suppose you didn't realize there was a scroll bar in the code box. Sorry about that!

Thats it! I knew it would be obvious... :p

Thanks a bunch Mr. Bougo! +1


RE: Console Tips & Tricks - FinBiteLeaf - 03-02-2020

Hi! Probably i am too stupid, but i can't figure out what code to input in console if i want to make the following: press W button to use Blaster - > If Blaster is already used, pressing of W button changes it to previously used weapon.

Please help


RE: Console Tips & Tricks - martin-t - 03-05-2020

The first post pretty much shows everything you need. Use cl_hook_activeweapon to get the name of the current weapon. If it's blaster (the post shows how to build conditions), bind W to prev weapon (not sure the exact command name but it's on Q by default i think). If it's anything else, bind W to blaster. The config.cfg shows how to set binds - you can do it each time the cl_hook_activeweapon alias runs. Ofc if you've never coded before, don't try to do all this at once - split it into multiple steps, make sure each one works separately, then combine them.