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

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

Ответ
 
Extremator

offline
Опыт: 40,317
Активность:
Мой второй триггер на Jass'е
логическое продолжение темы - xgm.guru/forum/showthread.php?t=59667
Это честно говоря мой не второй триггер на Jass'e, но по сути
это нечто следующее, рассмотрение чего я бы хотел попросить.
Он на много больше и сложнее первого, но по сути не является чем-то уже совсем сложным.
Коротко объясню суть его работы - есть предметы с зарядами, и есть скилл который можно
использовать только на предметы. Смысл применения скилла заключается в том что бы
первым применением запомнить предмет на который был произведён клик
а вторым - как бы соединить оба предмета вместе, при это объединив число их зарядов.
Такое вот сложение, первый предмет вставляется во второй...
есть нюанс - можно использовать только на те предметы, которые имеются в данный момент
в инвентаре юнита, а так же только те предметы, которые входят в особый перечень!
При этом в каждый тип предметов имеет разную заполняемость на один слот...
Раскидаю отдельно по функция в каждый отдельный кат (надеюсь это не ухудшит читаемость для вас).
» TriggerAddEvent_Unit_SpellCast
// я сделал свою функция на регистрацию события
function TriggerAddEvent_Unit_SpellCast takes trigger t returns nothing
    local integer i = 16
    loop
        set i = i - 1
        call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        exitwhen i == 0
    endloop
endfunction
» items_sum_option_Init
// тут я задаю данные в свою своего рода БД
function items_sum_option_Init takes nothing returns nothing
    // максимум предметов (складываемых)
    set items_sum_option_Max = 5
    // предмет 1 - Шкура
    set items_sum_option_type[1] = 'I001'
    set items_sum_option_charge_max[1] = 5
    // предмет 2 - Булыжник
    set items_sum_option_type[2] = 'I002'
    set items_sum_option_charge_max[2] = 10
    // предмет 3 - Камень
    set items_sum_option_type[3] = 'I005'
    set items_sum_option_charge_max[3] = 10
    // предмет 4 - Бревно
    set items_sum_option_type[4] = 'I003'
    set items_sum_option_charge_max[4] = 15
    // предмет 5 - Доска
    set items_sum_option_type[5] = 'I004'
    set items_sum_option_charge_max[5] = 15    
endfunction
» items_sum_condition_cast
// проверка скилла который каставал юнит
function items_sum_condition_cast takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction
» items_sum_TypeCheck
// циклом перебираю типы предмета,
// даю предмет - получаю номер массива с таким же предметом
// с ним и работаю
function items_sum_TypeCheck takes item I returns integer
    local integer L = 0
    local integer N = 0
    loop
        set L = L + 1
        if GetItemTypeId(I) == items_sum_option_type[L] then
            set N = L
        endif
        exitwhen L == items_sum_option_Max
    endloop
    return N
endfunction
» items_sum_UnitCheck
// аналогичное предыдущему, циклом ищу нужного юнита
// из тех, которые уже успели начать выбирать итем для складывания
function items_sum_UnitCheck takes unit U returns integer
    local integer L = 0
    local integer N = 0
    loop
        set L = L + 1
        if U == items_sum_unit[L] then
            set N = L
        endif
        exitwhen L == items_sum_Max
    endloop
    return N
