DM balancer

Статус
В этой теме нельзя размещать новые ответы.
Сообщения
76
Реакции
3
Помог
1 раз(а)
Как сделать так чтобы живых игроков данный дм не переводил, а только тех кто умер. Потому что если у игрока есть к примеру турели, то его данный дм переводить за другую команду.

Код:
/*****=====--------
Привіт, ви намагаєтеся прочитати мій код... добре

DM balance - вас дратують ігри Deathmatch без Rond-less,
де жоден із модулів балансу команд не працює?

Я сподіваюся, що так.. Гаразд, десь є балансир CSDM, але, чесно кажучи, наскільки я знаю, він трохи кульгавий,
оскільки він працює на рахунок смертей...

Цей плагін перевіряє команди, коли гравець відключається,
або коли гравець набирає "/balance" у чаті, тож нікому не потрібно змінювати команду
вручну, АБО коли почнеться новий раунд...

--Чому метод виявлення відключення кращий?
На мій погляд, різниця в командах насправді створюється тим, що гравець роз'єднується,
тому - коли гравець від'єднується, гравців стає менше
і тому команди втрачають рівновагу... добре, звучить тупо :D Сподіваюся, ви зрозуміли (:

--Як це працює?
Алгоритм
1. Гравець роз'єднується або йде командою глядачів / починає раунд / "/баланс"
2. Спрацьовує лічильник гравців
3. Під час підрахунку гравців підраховуються результати, щоб побачити, чи варто когось передавати
4. Якщо варто когось перевести, то вибирають випадкового гравця з найсильнішої команди
5. Якщо випадковий гравець не з потрібної команди або є інша проблема, це повторюється
6. Коли нарешті знайдено, він передає його, показує оголошення чату...
7.* Якщо гравець підключається, він змушений приєднатися до найслабшої команди... (якщо ввімкнено)

--Кредити
* Більшість зроблено мною (Chill it BanG) "більшість" становить приблизно 97%, якщо вам подобається математика
* Більшість коду, який використовується в частині обмеження команди, взято з ConnorMcLeod,
з теми - https://forums.alliedmods.net/showthread.php?t=63818

--Завдяки...
* DonKisgot (https://forums.alliedmods.net/member.php?u=100584) за чудові ідеї та відгуки

--ChangeLog
v1.43 -
* Виправлено повідомлення ML "U_R_CT".
* Невелика оптимізація.

v1.41 -
* Додано підтримку ML, тепер ви можете перекладати повідомлення на свою мову та перемикати їх за допомогою amx_langmenu!

v1.4 -
* Знову ж таки, виправлено помилки в частині teamlimit
* Додано звук при передачі для перенесеного гравця (dmb_playsound)
* Додано прозоре згасання екрану під час переходу для переведеного гравця в колір його/її нової команди (dmb_fadescreen)
* Додано сповіщення про команду «say /balance»: «[DMB] У команді суперників більше гравців, ніж у вашій? Введіть «/balance» у чаті, щоб виправити це!»
  (dmb_infodelay). ПРИМІТКА: якщо менше 20, він вимкнений, і ні, це не пов’язано з «dmb_printinchat»
* Все ще є деякі проблеми, коли команди погано збалансовані. Це помилка get_players з прапорцем "e"?

v1.35 -
* Зроблено код легшим для читання (код був трохи переплутаний з "indenter")
* Виправлено деякі помилки, пов’язані з teamlimit
* Виправлена власна помилка виконання для "cs_get_user_team"
* Спосіб пошуку випадкового гравця тепер швидший!

v1.3 -
* Додано dmb_respawn cvar, тому гравці після переходу можуть бути відроджені до своїх нових команд (може бути корисним у таких модах, як CTF та GG)
  (сподіваюся, це виправить помилку в CTF, коли гравці після передачі не могли відродитися)
* Додано dmb_printincons cvar, оскільки код стає більшим і стає досить важко побачити, що відбувається.
  Здебільшого для налагодження це має бути встановлено на 0;)
* Додано команди, які перевіряють, чи входить хтось до команди глядачів.
* Виправлено деякі невеликі помилки, коли іноді балансир зупинявся на пошуку випадкового гравця, але
  пам’ятайте, якщо ваш сервер досить заповнений, пошук гравця може зайняти до 10 секунд.
* Позбудьтеся деяких непотрібних змінних.

v1.21 -
* Знайдено помилку, яка «вимкнула» плагін балансу, якщо було ввімкнено teamlimit, але нікого не примушували до найслабшої команди.
* Зроблено легше читати тести "якщо" в деяких частинах коду.

v1.2 -
* Додано teamlimit, який змушує приєднатися до найслабшої команди (dmb_teamlimit) (Примітка: подивіться на кредити)
* Додано cvar для контролю часу після початку раунду, коли перевіряється баланс
* Додано CVAR для ввімкнення/вимкнення сповіщень чату
* Невелика оптимізація коду
* Видалено ColorChat, оскільки client_print_color недоступний у amxx 1.8.2
* Покращена система ідентифікації коду, я відчуваю, що мені це погано :D

v1.1 -
* Виправлена помилка виконання (іноді він намагався перенести відключеного гравця, лол)
* Виправлена проблема, коли випадковий гравець вибирався з найслабшої команди
* Додано cvars, команди чату та консолі
* Додано більш складні обчислення, щоб переконатися, що баланс необхідний

v1.0 -
* Найперша версія, без CVAR і команд

--Команди
*Чат
/balance - запускає алгоритм перевірки команд
*Консоль
dmb_balance - Те саме, що "/balance", лише доступне для адміністратора з "ADMIN_KICK"

--Cvars
dmb_saybalance - (1) вмикає / (0) вимикає команду "say /balance" (за замовчуванням 1)
dmb_minplayers - Гравці, необхідні для початку балансу (за замовчуванням 2)
dmb_roundstarttime - час (у секундах) після початку раунду, коли можна перевірити баланс команди (за замовчуванням 10)
dmb_printinchat - (1) вмикає / (0) вимикає повідомлення чату (за замовчуванням 1)
dmb_printincenter - (1) вмикає / (0) вимикає повідомлення центру екрана (за замовчуванням 1)
dmb_printincons - (1) вмикає / (0) вимикає інформацію про налагодження консоліm не слід використовувати, якщо плагін, оскільки він містить купу повідомлень (за замовчуванням 0)
dmb_teamlimit - (1) вмикає / (0) вимикає ліміт команди. Це змушує гравця приєднатися до найслабшої команди
dmb_respawn - (1) вмикає / (0) вимикає відродження після передачі - тому гравці не будуть хапати прапор колишньої команди (CTF) або наносити удари колишніх товаришів по команді (GG) (за замовчуванням 0)
dmb_infodelay - Час у секундах. Як часто буває «[DMB] Команда суперників має більше гравців, ніж ваша? Введіть «/balance» у чаті, щоб виправити це!» показало повідомлення. Якщо менше 20 або "dmb_saybalance 0" - вимкнено (за замовчуванням 120)
dmb_playsound - (1) включає / (0) вимикає звук при передачі. Звук схожий на "біп" (за замовчуванням 1)
dmb_fadescreen - (1) вмикає / (0) вимикає прозоре затухання екрана в новій команді гравців. Лише для переведеного гравця (за замовчуванням 1)
dmb_version - показує версію плагіна, не торкайтеся цього...
-----======*******/

