Jump to content

Cheetah HUD (Backwards Strafe + Horizontal Accelmeter)

Recommended Posts



Cheetah HUD is now included with the PHGP.tv Reflex Run HUD



This is a feature packed update to the Reflex Run Accelmeter.

Added features include:

- compatibility with backwards strafe jumping

- improved smoothness of visuals

- an option to represent the accelmeter in its classic line form (as seen in Q3 DeFRaG)

- settings to customise visibility, size and scale

Share this post

Link to post
Share on other sites






I think the Reflex Run HUD is fantastic. I use its accelmeter all the time. However my opinion about this particular feature, which I have gathered from my own runs and from speaking with other runners, is that it has a few problems:

- it does not work for backwards strafe jumps

- its usage for strafe-only turning seems pointless

- unless you move it down towards the crosshair, it does not indicate whether you are lined up with the optimal angle or not

- some runners do not like its circular design, and would prefer a straight horizontal bar in the style of the Camping Gaz HUD from DeFRaG


In this thread, I will solve these problems. I will not provide full scripts - rather, I will provide the necessary pieces of code which you will need to copy and paste into the rrHUD_AccelMeter.lua file. This means that you need to have downloaded the Reflex Run HUD from the above link.


Let us look at the most important of these: going backwards. This one is quite simple to solve. Scroll down to line 96 of rrHUD_AccelMeter and add the highlighted code:

  -- Draw angle

  local vec_x = Vector2D.new(1,0)
  local vec_nx = Vector2D.new(-1,0)

  local pl_ang = posAngle(specPl.anglesDegrees.x+90)
  local vel_ang
  if playerSpeed.y >= 0 then vel_ang = playerSpeed:angle(vec_nx)
  else vel_ang = math.pi + playerSpeed:angle(vec_x) end

  -- ADD THIS *****
  if specPl.buttons.back then
    vel_ang = -vel_ang
    pl_ang = -pl_ang + 180
  -- *****

  local min_ang = math.acos(320/playerSpeed:size())
  local opt_ang = math.acos((320-accel)/playerSpeed:size())


That will enable you to practice backwards strafe jumps much more effectively. If you are new to this way of jumping, it can be confusing since the mouse must be moved into the opposite direction than if you are going forwards. The HUD updated with this code will help you learn how to position your mouse. Remember, if the BLUE line is BETWEEN your crosshair and the optimal (green line) angle, then you are moving your mouse in the WRONG direction.

With that done, now let us make it so the accelmeter only appears when we are doing forwards or backwards strafe jumps and not strafe-only jumps. Go to line 143 and add the if-end code:

  if specPl.buttons.forward or specPl.buttons.back then -- ADD THIS LINE

  nvgArc(0,0, lineSize, ang_diff_min-math.pi/2, ang_diff_op-math.pi/2, dir)
  nvgStrokeColor(ColorA(PHGPHUD_BLUE_COLOR, 120))

  nvgArc(0,0, lineSize, ang_diff_op_m-math.pi/2, ang_diff_op-math.pi/2, dir)
  nvgStrokeColor(ColorA(PHGPHUD_GREEN_COLOR, 120))





Now we want the HUD to indicate how close we are to that optimal angle - without moving the whole thing in front of the crosshair. You may want to do this if, say, you do not want your crosshair view directly obstructed.

The way I accomplished this was by creating a new crosshair with a guide line (alternatively you may want to copy the code directly into the accelmeter file instead of creating new crosshairs). The default crosshairs.lua script file (in the widgets directory) must be edited - however do not edit it directly. Rather, copy and paste the file, call it something new (like mynewcrosshairs.lua), open the new file, and rename every instance of Crosshairs to MyNewCrosshairs. Then enable the new widget in the options menu.

Now, create a 17th crosshair immediately after the first 16:

    -- Crosshair 17
    if crosshairType == 17 then

        -- Outer Circle
        nvgCircle(0, 0, crosshairSize * 8)
        nvgStrokeWidth(crosshairStrokeWeight * 2);

        -- Guide Line
        nvgStrokeWidth(crosshairStrokeWeight * 2);
        nvgMoveTo(0, -115);
        nvgLineTo(0, -135);