endfunction
» items_sum_actions_cast
// основное тело триггера, при касте идёт большой ряд проверок
// и расчёт перераспеределения зарядов / удаление исчерпанного итема
function items_sum_actions_cast takes nothing returns nothing
    local unit u = GetTriggerUnit()// юнит-кастер
    local player p = GetOwningPlayer(u) // владелец кастера
    local item i = GetSpellTargetItem() // предмет цель-каста
    local integer t = 0 // номер типа предмета из "item_sum_option"
    local integer n = 0 // номер юнита в списке (после первого применения)
    local string s
    
    if UnitHasItem(u, i) then
        //call BJDebugMsg("юнит владеет указанным предметом")
        set t = items_sum_TypeCheck(i)
        if t > 0 then
            //call BJDebugMsg("предмет входит в список")
            if items_sum_Max > 0 then
                set n = items_sum_UnitCheck(u)
            endif
            // =====
            if n > 0 and UnitHasItem(u, items_sum_item_one[n]) == false then
                //call BJDebugMsg("прежний предмет был потерян")
                set items_sum_unit[n] = items_sum_unit[items_sum_Max]
                    set items_sum_unit[items_sum_Max] = null
                set items_sum_item_one[n] = items_sum_item_one[items_sum_Max]
                    set items_sum_item_one[items_sum_Max] = null
                set items_sum_charge_one[n] = items_sum_charge_one[items_sum_Max]
                // =====
                set items_sum_Max = items_sum_Max - 1
                // =====
                set n = 0
            endif
            // =====
            if n == 0 then
                //call BJDebugMsg("выбирается новый предмет")
                set items_sum_Max = items_sum_Max + 1
                // =====
                set items_sum_unit[items_sum_Max] = u
                set items_sum_item_one[items_sum_Max] = i
                set items_sum_charge_one[items_sum_Max] = GetItemCharges(i)
                // =====
                set s = "Сложить \"|c00ffcc00" + GetItemName(i) + "|r\" (|c00888888x" + I2S(GetItemCharges(i)) + "|r) и . . . <|c00ffcc00укажите предмет|r>"
                call DisplayTimedTextToPlayer(p,0.,0.,5.,s)
            else
                //call BJDebugMsg("выбирается второй предмет")
                set items_sum_charge_one[n] = GetItemCharges(items_sum_item_one[n])
                set items_sum_item_two[n] = i
                set items_sum_charge_two[n] = GetItemCharges(i)
                // =====
                if GetItemTypeId(items_sum_item_one[n]) == GetItemTypeId(items_sum_item_two[n]) then
                    //call BJDebugMsg("второй предмет совпадает")
                    if items_sum_item_one[n] != items_sum_item_two[n] then
                        //call BJDebugMsg("второй предмет не является первым")
                        if items_sum_charge_one[n] + items_sum_charge_two[n] <= items_sum_option_charge_max[t] then
                            //call BJDebugMsg("предметы бду сложены в один без остатка")
                            set s = "Вы соединили \"|c00ffcc00" + GetItemName(items_sum_item_one[n]) + "|r\" (|c00888888x" + I2S(items_sum_charge_one[n]) + "|r с |c00888888x" + I2S(items_sum_charge_two[n]) + "|r = |c00888888x" + I2S(items_sum_charge_one[n] + items_sum_charge_two[n]) + "|r)"
                            call DisplayTimedTextToPlayer(p,0.,0.,5.,s)
                            // =====
                            call SetItemCharges(items_sum_item_two[n], items_sum_charge_one[n] + items_sum_charge_two[n])
                            call RemoveItem(items_sum_item_one[n])
                            // =====
                            set items_sum_unit[n] = items_sum_unit[items_sum_Max]
                                set items_sum_unit[items_sum_Max] = null
                            set items_sum_item_one[n] = items_sum_item_one[items_sum_Max]
                                set items_sum_item_one[items_sum_Max] = null
                            set items_sum_charge_one[n] = items_sum_charge_one[items_sum_Max]
                            set items_sum_item_two[n] = null
                            // =====
                            set items_sum_Max = items_sum_Max - 1
                        else
                            //call BJDebugMsg("предметы складываются с остатком")
                            if items_sum_charge_two[n] < items_sum_option_charge_max[t] then
                                //call BJDebugMsg("можно доложить")
                                set s = "Вы соединили \"|c00ffcc00" + GetItemName(items_sum_item_one[n]) + "|r\" (|c00888888x" + I2S(items_sum_charge_one[n]) + "|r с |c00888888x" + I2S(items_sum_charge_two[n]) + "|r = |c00888888x" + I2S(items_sum_charge_one[n] - (items_sum_option_charge_max[t] - items_sum_charge_two[n])) + "|r и |c00888888x" + I2S(items_sum_option_charge_max[t]) + "|r)"
                                call DisplayTimedTextToPlayer(p,0.,0.,5.,s)
                                // =====
                                set items_sum_charge_one[n] = items_sum_charge_one[n] - (items_sum_option_charge_max[t] - items_sum_charge_two[n])
                                set items_sum_charge_two[n] = items_sum_charge_two[n] + (items_sum_option_charge_max[t] - items_sum_charge_two[n])
                                // =====
                                call SetItemCharges(items_sum_item_one[n], items_sum_charge_one[n])
                                call SetItemCharges(items_sum_item_two[n], items_sum_charge_two[n])
                                // =====
                                set items_sum_unit[n] = items_sum_unit[items_sum_Max]
                                    set items_sum_unit[items_sum_Max] = null
                                set items_sum_item_one[n] = items_sum_item_one[items_sum_Max]
                                    set items_sum_item_one[items_sum_Max] = null
                                set items_sum_charge_one[n] = items_sum_charge_one[items_sum_Max]
                                set items_sum_item_two[n] = null
                                // =====
                                set items_sum_Max = items_sum_Max - 1
                            else
                                //call BJDebugMsg("нельзя доложить")
                                set s = "Нельзя сложить \"|c00ffcc00" + GetItemName(items_sum_item_one[n]) + "|r\" (максимум |c00888888x" + I2S(items_sum_option_charge_max[t]) + "|r в одном слоте)"
                                call DisplayTimedTextToPlayer(p,0.,0.,5.,s)
                                // =====
                                set items_sum_item_two[n] = null
                            endif
                        endif
                    else
                        //call BJDebugMsg("второй предмет является первым")
                        set s = "Нельзя сложить \"|c00ffcc00" + GetItemName(items_sum_item_one[n]) + "|r\" с самим собой. Выберите другой <|c00ffcc00предмет|r>"
                        call DisplayTimedTextToPlayer(p,0.,0.,5.,s)
                    endif
                else
                    //call BJDebugMsg("второй предмет не совпадает")
                    set s = "Нельзя сложить \"|c00ffcc00" + GetItemName(items_sum_item_one[n]) + "|r\" и \"|c00ff0000" + GetItemName(items_sum_item_two[n]) + "|r\" (различные предметы)"
                    call DisplayTimedTextToPlayer(p,0.,0.,5.,s)
                    // =====
                    set items_sum_item_two[n] = null
                endif
            endif
        else
            //call BJDebugMsg("предмет не входит в список")
            call DisplayTimedTextToPlayer(p,0.,0.,5.,"|c00888888Невозможно применить к этому предмету|r")
        endif
    else
        //call BJDebugMsg("юнит не владеет указанным предметом")
        call DisplayTimedTextToPlayer(p,0.,0.,5.,"|c00888888Используйте на предметы в вашем инвентаре|r")
    endif

    set u = null
    set i = null
