Regen HP AP for knife

Regen HP AP for knife 1.5

Нет прав для скачивания
Код:
/*
    1.1 (11.08.2024 by mx?!):
        * Fixed cvar registration for 'amx_rk_max_hp', thx @Nord1cWarr1or
    1.2 (08.01.2025 by mx?!):
        * Fix resetting hp to maximum value when hp is already above maximum (set by another plugin), thx @Hailsane
    1.3 (05.02.2025 by mx?!):
        * Add GameCMS privilege access support
    1.4 (05.02.2025 by mx?!):
        * Add cvar 'amx_rk_access_mode` ('any of' or 'full presence' access mode by amxx flags)
    1.5 (04.04.2025 by mx?!):
        * Fixed wrong access/freq cvar values at first map (was wrong due to szOldVal and szNewVal placement)
*/

// Code based on plugin "Regen HP AP for knife" https://dev-cs.ru/resources/673/, author "I Am LeGenD"
new const PLUGIN_VERSION[] = "1.5"

#include <amxmodx>
#include <hamsandwich>
#include <reapi>

// AutoConfig name in 'amxmodx/configs/plugins', without .cfg extension.
// Comment to disable AutoConfig option
#define AUTO_CFG "knife_regen"

// GameCMS (from gamecms5.inc)
native Array:cmsapi_get_user_services(const index, const szAuth[] = "", const szService[] = "", serviceID = 0, bool:part = false);

enum _:PCVAR_ENUM {
    PCVAR__FREQ,
    PCVAR__ACCESS_FLAGS
}

enum _:CVAR_ENUM {
    CVAR__ACCESS_FLAGS,
    CVAR__ACCESS_FLAGS_STRING[64],
    CVAR__ACCESS_MODE,
    CVAR__MIN_ROUND,
    Float:CVAR_F__FREQ,
    Float:CVAR_F__HEAL_AMT,
    CVAR__ARMOR_AMT,
    Float:CVAR_F__MAX_HP,
    CVAR__MAX_ARMOR
}

new g_pCvar[PCVAR_ENUM], g_eCvar[CVAR_ENUM]
new HamHook:g_hDeploy, HamHook:g_hHolster
new bool:g_bCanAccess[MAX_PLAYERS + 1]

public plugin_init() {
    register_plugin("Regen HP AP for knife", PLUGIN_VERSION, "mx?!")

    RegCvars()

    g_hDeploy = RegisterHam(Ham_Item_Deploy, "weapon_knife", "OnItemDeploy_Post", true)
    g_hHolster = RegisterHam(Ham_Item_Holster, "weapon_knife", "OnItemHolster_Post", true)

    if(g_eCvar[CVAR_F__FREQ] == 0.0) {
        DisableHamForward(g_hDeploy)
        DisableHamForward(g_hHolster)
    }
}

RegCvars() {
    g_pCvar[PCVAR__ACCESS_FLAGS] = create_cvar( "amx_rk_access_flags", "",
        .description = "Доступ: услуга GameCMS или флаги доступа AMXX^nДля доступа для всех, задайте пустое значение"
    );
    bind_pcvar_string(g_pCvar[PCVAR__ACCESS_FLAGS], g_eCvar[CVAR__ACCESS_FLAGS_STRING], charsmax(g_eCvar[CVAR__ACCESS_FLAGS_STRING]))
    hook_cvar_change(g_pCvar[PCVAR__ACCESS_FLAGS], "hook_CvarChange")
    new szFlags[32]; get_pcvar_string(g_pCvar[PCVAR__ACCESS_FLAGS], szFlags, charsmax(szFlags))
    if(g_eCvar[CVAR__ACCESS_FLAGS_STRING][0] != '_') {
        ChangeAccessFlags(szFlags)
    }
  
    bind_pcvar_num(
        create_cvar( "amx_rk_access_mode", "0",
            .description = "Тип доступа по флагам AMXX: 0 - наличие всех перечисленных; 1 - наличие любого из"
        ),
        g_eCvar[CVAR__ACCESS_MODE]
    );

    bind_pcvar_num(
        create_cvar( "amx_rk_min_round", "0",
            .description = "Минимальный раунд для работы лечения",
            .has_min = true, .min_val = 0.0
        ),
        g_eCvar[CVAR__MIN_ROUND]
    );

    g_pCvar[PCVAR__FREQ] = create_cvar( "amx_rk_freq", "5.0",
        .description = "Частота лечения, в секундах (0 - отключить лечение)",
        .has_min = true, .min_val = 0.0
    );
    bind_pcvar_float(g_pCvar[PCVAR__FREQ], g_eCvar[CVAR_F__FREQ])
    hook_cvar_change(g_pCvar[PCVAR__FREQ], "hook_CvarChange")

    bind_pcvar_float(
        create_cvar( "amx_rk_heal_amt", "15",
            .description = "Объём лечения каждый тик amx_rk_freq",
            .has_min = true, .min_val = 1.0
        ),
        g_eCvar[CVAR_F__HEAL_AMT]
    );

    bind_pcvar_num(
        create_cvar( "amx_rk_armor_amt", "15",
            .description = "Объём восстановления брони каждый тик amx_rk_freq",
            .has_min = true, .min_val = 1.0
        ),
        g_eCvar[CVAR__ARMOR_AMT]
    );

    bind_pcvar_float(
        create_cvar( "amx_rk_max_hp", "0",
            .description = "Максимальный объём здоровья, который можно восстановить (0: использовать var_max_health)",
            .has_min = true, .min_val = 0.0
        ),
        g_eCvar[CVAR_F__MAX_HP]
    );

    bind_pcvar_num(
        create_cvar( "amx_rk_max_armor", "100",
            .description = "Максимальный объём брони, который можно восстановить",
            .has_min = true, .min_val = 1.0
        ),
        g_eCvar[CVAR__MAX_ARMOR]
    );

#if defined AUTO_CFG
    AutoExecConfig(.name = AUTO_CFG)
#endif
}