You may need to play around with the values here to customise it the way you want it to look. For example, this crosshair works best when the blue and green arcs in rrHUD_AccelMeter.lua are changed to these values:

  nvgArc(0,0, lineSize+20, ang_diff_min-math.pi/2, ang_diff_op-math.pi/2, dir)

  nvgArc(0,0, lineSize+20, ang_diff_op_m-math.pi/2, ang_diff_op-math.pi/2, dir)

So the lineSizes have 20 added to them, and the StrokeWidths are changed to 20 and 35.




For those who want a straight horizontal line for an accelmeter - not a circular one - I have something special for you.

Go back to the draw code at line 143 in rrHUD_AccelMeter.lua and change it to this (make sure to add those 4 cgaz locals):

  local cgazA1 = radius * math.cos(ang_diff_op_m-math.pi/2)
  local cgazA2 = radius * math.cos(ang_diff_op-math.pi/2)
  local cgazB1 = radius * math.cos(ang_diff_min-math.pi/2)
  local cgazB2 = radius * math.cos(ang_diff_op-math.pi/2)

  if specPl.buttons.forward or specPl.buttons.back then

  nvgMoveTo(cgazB1, 0);
  nvgLineTo(cgazB2, 0);
  nvgStrokeColor(ColorA(PHGPHUD_BLUE_COLOR, 120))

  nvgMoveTo(cgazA1, 0);
  nvgLineTo(cgazA2, 0);
  nvgStrokeColor(ColorA(PHGPHUD_GREEN_COLOR, 120))


