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

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

Ответ
 
Preveder
StarCraft II® Inside
offline
Опыт: 1,927
Активность:
Приколы с TriggerSleepAction
Давеча столкнулся с забавной проблемой.

Имеется триггер. Этот смотрит в чат, реагируя на команду, допустим, "-ролик".

Далее триггер запускает через ExecuteFunc функцию, отвечающую за выполнение команды.

В этой функции имеется обычный вызов через call функции, в которой перечислены все действия ролика. Так вот, всё это дело эпично накрывается медным тазом.

Мало того, что TriggerSleepAction не пашут и ролик останавливается, так ещё и половина свистелок и перделок тоже накрываются. Было замечено, что откидывают копыта все игровые таймеры О_О!

Зато, если call заменить на ExecuteFunc и вызвать действия ролика по имени функции, всё снова работает.

Вопрос. Какой-же всё таки комбинацией надо вызывать функцию, чтобы не боятся, что Wait всё испортит (100% создатся новый, хороший годный поток)?

Дано: call, TriggerEvaluate(в ней вейты нельзя), TriggerExecute, ExecuteFunc.

Как следует из вышегоописанного, схема Действие триггера->ExecuteFunc->call приносит печаль в наш мир.
А вот Действие триггера->ExecuteFunc->ExecuteFunc работает.

Есть ли какие-либо трюки с потоками, чтобы гарантированно безопасно запустить функцию с вейтами? Без них в ролике не получается - дробить цельную функцию на 100500 мелких с таймерами - это маразм, имхо, да и времени убить много надо.
Старый 29.01.2010, 14:11
DioD

offline
Опыт: 45,134
Активность:
ну гадалка в декрете а ваше абстрактное представление о том как работает варкрафт не имеет никакой научной и практической ценности.
код в студию.
Старый 29.01.2010, 14:34
bee
vjass.optimizer
offline
Опыт: 16,615
Активность:
Старый 29.01.2010, 14:38
Preveder
StarCraft II® Inside
offline
Опыт: 1,927
Активность:
Вот такой лолкод:

» раскрыть
Код:
scope MAPCONSOLE

struct console
    static trigger CommandHandler=CreateTrigger()
    static hashtable CommandDatabase=InitHashtable()
    static string EnteredString=""
    static string Stamp="[Console]:>"
        static method wordparser takes string s, integer word returns string
        local string array Chkstr
        local integer Last=0
        local integer A=1
        local integer I=0
        local integer Length=1
        loop
        exitwhen((SubString(s,0,Length)==s))
            set Length=Length+1
        endloop
        loop
        exitwhen(A>Length)
        exitwhen((word+1)==I)
            if(SubString(s,A-1,A)==" ") then
                set Chkstr=SubString(s,Last,(A-1))
                set Last=A
                set I=I+1
            elseif(A==Length) then
                set Chkstr[I]=SubString(s,Last,A)
            endif
            set A=A+1
        endloop
        return Chkstr[word]    
    endmethod
    static method print takes player p, string s returns string
        call DisplayTextToPlayer(GetTriggerPlayer(),0,0,console.Stamp+console.getenteredcomma  nd()+"->"+s)
        return s
    endmethod
    static method havecommand takes string command returns boolean
        return HaveSavedString(console.CommandDatabase,StringHash(StringCase(command,true)),0)
    endmethod
    static method addcommand takes string command, string commandfuncname returns nothing
        call SaveStr(console.CommandDatabase,StringHash(StringCase(command,true)),0,commandfu  ncname)
    endmethod
    static method getcommandaction takes nothing returns string
        return LoadStr(console.CommandDatabase,StringHash(StringCase(console.getenteredcommand(  ),true)),0)
    endmethod
    static method getenteredstring takes nothing returns string
        return console.EnteredString
    endmethod
    static method getenteredcommand takes nothing returns string
        return console.wordparser(console.EnteredString,0)
    endmethod
    static method getenteredword takes integer wordnum returns string
        return console.wordparser(console.EnteredString,wordnum)
    endmethod
    static method commandaction takes nothing returns nothing
        set console.EnteredString=SubString(GetEventPlayerChatString(),1,StringLength(GetEve  ntPlayerChatString()))
        if console.havecommand(console.getenteredcommand()) then
            call ExecuteFunc(console.getcommandaction())
        else
            call game.ErrorMessage(GetTriggerPlayer(),44)
        endif
    endmethod
    static method condition takes nothing returns boolean
        return SubString(GetEventPlayerChatString(),0,1)==mapconfig.ChatCommandPrefix
    endmethod
    static method init takes nothing returns nothing
        call TriggerRegisterAnyPlayerChatEvent(console.CommandHandler,mapconfig.ChatCommandPr  efix,false)
        call TriggerAddCondition(console.CommandHandler,Condition(function console.condition))
        call TriggerAddAction(console.CommandHandler,function console.commandaction)
    endmethod
endstruct

function ConsoleCommandRolik takes nothing returns nothing
    call ExecuteFunc("s__game_LooseCinematic")
    //call game.LooseCinematic()
endfunction

function InitConsole takes nothing returns nothing
    call console.init()
    call console.addcommand("rolik","ConsoleCommandRolik")
endfunction

endscope


[i]Preveder добавил:

Bee, читал. Я знаю, что ExecuteFunc в теории должна запускать новый поток, но в моём случае есть загвоздки.
Старый 29.01.2010, 14:44
DioD

offline
Опыт: 45,134
Активность:
и где хоть одно ожидание?
и вообще писать статичные стракты тем более таким образом насилие над движком оно же компилируется в жуткую кашу.
Старый 29.01.2010, 14:45
Preveder
StarCraft II® Inside
offline
Опыт: 1,927
Активность:
Цитата:
Сообщение от DioD
и где хоть одно ожидание?

