eukara / freecs

Clean-room Counter-Strike 1.5 in QuakeC, using Nuclide SDK. Previously known as OpenCS! (2016)
https://www.frag-net.com/projects.html
ISC License
183 stars 16 forks source link

recoil/gunplay rework intial #29

Closed mikota closed 1 year ago

mikota commented 1 year ago

The changes to the gunplay this rework entails are shown off in this video

This is a rework of the recoil system in FreeCS. The hope is to bring it closer to the original feel of Counter-Strike. There are numerous changes to the system:

-The punchangle recovery has been slightly modified. The important one is the recovery of the vertical recoil/punchangle. The new formula used to calculate the recovery is less sudden for very high vertical recoil compared to the original. This code had to be changed in the Nuclide source, so you can see it here: https://github.com/mikota/nuclide/commit/bde001b781fd69ae8f012bfa1d47842a32b6b258

atomGit commented 1 year ago

no offense to anyone, but personally i was never a fan of the randomness of the weapons - i suspect a lot of players found it to be annoying

the way randomness is currently isn't too bad, but i, for one, am certainly not in favor of amplifying it further and would instead lean toward reducing it

atomGit commented 1 year ago

perhaps more reasoning on my part is warranted...

when valve got their hands on cs they dumbed it down in an attempt to level the playing field, part of that being increasing bullet randomness, and this pissed off a lot of users to the point where, years later, they apparently reduced/reverted some of the changes

IMHO, going in the same general direction as valve with FreeCS regarding randomness is a potential mistake

personally, i'm not a fan of bullet randomness at all - no matter what the gun is or what the player is doing (running/jumping/falling/etc.) i would prefer if the bullets land wherever the crosshair does

just my $0.2 :)

eukara commented 1 year ago

The Nuclide changes can be migrated to cstrike by implementing Physics_InputPreMove into the player class there and calling the super function (super::Physics_InputPreMove) so that you don't have to implement the entire thing, then doing the punchangle *= [...] modifications there. That way the change can be kept only to CS and not affecting the other games.

I do think, judging by the video you'd posted on Matrix, that it appears closer to the shooting in CS than my attempt. Good job! I think @atomGit has a point regarding randomness and we can try to work around some of that (or it can always be turned into a cvar... we can indeed have both things).

atomGit commented 1 year ago

or it can always be turned into a cvar

ah, yeah - i like that idea!

that should suit everyone, especially if randomness could be selected on a scale from 0-10 or whatever

mikota commented 1 year ago

The Nuclide changes can be migrated to cstrike by implementing Physics_InputPreMove into the player class there and calling the super function (super::Physics_InputPreMove) so that you don't have to implement the entire thing, then doing the punchangle *= [...] modifications there. That way the change can be kept only to CS and not affecting the other games.

Thank you I will try to figure it out.

As far as @atomGit 's accuracy concerns, it's a complicated issue. The first problem comes from the fact that we don't have shared terminology about the way it works, and so it's hard to talk about it..

For example, Beta 1.0 of Counter-Strike is the most random of all the versions in many ways. Even while standing still with the M4 or the USP, your bullets will fly way outside your crosshair (usually called first shot accuracy). If you spam the USP they fly even more (usually called firing inaccuracy spread), and when continuously firing the M4, it gets incredibly ridiculous (bullets go farther if you're standing still than if you run and gun the same weapon in CS 1.6), and the iconic CS recoil pattern is not there yet.

In Beta 4.0, a lot of that firing inaccuracy spread was gone, but many weapons still retained the wacky first shot accuracy where you can't hit the broad side of a barn even with your first shot. As well as that, the base recoil now works the way it does in CS 1.6, and the way it works in the current version of my changes - the recoil has a base strength for each automatic weapon, and it gets amplified during the early to mid part of the spray and winds down towards the end. As well as that, the weapon randomly switches horizontal direction - as it does in 1.6 and my current version (I'd call this recoil direction randomness).

