|
|
|
|
Проблема с ограничением кол-ва предметов
|
|
Aloof | Дата: Вторник, 17 Июля 2012, 18:31:42 | Сообщение # 1 |
5 уровень
Группа: Проверенные
Сообщений: 107
Награды: 0
Репутация: 14
Блокировки:
| Есть некий предмет X, который должен присутствовать у героя не более, чем в одном количестве.
Для этого я сделал 2 триггера на события EVENT_PLAYER_UNIT_SELL_ITEM и EVENT_PLAYER_UNIT_PICKUP_ITEM. Логика такая: если был куплен, то предмет уничтожается, деньги возвращаются; если был получен, то предмет падает рядом с героем. Насколько я понял, второе событие --- более общий случай, то есть оно будет срабатывать даже если предмет был куплен, причём срабатывает раньше, чем EVENT_PLAYER_UNIT_SELL_ITEM. И появилась проблема: при покупке второго предмета он падает на землю. Как избежать этого? Делать нулевой таймер?
|
|
|
|
Extremator | Дата: Вторник, 17 Июля 2012, 18:50:52 | Сообщение # 2 |
10 уровень
Группа: Проверенные
Сообщений: 3199
Награды: 0
Репутация: 1018
Блокировки:
| сделай покупку пустышки...
купил "псевдо-арт" если у героя есть уже АРТ, то... удалить псевдо-арт и дать денег иначе, дать герою АРТДобавлено (17 Июля 2012, 18:50:52) --------------------------------------------- или у тебя проблема в части подсчёта одинаковых предметов у юнита в инвентаре? хд
|
|
|
|
Aloof | Дата: Вторник, 17 Июля 2012, 19:40:15 | Сообщение # 3 |
5 уровень
Группа: Проверенные
Сообщений: 107
Награды: 0
Репутация: 14
Блокировки:
| Идея интересная, но как раз мою проблему вроде не решает, потому что проблема в срабатывании другого триггера, который выбрасывает предмет. Т.е. просто выбросит этот предмет-пустышку, ничего не изменится, по-моему.
|
|
|
|
SirNikolas | Дата: Вторник, 17 Июля 2012, 19:51:25 | Сообщение # 4 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
| При дропе предмета приписываешь в хэш к нему true, запускаешь нулевой таймер. По истечении удаляешь значение из хэша. При получении предмета (*_PICKUP_ITEM) проверяешь, если в хэше true - значит, предмет передан, если false - куплен.
|
|
|
|
Naturekid | Дата: Вторник, 17 Июля 2012, 20:10:20 | Сообщение # 5 |
Группа: Заблокированные
Сообщений: 4982
Награды: 3
Репутация: 3347
Блокировки:
| Quote (Extremator) если у героя есть уже АРТ, то... удалить псевдо-арт и дать денег [тролльская придирка] А если у героя больше 6 предметов в инвентаре и нужный предмет для проверки находится в скрытом режиме? Тогда это условие не поможет, только через запоминание переменных
|
|
|
|
Extremator | Дата: Вторник, 17 Июля 2012, 20:38:12 | Сообщение # 6 |
10 уровень
Группа: Проверенные
Сообщений: 3199
Награды: 0
Репутация: 1018
Блокировки:
| Quote (Aloof) Идея интересная, но как раз мою проблему вроде не решает, потому что проблема в срабатывании другого триггера, который выбрасывает предмет. Т.е. просто выбросит этот предмет-пустышку, ничего не изменится, по-моему.
иди делай как я сказал -_-
при покупке пустышки твой второй триггер не сработает, потому что ты получишь пустышку, а не сам арт
и если у героя есть арт, то арте ему не дадут а если нету, то дадут... тогда запустится 2й триггер, который посчитает что у героя только 1 арт (который ему только что дали) и ничего не выбросит
всё
|
|
|
|
Aloof | Дата: Пятница, 03 Августа 2012, 00:34:56 | Сообщение # 7 |
5 уровень
Группа: Проверенные
Сообщений: 107
Награды: 0
Репутация: 14
Блокировки:
| Quote (SirNikolas) При дропе предмета приписываешь в хэш к нему true, запускаешь нулевой таймер. По истечении удаляешь значение из хэша. При получении предмета (*_PICKUP_ITEM) проверяешь, если в хэше true - значит, предмет передан, если false - куплен. Так некто может положить предмет на землю, а затем другой герой его подобрать. Мне кажется нелогичным, что событие поднятие предмета наступает раньше события покупки.
Да и потом: я так понял, что подобная логика основывается на том, что последовательность вызовов будет такая:
1) Обработчик события "выброс предмета" (т.е. кто-то хочется поделиться предметом), здесь запускается нулевой таймер 2) Обработчик события *_PICKUP_ITEM 3) Обработчик нулевого таймера
А есть гарантии, что вызов обработчика нулевого таймера будет именно после (2), а не после (1)? Где-то об этом можно почитать?
Quote (Extremator) при покупке пустышки твой второй триггер не сработает, потому что ты получишь пустышку, а не сам арт
и если у героя есть арт, то арте ему не дадут а если нету, то дадут... тогда запустится 2й триггер, который посчитает что у героя только 1 арт (который ему только что дали) и ничего не выбросит Это несколько геморройный путь, но я тебя понял.Добавлено (03 Августа 2012, 00:33:53) --------------------------------------------- Блин, тут была моя ошибка.
В общем, все нормально: событие EVENT_PLAYER_UNIT_SELL_ITEM вызывается, как я и хотел --- перед событием EVENT_PLAYER_UNIT_PICKUP_ITEM. Условие для этих двух событий я сделал одинаковое, это и была ошибка. Когда юнит покупает предмет, что его еще нет в инвентаре, а когда он получил предмет, я на это не обратил внимание сначала. Добавлено (03 Августа 2012, 00:34:56) --------------------------------------------- Когда юнит покупает предмет, то его еще нет в инвентаре, а когда он получил предмет, то он уже есть.*
|
|
|
|
SirNikolas | Дата: Вторник, 07 Августа 2012, 13:19:18 | Сообщение # 8 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
| Quote (Aloof) А есть гарантии, что вызов обработчика нулевого таймера будет именно после (2), а не после (1)? JASS не поддерживает многопоточность. Если один раз последовательность вызовов была такой, значит, она будет такой всегда.
|
|
|
|
Aloof | Дата: Среда, 08 Августа 2012, 18:15:57 | Сообщение # 9 |
5 уровень
Группа: Проверенные
Сообщений: 107
Награды: 0
Репутация: 14
Блокировки:
| Quote (SirNikolas) JASS не поддерживает многопоточность ExecFunction --- исключение?
|
|
|
|
Hexing | Дата: Среда, 08 Августа 2012, 18:19:24 | Сообщение # 10 |
10 уровень
Группа: Проверенные
Сообщений: 1645
Награды: 1
Репутация: 432
Блокировки:
| Quote (Aloof) ExecFunction --- исключение? +1, на хгм читал статью про написание координат курсора в игре, так там говорилось про то что в ходе игры получается много потоков, хотя читал давно, может имелись в виду потоки не связанные с jass обработкой, и вполне может быть что это присходит в 1 поток SirNikolas, можно ли пруф?
|
|
|
|
SirNikolas | Дата: Среда, 08 Августа 2012, 18:32:54 | Сообщение # 11 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
| ExecuteFunc, TriggerExecute, ForGroup, а также все функции перебора предметов и декора лишь имитируют многопоточность. На деле все выполняется последовательно. Добавлено (08 Августа 2012, 18:32:54) --------------------------------------------- Разница будет заметна, только если поставить TriggerSleepAction.
|
|
|
|
Aloof | Дата: Среда, 08 Августа 2012, 18:41:10 | Сообщение # 12 |
5 уровень
Группа: Проверенные
Сообщений: 107
Награды: 0
Репутация: 14
Блокировки:
| Quote (SirNikolas) ExecuteFunc, TriggerExecute, ForGroup, а также все функции перебора предметов и декора лишь имитируют многопоточность. На деле все выполняется последовательно. Т.е. ExecFunction() просто ставит код на выполнение в очередь, а TriggerExecute выполняет прямо тут же, прерывая выполнение текущего триггера?
|
|
|
|
kapa6acvlk | Дата: Среда, 08 Августа 2012, 18:44:02 | Сообщение # 13 |
Группа: Проверенные
Сообщений: 612
Награды: 0
Репутация: 361
Блокировки:
| Quote (Aloof) Т.е. ExecFunction() просто ставит код на выполнение в очередь, а TriggerExecute выполняет прямо тут же это вряд-ли, но вызов триггера происходит быстрее, чем ExecFunction(), по крайней мере на хайве так писали во многих темах. А очередь будет и там и там.
Как говориться, не обязательно есть всю кучу говна, чтобы понять, что она однородна. © Александр Зорич
Сообщение отредактировал kapa6acvlk - Среда, 08 Августа 2012, 18:44:22 |
|
|
|
SirNikolas | Дата: Среда, 08 Августа 2012, 18:51:19 | Сообщение # 14 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
| Quote (Aloof) а TriggerExecute выполняет прямо тут же, прерывая выполнение текущего триггера? Они все так делают. Если не пользоваться Sleep'ом, эти "потоки" будут выполняться в порядке стека, как обычные функции.
Добавлено (08 Августа 2012, 18:47:49) --------------------------------------------- Code void a() { printf("1") ExecuteFunc("b") printf("3") ExecuteFunc("c") printf("5") }
void b() { printf("2") TriggerSleepAction(2.) printf("7") }
void c() { printf("4") TriggerSleepAction(1.) printf("6") }
Добавлено (08 Августа 2012, 18:51:19) --------------------------------------------- Кстати, TriggerSleepAction(.0) тоже прерывает поток и, по-видимому, ставит в конец очереди исполнения, поэтому это можно использовать вместо нулевого таймера. Но из-за багнутости функции ожидания этого никто не делает.
|
|
|
|
Aloof | Дата: Среда, 08 Августа 2012, 18:55:06 | Сообщение # 15 |
5 уровень
Группа: Проверенные
Сообщений: 107
Награды: 0
Репутация: 14
Блокировки:
| SirNikolas, результат выполнения не можешь сразу тут приложить? Я тебе поверю. Добавлено (08 Августа 2012, 18:55:06) --------------------------------------------- Я ожидаю такого: 1 3 5 2 4 6 7
|
|
|
|
SirNikolas | Дата: Среда, 08 Августа 2012, 18:56:58 | Сообщение # 16 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
|
|
|
|
|
Aloof | Дата: Среда, 08 Августа 2012, 18:57:17 | Сообщение # 17 |
5 уровень
Группа: Проверенные
Сообщений: 107
Награды: 0
Репутация: 14
Блокировки:
| Брр, или ты уже по номерам их расположил?
|
|
|
|
Hexing | Дата: Среда, 08 Августа 2012, 18:57:58 | Сообщение # 18 |
10 уровень
Группа: Проверенные
Сообщений: 1645
Награды: 1
Репутация: 432
Блокировки:
| Quote (Aloof) Я ожидаю такого: 1 3 5 2 4 6 7 и правильно делаешь Quote (SirNikolas) Кстати, TriggerSleepAction(.0) тоже прерывает поток и, по-видимому, ставит в конец очереди исполнения, поэтому это можно использовать вместо нулевого таймера. Но из-за багнутости функции ожидания этого никто не делает. а вы считаете это уместным? при использовании с нулём багов не будет?
|
|
|
|
SirNikolas | Дата: Среда, 08 Августа 2012, 19:02:00 | Сообщение # 19 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
| Quote (Hexing) при использовании с нулём багов не будет? Проверено. Работает корректно. Для GUI-шников сойдет. Но я все же рекомендую таймеры.
Сообщение отредактировал SirNikolas - Среда, 08 Августа 2012, 19:11:01 |
|
|
|
Aloof | Дата: Среда, 08 Августа 2012, 19:02:12 | Сообщение # 20 |
5 уровень
Группа: Проверенные
Сообщений: 107
Награды: 0
Репутация: 14
Блокировки:
| SirNikolas, OK, спасибо. Получается, никаких различий между ExecFunction("SomeFunction") и call SomeFunction() без sleep'ов нет вообще?
|
|
|
|
SirNikolas | Дата: Среда, 08 Августа 2012, 19:08:19 | Сообщение # 21 |
Группа: Модераторы
Сообщений: 6729
Награды: 1
Репутация: 1867
Блокировки:
| Есть. ExecuteFunc работает медленнее, но зато можно организовать массив строк с именами функций. А в порядке выполнения - да, вообще нет.
Добавлено (08 Августа 2012, 19:08:19) --------------------------------------------- А, ну еще можно через Execute завязать две функции друг на друга. По строке же можно вызывать функции из любой части кода, а не только те, что сверху.
|
|
|
|
|
|
|
|
|
|
|