Yekta's Combo Sprite

Yekta's Combo Sprite 3.2

Нет прав для скачивания
Сообщения
134
Реакции
463
Помог
2 раз(а)
Небольшой форк плагина для более удобного тестирования и установки "стилей"

new const g_szGlobalDir[] = "combo_war_line"; //вписываем сюда, название папки с нужным стилем
  • combo_war_line
  • combo_face
  • combo_cards
  • combo_krunker
Код:
/*

https://forum.csduragi.com/eklentiler-pluginler/yektas-combo-sprite-t35501.html
https://dev-cs.ru/resources/720/
https://github.com/yek-ta/AMXX-PLUGINS/tree/master/Yekta's%20Combo%20Sprite
255 215 0
*/
#include <amxmodx>
#include <reapi>

#define PLUGIN "Yekta's Combo Sprite"
#define VERSION "3.2"
#define AUTHOR "Yek'-ta"

#define SHOWTIME 3.0//Show time alert. It should be float

//#define DEBUG //for testing (say !combo)

new const g_szGlobalDir[] = "combo_war_line"; //Sprite folder name (sprites/***/g_szSettingsFileName) [combo_cards, combo_face]
new const g_szSettingsFileName[][] = {  //Sprite file name [without expansion] (sprites/g_szGlobalDir/***)
"c4_set",
"c4_defuse",
"kill_knife",
"kill_he",
"kill_headshot",
"kill_1",
"kill_2",
"kill_3",
"kill_4",
"kill_5",
"kill_6",
"kill_7",
"kill_8",
"kill_9",
"kill_10",
"kill_combo"
}

#define HUD_HIDE_FLASH (1<<1)
#define HUD_HIDE_CROSS (1<<6)
#define HUD_DRAW_CROSS (1<<7)

#define CSW_SHIELD  2
new isitON[MAX_PLAYERS + 1]
new kills[MAX_PLAYERS + 1]
new bool: PlayerOnOff[MAX_PLAYERS + 1]

enum _:MESSAGES {
    g_iMsg_WeaponList,
    g_iMsg_ScreenFade,
    g_iMsg_CurWeapon,
    g_iMsg_SetFOV,
    g_iMsg_HideWeapon,
    g_iMsg_Crosshair
}
new g_Messages[MESSAGES];
new g_Messages_Name[MESSAGES][] = {
    "WeaponList",
    "ScreenFade",
    "CurWeapon",
    "SetFOV",
    "HideWeapon",
    "Crosshair"
}

public plugin_init(){

    register_plugin(PLUGIN, VERSION, AUTHOR)
    for(new i; i < sizeof g_Messages; i++){
        g_Messages[i] = get_user_msgid(g_Messages_Name[i]);
    }
    RegisterHookChain(RG_CBasePlayer_Spawn, "CBasePlayer_Spawn",true);
    RegisterHookChain(RG_CBasePlayer_Killed, "CBasePlayer_Killed", true);

    RegisterHookChain(RG_PlantBomb, "PlantBomb_Post", true);
    RegisterHookChain(RG_CGrenade_DefuseBombEnd, "CGrenade_DefuseBombEnd_Post", true);

    register_event("CurWeapon","comboHudGoster","be", "1=1")
    register_clcmd("say /combosprite", "comboonoff");

    #if defined DEBUG
    register_clcmd("say !combo", "Combo_test");
    #endif
}

#if defined DEBUG
public Combo_test(id)
{
    isitON[id]++

    comboHudGoster(id);
    client_print(0, print_chat, "%i", isitON[id]);
    set_task(1.5 ,"Combo_test", id);

    if(isitON[id] == 11){
        isitON[id] = -6;
    }
}
#endif