To top it off, there is some movement spread inaccuracy (bullets flying in a random radius after recoil is calculated) in Beta 4.0, but I'm not sure exactly how it works. What I am sure of though, is that there is also movement recoil inaccuracy (recoil gets stronger and recoil variance gets stronger the more you move), and it's pretty strong.

In Beta 6.0, there is again differences. Firing inaccuracy spread seems to have come back, though weaker, and then there's this, and then there's that...

Point is, there was never a point where bullets would just go where your crosshair is in CS, unless there's some secret Beta -36.2b I'm not aware of. Each version had it's own systems, and each new version seems to have, alongside adding new ones, kept the old ones but with tweaked values. The later versions, post beta, are very complex. If you really wanted to, you could create for example Beta 4.0 behavior in this commit's system by setting float divisor in Cstrike_CalculateAccuracy to a very high value (to remove the firing inaccuracy spread) and adding a big constant to the return value, such as 0.05f (to add the ridiculously bad first shot accuracy). You could also remove the recoil going above the crosshair altogether, but then you're not playing any version of CS (maybe it's RQ3, maybe it's Urban Terror?)

With that said, I'm not a hater of weakening the randomness. The goal here was to create something close to original Counter-Strike, but even with that, my changes are still less random than 1.6, in some cases by a lot, and I'm down to lower it further in certain cases (and it's not my project anyway - this should be @eukara 's decision). I'll try to create cvar(s?) that control the amount of random stuff, but what does that even mean (one cvar to control all randomness, or separate cvar for firing inaccuracy spread, seperate for firing inaccuracy recoil variance, separate for first shot accuracy multiplier, separate for base recoil strength, separate for recoil above crosshair multiplier, separate for etc etc etc...)?

I'll try to figure it out and welcome suggestions on how exactly to do it, but I definitely don't think a recreation of CS should disable all the randomness and recoil, because then you're not playing CS.

atomGit commented 1 year ago

hi again @mikota

... but what does that even mean (one cvar to control all randomness, or separate cvar for firing inaccuracy spread, seperate for firing inaccuracy recoil variance, separate for first shot accuracy multiplier, separate for base recoil strength, separate for recoil above crosshair multiplier, separate for etc etc etc...)?

i'm admittedly out of my league here, but perhaps a KISS approach would be good enough where randomness in all conditions could be scaled with a single cvar??? i assume that would keep everything proportional

assuming that's not too difficult, i'd still propose that the lowest value be 0 - no, or minimal randomness - and the default value be... whatever

eukara commented 1 year ago

I trust your judgment @mikota. I know coming from games like ProMode/CPMA that there's demand for a mode that involves little randomness (or some predictable patterns at the least, which is what I attempted with exception to shotguns obviously).

I didn't have much confidence in my ability to recreate the spray patterns/recoil to the degree that you did, so I tried to at least make something that played okay - striking the balance between pleasing players that look for a challenge while being 'close enough' to everyone else who's only casually played CS.

So I'm not bullish about my implementation and I'm very happy that you contributed this here :)

eukara commented 1 year ago

hi again @mikota

... but what does that even mean (one cvar to control all randomness, or separate cvar for firing inaccuracy spread, seperate for firing inaccuracy recoil variance, separate for first shot accuracy multiplier, separate for base recoil strength, separate for recoil above crosshair multiplier, separate for etc etc etc...)?

i'm admittedly out of my league here, but perhaps a KISS approach would be good enough where randomness in all conditions could be scaled with a single cvar??? i assume that would keep everything proportional

assuming that's not too difficult, i'd still propose that the lowest value be 0 - no, or minimal randomness - and the default value be... whatever

There's multiple types of choices randomness goes through, some of it is very much desired. One example is the direction a bullet/punch may fly. For example it may choose to go left, or go right relative to the player camera. If you turned off randomness in the left/right scenario, it'll only ever go into one direction.

Vertically, as everyone knows it will generally go up (by the amount specified by the 'shot multiplier', and gradually get lower when not firing).

So what one could do is take the 'shot multiplier' into account when choosing the direction. This isn't random but generally might feel so to the players that don't pay much attention.