(yes I called them cgazXX because I couldn't think of anything else)

This code takes the x-coordinates of the arcs and represents them as a line. Possibly there is a more elegant solution that does not require using all the arc code. I'm not bothered to find it though, since this solution works just fine.

You can adjust the StrokeWidth values to your liking. I think 35 is good; you may prefer a thinner or a thicker line.

Share this post

Link to post
Share on other sites

And of course some screenshots to show how it looks.

These are my attempts at backwards strafe jumping across Blindlight's bldf1.


Accelmeter edited with red guide line:



Horizontal accelmeter:



Both (for comparison):






I like to compete against runners from other countries. There is a nice EU race server that I occasionally visit. The accelmeter HUD, however, does not work well with high ping. I am not sure of the reason for this but it is certainly something that I would like to see fixed. Something inside the code needs to be made non-ping dependent.

Share this post

Link to post
Share on other sites

man I say thanks to this, unfortunately I've just been bombing my rr_accelmeter lua file by following your step by step process.

providing a link would be marvelous for newbie coder like me. think about the non coders.

back to the usual rr_accelmeter


newbie represent ok but still... think about us

sharing modded files would be welcome.



Share this post

Link to post
Share on other sites

Mad props on this! But better yet, you can just create a PR on RR github with these additions (with included options menu for toggling and stuff) and I'll gladly merge it into mainstream! ;D

I haven't tried making toggle options for a widget before so I'm not sure how to do it. I suppose tonight I'll look through the official Reflex widgets and copy + paste get inspiration from the code there.

I tinkered with the HUD a bit more today and made the accelmeter scalable. Testing done on Benje's rr_bejred.


With the horizontal accelmeter:






Also works for the circular accelmeter:




Oops. Too big and it wraps around to the other side:



Or both for the masochistic:



It can be scaled with any value. There is a slight issue: the bigger the scale, the quicker the meter moves, and the more jittery it becomes. But runners will be able to test different values for themselves and find one that feels comfortable and is suitable for their mouse sensitivity.

I'll make a slider thing in the widget options screen so changing scale will be easy (instead of editing the code directly).

I'll also see if I can make it easy to switch from circular to horizontal with an option button (again without having to mess around with code).

Anyone have any ideas about what else would be a great addition to the HUD?

Share this post

Link to post
Share on other sites

Options menu is easy enough, you can just look through default. I could do it for you if you want, but I think it's better you do it since you know what options you want! ;)


Also this goes for anyone that wants to contribute to RR HUD, it is an open source project so contributes are very welcomed. All you need to do is create a PR on github and I'll review it :)

Share this post

Link to post
Share on other sites

All you need to do is create a PR on github and I'll review it :)

I have submitted it to your git repository.

As the image of the options screen demonstrates, I have opted for over-doing it. Maybe you want to change some things,  whatever you think is suitable.

If you want to keep the guide circle/line that I put in, you could make it more stylish, since at the moment its just a basic circle plus a line. Perhaps a stylised arrow rather than a line, something that would fit the rest of the Reflexrun HUD theme.

The options do not use the default scale/offset settings (contra the suggestion in this thread [though I believe that concern is about widgets that provide no way for the user to reposition things without editing code, rather than how I have done it]). The reason why I have put in custom scale/offset settings is, firstly, because there are 2 accelmeters here, not 1, meaning that they need independent settings. But more importantly, because the default scale setting is not appropriate for scaling the accelmeter. My way of scaling works better, as the screenshots from the above posts show.

One other thing: what was your original intention with the blue area? The way it currently works in your build of the accelmeter is that it is a no-go zone. That is, the runner needs to get their crosshair out of the blue and into the green. I have not changed this, but perhaps you meant for the blue to go on the other side? That the blue should act as a suboptimal-but-still-increases-accel zone, rather than a hazard?

Share this post

Link to post
Share on other sites

Ok i'm still a newbie with movements, I know some strafe jumping, I can do telejumps without and with strafe.

My main concern now for progressing is keeping speed, or gaining speed. and overall how not loosing speed.

I thought the guide line would do it but it is only a still mark on the screen corresponding to the crosshair's position.

let's take an example: I'm strafe jumping with forward + left strafe in a corridor, I turn to the right at the end with right strafe only.

this is the moment I get lost with the rr_accelemeter [and now it is not showing when you strafe only, it tends to be more difficult for me]

I would like to have something that helps to know where to replace the crosshair to keep the speed and gain more.


extra note;: the line feels now more laggy than the circle one.. it is less smooth [ok still my newbie skill maybe ^^]

ok I could launch q3a with cpm and train with cgazhud on... I just love reflex too much, wanna stick to it


thank you for the hard work, it is helping me a lot for run tech matter


best to you all for magic lua widgets



Share this post

Link to post
Share on other sites

Yes, the line will have a bit of a jittery feel because I set its default scale to 3.

Try changing to scale to lower values if it is not pleasant. Larger scales accentuate the jitter. I don't know if it is possible to smooth it out any more than it already is.

I do not understand the difficulty you are having. Are you sure you are strafe jumping correctly?


Strafe-only jumping was removed since it did not help and so was annoying. The only thing you need to know about that technique is:

- hold left strafe and move mouse left, or

- hold right strafe and move mouse right

- don't hold forward

- if you are coming out of a strafe+forward jump, the strafe-only jump must be in the opposite direction or you will lose speed

Share this post

Link to post
Share on other sites

thank you man, i appreciate.


I got problems for switching... most important part is pressing strafe just before moving mouse. the strafe key is puppetmaster, the mouse move is the puppet

an image which helps me reminding this simple thing.

And you know how it is, I gain speed a lot when I don't focus on it, I guess the body is learning and I guess it is not fast enough for my mind :P


yes the aspect ratio solved it! 2 is good , 3 is not. [I would have liked to be able to set to 1.5 which I used with the original rr accelmeter]


now it works as expected :wub:



Edited by Ohm sweet

Share this post

Link to post
Share on other sites

OK I have even better news

After looking through the code again I found the reason for most of the jitter.

There is a function called posAngle(angle) which the player angle is passed through. The problem is that in this function the angle is furthermore passed through the math.modf function. This modf function is typically used to separate a float into an integer and the fractional component. Here the function returns the integer of the angle but makes its fraction disappear.

In other words: if your angle is (e.g.) 90.285652160645, the function will delete the part after the decimal point - giving you 90 back.

Since the display of the accelmeter depends on your angle, with the loss of the fraction it will snap from one integer to another. So it doesn't care that you moved from 90.28.... to 90.29.... 90.30.... 90.31.... 90.32.... it will just wait until you hit 91, then suddenly update. This is not all that noticeable at default scale of 1, but at higher scales it becomes very obvious. Hence the jitter.


The solution:

Delete/comment out line 75

--angle = math.modf(angle, 360)


This does not completely eradicate the jitter (having it 100% smooth is probably impossible). But as far as I can tell, it looks much nicer than before, especially at speeds over 1000ups. Having the scale maxed out at 20 perhaps now even looks better than scale of 3 without the change.

So can other people test this, to confirm that it's not just my eyes, that it really does look better? Try moving the scale up and down, to see if the jitter does look reduced?

quartz: was there an important reason why modf was used here? Will removing it break anything? In my testing after removing the modf, everything still seemed to be fine to me, nothing obvious broke. If it's all good, then we can send another update to git.

Share this post

Link to post
Share on other sites

Even better news x2

What I was noticing is that the remaining jitter occurred when the optimum angle was updating. Basically, the accelmeter appeared smooth when you moved your crosshair through the blue region, but as soon as you hit the green the jitter started.

There are a bunch of things that update for this, starting line 113. Importantly, the updates depend on timing:

if timer2 >= 1/fps then .....


This "fps" local is set to 120. I am not sure why 120 was chosen specifically. What I did realise is that doubling this to 240 almost completely eliminates the remaining jitter.

I guess doing so makes the accelmeter update more frequently (from 120 times a second to 240 times a second I suppose, something like that).

I tested this on max scale, it did appear quite smooth and pretty much jitter-free. It's perfect now.


Again, I didn't see any negative consequences after doing this. Perhaps it might cause a performance loss from having it update more frequently? I didn't see a performance loss, but maybe I need to test it some more.

If it does cause performance issues, then I might add to the widget options screen the ability to choose these values (e.g. slider starting at 120, can slide up to 240 or to some arbitrarily high number).

Share this post

Link to post
Share on other sites

That function was because angles were not normalized before, but electro fixed it quite soon after RR was released actually (angles range changed everytime you switched map or something like from 0 to 360 or -180 to 180 or -260 to 100, weird stuff like that). I made a function to normalize the angles to 0-360 I think, I don't quite remember.


In relation to the FPS, I don't think increasing it will affect anything (in a bad way I mean), but unless you run the game higher than the FPS specified it won't make that much of a difference as I suppose it is tied to the game fps :)