#include <amxmodx>
#include <amxmisc>
#include <cstrike>
#include <hamsandwich>

#define PLUGIN "DM balance"
#define VERSION "1.43"
#define AUTHOR "Chill it BanG"


// variables for cvars...
new c_dmb_saybalance
new c_dmb_minplayers
new c_dmb_printinchat
new c_dmb_printincenter
new c_dmb_teamlimit
new c_dmb_roundstarttime
new c_dmb_respawn
new c_dmb_printincons
new c_dmb_infodelay
new c_dmb_playsound
new c_dmb_fadescreen

//some variables
new countCT,countTS,countALL //player count
new randPid //random player id
new randPnick[32] //random player nick
new CTList[32] // list of CT`s
new TSList[32] // list of T`s



public plugin_init() {
    //plugin info..
    register_plugin(PLUGIN, VERSION, AUTHOR)
    //lang file
    register_dictionary("DM_balance.txt")
    
    //commands
    register_concmd("dmb_balance","counter",ADMIN_KICK,"Looks if balance is needed")
    register_clcmd("say /balance","get_pcount_say",_,"Looks if balance is needed")
    
    //cvars
    c_dmb_saybalance = register_cvar("dmb_saybalance", "1") //controls "say /balance"
    c_dmb_minplayers = register_cvar("dmb_minplayers", "4") //players needed to plugin to work
    c_dmb_roundstarttime = register_cvar("dmb_roundstarttime", "20") //time after round start when balance checks teams
    c_dmb_printinchat = register_cvar("dmb_printinchat", "0") //controls chat messages
    c_dmb_printincenter = register_cvar("dmb_printincenter", "0") //controls center announcments
    c_dmb_printincons = register_cvar("dmb_printincons", "0")//announcments in console, should be 0, since it is more for debugging
    c_dmb_teamlimit = register_cvar("dmb_teamlimit", "1") //controls team limit,
    c_dmb_respawn = register_cvar("dmb_respawn", "0") //respawn or not to respawn player when player is transfered
    c_dmb_infodelay = register_cvar("dmb_infodelay", "120")//time, how often msg with "/balance" should appears, must be grater than "20"
    c_dmb_playsound = register_cvar("dmb_playsound", "0")//play or not to play sound to player when transfered
    c_dmb_fadescreen = register_cvar("dmb_fadescreen", "1")//fade screen for a little when transfered?
    register_cvar("dmb_version", "1.43", FCVAR_SERVER | FCVAR_SPONLY) //version, seems legit
    
    //events
    register_logevent( "Event_RoundStart", 2, "0=World triggered", "1=Round_Start" ) //Round start
    register_logevent("team_join",3,"1=joined team") //joined team
    
    if(get_pcvar_num(c_dmb_saybalance) == 1 && get_pcvar_num(c_dmb_infodelay) > 20){
    set_task(get_pcvar_float(c_dmb_infodelay), "SayBalanceInfo",_,_,_,"b")
    } //spam info about "say /balance command"
    
}