В функции, отвечающей за ролик. Сначала триггер работает функцией commandaction. Затем, функция commandaction вызывает ConsoleCommandRolik через ExecuteFunc (в теории, уже создался новый поток). И вот в этой-то функции вызов функции с действием самого ролика. Т.е. по идее через call она должна идти в одном потоке. И тут вейты не работают. Тогда через создание ещё одного потока:

Код:
function ConsoleCommandRolik takes nothing returns nothing
    call ExecuteFunc("s__game_LooseCinematic") - вейты работают в вызываемой функции
    //call game.LooseCinematic() - вейты не работают.
endfunction


Все механика этой "консоли" выше.

Отредактировано Preveder, 29.01.2010 в 14:59.
Старый 29.01.2010, 14:50
adic3x

offline
Опыт: 108,439
Активность:
я бы сразу делал на таймерах - куда меньше подводных камней
Старый 29.01.2010, 15:09
Preveder
StarCraft II® Inside
offline
Опыт: 1,927
Активность:
Ответа на вопрос "100% верная комбинация для запуска функции с ожиданиями" не получил.

Но предполагаю, что будет верным в данном случае создание триггера-контейнера с функцией в действиях. То бишь TriggerExecute(). Единственный минус - триггер надо создавать.

Либо, получается, ExecuteFunc->ExecuteFunc чтоб уж наверняка. :) Но мне не нравится, что надо постоянно следить за именами функций в данном варианте. Поменял имя, забыл - лови фатал, сиди разбирай, где накосячил.

Теперь юзаю первый вариант, всё устраивает. :)
Старый 29.01.2010, 16:08
DioD

offline
Опыт: 45,134
Активность:
покажи код с ожиданиями а не левую систему, зачем вообще ты этот левый код выложил?
Старый 29.01.2010, 17:57
Preveder
StarCraft II® Inside
offline
Опыт: 1,927
Активность:
Цитата:
Сообщение от DioD
покажи код с ожиданиями а не левую систему, зачем вообще ты этот левый код выложил?

Вот, собственно, кусок кода функции с роликом:
Код:
function Тра-ля-ля takes nothing returns nothing
        local real x=GetRectCenterX(рект_такой-то)
        local real y=GetRectCenterY(рект_такой-то)
        call game.GameOverInit()
        call ForceCinematicMode(группа_игроков,true)
        call SetUserControlForceOff(группа_игроков)
        call PlaySoundFromOffsetBJ(music.listedtrack[12].trackfile,100,73.00)
        call ForceCameraApply(группа_игроков,камера_такая-то,true,0.5)
        call TriggerSleepAction(2.0)
        call ForceCameraShake(группа_игроков,true,5.0)

Всё что до первого Wait - выполняется, после - камера не трясётся, и так далеe... Вся функция короче обрывается. И вместе с ней - половина триггерного функционала (таймеры убиваются и т.д.).
Старый 29.01.2010, 18:08
ScorpioT1000
Работаем
offline
Опыт: отключен
что за группа_игроков ?
нихрена не понятно с коде. ты 100% знаешь что функция обрывается? принт юзал?
Старый 29.01.2010, 19:06
Preveder
StarCraft II® Inside
offline
Опыт: 1,927
Активность:
ScorpioT1000, естественно юзал мессагу. Ставил перед вейтом и после. Перед вейтом - показывалось, после - пусто.
Группа игроков - это force, для игроков которой выполняется Enum-функция.

Отредактировано Preveder, 29.01.2010 в 19:16.
Старый 29.01.2010, 19:11
ScorpioT1000
Работаем
offline
Опыт: отключен
что за группа? просто всякие GetTrigger... после вейта не пашут. хм, хотя они и так не должны пахать.
и вобще execute не надо, каждый триггер и так новый поток
Старый 29.01.2010, 19:21
Preveder
StarCraft II® Inside
offline
Опыт: 1,927
Активность:
Цитата:
Сообщение от ScorpioT1000
что за группа? просто всякие GetTrigger... после вейта не пашут. хм, хотя они и так не должны пахать.
и вобще execute не надо, каждый триггер и так новый поток

Я просто переименовал названия переменных в более короткий вид для читабельности, чтобы функция на всю ширину моего поста не разъежалась. Никаких "опасных" функций там нет.

Проблема в общем-то решена. Но почему цепочка вызовов

1 Действие триггера
||
2 Вызов функции через ExecuteFunc
||
3 Вызов функции через call

даёт нерабочие вейты, это загадка. По идее, 2) создаёт поток, и call уже в нём исполняется. Странно. Приходится почему-то ещё один поток вызывать.
Старый 29.01.2010, 19:42
ScorpioT1000
Работаем
offline
Опыт: отключен
я не понимаю, зачем экзекут?
каждый триггер и так новый поток
Старый 29.01.2010, 19:49
Preveder
StarCraft II® Inside
offline
Опыт: 1,927
Активность:
ScorpioT1000, таким образом работает мой триггер, 4 пост сверху в теме.
Старый 29.01.2010, 20:34
ScorpioT1000
Работаем
offline
Опыт: отключен
вобщем, я могу сказать только что в экзекученной ф-ции вейты должны пахать хорошо. попробуй локализировать ошибку, сделать другое событие
Старый 30.01.2010, 23:12
DioD

offline
Опыт: 45,134
Активность:
просто гениальная система автора вешает поток.
Старый 31.01.2010, 06:26
ScorpioT1000
Работаем
offline
Опыт: отключен
ну да, скорее всего, только не вижу, чему вешать
Старый 31.01.2010, 10:06
DioD

offline
Опыт: 45,134
Активность:
ты не заметил что автор выкладывает какойто бутор вместо кода?
Старый 31.01.2010, 10:21
Ответ

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

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

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

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



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