andrei-drexler / ironwail

High-performance QuakeSpasm fork
GNU General Public License v2.0
526 stars 49 forks source link

[Feature Request] v_gunkick 2 effect doesn't shake the screen as much with the Nailguns #87

Closed Muleke closed 2 years ago

Muleke commented 2 years ago

Title. I don't know if this is actually intended, but, compared to QE (Quake Enhanced) and QSS, when firing the Nailgun or Super Nailgun with v_gunkick 2, the screen doesn't tilt as much. For instance, on Ironwail, when firing a Nailgun, the screen goes up a bit and pretty much stays in that position until you stop shooting, instead of tilting up and down constantly, giving the feel of firing a machinegun.

I am running Ironwail 0.6.0.

gilabogus commented 2 years ago

The original game doesn't have v_gunkick cvar and thus the "gun kicking" couldn't be disabled. I suspect it's also the reason why it's the same (no command to disable it) in Quake Enhanced re-release.

At some point one of the engines added v_gunkick command. If you check FitzQuake Mark V, it has possible values:

0 - disabled 1 - WinQuake behavior 2 - smoother animation

I think this was adopted by Quakespasm as well, even though there's nothing about it in the documents.

garoto commented 2 years ago

It's mentioned in Misc\fitzquake085.txt.

Muleke commented 2 years ago

The original game doesn't have v_gunkick cvar and thus the "gun kicking" couldn't be disabled. I suspect it's also the reason why it's the same (no command to disable it) in Quake Enhanced re-release.

At some point one of the engines added v_gunkick command. If you check FitzQuake Mark V, it has possible values:

0 - disabled 1 - WinQuake behavior 2 - smoother animation

I think this was adopted by Quakespasm as well, even though there's nothing about it in the documents.

Ok, but, sorry, I don't see how this is related to what I reported. What you said is true though.

I reported this because, since Ironwail is a fork of QuakeSpasm, I thought this feature (v_gunkick 2) would have the same visual effect in both engines, but they are different, at least when firing the NG and SNG.

gilabogus commented 2 years ago

I just tried Ironwail 0.6.0 and Quakespasm 0.94.4 and NG/SNG firing look the same to me with v_gunkick 2 (the screen shakes but very tiny amount). However it is different in Quakespasm-Spiked!

Muleke commented 2 years ago

I just tried Ironwail 0.6.0 and Quakespasm 0.94.4 and NG/SNG firing look the same to me with v_gunkick 2 (the screen shakes but very tiny amount). However it is different in Quakespasm-Spiked!

Ohh, I thought QS and QSS shared the same gun kick behavior! That's why I assumed that. I mainly use QSS, btw. Sorry about that! However, I still think the v_gunkick 2 effect can be improved in Ironwail.

mhQuake commented 2 years ago

This feature always felt unfinished in the original FitzQuake source (which is where it originally comes from) and I assume that QSS just fixes it, but I haven't checked the code to verify. It's easy enough to just rewrite and the resulting lerped gunkick is a nice visual step-up.

mhQuake commented 2 years ago

Suggested patch.

In view.c

vec3_t v_punchangles[2]; // copied from cl.punchangle.  0 is current, 1 is previous value. never the same unless map just loaded

In V_CalcRefdef:

    // v_gunkick
    if (v_gunkick.value == 1) // original quake kick
    {
        r_refdef.viewangles[0] += cl.punchangle[0];
        r_refdef.viewangles[1] += cl.punchangle[1];
        r_refdef.viewangles[2] += cl.punchangle[2];
    }
    else if (v_gunkick.value == 2) // lerped kick
    {
        float punchblend = (cl.time - cl.punchtime) / 0.1f;

        if (punchblend < 0.0f) punchblend = 0.0f;
        if (punchblend > 1.0f) punchblend = 1.0f;

        r_refdef.viewangles[0] += v_punchangles[1][0] + (v_punchangles[0][0] - v_punchangles[1][0]) * punchblend;
        r_refdef.viewangles[1] += v_punchangles[1][1] + (v_punchangles[0][1] - v_punchangles[1][1]) * punchblend;
        r_refdef.viewangles[2] += v_punchangles[1][2] + (v_punchangles[0][2] - v_punchangles[1][2]) * punchblend;
    }

When going to a new map:

    // clear punch angles
    v_punchangles[0][0] = v_punchangles[0][1] = v_punchangles[0][2] = 0.0f;
    v_punchangles[1][0] = v_punchangles[1][1] = v_punchangles[1][2] = 0.0f;
    cl.punchangle[0] = cl.punchangle[1] = cl.punchangle[2] = 0.0f;
    cl.punchtime = 0;

In cl_parse.c, CL_ParseClientdata, after reading the SU_PUNCH* bits:

    extern vec3_t v_punchangles[2];

    if (v_punchangles[0][0] != cl.punchangle[0] || v_punchangles[0][1] != cl.punchangle[1] || v_punchangles[0][2] != cl.punchangle[2])
    {
        // beginning a new punch
        VectorCopy (v_punchangles[0], v_punchangles[1]);
        VectorCopy (cl.punchangle, v_punchangles[0]);
        cl.punchtime = cl.time;
    }

And add double punchtime to the client_state_t struct.

andrei-drexler commented 2 years ago

Thanks, @mhQuake, applied in ddc599dfe3418faae88f412af8e2109c7ac237aa.

PS I wouldn't necessarily call the FitzQuake implementation unfinished, though, it's very similar to this version, the main difference being that it always interpolates from the current local value to the last punchangle from the server, instead of interpolating between the last two server values. This makes it smoother during sequences with wild swings, when the client doesn't get a chance to reach the endpoint before the server sends a significantly different angle (such as the earthquake at the beginning of the mg1 hub map). In any case, the cvar is named v_gunkick, and for this particular use case the FitzQuake version does seem too smooth.