/***
Triggers - turn balance on
***/

//Player disconnect
public client_disconnect(player){
    set_task(1.0,"counter")
    
    //check if chat massages are allowed (dmb_printinchat)
    if(get_pcvar_num(c_dmb_printinchat) == 1 && countALL >= get_pcvar_num(c_dmb_minplayers)){   
        //print what is happening..                       
        client_print(0,print_chat,"%L",LANG_PLAYER, "IS_NEEDED")
        }   
    
}
//if round starts - possible there is 1 vs "more than 1" game ;)
public Event_RoundStart() {
    set_task (get_pcvar_float(c_dmb_roundstarttime), "counter")
    
    //check if chat massages are allowed (dmb_printinchat)
    if(get_pcvar_num(c_dmb_printinchat) == 1 && countALL >= get_pcvar_num(c_dmb_minplayers)){   
        //print what is happening..                       
        client_print(0,print_chat,"%L",LANG_PLAYER, "IS_NEEDED")
        }   
    
}
//say comand
public get_pcount_say(player) {
    new balancer[32]
    get_user_name(player, balancer,31)
    if(get_pcvar_num(c_dmb_printincons) == 1){
        client_print(0,print_console,"[DMB] %s used /balance", balancer) //just for testing
    }   
    if (get_pcvar_num(c_dmb_saybalance) == 1){
        
        counter()
        
    //check if chat massages are allowed (dmb_printinchat)
        if(get_pcvar_num(c_dmb_printinchat) == 1 && countALL >= get_pcvar_num(c_dmb_minplayers)){   
        //print what is happening..
        new used_bal[64]
        formatex(used_bal,63,"%L", LANG_PLAYER, "USED_BAL", balancer)
        client_print(0,print_chat,used_bal)
        }   
    }
}

