Всем доброго времени суток! Возник следующий вопрос: как я могу в jass или с помощью триггеров получить номер игрока по его цвету? Пытаюсь решить следующую задачу: На карте первый игрок назначается своеобразным администратором игры, он может прописать команду в чат, где укажет цвет игрока, например green, после чего все сооружения и юниты, подконтрольные зеленому игроку будут убиты. Проблема заключается в том, что если игроки выберут себе цвета по вкусу, то может получится неразбериха, например админ введет green пытаясь, образно говоря, "кикнуть" игрока, выбравшего себе зеленый цвет, а пострадает игрок, который занял при присоединении к игре 7 слот. В голову приходит только такое решение: при выборе всех юнитов, подконтрольных игроку, как то получать номер этого игрока по цвету. Прошу помощи.

Принятый ответ

Слишком сложно.
Вот так попроще будет.
Код
function StringToPlayerColor takes string color returns playercolor
    set color = StringCase(color, false)
	
    if color == "red" then
        return PLAYER_COLOR_RED
    elseif color == "blue" then
        return PLAYER_COLOR_BLUE
    elseif color == "teal" then
        return PLAYER_COLOR_CYAN
    elseif color == "purple" then
        return PLAYER_COLOR_PURPLE
    elseif color == "yellow" then
        return PLAYER_COLOR_YELLOW
    elseif color == "orange" then
        return PLAYER_COLOR_ORANGE
    elseif color == "green" then
        return PLAYER_COLOR_GREEN
    elseif color == "pink" then
        return PLAYER_COLOR_PINK
    elseif color == "gray" then
        return PLAYER_COLOR_LIGHT_GRAY
    elseif color == "light blue" then
        return PLAYER_COLOR_LIGHT_BLUE
    elseif color == "dark green" then
        return PLAYER_COLOR_AQUA
    elseif color == "brown" then
        return PLAYER_COLOR_BROWN
    elseif color == "maroon" then
        return PLAYER_COLOR_MAROON
    elseif color == "navy" then
        return PLAYER_COLOR_NAVY
    elseif color == "turquoise" then
        return PLAYER_COLOR_TURQUOISE
    elseif color == "violet" then
        return PLAYER_COLOR_VIOLET
    elseif color == "wheat" then
        return PLAYER_COLOR_WHEAT
    elseif color == "peach" then
        return PLAYER_COLOR_PEACH
    elseif color == "mint" then
        return PLAYER_COLOR_MINT
    elseif color == "lavender" then
        return PLAYER_COLOR_LAVENDER
    elseif color == "coal" then
        return PLAYER_COLOR_COAL
    elseif color == "snow" then
        return PLAYER_COLOR_SNOW
    elseif color == "emerald" then
        return PLAYER_COLOR_EMERALD
    elseif color == "peanut" then
        return PLAYER_COLOR_PEANUT
    endif
	
    return null
endfunction

function StringToPlayer takes string color returns player
    local integer i
    set bj_setPlayerTargetColor = StringToPlayerColor(color)
	
    if bj_setPlayerTargetColor != null then
        set i = 1
        loop
            set bj_forceRandomCurrentPick = Player(i)
			if GetPlayerSlotState(bj_forceRandomCurrentPick) == PLAYER_SLOT_STATE_PLAYING and /*
            */ GetPlayerColor(bj_forceRandomCurrentPick) == bj_setPlayerTargetColor then
				return bj_forceRandomCurrentPick
			endif
			
            set i = i + 1
			
            exitwhen i == bj_MAX_PLAYERS
        endloop
    endif
	
    return null
endfunction

function KickPlayer takes nothing returns boolean
    call KillUnit(GetFilterUnit())
    return false
endfunction

function MyTrig_Actions takes nothing returns nothing
    local string color = GetEventPlayerChatString()
    local player p = StringToPlayer(SubString(color, 3, StringLength(color)))
    if p != null then
        call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, p, Filter(function KickPlayer))
        set p = null
    endif
endfunction

function InitMyTrig takes nothing returns nothing
    set gg_trg_My = CreateTrigger(  )
    call TriggerRegisterPlayerChatEvent( gg_trg_My, Player(0), "gg", false )
    call TriggerAddAction( gg_trg_My, function MyTrig_Actions )
endfunction
Должно работать.
Чутка подправил.
`
ОЖИДАНИЕ РЕКЛАМЫ...
2
25
5 лет назад
2
Можно так не заморачиваться, а менять цвет юнита входящего в область карты на цвет прикреплённый к игроку. А при смене цвета выбирать всех юнитов игрока и делать то же самое.
2
28
5 лет назад
Отредактирован PT153
2
Можно так не заморачиваться, а менять цвет юнита входящего в область карты на цвет прикреплённый к игроку. А при смене цвета выбирать всех юнитов игрока и делать то же самое.
А можно вообще отключить выбор цвета в меню выбора карты.
0
25
5 лет назад
0

И разве SetPlayerColorBJ вызывает проблемы?
2
28
5 лет назад
Отредактирован PT153
2
Реализация на JASS.
Код
Можно bj_setPlayerTargetColor заменить на локальную, которую даже можно не обнулять.
function StringToPlayerColor takes string color returns playercolor
    set color = StringCase(color, false)
    if color == "red" then
        return PLAYER_COLOR_RED
    elseif color == "blue" then
        return PLAYER_COLOR_BLUE
    elseif color == "cyan" then
        return PLAYER_COLOR_CYAN
    elseif color == "purple" then
        return PLAYER_COLOR_PURPLE
    elseif color == "yellow" then
        return PLAYER_COLOR_YELLOW
    elseif color == "orange" then
        return PLAYER_COLOR_ORANGE
    elseif color == "green" then
        return PLAYER_COLOR_GREEN
    elseif color == "pink" then
        return PLAYER_COLOR_PINK
    elseif color == "light gray" then
        return PLAYER_COLOR_LIGHT_GRAY
    elseif color == "light blue" then
        return PLAYER_COLOR_LIGHT_BLUE
    elseif color == "aqua" then
        return PLAYER_COLOR_AQUA
    elseif color == "brown" then
        return PLAYER_COLOR_BROWN
    endif
    return null
endfunction

function StringToPlayerId takes string color returns integer
    local integer i
    set bj_setPlayerTargetColor = StringToPlayerColor(color)
    if bj_setPlayerTargetColor != null then
        set i = 0
        loop
            if GetPlayerColor(Player(i)) == bj_setPlayerTargetColor then
                return i
            endif
            set i = i + 1
            exitwhen i == bj_MAX_PLAYERS
        endloop
    endif
    return -1
endfunction

Можно поступить иначе: создать структуру для играющих игроков с сохранением полученного объекта в структуры в какой-нибудь массив, в которой будет сохранятся строчный цвет игрока (который можно будет определить функцией, обратной StringToPlayerColor), а при написании в чат пробегаться по массиву игроков и смотреть, у кого же нужный цвет.
0
15
5 лет назад
0
Спасибо большое за помощь. Завтра с утра на свежую голову разберу код.
2
28
5 лет назад
Отредактирован PT153
2
Можно, между прочим, сразу игрока получать, а случае неверной строки возвращать null.
2
32
5 лет назад
2
0
15
5 лет назад
0
Код приспособил к своему, немного поменял для своих нужд, осталась только одна проблема, я делаю это на патче 1.30 для 24 игроков,а так как близзы убрали mpq не могу залезть внутрь и поискать в common.j переменные для цветов, которые они добавили с новыми патчами. Кто то знает может эту инфу? Наверно драколич разве что...
2
24
5 лет назад
2
Meddin, есть же софт который позволяет и в новые архивы влезть, от того-же автора, что значительную часть софта для работы с MPQ писал.
0
15
5 лет назад
0
prog, честно говоря совсем не в курсе, даже не знаю где теперь новые архивы располагаются. Я смотрю в папке дата какие то файлы с расширениями idx. Это оно вообще?
2
24
5 лет назад
2
0
15
5 лет назад
0
prog, благодарю тебя.
2
28
5 лет назад
2
Залезь и глянь, возможно, для новых цветов таких переменных не завезли, так как их не в новом TESH. Если их нет, то можешь свои завести, уверен, все новые цвета можно получить через использование ConvertPlayerColor(12) -- ConvertPlayerColor(23).

Остался ещё способ отключения выбора цвета.
2
15
5 лет назад
Отредактирован Meddin
2
PT153, глянул переменные для новых цветов есть и они точно такие же, как названия цветов. Возможно кому то будет полезна инфа:
Player 13 - Maroon - PLAYER_COLOR_MAROON
Player 14 - Navy - PLAYER_COLOR_NAVY
Player 15 - Turquoise - PLAYER_COLOR_TURQUOISE
Player 16 - Violet - PLAYER_COLOR_VIOLET
Player 17 - Wheat - PLAYER_COLOR_WHEAT
Player 18 - Peach - PLAYER_COLOR_PEACH
Player 19 - Mint - PLAYER_COLOR_MINT
Player 20 - Lavender - PLAYER_COLOR_LAVENDER
Player 21 - Coal - PLAYER_COLOR_COAL
Player 22 - Snow - PLAYER_COLOR_SNOW
Player 23 - Emerald - PLAYER_COLOR_EMERALD
Player 24 - Peanut - PLAYER_COLOR_PEANUT.
Да так глянул, что варкрафт поломался к чертям собачим, просто при запуске игры/лаунчера/редактора выходило окно, что произошла ошибка при запуске и предлагало отправить репорт близзам. Это крайне странно, потому как я просто посмотрел common.j, ничего в нем не редактируя, и закрыл, скопировав нужные переменные. Проблему удалось решить только переустановкой вара, причем удалял и чистил реестр вручную, так как утилита для удаления от близзов тоже крашилась при запуске. Кстати заметил, что если не все слоты будут заняты, например если занять первые несколько слотов, потом один пропустить и заполнить следующие игроками, то для того игрока, который занимает первый слот после пропущенного почему то удаление всех юнитов не срабатывает. Например, если я при создании игры второй слот оставляю пустым, затем в третий слот сую компа, потом в четвертый компа и стартую, то когда в игре пропишу команду, чтобы убило все войска игроку, который в третьем слоте, то ничего не происходит. Сейчас пытаюсь понять в чем дело.
Понял, по-любому не срабатывает условие в цикле, так как "разрывный" между игроками слот пуст.
2
28
5 лет назад
2
Понял, по-любому не срабатывает условие в цикле, так как "разрывный" между игроками слот пуст.
Скорее всего, из-за того, что игрока нет, возвращается НИЧЕГО, и поток обрубается.
Стоит завести свой массив игроков и искать в нём.
0
15
5 лет назад
0
PT153, да уже пофиксил, просто добавил условие на проверку статуса слота игрока:
loop
			if GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then
				if GetPlayerColor(Player(i)) == bj_setPlayerTargetColor then
					return i
				endif
			endif
			
            set i = i + 1
			
            exitwhen i == bj_MAX_PLAYERS
        endloop
Еще вот думаю, надо учесть случай, если админ захочет себе взять иной цвет, не красный. Тогда красный может быть у кого то из игроков. Во-первых поколдую, чтобы с красным цветом работало. Во-вторых надо теперь админа защитить от того, чтобы он сам себя из игры не вышиб. Допустим, у него синий цвет, он напишет "blue" и его же юнитов и здания удалит.
4
26
5 лет назад
4
А почему ты, как админ, пишешь цвет, а не выбираешь юнита и пишешь kick? Так бы автоматом определял владельца юнита и убивал его войска.
2
28
5 лет назад
2
Так колдовать нечего.
Код
function StringToPlayerColor takes string color returns playercolor
    set color = StringCase(color, false)
    if color == "red" then
        return PLAYER_COLOR_RED
    elseif color == "blue" then
        return PLAYER_COLOR_BLUE
    elseif color == "cyan" then
        return PLAYER_COLOR_CYAN
    elseif color == "purple" then
        return PLAYER_COLOR_PURPLE
    elseif color == "yellow" then
        return PLAYER_COLOR_YELLOW
    elseif color == "orange" then
        return PLAYER_COLOR_ORANGE
    elseif color == "green" then
        return PLAYER_COLOR_GREEN
    elseif color == "pink" then
        return PLAYER_COLOR_PINK
    elseif color == "light gray" then
        return PLAYER_COLOR_LIGHT_GRAY
    elseif color == "light blue" then
        return PLAYER_COLOR_LIGHT_BLUE
    elseif color == "aqua" then
        return PLAYER_COLOR_AQUA
    elseif color == "brown" then
        return PLAYER_COLOR_BROWN
    endif
    return null
endfunction

function StringToPlayerId takes string color, player admin returns player
    local integer i
    local player p
    local playercolor col = StringToPlayerColor(color)
    if col != null then
        set i = 0
        loop
            set p = Player(i)
            // В вызове этой функции в триггере с событием на чат в качестве admin передаём GetTriggerPlayer().
            // Сначала проверится, не админ ли это. Если это админ, дальнейшие условия скипаются.
            // Если всё-таки не админ, проверяется статус. Если слот пуст или игрок вышел, дальнейшие условия скипаются.
            // Если игрок всё ещё играет, то сверяем цвета. Если цвета не равны, то выходим из условия.
            // Если всё правда, то возвращаем индекс или сразу игрока.
            if p != admin and GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING and GetPlayerColor(p) == col then
                return p
            endif
            set i = i + 1
            exitwhen i == bj_MAX_PLAYERS
        endloop
    endif
    return null
endfunction
0
15
5 лет назад
0
PT153, спасибо, но я немного иначе решил проблему с админом, я просто перебираю игроков начиная с 1, то есть 0 игрок всегда скипается таким образом.
8gabriel8, просто начал двигаться уже в таком направлении, сначала я сделал вообще не цвет а номер игрока, но мне сказали, что по номеру кикать геморно, попросили сделать кик через цвет и как то пошло поехало...
К тому же представь ситуацию, допустим в FFA остался игрок, который играет за орду, он по факту проиграл, его вынесли, но он успел где-нибудь в одном из захолустных местечек карты построить мейн на последние деньги. И у него есть блейд, которым он уходит в виндволк. Админу придется ждать, пока он выйдет из виндвока, чтобы прожать блейда и прописать кик. Легче уже через цвет, как по мне.
2
26
5 лет назад
2
Понятно. Но подумай всё-таки, чтобы этот вариант предложить, просто эти 24 цвета порой бывают столь похожи, что легко перепутать и не тот прописать.
0
15
5 лет назад
0
Короче осталась только единственная проблема, почему то не работает с красным цветом, если я ставлю админу любой другой, а одному из игроков красный. Вот тут чет я даже не знаю, в чем дело. Вроде все логично в коде теперь, все как надо.
8gabriel8, это да, я согласен. Уже обсуждали и этот момент, пришли к выводу, что логичнее копать в сторону кика по нику игрока, но мне это тоже не особо нравится, поскольку такие ники иногда бывают, тоже хрен еще напишешь в точности.
2
28
5 лет назад
Отредактирован PT153
2
А у админа какой id?

А ты добавил красный цвет в функцию получения цвета?
Ну и я не понял, что именно не работает.
2
26
5 лет назад
2
А как насчёт создания диалога, кого кикнуть?
0
15
5 лет назад
Отредактирован Meddin
0
PT153, да. Он там есть. Он у тебя и был же в твоей функции изначально.
Ну у админа id 0, так как он первый слот занимает всегда. Не работает именно тот момент, когда красный цвет у кого-нибудь из игроков, например пусть у нас Игрок 1 - админ, будет синего цвета, а Игрок 2 - обычный игрок себе поставит красный цвет. В этот случае вот не работает.
8gabriel8, хм, это не плохая идея кстати. Я подумаю над этим. Спасибо. Но тогда надо как то сделать "включатель" этого диалога, чтобы он появлялся, когда админ захочет, в принципе, можно просто по команде в чат сделать...
2
28
5 лет назад
2
А как насчёт создания диалога, кого кикнуть?
Тут обратная ситуация: нужно по id игрока узнать его цвет, ведь в диалоге должны быть только те игроки, что ещё играют.
Meddin:
Он у тебя и был же в твоей функции изначально.
Так а что не работает-то?
Чтобы оставить комментарий, пожалуйста, войдите на сайт.