public comboonoff(id){
    PlayerOnOff[id] = !PlayerOnOff[id]
    client_print_color(id, id, "^1Combo Sprite is ^3%s", PlayerOnOff[id] ? "ON" : "OFF")
}
public plugin_precache(){
    new szData[64];
   
    for(new i = 0; i < sizeof g_szSettingsFileName; i++)
    {
        formatex(szData,charsmax(szData),"sprites/%s/%s.spr",g_szGlobalDir,g_szSettingsFileName[i]);
        precache_model(szData);
        precache_generic(szData);
    }
}
public client_putinserver(id){
    PlayerOnOff[id] = true;
    kills[id] = 0;
}
public CBasePlayer_Killed(iVictim, iKiller)
{
    if(!is_user_connected(iKiller) || iVictim == iKiller)
        return HC_CONTINUE;

    kills[iVictim] = 0
    kills[iKiller] += 1;

    if(!PlayerOnOff[iKiller])
        return HC_CONTINUE;

    remove_task(1997+iKiller);

    if(get_member(iVictim, m_bHeadshotKilled))
        isitON[iKiller] = -1;
    else if(get_member(iVictim, m_bKilledByGrenade))
        isitON[iKiller] = -2;
    else if(get_user_weapon(iKiller) == CSW_KNIFE)
        isitON[iKiller] = -3;
    else
        isitON[iKiller] = kills[iKiller];

    comboHudGoster(iKiller)
    set_task(SHOWTIME,"RemoveHUD",1997+iKiller);

    return HC_CONTINUE;
}
public RemoveHUD(numara){
    numara = numara-1997
    if(get_member(numara, m_iFOV) == 90){
        isitON[numara] = 0;
        Hide_NormalCrosshair(numara, 0);
        show_crosshair(numara, 0)
    }
    else {
        set_task(1.0,"RemoveHUD",1997+numara);
    }
}
public CBasePlayer_Spawn(oyuncu){
    kills[oyuncu] = 0;
}
public comboHudGoster(id){
    if(isitON[id] == 0){
        return PLUGIN_HANDLED
    }
    else if(get_member(id, m_iFOV) != 90){
        return PLUGIN_HANDLED
    }
    static userwpn, prim, sprtxt[64]
    userwpn = get_user_weapon(id, prim)

    switch (isitON[id])
    {
        case -5: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[0]); }
        case -4: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[1]); }
        case -3: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[2]); }
        case -2: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[3]); }
        case -1: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[4]); }
        case 1: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[5]); }
        case 2: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[6]); }
        case 3: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[7]); }
        case 4: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[8]); }
        case 5: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[9]); }
        case 6: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[10]); }
        case 7: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[11]); }
        case 8: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[12]); }
        case 9: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[13]); }
        case 10: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[14]); }
        default: { formatex(sprtxt,charsmax(sprtxt),"%s/%s",g_szGlobalDir,g_szSettingsFileName[15]); }
    }
    switch (userwpn)
    {
        case CSW_P228: { Msg_WeaponList(id, sprtxt,9,52,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_HEGRENADE: { Msg_WeaponList(id, sprtxt,12,1,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_XM1014: { Msg_WeaponList(id, sprtxt,5,32,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_C4: { Msg_WeaponList(id, sprtxt,14,1,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_MAC10: { Msg_WeaponList(id, sprtxt,6,100,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_AUG: { Msg_WeaponList(id, sprtxt,4,90,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_SMOKEGRENADE: { Msg_WeaponList(id, sprtxt,13,1,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_ELITE: { Msg_WeaponList(id, sprtxt,10,120,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_FIVESEVEN: { Msg_WeaponList(id, sprtxt,7,100,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_UMP45: { Msg_WeaponList(id, sprtxt,6,100,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_GALIL: { Msg_WeaponList(id, sprtxt,4,90,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_FAMAS: { Msg_WeaponList(id, sprtxt,4,90,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_USP: { Msg_WeaponList(id, sprtxt,6,100,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_GLOCK18: { Msg_WeaponList(id, sprtxt,10,120,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_MP5NAVY: { Msg_WeaponList(id, sprtxt,10,120,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_M249: { Msg_WeaponList(id, sprtxt,3,200,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_M3: {Msg_WeaponList(id, sprtxt,5,32,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_M4A1: { Msg_WeaponList(id, sprtxt,4,90,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_TMP: { Msg_WeaponList(id, sprtxt,10,120,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_FLASHBANG: { Msg_WeaponList(id, sprtxt,11,2,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_DEAGLE: { Msg_WeaponList(id, sprtxt,8,35,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_SG552: { Msg_WeaponList(id, sprtxt,4,90,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_AK47: { Msg_WeaponList(id, sprtxt,2,90,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_KNIFE:{ Msg_WeaponList(id, sprtxt,-1,-1,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_P90: { Msg_WeaponList(id, sprtxt,7,100,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 0); }
        case CSW_SCOUT: { Msg_WeaponList(id, sprtxt,2,90,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 1); }
        case CSW_AWP: { Msg_WeaponList(id, sprtxt,1,30,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 1); }
        case CSW_SG550: { Msg_WeaponList(id, sprtxt,4,90,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 1); }
        case CSW_G3SG1: { Msg_WeaponList(id, sprtxt,2,90,-1,-1,0,11,CSW_SHIELD,0);Hide_NormalCrosshair(id, 1); }
    }
    Msg_SetFOV(id, 89);
    Msg_CurWeapon(id, 1,CSW_SHIELD,prim);
    Msg_SetFOV(id, 90);
    return PLUGIN_CONTINUE
}
stock Hide_NormalCrosshair(id, flag){
    if(flag == 1){
        message_begin(MSG_ONE, g_Messages[g_iMsg_HideWeapon], _, id);
        write_byte(HUD_HIDE_CROSS | HUD_HIDE_FLASH);
        message_end();
    }
    else{
        message_begin(MSG_ONE, g_Messages[g_iMsg_HideWeapon], _, id);
        write_byte(HUD_DRAW_CROSS | HUD_HIDE_FLASH);
        message_end();
    }
}
stock show_crosshair(id, flag){
    message_begin(MSG_ONE_UNRELIABLE, g_Messages[g_iMsg_Crosshair], _, id);
    write_byte(flag);
    message_end();
}
stock Msg_CurWeapon(id, IsActive,WeaponID,ClipAmmo){
    message_begin(MSG_ONE,g_Messages[g_iMsg_CurWeapon], {0,0,0}, id);
    write_byte(IsActive);
    write_byte(WeaponID);
    write_byte(ClipAmmo);

    message_end();
}
stock Msg_WeaponList(id, const WeaponName[],PrimaryAmmoID,PrimaryAmmoMaxAmount,SecondaryAmmoID,
SecondaryAmmoMaxAmount,SlotID,NumberInSlot,WeaponID,Flags){
    message_begin(MSG_ONE,g_Messages[g_iMsg_WeaponList], {0,0,0}, id);
    write_string(WeaponName);
    write_byte(PrimaryAmmoID);
    write_byte(PrimaryAmmoMaxAmount);
    write_byte(SecondaryAmmoID);
    write_byte(SecondaryAmmoMaxAmount);
    write_byte(SlotID);
    write_byte(NumberInSlot);
    write_byte(WeaponID);
    write_byte(Flags);
    message_end();
}

stock Msg_SetFOV(id, Degrees){
    message_begin(MSG_ONE,g_Messages[g_iMsg_SetFOV], {0,0,0}, id);
    write_byte(Degrees);
    message_end();
}


public PlantBomb_Post(const id)
{
    new iBomb = GetHookChainReturn(ATYPE_INTEGER);

    if(!is_nullent(iBomb))
    {
    isitON[id] = -5;
    comboHudGoster(id);
    set_task(SHOWTIME,"RemoveHUD",1997+id);
    }
}

public CGrenade_DefuseBombEnd_Post(const iBomb, const id)
{
    if(!is_nullent(iBomb))
    {
    isitON[id] = -4;
    comboHudGoster(id);
    set_task(SHOWTIME,"RemoveHUD",1997+id);
    }
}

В комбо лист внес небольшие дополнения, теперь цепь оповещаемых событий выглядит так:
  • Установка C4
  • Дефьюз C4
  • Убийство ножом
  • Убийство HE гранатой
  • Убийство в голову
  • Убийство с 1 по 10
  • Комбо убийство (когда больше 10)

Сделал 4 варианта стилей в более минималистичном дизайне, и размере. (спрайты должны смотреться адекватно вплоть до разрешения 800х600)
Вдохновлялся\использовал идеи\брал ресурсы из интерфейсов таких игр как - CS2 \ COD Warzone \ Warface \ Krunker.io


Небольшое Превью:

Replace this function
 

Вложения

Последнее редактирование:
Сообщения
94
Реакции
13
medusa, сделать бы ещё убийство с молотова, слепой, через дым, через стену, через стену в голову.
если это возможно сделать в кс
 
Последнее редактирование модератором:
Сообщения
775
Реакции
293
Помог
11 раз(а)
OskaR, через стену и через стену в голову точно можно, я для себя в этом плагине это добавлял
25 Июл 2023
С Молотова думаю тоже не проблема, а вот что насчёт дыма, тут есть сомнения
 
Сообщения
839
Реакции
519
Помог
12 раз(а)
OskaR, через стену и через стену в голову точно можно, я для себя в этом плагине это добавлял
25 Июл 2023
С Молотова думаю тоже не проблема, а вот что насчёт дыма, тут есть сомнения
на месте спавна дыма сохранять позицию, далее при каждом выстреле придется просчитывать пересекает ли трейс условный бокс дыма
 
Сообщения
134
Реакции
463
Помог
2 раз(а)
OskaRа вот что насчёт дыма, тут есть сомнения
Функция IsLineBlockedBySmokeпроверяет пересекает ли линия облако дыма (определяет длину линии обзора покрытой каждым облаком и суммирует их - если оно переходит порог то возвращает true т.е. линия заблокирована облаком дыма)

Код:
#include <amxmodx>
#include <fakemeta>
#include <reapi>
#include <xs>

enum _:SmokeData_s
{
    SMOKE_ENTITY_ID,
    Float:SMOKE_ORIGIN[3]
};

new Array:g_aSmokes;

public plugin_init()
{
    g_aSmokes = ArrayCreate(SmokeData_s);

    register_forward(FM_Think, "Think_Post", true);
    RegisterHookChain(RG_CSGameRules_RestartRound, "CSGameRules_RestartRound_Post", true);
    RegisterHookChain(RG_CGrenade_ExplodeSmokeGrenade, "CGrenade_ExplodeSmokeGrenade_Post", true);
}

public Think_Post(iEnt)
{
    new index = FindSmokeId(iEnt);

    if (index != -1)
    {
        if (get_entvar(iEnt, var_flags) & FL_KILLME)
        {
            ArrayDeleteItem(g_aSmokes, index);
        }
    }
}

public CSGameRules_RestartRound_Post()
{
    ArrayClear(g_aSmokes);
}

public CGrenade_ExplodeSmokeGrenade_Post(const this)
{
    new eTempSmoke[SmokeData_s];

    eTempSmoke[SMOKE_ENTITY_ID] = this;
    get_entvar(this, var_origin, eTempSmoke[SMOKE_ORIGIN]);

    // https://github.com/s1lentq/ReGameDLL_CS/blob/46f697fb4697ffbbf51ac70cb8f3d41a5ae89922/regamedll/dlls/ggrenade.cpp#L578
    ArrayPushArray(g_aSmokes, eTempSmoke);
}

stock bool:IsLineBlockedBySmoke(const Float:from[3], const Float:to[3])
{
    const Float:smokeRadius = 115.0;

    new const Float:smokeRadiusSq = smokeRadius * smokeRadius;

    new Float:totalSmokedLength;

    new Float:sightDir[3];
    xs_vec_sub(to, from, sightDir);

    new Float:sightLength = NormalizeInPlace(sightDir);

    new iSize = ArraySize(g_aSmokes);

    for (new i; i < iSize; i++)
    {
        new eTempSmoke[SmokeData_s]; ArrayGetArray(g_aSmokes, i, eTempSmoke);

        new Float:smokeOrigin[3]; xs_vec_copy(eTempSmoke[SMOKE_ORIGIN], smokeOrigin);

        new Float:toGrenade[3]; xs_vec_sub(smokeOrigin, from, toGrenade);

        new Float:alongDist = DotProduct(toGrenade, sightDir);

        new Float:close[3];

        if (alongDist < 0.0)
        {
            xs_vec_copy(from, close);
        }
        else if (alongDist >= sightLength)
        {
            xs_vec_copy(to, close);
        }
        else
        {
            new Float:tempsightDir[3]; xs_vec_add_scaled(Float:{0.0, 0.0, 0.0}, sightDir, alongDist, tempsightDir);
            xs_vec_add(from, tempsightDir, close);
        }

        new Float:toClose[3]; xs_vec_sub(close, smokeOrigin, toClose);

        new Float:lengthSq = LengthSquared(toClose);

        if (lengthSq < smokeRadiusSq)
        {
            new Float:fromSq = LengthSquared(toGrenade);
            new Float:tempSq[3]; xs_vec_sub(smokeOrigin, to, tempSq);
            new Float:toSq = LengthSquared(tempSq);

            if (fromSq < smokeRadiusSq)
            {
                if (toSq < smokeRadiusSq)
                {
                    new Float:temp_totalSmokedLength[3]; xs_vec_sub(to, from, temp_totalSmokedLength);
                    totalSmokedLength += xs_vec_len(temp_totalSmokedLength);
                }
                else
                {
                    new Float:halfSmokedLength = floatsqroot(smokeRadiusSq - lengthSq);

                    new Float:temp_totalSmokedLength[3]; xs_vec_sub(close, from, temp_totalSmokedLength);

                    if (alongDist > 0.0)
                    {
                        totalSmokedLength += halfSmokedLength + xs_vec_len(temp_totalSmokedLength);
                    }
                    else
                    {
                        totalSmokedLength += halfSmokedLength - xs_vec_len(temp_totalSmokedLength);
                    }
                }
            }
            else if (toSq < smokeRadiusSq)
            {
                new Float:halfSmokedLength = floatsqroot(smokeRadiusSq - lengthSq);

                new Float:temp_totalSmokedLength[3]; xs_vec_sub(close, to, temp_totalSmokedLength);

                new Float:v[3]; xs_vec_sub(to, smokeOrigin, v);

                if (DotProduct(v, sightDir) > 0.0)
                {
                    totalSmokedLength += halfSmokedLength + xs_vec_len(temp_totalSmokedLength);
                }
                else
                {
                    totalSmokedLength += halfSmokedLength - xs_vec_len(temp_totalSmokedLength);
                }
            }
            else
            {
                new Float:smokedLength = 2.0 * floatsqroot(smokeRadiusSq - lengthSq);
                totalSmokedLength += smokedLength;
            }
        }
    }

    new const Float:maxSmokedLength = 0.7 * smokeRadius;

    return (totalSmokedLength > maxSmokedLength);
}

stock Float:NormalizeInPlace(Float:a[])
{
    new Float:flLen = xs_vec_len(a);
    if (flLen > 0)
    {
        a[0] /= flLen;
        a[1] /= flLen;
        a[2] /= flLen;
    }
    else
    {
        a[0] = 0.0;
        a[1] = 0.0;
        a[2] = 1.0;
    }
    return flLen;
}

stock Float:DotProduct(const Float:a[], const Float:b[])
{
    return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
}

stock Float:LengthSquared(const Float:a[])
{
    return (a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
}

FindSmokeId(smoke_id)
{
    new iSize = ArraySize(g_aSmokes);

    for (new i; i < iSize; i++)
    {
        new eTempSmoke[SmokeData_s]; ArrayGetArray(g_aSmokes, i, eTempSmoke);

        if (eTempSmoke[SMOKE_ENTITY_ID] == smoke_id)
        {
            return i;
        }
    }

    return -1;
}


credits: fl0wer
 
Сообщения
21
Реакции
4
@medusa,не отображаются спрайты, даже при дебаге попоробовал

new const g_szGlobalDir[] = "combo_cards";
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу