XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Желтая пресса: обучающие статьи
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

 
DioD

offline
Опыт: 45,134
Активность:
Построение "VoteKick" механизма

ПС, это пока еще не статья, а её маленький кусок, буду править как оформление так и описание.



Содержание:


Вступление
1) Отлов ввода
-По номеру игрока
-По цвету игрока
-По имени игрока

2) Построение системы учёта голосов
-Учёт голосов
-Автоматическое голосование
-Лишение голоса

3) Графическое оформление системы голосования
-Выбор языка
-Выбор стиля
-Настройка авто голосования

Послесловие

Механизм, который может сделать игру приятнее и интереснее, никогда не бывает лишним.
В отличии от простого кика хостом, который не всегда адекватен, выкидывание из игры путём голосования гораздо более целесообразно.
Готовый пример не может нести достаточную образовательную нагрузку, поэтому я решил написать небольшую статью.

1) Отлов ввода



Всё что нужно для отлова ввода команды игроками это триггер, в этом разделе голосование не включено в обсуждение, так что нем не требуется ни переменных дополнительных объектов

-Функции для обработки



Код:
function VoteRegister takes trigger T, string V returns nothing
    local integer L = 11
    loop
        if L!= 3 or L!=6 then
            call TriggerRegisterPlayerChatEvent(T,Player(L),V,false)
        endif
        set L = L-1
        exitwhen L <0
    endloop
endfunction
В аргументы включена строка и триггер который будет хостом всех событий
как пример включено лишение голоса игроков 4 и 7, вы можете изменить или убрать это.

Как пример
    call VoteRegister(gg_trg_Players_Kick,"-VoteKick")


Мы успешно зарегестрировали события, теперь действие.
Так как строка для регестрации может меняться (язык ввода, это ниже) нам потребуется немного мозга...

Код:
function Trig_Kick_Player_Actions takes nothing returns nothing
    local integer I = StringLength(GetEventPlayerChatStringMatched())+1
    local integer T = StringLength(GetEventPlayerChatString())
    local string  S = SubString(GetEventPlayerChatString(),I,T)
    local player  P = IsPlayerNumber(S)
    if P != null then
        call Echo(I2S(GetPlayerId(P) + 1))
    endif
endfunction
Крайне тупая конструкция, в основном из за того что она универсальна
I = Возращает строку, накоторую реагировал триггер
T = Возращает общую длину введённой строки
S = Возращает то, что мы непосредственно ввели по мимо ключевого слова
Далее идут основные функции...


Код:
function Echo takes string S returns nothing
    call DisplayTextToPlayer(GetLocalPlayer(),0.1,0.1,S)
endfunction
Вывод текста, так как кикать нам некого, а тестирование необходимо


Код:
function IsPlayerNumber takes string S returns player
    local integer I = S2I(S)
    local integer L = StringLength(S)
    if L > 2 then
        call Echo("Invalid type")
        return null
    endif
    if not IsNumber(S) then
        call Echo("Invalid type")
        return null
    endif
    if I <1 or I >12 then
        call Echo("Invalid type")
        return null
    endif
    return Player(I-1)
endfunction
Ядро проверки на введение номера игрока
-Длина не больше 2х символов
-Оба символа цифры
-Цифры могут быть игроками


Код:
function IsNumber takes string S returns boolean
    return S == I2S(S2I(S))
endfunction
Определяет, является ли строка цифрой


И так, отлов номера игрока закончен, вы можете собрать функции в триггер и использовать их.

Номер игрока это хорошо, но цвет я думаю лучше, дляотлова поцвету нас всего навсего потребуется добавить одну функцию, и то крайне простую:

Код:
function ColorTable takes string S returns player
    if S == "red" then
        return Player(0)
    elseif S == "blue" then
        return Player(1)
    elseif S == "teal" then
        return Player(2)
    elseif S == "purple" then
        return Player(3)
    elseif S == "yellow" then
        return Player(4)
    elseif S == "orange" then
        return Player(5)
    elseif S == "green" then
        return Player(6)
    elseif S == "pink" then
        return Player(7)
    elseif S == "grey" then
        return Player(8)
    elseif S == "cyan" then
        return Player(9)
    elseif S == "aqua" then
        return Player(10)
    elseif S == "brown" then
        return Player(11)
    endif
    return null
endfunction


Обратите внимание на то что функция возращает игрока, а не его номер, это достаточно важно, когда будете собирать подобные механизмы старайтесь обращаться к объектам напрямую.

Код:
function IsPlayerNumber takes string S returns player
    local integer I = S2I(S)
    local integer L = StringLength(S)
    local player P = ColorTable(StringCase(S,false))
    if P != null then
        return P
    endif
    if L > 2 then
        call Echo("Invalid type")
        return null
    endif
    if not IsNumber(S) then
        call Echo("Invalid type")
        return null
    endif
    if I <1 or I >12 then
        call Echo("Invalid type")
        return null
    endif
    return Player(I-1)
endfunction


Маленькое дополнение в ядро проверки, сверка с базой данных, ставиться до сверки с числом, так как имя не может быть меньше 3х символов.
Еще одно, сверка чувствительна к регистру, поэтому мы его убиваем.

Отредактировано DioD, 03.01.2007 в 17:16.
Старый 03.01.2007, 15:46
dk

offline
Опыт: 60,293
Активность:
Имхо это наработка, а не статья. Наконец-то диод решил вывести в свет свой механизм, кика по голосованию, юзать который будет только он сам )
Старый 03.01.2007, 16:23
DioD

offline
Опыт: 45,134
Активность:
статья прилагает примеры, я решил написать статью по применению определённых функций, нуи построение этих самых функций в логические цепи
результатом будет наработка - процессом создания статья.
Старый 03.01.2007, 17:00
bladehamster

offline
Опыт: 3,660
Активность:
А без джасса можно плз...?
Старый 03.01.2007, 18:04
Aspid

offline
Опыт: 8,361
Активность:
DioD ммм такой вопросик - где это может пригодиться?
Старый 03.01.2007, 18:14
dk

offline
Опыт: 60,293
Активность:
Там где используется обычный кик, пригодится и этот. АоС, Арены, командные ТД и т.д. )
Старый 03.01.2007, 18:36
DioD

offline
Опыт: 45,134
Активность:
он везде пригодиться...
Старый 03.01.2007, 19:51
remal
нечто
offline
Опыт: 2,087
Активность:
нечто такое мне нравится больше (идея скомуниздена из battleships'ов)
Код:
function PlayerNameColored takes player PL returns string
    local string array colors
    set colors[0] = "|cffff0000"
    set colors[1] = "|cff0000ff"
    set colors[2] = "|cff40e0D0"
    set colors[3] = "|cff800080"
    set colors[4] = "|cffffff00"
    set colors[5] = "|cffffa500"
    set colors[6] = "|cff00ff00"
    set colors[7] = "|cffffc0cb"
    set colors[8] = "|cff808080"
    set colors[9] = "|cff87cefa"
    set colors[10] = "|cff006400"
    set colors[11] = "|cff8b4513"

    return colors[GetPlayerId(PL)] + GetPlayerName(PL) + "|r"
endfunction

function ColorOfPlayer takes player PL returns string
    local string array colors
    set colors[0] = "|cffff0000"
    set colors[1] = "|cff0000ff"
    set colors[2] = "|cff40e0D0"
    set colors[3] = "|cff800080"
    set colors[4] = "|cffffff00"
    set colors[5] = "|cffffa500"
    set colors[6] = "|cff00ff00"
    set colors[7] = "|cffffc0cb"
    set colors[8] = "|cff808080"
    set colors[9] = "|cff87cefa"
    set colors[10] = "|cff006400"
    set colors[11] = "|cff8b4513"

    return colors[GetPlayerId(PL)]
endfunction

//------------------------------------------------------------------

constant function KickVotes_AlliesOnly takes nothing returns boolean
    return true
endfunction

constant function KickVotes_Timeout takes nothing returns real
    return 10.
endfunction

function Trig_KickVotes_WaitForClick_Actions takes nothing returns nothing
    set bj_lastCreatedButton = GetClickedButton()
endfunction

function Trig_KickVotes_Actions takes nothing returns nothing
    local integer KickingPlayer = GetPlayerId(GetTriggerPlayer())
    local trigger VoteTrigger
    local dialog VoteDialog = null
    local button array Buttons
    local integer KickIndex
    local integer i
    local timer TimeoutTimer
    local timerdialog TimeoutTimerDialog
    local trigger VoteYesTrig
    local trigger VoteNoTrig
    local integer TotalVotes

    // creating dialog to choose player to kick
    set i = 0
    loop
        if Player(i) != Player(KickingPlayer) then
            if (GetPlayerController(Player(i)) == MAP_CONTROL_USER)and(GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING) then
                if (KickVotes_AlliesOnly() and IsPlayerAlly(Player(i), Player(KickingPlayer))) or (not KickVotes_AlliesOnly()) then
                    if VoteDialog == null then
                        set VoteDialog = DialogCreate()
                        call DialogClear(VoteDialog)
                    endif
                    // PlayerNameColored needed!
                    set Buttons[i] = DialogAddButton(VoteDialog, PlayerNameColored(Player(i)), 0)
                endif
            endif
        endif
        set i = i + 1
        exitwhen i > 12
    endloop

    // if there is no one player to kick then return
    if VoteDialog == null then
        call DisplayTextToPlayer(GetTriggerPlayer(), 0.0, 0.0, "|cffffaa00There must be at least 3 players in your team to kick!|r")
        return
    endif

    // adding Cancel button and showing dialog
    call DialogSetMessage(VoteDialog, "Choose player to kick")
    set Buttons[12] = DialogAddButton(VoteDialog, "|cffffffffC|r|cffffaa00ancel|r", 67)
    call DialogDisplay(Player(KickingPlayer), VoteDialog, true)
    
    // waiting for some button pressed
    set VoteTrigger = CreateTrigger()
    call TriggerRegisterDialogEvent(VoteTrigger, VoteDialog)
    set Buttons[13] = bj_lastCreatedButton
    set bj_lastCreatedButton = null
    call TriggerAddAction(VoteTrigger, function Trig_KickVotes_WaitForClick_Actions)
    loop
        if GetTriggerExecCount(VoteTrigger) > 0 then
            exitwhen true
        endif
        call TriggerSleepAction(1)
    endloop

    // get what button was pressed and destroying dialog
    set KickIndex = 0
    loop
        if bj_lastCreatedButton == null then
            set KickIndex = 12
        endif
        if bj_lastCreatedButton == Buttons[KickIndex] then
            exitwhen true
        endif
        set KickIndex = KickIndex + 1
        exitwhen KickIndex > 11
    endloop
    
    // clearning up...
    call DestroyTrigger(VoteTrigger)
    set VoteTrigger = null
    call DialogDisplay(Player(KickingPlayer), VoteDialog, false)
    call DialogClear(VoteDialog)
    call DialogDestroy(VoteDialog)
    set VoteDialog = null
    set bj_lastCreatedButton = Buttons[13]
    set i = 0
    loop
        set Buttons[i] = null
        set i = i + 1
        exitwhen i > 13
    endloop

    // if Cancel was pressed then return
    if KickIndex > 11 then
        return
    endif

    call DisplayTextToForce(GetPlayersAll(), "Starting voting to kick " + PlayerNameColored(Player(KickIndex)) + "...")
    
    // setting timeout timer
    set TimeoutTimer = CreateTimer()
    call TimerStart(TimeoutTimer, KickVotes_Timeout(), false, null)
    call ResumeTimer(TimeoutTimer)
    set TimeoutTimerDialog = CreateTimerDialog(TimeoutTimer)
        // ColorOfPlayer needed!
    call TimerDialogSetTitle(TimeoutTimerDialog, ColorOfPlayer(Player(KickIndex))+"Kick|r Y:0 N:0")

    // creating vote dialog
    set VoteDialog = DialogCreate()
    call DialogClear(VoteDialog)
    call DialogSetMessage(VoteDialog, "Kick " + PlayerNameColored(Player(KickIndex)) + "?")
    
    // registering needed triggers
    set VoteYesTrig = CreateTrigger()
    set VoteNoTrig = CreateTrigger()
    call TriggerRegisterDialogButtonEvent(VoteYesTrig, DialogAddButton(VoteDialog, "|cffffffffY|r|cffffaa00es|r", 89))
    call TriggerRegisterDialogButtonEvent(VoteNoTrig, DialogAddButton(VoteDialog, "|cffffffffN|r|cffffaa00o|r", 78))

    // showing vote dialog
    set i = 0
    set TotalVotes = 0
    loop
        if i != KickIndex then
            if (GetPlayerController(Player(i)) == MAP_CONTROL_USER)and(GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING) then
                if (KickVotes_AlliesOnly() and IsPlayerAlly(Player(i), Player(KickingPlayer))) or (not KickVotes_AlliesOnly()) then
                    set TotalVotes = TotalVotes + 1
                    call DialogDisplay(Player(i), VoteDialog, true)
                    if Player(i) == GetLocalPlayer() then
                        call TimerDialogDisplay(TimeoutTimerDialog, true)
                    endif
                endif
            endif
        endif
        set i = i + 1
        exitwhen i > 12
    endloop

    // voting...
    loop
        call TriggerSleepAction(1)
        call TimerDialogSetTitle(TimeoutTimerDialog, ColorOfPlayer(Player(KickIndex))+"Kick|r Y:"+I2S(GetTriggerExecCount(VoteYesTrig))+" N:"+I2S(GetTriggerExecCount(VoteNoTrig)))
        exitwhen GetTriggerExecCount(VoteYesTrig) + GetTriggerExecCount(VoteNoTrig) >= TotalVotes
        exitwhen GetTriggerExecCount(VoteYesTrig) >= R2I((TotalVotes+1.0) / 2.0 + 0.5)
        exitwhen TimerGetRemaining(TimeoutTimer) <= 0
    endloop

    // kicking
    if GetTriggerExecCount(VoteYesTrig) > GetTriggerExecCount(VoteNoTrig) + 1 then
        call DisplayTextToForce(GetPlayersAll(), PlayerNameColored(Player(KickIndex)) + " was kicked!")

        // ###################################################################
        // # here must be a code to be executed before player will be kicked #
        // ###################################################################
        
        call CustomDefeatBJ(Player(KickIndex), "Kicked!")
    else
        call DisplayTextToForce(GetPlayersAll(), PlayerNameColored(Player(KickIndex)) + " was NOT kicked!")
    endif
    
    // clearning up...
        // timer window
    call TimerDialogDisplay(TimeoutTimerDialog, false)
    call DestroyTimerDialog(TimeoutTimerDialog)
    set TimeoutTimerDialog = null
        // timer
    call DestroyTimer(TimeoutTimer)
    set TimeoutTimer = null
        // voting dialog
    set i = 0
    loop
        call DialogDisplay(Player(i), VoteDialog, false)
        set Buttons[i] = null
        set i = i + 1
        exitwhen i > 11
    endloop
    call DialogClear(VoteDialog)
    call DialogDestroy(VoteDialog)
    set VoteDialog = null
        // voting triggers
    call DestroyTrigger(VoteYesTrig)
    set VoteYesTrig = null
    call DestroyTrigger(VoteNoTrig)
    set VoteNoTrig = null
endfunction

// this function initialize kick system. call it at map initialization or when you need it:)
function InitKickVotes takes nothing returns nothing
    local trigger KickTrigger = CreateTrigger()
    local integer i = 0
    loop
        call TriggerRegisterPlayerChatEvent(KickTrigger, Player(i), "-kick", true)
        set i = i + 1
        exitwhen i > 11
    endloop
    call TriggerAddAction(KickTrigger, function Trig_KickVotes_Actions)
endfunction
после набора "-kick" появляется диалог для выбора игрока для голосования на кик. потом для всех появляется диалог-голосовалка.
функция KickVotes_AlliesOnly определяет кикаем ли только союзников
функция KickVotes_Timeout - время на голосование

вся система обсалютно независима. не использует переменных и тп.
Старый 03.01.2007, 20:16
DioD

offline
Опыт: 45,134
Активность:
вылезающие кнопки могут сильно мешать, куда проще
  1. один игрок начинает голосование
остальные пишут yes\no
Старый 03.01.2007, 20:24
NETRAT

offline
Опыт: 83,712
Активность:
да, если использовать диалоги, то следует паузить игру(ибо действительно, выведение диалога в ответственный игровой момент - это попа) пока все не проголосовали, а это может надолго остановить игру
Старый 03.01.2007, 21:13
VBSniper
Ёк макарёк
offline
Опыт: 3,486
Активность:
А сккажи я чёт не разберусь, где по голосованию?? Мне поголосованию нужно!
Старый 22.01.2007, 18:59
DioD

offline
Опыт: 45,134
Активность:
по голосованию, байкотировали мою очередную задумку, вот дописывать и не буду
Старый 22.01.2007, 19:32
Murloc
Powered by Q
offline
Опыт: 16,977
Активность:
Вообще задумка кул, узнал кмного нового прочитав тему, не сцать диод, прорвёшься.
Старый 22.01.2007, 20:54
Alibek
Choops
offline
Опыт: 12,699
Активность:
Grisha2007
откопал тож...
Старый 15.11.2007, 17:30
DFlyer
<3 MJ
offline
Опыт: 42,879
Активность:
Alibek
Ему кто-то дал ссылку на этот топег. Чтоб задавал вопросы, если что-то непонятно.
Старый 15.11.2007, 17:38
Kel_TuZaD

offline
Опыт: 1,630
Активность:
Не в некотрых типах карт это может пригодится что бы кикать итем стилеров или отчайных нубов... Ведь здесь идет голосование,а не решение хоста так что норм игроков кикнуть не получится..
Поэтому мне кажется что беспредела не буит.
Старый 21.11.2007, 10:33

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 14:27.