endfunction
» InitTrig_items_sum_jass
// инициализация триггера
function InitTrig_items_sum_jass takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerAddEvent_Unit_SpellCast(t)
    call TriggerAddCondition(t, Condition(function items_sum_condition_cast))
    call TriggerAddAction(t, function items_sum_actions_cast)
    // инициализация данных
    call items_sum_option_Init()
    // =====
    set t = null
endfunction
» globals
// мои глобалки
globals
    // tiems_sum_
    integer items_sum_Max = 0 // - вот тут я забыл поставить ноль, и у меня ничего не работал на середине триггера :DDD
    unit array items_sum_unit
    item array items_sum_item_one
    integer array items_sum_charge_one
    item array items_sum_item_two
    integer array items_sum_charge_two
    string items_sum_string
    // tiems_sum_option_
    integer items_sum_option_Max
    integer array items_sum_option_type
    integer array items_sum_option_charge_max
endglobals
Доп.вопрос 1: локалку "игрок" нужно обнулять?
Доп.вопрос 2: какое число вернёт return из цикла? (при совпадении несколько раз) первое/последнее совпавшее?
P.S.: Если читая всё это вы забыли в чём суть треда - напомню, я хочу знать что я тат делал хорошо, а что не очень.
Старый 12.05.2014, 08:10
Buulichkaa
Делаю спеллы за еду
offline
Опыт: 20,171
Активность:
ну ёмаё, статьи, статьи же есть! до всего, о чем тут спрашивается, можно логически дойти самому, прочитав пару-тройку статей
Buulichkaa добавил:
циклический перебор типов для того чтобы узнать индекс определенного типа - раковня, делаем нормальную БД, по равкоду сохраняем в глобальный массив наш индекс (или что там ещё нам надо)
Buulichkaa добавил:
ЧИТАЙ СТАТЬИ ПАДЛО!
Старый 12.05.2014, 10:35
Extremator

offline
Опыт: 40,317
Активность:
прекрати :DD
не пугай меня хД
я познаю мир жассика :D
Старый 12.05.2014, 10:40
Borodach

offline
Опыт: 11,871
Активность:
  1. Не надо
  2. Вернет последнее совпашее. Перед ретурном bjdebugmsg(i2s(n)), покажет ответ.
А так нормально для начинающего....
Старый 12.05.2014, 12:11
Tobi123

offline
Опыт: 7,826
Активность:
Extremator:
Доп.вопрос 1: локалку "игрок" нужно обнулять?
Она является хендлом, значит требует обнуления. Все хендлы надо обнулять.
Tobi123 добавил:
Borodach:
Не надо
А это рак.
Старый 12.05.2014, 16:28
adic3x