/***
Here the fun starts (:
***/

//Just counting players and going to next step
public counter(){
    new printcons = get_pcvar_num(c_dmb_printincons)
    get_players(CTList, countCT, "e", "CT") //Gets count of CT`s
    get_players(TSList, countTS, "e", "TERRORIST") //Gets count of T`s
    countALL = countCT + countTS //gets everyone counted
    
    //check if console commands are allowed
    if(printcons){
        client_print(0,print_console,"[DMB] Counting") //just for testing
    }
    if(countALL >= get_pcvar_num(c_dmb_minplayers)){
        set_task (1.0,"balance_calc")
        if(printcons){
            client_print(0,print_console,"[DMB]CT`s:%d, TS: %d ALL: %d /// Enough players",countCT,countTS,countALL) //just for testing
        }
    }
    else {
        if(printcons){
            client_print(0,print_console,"[DMB]CT`s:%d, TS: %d ALL: %d /// Not enough players",countCT,countTS,countALL) //just for testing
        }
    }
}//end of counter




//Just counting... used in teamlimit part, in this case it won`t go to the next step
public get_pcount() {   
    get_players(CTList, countCT, "e", "CT") //Gets count of CT`s
    get_players(TSList, countTS, "e", "TERRORIST") //Gets count of T`s
    countALL = countCT + countTS //gets everyone counted
    
    //check if console commands are allowed
    if(get_pcvar_num(c_dmb_printincons) == 1){
        client_print(0,print_console,"[DMB] Counting, because of join_team") //just for testing
        client_print(0,print_console,"[DMB]CT`s:%d, TS: %d ALL: %d",countCT,countTS,countALL) //just for testing
    }
        
}//end of get_pcount
        

        
        
//check if balance is needed           
public balance_calc() {   
    new printcons = get_pcvar_num(c_dmb_printincons)
    //test #1 and 2 - it would be useless to do something if teams are well balanced or there ar not enough players
    if(countCT != countTS && countALL >= get_pcvar_num(c_dmb_minplayers)){
        if(printcons){
            client_print(0,print_console,"[DMB] Test #1 and #2 are true") //just for testing
        }           
        //test #3 - it would be useless to do something if the difference is just 1 player
        if (countCT +1 != countTS && countCT != countTS +1){
            if(printcons){
                client_print(0,print_console,"[DMB] Test #3 is true!") //just for testing
            }               
            //ok, if it gets there it seems to be legit, to transfer player!
            //choosing the strongest team
            if(countCT > countTS){ //if CT`s ar more than T`s
                if(printcons){
                    client_print(0,print_console,"[DMB] Going to transfer CT") //just for testing
                }
                trans_randomCT()
                    
            }
            if(countTS > countCT) // if T`s ...
            {
                if(printcons){
                    client_print(0,print_console,"[DMB] Going to transfer TS") //just for testing
                }
                trans_randomTS()
                    
            }
            if(countCT == countTS){
                //how dafaq this could happen? :D
                //be cool, just do nothing. -.-
                if(printcons){
                    client_print(0,print_console,"[DMB] This message should never appear (CT=TS)") //just for testing
                
                }   
            }
            
            }//end of test#3
            }//end of test#2 and #1
        } //end of balance_calc
        
                
                            
                
                
