GeneralsGamePatch icon indicating copy to clipboard operation
GeneralsGamePatch copied to clipboard

Change: Remove infantry target scatter from USA Laser Turret

Open xezon opened this issue 2 years ago • 19 comments

This change removes the infantry target scatter from the USA Laser Turret. It will no longer miss infantry at random. The miss chance was around 25% (sampled). This makes its targeting performance consistent with the USA Laser Crusader, that, despite having scatter too, never misses its infantry targets in practice.

The regular USA Patriot also has infantry target scatter, but will not fail to damage infantry when stationary, due its larger primary damage radius.

TODO

  • [ ] Re-add a bit of scatter vs Infantry so it looks nice
  • [ ] Add DamageType=TOPPLING to Laser Patriot

Before

https://github.com/TheSuperHackers/GeneralsGamePatch/assets/4720891/c8220727-7fc1-4ef8-b88b-285d48bf58f3

Rationale

The Laser weapon now works as one would expect without random misses. Performs consistent with USA Laser Crusader.

xezon avatar Jul 08 '23 06:07 xezon

This is a big buff to the strongest defense tower in the game, especially considering one of the best early game counters to a Laser turret (which can be airdropped by Dozer/Chinook into your base) is the Troop Crawler.

commy2 avatar Jul 08 '23 07:07 commy2

It is a considerable buff yes.

I suspect the scatter behavior is simply a result of Patriot Battery definition copy & paste, with no special consideration for the Laser weapons. If this was designed from scratch, then the scatter would likely raise more eyebrows than not.

I do not like the scatter, because it adds unnecessary randomness, but I also do not like making it stronger versus infantry.

If we could add a new LETHAL_LASER damage type with Thyme, then we could readjust the infantry damage to (somewhat) cancel the impact this change has.

xezon avatar Jul 08 '23 09:07 xezon

Then we should not add this until then, we don't want the laser turret buffed

MTKing4 avatar Jul 08 '23 12:07 MTKing4

I don't think it would be too much of a change objectively, but if you want people to play the patch, you need to sell it to them, and I expect "they buffed the Laser turret!" to not help. I may be wrong though.

commy2 avatar Jul 08 '23 12:07 commy2

Realistically fixing the Patriot Turret Range bug would be enough to cancel any buffs we add.

xezon avatar Jul 08 '23 12:07 xezon

I don't think it would be too much of a change objectively, but if you want people to play the patch, you need to sell it to them, and I expect "they buffed the Laser turret!" to not help. I may be wrong though.

You're not wrong, i know i would say that too if i was them

MTKing4 avatar Jul 08 '23 12:07 MTKing4

Fixing the Patriot Turret Range bug would not offset the buff at all. I have never seen the laser pat bug come into play in anything except in AOD lol. I will add I agree with fixing that bug though.

The laser patriot as commy2 points out is exceptionally strong as it is.

OoE-ExCaL avatar Aug 04 '23 17:08 OoE-ExCaL

Realistically fixing the Patriot Turret Range bug would be enough to cancel any buffs we add.

This is no good reasoning to make it better at closer ranges than it already is.

ImTimK avatar Aug 04 '23 17:08 ImTimK

Btw, don't lasers have KnockBack effect? Or recoil? At least in the game's logic with laser tanks anyway, so it kinda makes sense that it looses a bit of accuracy after each shot

MTKing4 avatar Aug 04 '23 19:08 MTKing4

Knock Back effect?

Nah, that would be stuff like Bunker Buster or Nuke Mig.

Or recoil?

Laser tank recoils. Laser turret doesn't. Doesn't make much sense either, but it's just a fancy animation.

commy2 avatar Aug 04 '23 19:08 commy2

Maybe Knockback is the wrong wording for it, but you get what i meant

Laser tank recoils. Laser turret doesn't. Doesn't make much sense either, but it's just a fancy animation.

Then We can add that animation and be done with it, no need to buff turrets, then it would make sense why it misses some shots

MTKing4 avatar Aug 04 '23 19:08 MTKing4

In my opinion the preferred approach here is to remove the scatter, then readjust the damage to nullify its effect. This would then get rid of the randomness, which is ultimately desired, because game state becomes more deterministic and therefore readable.

xezon avatar Aug 04 '23 20:08 xezon

Laserpat is very good vs moving inf, pretty sure this was done to slightly nerf it (no longer one clip). Not sure why you want to get rid of it, but if you do, atleast compensate by nerfing the damage by the same amount.

ImTimK avatar Aug 04 '23 22:08 ImTimK

pretty sure this was done to slightly nerf it

It's copy paste from the rocket version. Not a single thought was put into it.

commy2 avatar Aug 04 '23 22:08 commy2

It might be the case that they never tested it after copy paste, but how do we know for certain? Is the lasertank full proof laser weapons aren't supposed to miss like that?

Look, I don't mind if randomness gets removed, I only care about the balance part, one clip to kill one infantry unit (without reload) makes a huge difference and is a big buff.

ImTimK avatar Aug 04 '23 23:08 ImTimK

Laserpat is very good vs moving inf, pretty sure this was done to slightly nerf it (no longer one clip). Not sure why you want to get rid of it, but if you do, atleast compensate by nerfing the damage by the same amount.

Because generally randomization is undesired in a strategy game. Pseudo randomization is ok if sequence is predictable, but randomization typically is not predictable.