offline
Опыт: 107,539
Активность:
Она является хендлом, значит требует обнуления. Все хендлы надо обнулять.
А это рак.
Шли бы вы, уважаемый, лесом с такими советами. Вот вы тут утверждаете то, о чем сюда по всему имеете очень смутное представление, вроде "я где-то читал" и "мне почему-то так кажется". Хоть как-то сможете рассказать, зачем вообще обнуляются локальные переменные и что именно называют утечками?
player обнулять не надо. На самом деле можно поставить адика и не обнулять вообще ничего.
Старый 12.05.2014, 17:16
nvc123
new status
offline
Опыт: 59,284
Активность:
Extremator, тут реально надо бд
Старый 12.05.2014, 23:14
Extremator

offline
Опыт: 40,317
Активность:
ADOLF:
Хоть как-то сможете рассказать, зачем вообще обнуляются локальные переменные и что именно называют утечками?
Я не шарю канеш, но у меня есть следующего рода гипотеза...
Переменная типа player хранит хендл игрока, к которому будет приравниваться, до тех пока пока не будут обнулена (сама переменная).
Если бы это был юнит - то после смерти/удаления юнита - в переменной остался бы его хендл. Юнита нету - его хендл есть.
А с игроком такое невозможно - игроков всего 16, нельзя создать нового игрока с новым хендлом.
и нельзя удалить игрока, т.е. он не может потерять имеющийся у него хендл...
Обнулся не обнулся переменную - игрок останется в игре, и то хранит ли его хендл какие-то переменные или нет... Не важно? или важно? (тут у меня нету своего мнения, ибо не шарю).
ADOLF, я на трояк справился с ответом? :D
Extremator добавил:
nvc123:
Extremator, тут реально надо бд
ну я вроде бы его и сделал х)
но я так понимаю для GUI оно ещё шло... а для Jass'а - слишком примитивно, и неграмотно... Да?
Старый 13.05.2014, 08:23
DioD

offline
Опыт: 45,184
Активность:
ктото совершенно рак в знаниях о хэндлах, давайте я вам объясню:
Есть большая площадка, назовём её парковкой у супермаркета, на каждое место может припарковаться одна любая машина.
При заезде на парковку, машина получает талон с номером и должна припарковаться именно на это место.
Любой человек может подойти и спросить, на каком месте находится некая машина потому, что она ему тоже нужна и тоже получить такой-же талон как водитель который на ней заехал.
Вахтёр ведёт счетчик выданных талонов, когда люди уходят они отдают талон обратно и счётчик уменьшается.
Водитель не может уехать без машины, на то он и водитель.
До тех пор пока вахтёр не получил все талоны обратно, место не считается пустым и другие машины на него не пускаются.
Некоторые машины заезжают НАВСЕГДА, не важно сколько талонов выдано на них, не важно сколько талонов возвращено, место никогда не будет освобождено.
Вахтёр знает о таких машинах и вместо того чтобы выдавать каждый раз новый талон, он выдаёт всем обратившимся ксерокопии самого первого.
Именно поэтому Player(x) == Player(x)
condition(C) == condition(C)
но unit(A) != unit(A)
Для особых дебилов функции статического возврата прямо отмечены statiс в common.j
Крайний пример чуточку мимо кассы, те у кого в голове каша хотя-бы с колбасой спросят, а почему я сравниваю заезд на парковку таких же машин с выдачей талонов на существующие, но если чуть чуть подумать вы сами догадаетесь почему так.
Старый 13.05.2014, 13:26
adic3x

offline
Опыт: 107,539
Активность:
функции статического возврата прямо отмечены statiс в common.j
constant? Хотя сути не меняет.
Я расскажу немного по другому:
In computer programming, a handle is an abstract reference to a resource. © Wikipedia
В программировании дескриптор (handle) - абстрактная ссылка (отсылка) к чему либо.
Юниты создаются и удаляются, и им присваиваются дескрипторы. Однако цифры не бесконечны, поэтому реализован механизм повторного использования. Именно она и дает сбой, из-за которого рекомендуется обнулять локальные переменные некоторых типов.
Переменная player в jass - просто число. Но чтобы криворукие парни не пытались создать юнита для игрока -1 или 65536 записать что-либо в такую переменную можно только через функцию Player (int). При этом, как правильно пояснил DioD не используется механизм повторного пользования дескрипторами, поэтому и обнулять не нужно.
Старый 13.05.2014, 22:35
ScorpioT1000
Работаем
offline
Опыт: отключен
вообще-то я на основе знаний адольфа, тоада, диода и некоторых других ребят делал какраз данную статью
Старый 14.05.2014, 12:51
Ответ

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

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

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

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



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