Of course, we can add various scalers to all the different aspects of firing - which I am not against entirely as people will have an easier time tweaking the game to their liking. It just needs to be thoroughly documented so people have an idea of what they're exactly changing.

mikota commented 1 year ago

I manually upped some of the SMG values to make them more accurate.

I also added these cvars:

This is as simple as I could make it, I think. If you set all of these to zero, automatic rifles will basically behave like a quake MG (except more accurate).

Default values for all of these are 1. I tried to do a dummy recoil pattern for when guns_random_recoil_direction is set to zero as @eukara mentioned but it's not perfect yet.

mikota commented 1 year ago

The Nuclide changes can be migrated to cstrike by implementing Physics_InputPreMove into the player class there and calling the super function (super::Physics_InputPreMove) so that you don't have to implement the entire thing, then doing the punchangle *= [...] modifications there. That way the change can be kept only to CS and not affecting the other games.

This still needs to be done. And I'm also getting errors in the console about writing to a read only variable in CstrikeBulletRecoil class.

As far as what the default values for the new cvars should be, I'd personally let them stay at 1, as it's closest to feeling like Counter-Strike to me. Obviously, the values could be lowered up to zero if you want more quake-style gameplay. If you want the shooting to feel like Counter-Strike but still be able to jump around and spray all over the place, halving the value of guns_movement_inaccuracy and guns_firing_inaccuracy is a possible change. If you decide to lower the recoil, I recommed you don't set guns_recoil_strength to anything less than 0.8, as the effect that cvar has on the recoil is very drastic even with small increments/changes.

eukara commented 1 year ago

The error is probably about you writing into your m_flRandomSpread when the class it belongs to was never instanced. You can have classes in QC that are basically just namespaces, but if you want to write into class specific attributes you have to allocate them as an object.

One simple, quick and dirty fix is (if you want m_flRandomSpread to be a global that applies to weapon operations for all clients) to check for a global variable of that class, see if it is NULL or world and if so, to instance it. For example in any of the methods:

if (!g_cstrikeBulletRecoil)
   g_cstrikeBulletRecoil = spawn(CstrikeBulletRecoil);

/* now we have a valid instance to write into */
g_cstrikeBulletRecoil.m_flRandomSpread = [...]

Of course, if you want these to be player specific, the code would have to be different (allocating an instance per player, within the player.qc code). But that's why the code is not running as expected.

mikota commented 1 year ago

The error is probably about you writing into your m_flRandomSpread when the class it belongs to was never instanced. You can have classes in QC that are basically just namespaces, but if you want to write into class specific attributes you have to allocate them as an object.

One simple, quick and dirty fix is (if you want m_flRandomSpread to be a global that applies to weapon operations for all clients) to check for a global variable of that class, see if it is NULL or world and if so, to instance it. For example in any of the methods:

if (!g_cstrikeBulletRecoil)
   g_cstrikeBulletRecoil = spawn(CstrikeBulletRecoil);

/* now we have a valid instance to write into */
g_cstrikeBulletRecoil.m_flRandomSpread = [...]

Of course, if you want these to be player specific, the code would have to be different (allocating an instance per player, within the player.qc code). But that's why the code is not running as expected.

I decided to remove that part of the code as it was unnecessary anyway. This final commit brings the punchangle stuff into the cstrike codebase, as well as small tweaks to the recoil system.

eukara commented 1 year ago

Looks all good. Thank you very much for this rework effort!

atomGit commented 4 months ago

@mikota - how does one make use of these new autocvar_fcs_guns_* cvars? it seems they're not recognized when entering them in the console and i'd like to add them to server.cfg

mikota commented 4 months ago

@mikota - how does one make use of these new autocvar_fcs_guns_* cvars? it seems they're not recognized when entering them in the console and i'd like to add them to server.cfg

They're all prefixed with fcs_guns_. For example, fcs_guns_movement_inaccuracy 0.1 should make running and gunning a lot more viable if that's what you prefer. They work on my machine, but I have an old build atm so something might've gotten borked in the meantime.