so for example a sequence of

101010101010

would be ok, but a sequence of

111111000000

would be not ok, because now there are 6 consecutive identical cases which in case of the Laser Patriot would translate to 6 missed shots in succession. We do not want this.

Here is the relevant code for the Scatter:

uint32_t g_theGameLogicSeed[6] = { 0xF22D0E56, 0x883126E9, 0xC624DD2F, 0x0702C49C, 0x9E353F7D, 0x6FDF3B64 };

const float g_theMultFactor = 1.0 / (Pow(2.0, 32.0) - 1.0);

// Get the next random value based on the given seed.
uint32_t Random_Value(uint32_t seed[6])
{
    uint32_t tmp0 = seed[0];
    uint32_t tmp1 = seed[1];
    uint32_t tmp2 = seed[2];
    uint32_t tmp3 = seed[3];
    uint32_t tmp4 = seed[4];
    uint32_t tmp5 = seed[5];

    seed[4] += tmp5;
    seed[3] += (seed[4] < tmp4 || seed[4] < tmp5) + seed[4];
    seed[2] += (seed[3] < tmp3) + seed[3];
    seed[1] += (seed[2] < tmp2) + seed[2];
    seed[0] += (seed[1] < tmp1) + seed[1];

    if (++seed[5] == 0) {
        if (++seed[4] == 0) {
            if (++seed[3] == 0) {
                if (++seed[2] == 0) {
                    if (++seed[1] == 0) {
                        ++seed[0];
                    }
                }
            }
        }
    }

    return seed[0];
}

float Get_Logic_Random_Value_Real(float lo, float hi, const char *file, int line)
{
    float diff = hi - lo;

    if (diff > 0.0f) {
        return float(float(float(Random_Value(g_theGameLogicSeed) * g_theMultFactor) * diff) + lo);
    }

    return hi;
}

unsigned int WeaponTemplate::Fire_Weapon_Template(
...
    if (m_scatterRadius > 0.0f
        || (m_scatterRadiusVsInfantry > 0.0f && victim_obj != nullptr && victim_obj->Is_KindOf(KINDOF_INFANTRY))) {
        scatter = m_scatterRadius;
        PathfindLayerEnum layer = LAYER_GROUND;

        if (victim_obj != nullptr) {
            if (victim_obj->Is_KindOf(KINDOF_STRUCTURE)) {
                victim_obj->Get_Geometry_Info().Get_Center_Position(*victim_obj->Get_Position(), pos);
            }

            if (m_scatterRadiusVsInfantry > 0.0f && victim_obj->Is_KindOf(KINDOF_INFANTRY)) {
                scatter += m_scatterRadiusVsInfantry;
            }

            layer = victim_obj->Get_Layer();
        }

        scatter = Get_Logic_Random_Value_Real(0.0f, scatter);
        float angle = Get_Logic_Random_Value_Real(0.0f, DEG_TO_RADF(360.0f));
        Coord3D pos3;
        pos3.Zero();
        pos3.x = GameMath::Cos(angle) * scatter;
        pos3.y = GameMath::Sin(angle) * scatter;
        pos.x += pos3.x;
        pos.y += pos3.y;
        pos.z = g_theTerrainLogic->Get_Layer_Height(pos.x, pos.y, layer, nullptr, true);
    }
...

xezon avatar Aug 05 '23 05:08 xezon

It might be the case that they never tested it after copy paste, but how do we know for certain?

We know for certain that it is copy and pasted, because of lexical analysis of the relevant source code, including the white space characters: https://gist.github.com/commy2/8f4b61bb0c27febe7d3b7c64cdd08991/revisions

And we know for certain that is was insufficiently tested, because of otherwise unexplainable, but very noticable mistakes, like keeping the clip size of the Air and Assist versions at 4 instead of also changing them to 3, or the different sound effects between the weapons, which represent different stages of code development that were improperly applied to all copies. And also because of other very obvious mistakes associated with the Laser turret, for example the range bug, and in single player, the immortial invisible drones that draw fire from units trying to enter the Townes' base and completely break the premise of the map.

I can not see intent where there so obviously is none. What we don't know is, if were the code properly tested, would they have ended up with the conclusion that ScatterVsInfantry is actually good at 10.0, despite looking horrendous visually. I don't know, and it also doesn't even matter. If you want to change this however, you need a good reason to. It doesn't even have to amount to a buff if changed in conjunction with other weapon properties. Xezon explains this.

commy2 avatar Aug 05 '23 06:08 commy2

Imo, scatter radius itself is not an issue as long as units are getting hit with damage radius. So it needs to be reduced but not removed.

My reasoning is that it makes multiple attacks (especially simultaneous) just look better when not hitting the same exact spot

Float1ngFree avatar Jun 09 '24 00:06 Float1ngFree

I took a look at the damage types and it looks like there are 3 to 5 which can be misappropriated for a new laser damage type for as long as Thyme is not involved:

WATER    maybe
DEPLOY   yes
HACK     yes
PENALTY  maybe
TOPPLING yes, undocumented

Basically we would have to add new damage type to laser patriot weapons, then add it to all armors that have a custom EXPLOSION damage.

And with Thyme we can then rename it to "LASER_PATRIOT"

xezon avatar Jun 09 '24 05:06 xezon