GeneralsGamePatch icon indicating copy to clipboard operation
GeneralsGamePatch copied to clipboard

China Propaganda Bonus resets weapon reload

Open xezon opened this issue 4 years ago • 8 comments

  • Relates to #149

China Propaganda Bonus resets weapon reload. This can be easily tested on China Nuke Cannon. When Propaganda is added or removed from the unit, the weapon will reload instantly and the Nuke Cannon can shoot immediately again.

Replay: PROPAGANDA_BUG_REPLAY.zip

https://user-images.githubusercontent.com/4720891/136426285-bd285c9b-4493-4eca-b7c6-476049373da8.mp4

xezon avatar Oct 07 '21 16:10 xezon

Hi, I think this is a bug specifically with how the Nuke Cannon's weapon works rather than Propaganda as a whole... I might be wrong but I'm 80% certain.

EnigmaZift avatar Oct 19 '21 15:10 EnigmaZift

It's the interaction between the two: Shared reload time and rate of fire bonuses.

commy2 avatar Oct 19 '21 16:10 commy2

Bug, needs fixing.

ReLaX82 avatar Feb 11 '22 12:02 ReLaX82

It affects all weapon reloads, also it can't be fixed, not through modding anyway

ZekeDlyoung avatar Feb 12 '22 00:02 ZekeDlyoung

  • Relates to #149

xezon avatar May 05 '23 08:05 xezon

To fix this, the weapon reload progress needs to be kept after the new fire rate is applied.

xezon avatar Sep 15 '23 13:09 xezon

Progress should be transferred proportionally. If total reload time before is 10, after is 8, and the current progress is 5/10 seconds, the progress with bonus should be set to 4/8 + delta_t.

commy2 avatar Sep 15 '23 13:09 commy2

Logic appears to be here:

void Weapon::On_Weapon_Bonus_Change(const Object *source_obj)
{
    WeaponBonus bonus;
    Compute_Bonus(source_obj, 0, bonus);
    bool time_set = false;
    int time;

    if (Get_Status() == RELOADING_CLIP) {
        time = m_template->Get_Clip_Reload_Time(bonus);
        time_set = true;
    } else if (Get_Status() == BETWEEN_FIRING_SHOTS) {
        time = m_template->Get_Delay_Between_Shots(bonus);
        time_set = true;
    }

    if (time_set) {
        m_whenLastReloadStarted = g_theGameLogic->Get_Frame();
        m_whenWeCanFireAgain = time + m_whenLastReloadStarted;

        if (source_obj->Is_Share_Weapon_Reload_Time()) {
            for (int i = 0; i < WEAPONSLOT_COUNT; i++) {
                Weapon *weapon = const_cast<Weapon *>(source_obj->Get_Weapon_In_Weapon_Slot(static_cast<WeaponSlotType>(i)));

                if (weapon != nullptr) {
                    weapon->Set_Next_Shot(m_whenWeCanFireAgain);
                    weapon->Set_Status(RELOADING_CLIP);
                }
            }
        }
    }
}

xezon avatar Oct 24 '23 15:10 xezon