//And finaly, moment of transfer (:
//If CT needs to be transfered... find random CT           
public trans_randomCT(){
    new printcons = get_pcvar_num(c_dmb_printincons)
    if(printcons){
        client_print(0,print_console,"[DMB] Searching for random CT") //just for testing
    }
    
    new CT[32] = "CT"
    new randomCT
    new teamCT[32]
    //so random player   
    randomCT = random_num(0, countCT -1)
    
    randPid = CTList[randomCT]
    //Check if player really comes from right team... shit may happen :D
    // ... AND if player is in server, do the thing, if not, repeat!
    if (is_user_connected(randPid)){               
        get_user_team(randPid,teamCT,31)
        //if random player is CT                   
        if(equali(teamCT,CT)){
            cs_set_user_team(randPid,CS_TEAM_T,CS_T_TERROR)
            if(printcons){
                client_print(0,print_console,"[DMB] Found the winner! with id: %d",randPid) //just for testing
            }   
                                
            //Lets say that someone is transfered, so people would know that :D
            //Check if print messages are enabled (dmb_printinchat)
                        
            if(get_pcvar_num(c_dmb_printinchat) == 1){
                get_user_name(randPid,randPnick,31)
                new is_now_ter[64]
                formatex(is_now_ter, 63, "%L",LANG_PLAYER,"IS_NOW_T", randPnick)
                client_print(0,print_chat,is_now_ter)
            }
                                
            //Print message in center of screen, to our conest winner.. lol
            //Check if center messages ar allowed (dmb_printincenter)
            if(get_pcvar_num(c_dmb_printincenter) == 1){
                client_print(randPid,print_center,"%L", LANG_PLAYER, "U_R_T")
            }
            //play "beep" sound, if allowed
            if(get_pcvar_num(c_dmb_playsound)){
                client_cmd(randPid, "spk buttons/blip2")
            }
            //fade screen red, if allowed
            if(get_pcvar_num(c_dmb_fadescreen)){
                message_begin(MSG_ONE, get_user_msgid("ScreenFade"), {0,0,0}, randPid)
                write_short(1<<10)
                write_short(1<<10)
                write_short(0x0000)
                write_byte(255)
                write_byte(0)
                write_byte(0)
                write_byte(75)
                message_end()
            }
            //if respawn is enabled, respawn to new spawn       
            if(get_pcvar_num(c_dmb_respawn) == 1){
                //ExecuteHamB(Ham_CS_RoundRespawn, randPid)
                set_task(0.5,"spawner")
                if(printcons){
                    client_print(0,print_console,"[DMB] Prepearing to spawn a player!") //just for testing
                }   
            }
        }
        else {
            //if player is not CT O_O, count again
            set_task (0.1,"counter")
        }
    }
    else {
        //If random player is not connected count again, maybe now player counts are better       
        set_task (0.1,"counter")
        
        if(printcons){
            client_print(0,print_console,"[DMB] Something went wrong, randPid is not connected. (ID:%d)", randPid) //just for testing
        }
    
    }
}
                
                            
                