Thing is, I dedicated like a whole week of reading and understanding stuff about quake strafes and angles and all that crap and then tried to quickly come up with something similar for Reflex that worked. Looking back at the code now I see I used a lot of dirty tricks and whatnot, should probably try to smooth it all out :P


EDIT: Regarding any improvements you find worthy of including, I'm all up for it mate! As long as it works ^^

Edited by quartz

Share this post

Link to post
Share on other sites

The strange thing about it is, that I noticed after doing further testing, is that the jitter occurs if the accelmeter's fps is not equal to or more than the game's frame rate.


I normally use com_maxfps of 125, so I tested the accelmeter by setting its fps to 124. That did cause jitter, which was eliminated as soon as I increased its fps to 125. That single frame made a lot of difference, apparently.

I tested with com_maxfps of 200, and set its fps to 199. Again there was jitter, which disappeared as soon as I put it to 200.

I guess that explains why I observed the jitter to disappear when I doubled it from 120 to 240 (since I had com_maxfps 125). It just doesn't like being lower than the frame rate (but higher is fine).


So what I've done is that I made its fps tied to whatever the com_maxfps a player has set.

Though there is a slight problem with that. I'm not sure if I uncovered a Reflex bug or if it's my system, but some of the com_maxfps settings (set via the graphics options screen) don't seem to work properly.

- 60/90/125 work fine

- 144 doesn't (the frame rate goes up to around 160-170)

- 167 doesn't (frame rate goes up to 200)

- 200 works fine

- 250 works fine

- 333 doesn't (frame rate goes up to 400)

I can't check the higher values because I can't reach them. I don't think it is a problem with the options screen itself, since I checked that setting it to (e.g.) 167 does indeed set com_maxfps to 167 (and not 200).

Of course, the jitter occurred on these questionable settings. Even though the com_maxfps was 167, and the accelmeter widget read this and set its fps to 167, the jitter occurred due to the real frame rate going up to 200.

Share this post

Link to post
Share on other sites


