SmileYzn / MatchBot

Counter-Strike 1.6 Match Plugin for ReHLDS and ReGameDLL_CS
GNU General Public License v3.0
28 stars 14 forks source link

Fet: Buy greades limit(per a round) #113

Closed jonathan-up closed 7 months ago

jonathan-up commented 7 months ago

The default behavior of the game only limits the maximum number of buying, you can still buy grenades again after you use them

SmileYzn commented 7 months ago

Why not set freezetime exactly to 15 seconds? When freezetime ends, buy time shoud end.

I always tryed to understand that fix

jonathan-up commented 7 months ago

Most people buy items outside the freezetime for a variety of reasons

jonathan-up commented 7 months ago

Just additional feature, it could be set 0 to disable it. β€œHarmless” hah.

SmileYzn commented 7 months ago

I will try to do that using rebuy struct instead of do manually checks in matchbot code

SmileYzn commented 7 months ago

I launch a action build with this idea. and variables too. But i used m_rgItems of CBasePlayer to check the number of grenades per round.

// Number of HE grenade allowed per round
//
// 0 Disable restriction
//
// Default "0"
mb_round_grenade_count "0"

// Number of smoke grenade allowed per round
//
// 0 Disable restriction
//
// Default "0"
mb_round_smoke_count "0"

// Number of flashbangs allowed per round
//
// 0 Disable restriction
//
// Default "0"
mb_round_flash_count "0"

To be honest, i guess a simple check if player is buying more grenades out of freezetime will solve this issue to.

Like

    if (type == ITEM_TYPE_BUYING)
    {
        if (item == ITEM_HEGRENADE || item == ITEM_SMOKEGRENADE || item == ITEM_FLASHBANG)
        {
            if (gMatchBot.GetState() == STATE_FIRST_HALF || gMatchBot.GetState() == STATE_SECOND_HALF || gMatchBot.GetState() == STATE_OVERTIME)
            {
                if (g_pGameRules)
                {
                    if (!CSGameRules()->IsFreezePeriod())
                    {
                        gMatchUtil.ClientPrint(Player->edict(), PRINT_CENTER, "#Cstrike_TitlesTXT_Weapon_Not_Available");

                        return true;
                    }
                }
            }
        }
    }

I really do not know what is the best solution, but yout idea is now part of matchbot

Really thanks for contribution! πŸ™‡β€β™‚οΈ πŸ™ πŸ‘

jonathan-up commented 7 months ago

Oh I check the code from branch main, your code is better! but there may be a bug, you only reset m_rgItems on freezetime , right?

jonathan-up commented 7 months ago

This can result in careless players not being able to buy grenades outside of the freezetime

SmileYzn commented 7 months ago

Did you tested it? Any buy in freeze time will reset that and players will able to buy

jonathan-up commented 7 months ago

Not test yet. But I check your code

if (CSGameRules()->IsFreezePeriod() && !Player->m_rgAmmo[AMMO_HEGRENADE])
{
    // Reset variable
    Player->m_rgItems[0] = 0;
}

you reset m_rgItems on freezetime only, maybe this means that if a player forgets to buy grenades, he cannot buy it outside of the freeze time because m_rgItems not reset.

jonathan-up commented 7 months ago

Or the player has a flash bomb left over from the previous round, This may also cause the m_rgItems not to be reset

SmileYzn commented 7 months ago

I will put roundRestart event, since i try to put in this way to avoid more one hook to Round Restart

πŸ‘

SmileYzn commented 7 months ago

I guess that should work now!

Thanks for patience bro πŸ™

jonathan-up commented 7 months ago

emm... I think it should not put reset data on Round Restart, it shoud on Player Spawn, and set data as player's bpammo. this fix if player have grenades from pre round, he can still use them and buy them again.

jonathan-up commented 7 months ago

like this.

void HC_CBasePlayer_Spawn(IReGameHook_CBasePlayer_Spawn *chain, CBasePlayer *player)
{
    int index = player->entindex();

    int flashCount = getPlayerBpAmmo(player, WEAPON_FLASHBANG);
    int hegreCount = getPlayerBpAmmo(player, WEAPON_HEGRENADE);
    int smokeCount = getPlayerBpAmmo(player, WEAPON_SMOKEGRENADE);

    if (index <= MAX_CLIENTS)
    {
        MatchFeatures::playerGrenades[index][FLASH] = flashCount;
        MatchFeatures::playerGrenades[index][HEGRE] = hegreCount;
        MatchFeatures::playerGrenades[index][SMOKE] = smokeCount;
    }

    chain->callNext(player);
}
int getPlayerBpAmmo(CBasePlayer *player, int weapId) {
    auto pInfo = g_ReGameApi->GetWeaponSlot(static_cast<WeaponIdType>(weapId));
    if (!pInfo) {
        return 0;
    }

    auto pWeapon = player->ForEachItem<CBasePlayerWeapon>(pInfo->slot, [pInfo](CBasePlayerWeapon *pWeapon) {
        return (pWeapon->IsWeapon() && pWeapon->m_iId == pInfo->id);
    });

    if (!pWeapon) {
        return 0;
    }

    return player->m_rgAmmo[pWeapon->m_iPrimaryAmmoType];
}