//If TS needs to be transfered ... find random TS           
public trans_randomTS(){
    new printcons = get_pcvar_num(c_dmb_printincons)
    if(printcons){
        client_print(0,print_console,"[DMB] Searching for random TS") //just for testing
    }   
    new TERRORIST[32] = "TERRORIST"   
    new randomTS
    new teamTS[32]
    //so random player   
    randomTS = random_num(0, countTS -1)
    
    randPid = TSList[randomTS]
    //Check if player really comes from right team... shit may happen :D
    if (is_user_connected(randPid)){               
        get_user_team(randPid,teamTS,31)
    
    //check if random player comes from T team       
        if(equali(teamTS,TERRORIST)){                   
            cs_set_user_team(randPid,CS_TEAM_CT,CS_CT_SAS)
            if(printcons){
                client_print(0,print_console,"[DMB] Found the winner! with id: %d",randPid) //just for testing
            }   
            //lets say that someone is transfered, so people would know that :D
            //check if allowed to print...
            if(get_pcvar_num(c_dmb_printinchat) == 1){   
                get_user_name(randPid,randPnick,31)
                new is_now_ct[64]
                formatex(is_now_ct, 63, "%L",LANG_PLAYER,"IS_NOW_CT", randPnick)
                client_print(0,print_chat,is_now_ct)
            }
            //Print msg in center + check if allowed
            if(get_pcvar_num(c_dmb_printincenter) == 1){
                client_print(randPid,print_center,"%L", LANG_PLAYER, "U_R_CT")
            }
            
            //play "beep" sound, if allowed
            if(get_pcvar_num(c_dmb_playsound)){
                client_cmd(randPid, "spk buttons/blip2")
            }
            //fade screen blue, if allowed
            if(get_pcvar_num(c_dmb_fadescreen)){
                message_begin(MSG_ONE, get_user_msgid("ScreenFade"), {0,0,0}, randPid)
                write_short(1<<10)
                write_short(1<<10)
                write_short(0x0000)
                write_byte(0)
                write_byte(0)
                write_byte(255)
                write_byte(75)
                message_end()
            }
            
            //if respawn is enabled, respawn to new spawn   
            if(get_pcvar_num(c_dmb_respawn) == 1){
            //ExecuteHamB(Ham_CS_RoundRespawn, randPid)
                set_task(0.5,"spawner")
            }
        }
            else {
                //if player has been disconnected, count again, maybe now player counts are better
                set_task (0.5,"counter")
            }
        }
        else {
            set_task (0.5,"counter")
        
            if(printcons){
                client_print(0,print_console,"[DMB] Something went wrong, random player is not connected") //just for testing
            }
        }
    }

    
    
    
//The respawner.. lol, if it is enabled
public spawner(){
    ExecuteHamB(Ham_CS_RoundRespawn, randPid)
    if(get_pcvar_num(c_dmb_printincons) == 1){
        client_print(0,print_console,"[DMB] Player %s respawned after transfer",randPnick) //just for testing
    }   
}
    
public SayBalanceInfo(){
    client_print(0,print_chat,"%L", LANG_PLAYER, "SAY_CMD_AD")
}
    
    
    
                
///////////
// Start of teams limiter, that does not allow to join to the strongest team
// Actually, it allows, but quickly transfers to the weakest team
//////////
/// code taken from ConnorMcLeod (https://forums.alliedmods.net/member.php?u=18946)
/// from thread - https://forums.alliedmods.net/showthread.php?t=63818
/// just edited to fit for limit teams, since I am beginner at coding :D
/////////


public team_join() {   
    if(get_pcvar_num(c_dmb_teamlimit) == 1){   
        //get count of players at first
        get_pcount()
        new loguser[80], name[32]
        new temp[2]
        read_logargv(0, loguser, 79)
        parse_loguser(loguser, name, 31)

        new id = get_user_index(name)

        if(is_user_bot(id))
            return

        read_logargv(2, temp, 1)
        switch(temp[0])
        {
            case 'T' :
            {
                if(countTS -1> countCT && is_user_connected(id)){
                    cs_set_user_team(id,CS_TEAM_CT,CS_CT_SAS)
                    if(get_pcvar_num(c_dmb_printincons) == 1){
                        client_print(0,print_console,"[DMB] Forced player to join CT. CT`s: %d T`s: %d ALL: %d", countCT,countTS,countALL) //just for testing
                    }   
                }

            }
            case 'C' :
            {
                if(countCT -1 > countTS && is_user_connected(id)){
                    cs_set_user_team(id,CS_TEAM_T,CS_T_TERROR)
                    if(get_pcvar_num(c_dmb_printincons) == 1){
                            client_print(0,print_console,"[DMB] Forced player to join TS. CT`s: %d T`s: %d ALL: %d", countCT,countTS,countALL) //just for testing   
                    }   
                }
            }
            case 'S' :
            {
                set_task(0.5, "counter")
                if(get_pcvar_num(c_dmb_printincons) == 1){
                    client_print(0,print_console,"[DMB] Player joined Spectator. CT`s: %d T`s: %d ALL: %d", countCT,countTS,countALL) //just for testing
                }   
            }
        }
    }   
}//end of team_join
//end of whole code (:
 
Статус
В этой теме нельзя размещать новые ответы.

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

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