- 144 doesn't (the frame rate goes up to around 160-170)


​for this one you just have to enable vertical sync in the options, assuming you have a 144hz monitor set to this refresh rate. ;)


I received one two weeks ago, and I also saw that com_max fps 144 was around 160-170.

I had the idea to put the vsync on and it was ok



Share this post

Link to post
Share on other sites

​I had the idea to put the vsync on and it was ok

​oww I didn't think of that. But after testing the accelmeter again with vsync on at 144 and 167 the jitter disappeared as it should. So it's all good.



Any chance at a stand alone widget that only requires reflexcore.lua?

​I will not be providing a stand alone at this time.

Note that you do not need to enable the whole Reflex Run HUD just to use the accelmeter. You can individually enable each rr_SOANDSO widget by clicking their "visible" button.

Share this post

Link to post
Share on other sites

I've been testing different features to see if there is any way to improve things further. Most of the stuff I came up with probably isn't too useful, so it's unlikely that I'll make them available.

But I'll offer a look in case I happen to have made something that people find super appealing.


This one is an inversion of the circle accelmeter. Useful for a meter that pops down from the top of the screen (or even for having it circle underneath the crosshair instead of above it).




In the spirit of customisation, the option to make it look colourful (works for both the circle and line accelmeter).





A couple of other things (no pics, use your imagination):

I noticed in some of the speedmeter widgets that people created - a line that not only grows in size depending on player speed but that also changes colour depending on the speed (e.g. green for slow, red getting faster, etc). I implemented this in the accelmeter - it begins yellow and gradually becomes redder the faster you go. It's a neat way to combine accelmeter and speedmeter into one, though it seemed more of an ornament than anything else.

Continuing from this, I made an option so the accelmeter represents true health. That is, it appears blue at 400 and red at near 0 (with shades of purple between those extremes). Again, it's a novelty that maybe won't be too much of an assistant, though perhaps this kind of visual clue will help some people play better (seeing it get redder and redder and you'll know it's time to turn and run).

Share this post

Link to post
Share on other sites


The final wish I had for the script was to make it non-ping dependent. This would, I believe, enable better international race competition.

This has now been achieved.


Runners who connect to distant race servers - pinging 300+ milliseconds - would have noticed that the accelmeter is delayed while strafe jumping. The reason for this:

getPlayer() and getLocalPlayer()

These give us player arrays that we can do interesting things with in script (the first function gives us the player whose eyes we are looking through, the second gives us the local client). Most of the variables in these arrays are not affected by ping. You can check your speed, what weapon you have selected, how much health you have, what angle you are facing, etc., without having to wait 300+ milliseconds for the answer. We encounter problem, however, when we want to know what button we pushed:


Although this is, quite simply, an array of your forward, backward, left, right, jump and attack buttons, it is ping dependent. The accelmeter needs to use this array because it needs to know when you are strafing left and when you are strafing right. The result is a ping delayed accelmeter.


The solution is an accelmeter that does not use player.buttons. One that uses player.anglesDegrees instead: being an array - one that is not affected by ping - of your yaw (looking left and right) and your pitch (looking up and down) [also apparently of roll, which would be useful for an aeroplane mod I guess].

So, by taking our current yaw, and comparing it to our yaw from a moment ago, we can determine if we have begun looking left or looking right. With this information, the accelmeter can tell us the optimum look angle.


The upshot: I have updated the accelmeter with a checkbox on its widget option screen labelled "High Ping Fix". (update pending quartz approval)

Click this option: using the accelmeter on 300+ ping will now feel the same as on zero ping.

One drawback: the anglesDegrees method is slightly buggy. With the option selected, expect occasional flickering of the accelmeter.

Share this post

Link to post
Share on other sites

A week or so ago, while I was in a race server, another racer expressed the desire to change the colour of the accelmeter. About the same time, I noticed that reflexcore contains script for colour-picking.

Since I added colours some time ago to my own personal version, I decided to add it to Reflex Run (with the addition of colour-pickers instead of manually entering colour-numbers).

Also added the option to invert the circle accelmeter.


These changes (and the high ping fix) have been added to develop version of the widget (they have not yet been put into master) .. this means you have to download it from this link:



What it looks like:


Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now