public hook_CvarChange(pCvar, szOldVal[], szNewVal[]) {
    if(pCvar == g_pCvar[PCVAR__FREQ]) {
        ChangeFreq(szNewVal)
        return
    }

    if(pCvar == g_pCvar[PCVAR__ACCESS_FLAGS]) {
        if(szNewVal[0] != '_') {
            ChangeAccessFlags(szNewVal)
        }
        else {
            new pPlayers[MAX_PLAYERS], iPlCount, pPlayer
            get_players(pPlayers, iPlCount, "h")
            for(new i; i < iPlCount; i++) {
                pPlayer = pPlayers[i]
                g_bCanAccess[pPlayer] = (cmsapi_get_user_services(pPlayer, "", szNewVal, 0) != Invalid_Array)
            }
        }
      
        return
    }
}

ChangeFreq(const szNewVal[]) {
    for(new pPlayer = 1; pPlayer <= MAX_PLAYERS; pPlayer++) {
        remove_task(pPlayer)
    }

    if(str_to_float(szNewVal) == 0.0) {
        DisableHamForward(g_hDeploy)
        DisableHamForward(g_hHolster)
        return
    }

    // else ->

    EnableHamForward(g_hDeploy)
    EnableHamForward(g_hHolster)

    if(CheckMinRound()) {
        for(new pPlayer = 1; pPlayer <= MAX_PLAYERS; pPlayer++) {
            if(is_user_alive(pPlayer) && get_user_weapon(pPlayer) == CSW_KNIFE) {
                SetTask(pPlayer)
            }
        }
    }
}

ChangeAccessFlags(const szNewVal[]) {
    g_eCvar[CVAR__ACCESS_FLAGS] = read_flags(szNewVal)
}

SetTask(pPlayer) {
    set_task(g_eCvar[CVAR_F__FREQ], "task_Regen", pPlayer, .flags = "b")
}

bool:CheckMinRound() {
    return (get_member_game(m_iTotalRoundsPlayed) + 1 >= g_eCvar[CVAR__MIN_ROUND])
}

public task_Regen(pPlayer) {
    if(!is_user_alive(pPlayer) || get_user_weapon(pPlayer) != CSW_KNIFE || !CheckMinRound()) {
        remove_task(pPlayer)
        return
    }

    new Float:fHealthValue = Float: get_entvar(pPlayer, var_health)
    new Float:fMaxHp = GetMaxHp(pPlayer)
    new ArmorType:iArmorType
    new iArmorValue = rg_get_user_armor(pPlayer, iArmorType)

    if(iArmorType == ARMOR_NONE) {
        iArmorType = ARMOR_KEVLAR
    }

    if(fHealthValue < fMaxHp) {
        set_entvar(pPlayer, var_health, floatmin(fHealthValue + g_eCvar[CVAR_F__HEAL_AMT], fMaxHp))
    }

    rg_set_user_armor(pPlayer, min(iArmorValue + g_eCvar[CVAR__ARMOR_AMT], g_eCvar[CVAR__MAX_ARMOR]), iArmorType)
}

Float:GetMaxHp(pPlayer) {
    if(g_eCvar[CVAR_F__MAX_HP] == 0.0) {
        return get_entvar(pPlayer, var_max_health)
    }

    return g_eCvar[CVAR_F__MAX_HP]
}

bool:CanAccess(pPlayer) {
    if(g_eCvar[CVAR__ACCESS_FLAGS_STRING][0] == '_') {
        return g_bCanAccess[pPlayer]
    }

    return AmxxAccess(pPlayer)
}

bool:AmxxAccess(pPlayer) {
    if(!g_eCvar[CVAR__ACCESS_FLAGS]) {
        return true
    }
  
    if(g_eCvar[CVAR__ACCESS_MODE]) {
        return ( (get_user_flags(pPlayer) & g_eCvar[CVAR__ACCESS_FLAGS]) > 0 )
    }
  
    return ( (get_user_flags(pPlayer) & g_eCvar[CVAR__ACCESS_FLAGS]) == g_eCvar[CVAR__ACCESS_FLAGS] )
}

public OnItemDeploy_Post(pWeapon) {
    if(!is_entity(pWeapon)) {
        return
    }

    new pPlayer = get_member(pWeapon, m_pPlayer)

    if(is_user_alive(pPlayer) && CanAccess(pPlayer) && CheckMinRound() && !task_exists(pPlayer)) {
        SetTask(pPlayer)
    }
}

public OnItemHolster_Post(pWeapon) {
    if(is_entity(pWeapon)) {
        remove_task(get_member(pWeapon, m_pPlayer))
    }
}

public client_putinserver(pPlayer) {
    if(g_eCvar[CVAR__ACCESS_FLAGS_STRING][0] == '_') {
        g_bCanAccess[pPlayer] = (cmsapi_get_user_services(pPlayer, "", g_eCvar[CVAR__ACCESS_FLAGS_STRING], 0) != Invalid_Array)
    }
}

public client_disconnected(pPlayer) {
    g_bCanAccess[pPlayer] = false
    remove_task(pPlayer)
}

public plugin_natives() {
    set_native_filter("native_filter")
}

public native_filter(const szNativeName[], iNativeID, iTrapMode) {
    return PLUGIN_HANDLED
}
Назад
Верх