Promote server
csb-speed-boost / addons / amxmodx / scripting / csb_speed_boost.sma
172 lines 4.7 KiB Pawn Raw Permalink History
/*
 * CSB Speed Boost
 * Copyright (C) 2026 counter-strike-boost.com
 *
 * Timed speed boosts. A boost raises the player's maxspeed for a configurable
 * number of seconds and is re-applied on every weapon switch (CurWeapon), so
 * switching weapons does not cancel it. Boosts come from two sources:
 *  - boost zones placed per map in addons/amxmodx/data/csb_boostzones/<map>.txt
 *    (one "x y z radius" per line), and
 *  - the /boost command (for shop or VIP integration; free by default).
 * A HUD line counts down the remaining boost time.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version. It is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See <https://www.gnu.org/licenses/> for details.
 */

#include <amxmodx>
#include <fun>
#include <fakemeta>

new const PLUGIN[] = "CSB Speed Boost"
new const VERSION[] = "1.0.0"
new const AUTHOR[]  = "counter-strike-boost.com"

#define MAX_ZONES 32
#define TASK_HUD 7331

new Float:g_fBoostUntil[33]
new Float:g_fBoostSpeed[33]

new Float:g_fZone[MAX_ZONES][4] /* x y z radius */
new g_iZones

new g_pEnabled, g_pSpeed, g_pDuration

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR)

    g_pEnabled  = register_cvar("csb_boost_enabled", "1")
    g_pSpeed    = register_cvar("csb_boost_speed", "400.0")
    g_pDuration = register_cvar("csb_boost_duration", "10.0")

    register_event("CurWeapon", "OnCurWeapon", "be", "1=1")
    register_clcmd("say /boost", "cmdBoost")
    register_clcmd("say_team /boost", "cmdBoost")

    loadZones()
    set_task(0.5, "taskZones", TASK_HUD, _, _, "b")
}

loadZones()
{
    g_iZones = 0

    new map[32], dir[96], path[160]
    get_mapname(map, charsmax(map))
    get_localinfo("amxx_datadir", dir, charsmax(dir))
    formatex(path, charsmax(path), "%s/csb_boostzones/%s.txt", dir, map)

    if (!file_exists(path))
        return

    new file = fopen(path, "rt")
    if (!file)
        return

    new line[128]

    while (!feof(file) && g_iZones < MAX_ZONES)
    {
        fgets(file, line, charsmax(line))
        trim(line)

        if (!line[0] || line[0] == ';' || line[0] == '#')
            continue

        new sx[16], sy[16], sz[16], sr[16]
        parse(line, sx, charsmax(sx), sy, charsmax(sy), sz, charsmax(sz), sr, charsmax(sr))

        g_fZone[g_iZones][0] = str_to_float(sx)
        g_fZone[g_iZones][1] = str_to_float(sy)
        g_fZone[g_iZones][2] = str_to_float(sz)
        g_fZone[g_iZones][3] = str_to_float(sr)

        if (g_fZone[g_iZones][3] < 16.0)
            g_fZone[g_iZones][3] = 16.0

        g_iZones++
    }

    fclose(file)
    log_amx("[CSB] Speed Boost: loaded %d zone(s).", g_iZones)
}

public cmdBoost(id)
{
    if (!is_user_alive(id))
    {
        client_print(id, print_chat, "[CSB] You must be alive to use a boost.")
        return PLUGIN_HANDLED
    }

    applyBoost(id, get_pcvar_float(g_pDuration))
    return PLUGIN_HANDLED
}

public taskZones()
{
    if (!get_pcvar_num(g_pEnabled))
        return

    new Float:now = get_gametime()
    new Float:dur = get_pcvar_float(g_pDuration)

    new players[32], num
    get_players(players, num, "a")

    for (new i = 0; i < num; i++)
    {
        new id = players[i]

        /* zone pickup */
        if (g_iZones > 0 && g_fBoostUntil[id] < now)
        {
            new Float:orig[3]
            pev(id, pev_origin, orig)

            for (new z = 0; z < g_iZones; z++)
            {
                new Float:dx = orig[0] - g_fZone[z][0]
                new Float:dy = orig[1] - g_fZone[z][1]
                new Float:dz = orig[2] - g_fZone[z][2]

                if (floatsqroot(dx * dx + dy * dy + dz * dz) <= g_fZone[z][3])
                {
                    applyBoost(id, dur)
                    break
                }
            }
        }

        /* HUD countdown */
        if (g_fBoostUntil[id] > now)
        {
            set_hudmessage(60, 220, 90, -1.0, 0.82, 0, 0.0, 0.6, 0.0, 0.0, 4)
            show_hudmessage(id, "Speed boost: %.1f s", g_fBoostUntil[id] - now)
        }
    }
}

public OnCurWeapon(id)
{
    if (!is_user_alive(id))
        return

    if (g_fBoostUntil[id] > get_gametime())
        set_user_maxspeed(id, g_fBoostSpeed[id])
}

applyBoost(id, Float:duration)
{
    g_fBoostUntil[id] = get_gametime() + duration
    g_fBoostSpeed[id] = get_pcvar_float(g_pSpeed)
    set_user_maxspeed(id, g_fBoostSpeed[id])

    client_print(id, print_chat, "[CSB] Speed boost for %.0f seconds!", duration)
}