Вот небольшой кусок кода с кнопкой и функцией клика по кнопке с покупкой предмета, как? можно сделать массив примерно на 15 предметов чтоб не создавать функцию клика для каждой кнопки c выдачей заранее подготовленного предмета.
private function click takes nothing returns nothing
    if GetPlayerState(GetOwningPlayer(udg_UnitBody[GetConvertedPlayerId(GetTriggerPlayer())]), PLAYER_STATE_RESOURCE_GOLD) >= 80 then 
     call SetPlayerStateBJ( GetOwningPlayer(udg_UnitBody[GetConvertedPlayerId(GetTriggerPlayer())]), PLAYER_STATE_RESOURCE_GOLD, ( GetPlayerState(GetOwningPlayer(udg_UnitBody[GetConvertedPlayerId(GetTriggerPlayer())]), PLAYER_STATE_RESOURCE_GOLD) - 80 ) )
    call UnitAddItemByIdSwapped(udg_Items[1],udg_UnitBody[GetConvertedPlayerId(GetTriggerPlayer())] )
    else
    call DisplayTextToForce( GetForceOfPlayer(GetOwningPlayer(udg_UnitBody[GetConvertedPlayerId(GetTriggerPlayer())])), "Нету деняг!!" )
    endif
endfunction

private function initSs takes integer id returns nothing
    local trigger Click = CreateTrigger()
    local trigger Click2 = CreateTrigger()
    local player p = GetOwningPlayer(GetTriggerUnit())
    set gameUIS = BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0)
   
    set butS[1] = BlzCreateSimpleFrame("Pistol", gameUIS, 0)
    call BlzFrameSetAbsPoint(butS[1], FRAMEPOINT_CENTER, 0.1, 0.5)
    call BlzTriggerRegisterFrameEvent(Click, butS[1], FRAMEEVENT_CONTROL_CLICK)
    call TriggerAddAction(Click, function click)
  
    set text1[1] = BlzCreateFrame("PistolText1", gameUIS, 0, 0)
    call BlzFrameSetAbsPoint(text1[1], FRAMEPOINT_CENTER, 0.1, 0.47)

    set text2[1] = BlzCreateFrame("PistolText2", gameUIS, 0, 0)
    call BlzFrameSetAbsPoint(text2[1], FRAMEPOINT_CENTER, 0.1, 0.46)
    
        call BlzFrameSetVisible(butS[1], false)
        call BlzFrameSetVisible(text1[1], false)
        call BlzFrameSetVisible(text2[1], false)
    
 if GetLocalPlayer() == p then
        call BlzFrameSetVisible(butS[1], false)
        call BlzFrameSetVisible(text1[1], false)
        call BlzFrameSetVisible(text2[1], false)
        endif
   
   
        set  Click = null
        set  Click2 = null
        set p = null
endfunction

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

Сразу хочу сказать, что события фреймов в рефе багованные, после патча 1.33 вдвойне багованные, здесь каждый выкручивается как может, но без компромиссов тут не обойтись, как и при любой разработке на рефе чего-то интереснее базовой милишки. Вроде в этой карте автор что-то смог толково сделать, рекомендую посмотреть магазин/инвентарь там. Ещё есть вариант перекатиться на южапи, отсутствие проблем там никто вроде не гарантирует, но там есть перспективы в развитии апи, в отличие от рефа, где разрабы заняты фиксом нежити.
По-моему, событие клика сейчас не особо жалуют, вроде делают через Enter и Leave, но я особо не в курсе.
Я пробую магазин делать я заранее сделал переменные для нужных мне предметов накидал код и заметил что под каждую кнопку нужно функцию клика делать и прикинул что код станет гигантским из за этого.
Нам нужен цикл. Создать какую-то базовую функцию для создания кнопки, вызвать её нужное количество раз, и у нас будет нужное количество кнопок.
Не обязательно на каждую кнопку делать свой триггер, и свою функцию обработки события, это можно сделать в одном триггере, и в одной функции, всё что нужно — это повесить на каждую кнопку своё событие. Естественно, событие можно добавить прямо в этом же цикле, где мы создаём кнопки. В триггере останется лишь получить триггернувшийся фрейм, и узнать связанный с ним предмет, который, естественно, нужно связать заранее, например в массиве.
Набросаю пример на луа, ибо не умею в джасс. Ну это так, база, в мультиплеерную карту как готовое решение это не пойдёт, да и в синглплеерную тоже из-за сломанных в рефе сейвов, чивоуштам. На каждую кнопку создал четыре фрейма. Для отслеживания клика используем тип "BUTTON", его прикроем сверху типом "BACKDROP". Ну и два текстовых фрейма для тултипа и стоимости.
код
-- Список доступных для продажи предметов, 15 штук
ItemDB = {'afac', 'spsh', 'ajen', 'bgst', 'belv', 'bspd', 'cnob', 'ratc','rat6','rat9', 'clfm', 'clsd', 'crys', 'dsum', 'rst1'}

FrameToItem = {} -- в будущем заполним эту таблицу, связав фреймы с кодами итемов
Buttons = {} -- в будущем заполним эту таблицу, связав фреймы со стоимостью итемов
CancelShopFrame = nil -- тут будет кнопка выхода из магазина

function Init()
    hero = CreateUnit(GetLocalPlayer(), FourCC('Hpal'), 0, 0, 0) --герой, которому будем выдавать предметы
    SetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_GOLD, 30000) --накинем голды
    initShop() --создадим магазин
end

function initShop()
    local size = 0.03 --размер кнопки
    local startX, y = 0.5, 0.5 --начальная позиция
    local rows, columns = 4, 4 --количество рядов и столбов
    local deltaX, deltaY = 0.05, -0.05 --расстояние между кнопками
    local counter = 1 --счётчик предметов
    local triggor = CreateTrigger()

    for r = 1, rows do --ряды
        y = y + deltaY
        for c = 1, columns do --столбцы
            local x = startX + deltaX * (c - 1)
            if counter >= 16 then -- 16-ую позицию использует для кнопки выхода
                CancelShopFrame = createButton(x, y, size, "ReplaceableTextures\\CommandButtons\\btncancel", "Exit shop", "")
                BlzTriggerRegisterFrameEvent(triggor, CancelShopFrame, FRAMEEVENT_CONTROL_CLICK)
                break
            end
            local item = ItemDB[counter] -- получили равкод итема
            local text, path = getItemInfo(item)
            local cost = math.random(1, 7000) -- в моём примере цена будет рандомная
            local button = createButton(x, y, size, path, text, ""..cost)

            BlzTriggerRegisterFrameEvent(triggor, button, FRAMEEVENT_CONTROL_CLICK)
            FrameToItem[button] = item --записали пару "фрейм = равкод предмета"
            Buttons[button] = cost --записали пару "фрейм = стоимость предмета"
            counter = counter + 1
        end
    end
    TriggerAddCondition(triggor, Condition(clickToShopFrame))
end

function getItemInfo(id) --вернёт иконку и тултип предмета из РО
    --увы, это можно сделать только создав экземпляр предмета, в идеале эти данные ещё бы записать куда, а можно и заранее написать прямо в коде
    local item = CreateItem(FourCC(id), 10000, 10000)
    local text = BlzGetItemTooltip(item)
    local path = BlzGetItemIconPath(item)
    RemoveItem(item)
    return text, path
end

function clickToShopFrame() -- здесь обрабатываем событие из триггора
    local frame = BlzGetTriggerFrame()
    resetFrame(frame) --клик по фрейму блокирует события клавы, так что такой костылёк может пригодиться, но не обязательно
    if frame == CancelShopFrame then
        for k, v in pairs(Buttons) do
            BlzFrameSetVisible(k, false)
        end
        BlzFrameSetVisible(frame, false)
        return
    end
    sellItem(frame)
end

function resetFrame(fr)
    BlzFrameSetEnable(fr, false)
    BlzFrameSetEnable(fr, true)
end

function sellItem(frame)
    -- Здесь мы проверяем голду и делаем что-нибудь с предметом
    local gold = PLAYER_STATE_RESOURCE_GOLD
    local currentGold = GetPlayerState(GetLocalPlayer(), gold)
    local cost = Buttons[frame] --получили цену предмета

    if cost <= currentGold then
        SetPlayerState(GetLocalPlayer(), gold, GetPlayerState(GetLocalPlayer(), gold) - cost)
        local item = CreateItem(FourCC(FrameToItem[frame]), 10000, 10000)
        if not UnitAddItem(hero, item) then -- если в инвентаре нет места, то создаём рядом
            SetItemPosition(item, GetUnitX(hero), GetUnitY(hero))
        end
        outputItemInfo(item, cost)
        return
    end
    print "Not enough gold!"
end

function outputItemInfo(item, cost)
    print("Received a |c0000FF80"..GetItemName(item).. "|r worth |c00FFFF00"..cost.."|r gold")
end

function createButton(x, y, size, iconPath, tooltipText, cost)
    -- Достаточно одного фрейма-кнопки, но для красоты и функциональности можно добавить всё что угодно
    -- В данном случае создаёт кнопку, иконку-бекдроп, тултип и текст фрейм для отображения стоимости

    local button = BlzCreateFrameByType("BUTTON", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "ScoreScreenTabButtonTemplate", 0)
    local icon = BlzCreateFrameByType("BACKDROP", "", button, "", 0)

    BlzFrameSetAllPoints(icon, button) --икнока будет полностью закрывать кнопку
    BlzFrameSetAbsPoint(button, FRAMEPOINT_CENTER, x, y)
    BlzFrameSetSize(button, size, size)
    BlzFrameSetTexture(icon, iconPath, 0, false)

    local tooltip = BlzCreateFrameByType("TEXT", "", button, "", 0)
    BlzFrameSetTooltip(button, tooltip)
    BlzFrameSetPoint(tooltip, FRAMEPOINT_BOTTOMLEFT, button, FRAMEPOINT_TOP, 0, 0)
    BlzFrameSetEnable(tooltip, false)
    BlzFrameSetText(tooltip, "|c00FFFF00"..tooltipText.."|r")

    local costFrame = BlzCreateFrameByType("TEXT", "", button, "", 0)
    BlzFrameSetPoint(costFrame, FRAMEPOINT_TOPLEFT, button, FRAMEPOINT_BOTTOMLEFT, 0, 0)
    BlzFrameSetPoint(costFrame, FRAMEPOINT_BOTTOMRIGHT, button, FRAMEPOINT_BOTTOMRIGHT, 0, -0.01)
    BlzFrameSetEnable(costFrame, false)
    BlzFrameSetText(costFrame, cost)
    BlzFrameSetTextAlignment(costFrame, TEXT_JUSTIFY_CENTER, TEXT_JUSTIFY_MIDDLE)

    return button, icon, tooltip, costFrame
end
На джассе примерно то же самое, только хуже.
Результат на видео и в карте.
Загруженные файлы
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
19
3 недели назад
0
Похожие вопросы:

ответ
Steal nerves, лови. Годный такой мануал.
На сишные структуры похожи. Короче. Прочитаешь на 2-3 раза - все поймешь.

1
27
3 недели назад
Отредактирован MpW
1
Не совсем понял ваш вопрос, что выхотите сделать. Внимательно раз 4-5 вчитал.
Вот небольшой кусок кода с кнопкой и функцией клика по кнопке с покупкой предмета, как?
код я посмотрел, он убер простой. Ничего сверхсложного логически, и уникального нн увидел. Однако, я не увидел никакой связи с магазином и итемами. У вас udg_Item хранят только от одного итема? Фреймы отображаются при выделении магазина? Сколько у вас магазинов? Один?
можно сделать массив примерно на 15 предметов чтоб не создавать функцию клика для каждой кнопки c выдачей заранее подготовленного предмета.
Видимо, у вас возникла проблема как структурировать всю эту базу данных информации. Так чего же вы не создали 15 итемов, и не показали.
Ладно. Примерно понял. Функцию клика можно не плодить, достаточно на всех 1 функции, просто будут разные триггеры запускаться.
Вот вы циклом создаете 15 кнопок fr[1-15], 15 триггеров tr[1-15]. Потом в функции click нужно перебрать какая кнопка нажата (индекс вытащить), а это можно сравнивать в действии, т.е. в функции click
  1. либо вызванный фрейм BlzGetTriggerFrame() перебираем с 15 фреймами fr
  2. либо запущенный триггер GetTriggeringTrigger() перебираем с 15 триггерами tr

Еще у вас проблема может с фреймовыми событиями, на один триггер можно записать 1 событие фрейма. Иначе, я замечал, что событие не работало. Возможна, я ошибаюсь. Но мне кащалось, что ивент просто перезаписывался на последний фрейм, и работало только у него. Вы сейчас пытались накинуть на 1 триггер 15 ивентов для разных фреймов, или что? Поэтому я вот для каждого фрейма создаю свой триггер. Это главное правило - создавать для каждого фрейма свой триггер
0
8
3 недели назад
0
Я пробую магазин делать я заранее сделал переменные для нужных мне предметов накидал код и заметил что под каждую кнопку нужно функцию клика делать и прикинул что код станет гигантским из за этого.
0
13
3 недели назад
0
На практике не знаю, но в теории можно задать кнопке контекст равный индексу слота, а в функции получить номер GetContext() и выдать айтем.
Ответы (1)
0
27
3 недели назад
Отредактирован MpW
0
BlzGetFrameByName(name, createContext)
Все равно это тоже надо будет циклом перебирать BlzGetTriggerFrame() с BlzGetFrameByName(name, 1-15), если говорить про рефордж
1
23
3 недели назад
Отредактирован Makeba
1
Сразу хочу сказать, что события фреймов в рефе багованные, после патча 1.33 вдвойне багованные, здесь каждый выкручивается как может, но без компромиссов тут не обойтись, как и при любой разработке на рефе чего-то интереснее базовой милишки. Вроде в этой карте автор что-то смог толково сделать, рекомендую посмотреть магазин/инвентарь там. Ещё есть вариант перекатиться на южапи, отсутствие проблем там никто вроде не гарантирует, но там есть перспективы в развитии апи, в отличие от рефа, где разрабы заняты фиксом нежити.
По-моему, событие клика сейчас не особо жалуют, вроде делают через Enter и Leave, но я особо не в курсе.
Я пробую магазин делать я заранее сделал переменные для нужных мне предметов накидал код и заметил что под каждую кнопку нужно функцию клика делать и прикинул что код станет гигантским из за этого.
Нам нужен цикл. Создать какую-то базовую функцию для создания кнопки, вызвать её нужное количество раз, и у нас будет нужное количество кнопок.
Не обязательно на каждую кнопку делать свой триггер, и свою функцию обработки события, это можно сделать в одном триггере, и в одной функции, всё что нужно — это повесить на каждую кнопку своё событие. Естественно, событие можно добавить прямо в этом же цикле, где мы создаём кнопки. В триггере останется лишь получить триггернувшийся фрейм, и узнать связанный с ним предмет, который, естественно, нужно связать заранее, например в массиве.
Набросаю пример на луа, ибо не умею в джасс. Ну это так, база, в мультиплеерную карту как готовое решение это не пойдёт, да и в синглплеерную тоже из-за сломанных в рефе сейвов, чивоуштам. На каждую кнопку создал четыре фрейма. Для отслеживания клика используем тип "BUTTON", его прикроем сверху типом "BACKDROP". Ну и два текстовых фрейма для тултипа и стоимости.
код
-- Список доступных для продажи предметов, 15 штук
ItemDB = {'afac', 'spsh', 'ajen', 'bgst', 'belv', 'bspd', 'cnob', 'ratc','rat6','rat9', 'clfm', 'clsd', 'crys', 'dsum', 'rst1'}

FrameToItem = {} -- в будущем заполним эту таблицу, связав фреймы с кодами итемов
Buttons = {} -- в будущем заполним эту таблицу, связав фреймы со стоимостью итемов
CancelShopFrame = nil -- тут будет кнопка выхода из магазина

function Init()
    hero = CreateUnit(GetLocalPlayer(), FourCC('Hpal'), 0, 0, 0) --герой, которому будем выдавать предметы
    SetPlayerState(GetLocalPlayer(), PLAYER_STATE_RESOURCE_GOLD, 30000) --накинем голды
    initShop() --создадим магазин
end

function initShop()
    local size = 0.03 --размер кнопки
    local startX, y = 0.5, 0.5 --начальная позиция
    local rows, columns = 4, 4 --количество рядов и столбов
    local deltaX, deltaY = 0.05, -0.05 --расстояние между кнопками
    local counter = 1 --счётчик предметов
    local triggor = CreateTrigger()

    for r = 1, rows do --ряды
        y = y + deltaY
        for c = 1, columns do --столбцы
            local x = startX + deltaX * (c - 1)
            if counter >= 16 then -- 16-ую позицию использует для кнопки выхода
                CancelShopFrame = createButton(x, y, size, "ReplaceableTextures\\CommandButtons\\btncancel", "Exit shop", "")
                BlzTriggerRegisterFrameEvent(triggor, CancelShopFrame, FRAMEEVENT_CONTROL_CLICK)
                break
            end
            local item = ItemDB[counter] -- получили равкод итема
            local text, path = getItemInfo(item)
            local cost = math.random(1, 7000) -- в моём примере цена будет рандомная
            local button = createButton(x, y, size, path, text, ""..cost)

            BlzTriggerRegisterFrameEvent(triggor, button, FRAMEEVENT_CONTROL_CLICK)
            FrameToItem[button] = item --записали пару "фрейм = равкод предмета"
            Buttons[button] = cost --записали пару "фрейм = стоимость предмета"
            counter = counter + 1
        end
    end
    TriggerAddCondition(triggor, Condition(clickToShopFrame))
end

function getItemInfo(id) --вернёт иконку и тултип предмета из РО
    --увы, это можно сделать только создав экземпляр предмета, в идеале эти данные ещё бы записать куда, а можно и заранее написать прямо в коде
    local item = CreateItem(FourCC(id), 10000, 10000)
    local text = BlzGetItemTooltip(item)
    local path = BlzGetItemIconPath(item)
    RemoveItem(item)
    return text, path
end

function clickToShopFrame() -- здесь обрабатываем событие из триггора
    local frame = BlzGetTriggerFrame()
    resetFrame(frame) --клик по фрейму блокирует события клавы, так что такой костылёк может пригодиться, но не обязательно
    if frame == CancelShopFrame then
        for k, v in pairs(Buttons) do
            BlzFrameSetVisible(k, false)
        end
        BlzFrameSetVisible(frame, false)
        return
    end
    sellItem(frame)
end

function resetFrame(fr)
    BlzFrameSetEnable(fr, false)
    BlzFrameSetEnable(fr, true)
end

function sellItem(frame)
    -- Здесь мы проверяем голду и делаем что-нибудь с предметом
    local gold = PLAYER_STATE_RESOURCE_GOLD
    local currentGold = GetPlayerState(GetLocalPlayer(), gold)
    local cost = Buttons[frame] --получили цену предмета

    if cost <= currentGold then
        SetPlayerState(GetLocalPlayer(), gold, GetPlayerState(GetLocalPlayer(), gold) - cost)
        local item = CreateItem(FourCC(FrameToItem[frame]), 10000, 10000)
        if not UnitAddItem(hero, item) then -- если в инвентаре нет места, то создаём рядом
            SetItemPosition(item, GetUnitX(hero), GetUnitY(hero))
        end
        outputItemInfo(item, cost)
        return
    end
    print "Not enough gold!"
end

function outputItemInfo(item, cost)
    print("Received a |c0000FF80"..GetItemName(item).. "|r worth |c00FFFF00"..cost.."|r gold")
end

function createButton(x, y, size, iconPath, tooltipText, cost)
    -- Достаточно одного фрейма-кнопки, но для красоты и функциональности можно добавить всё что угодно
    -- В данном случае создаёт кнопку, иконку-бекдроп, тултип и текст фрейм для отображения стоимости

    local button = BlzCreateFrameByType("BUTTON", "", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0), "ScoreScreenTabButtonTemplate", 0)
    local icon = BlzCreateFrameByType("BACKDROP", "", button, "", 0)

    BlzFrameSetAllPoints(icon, button) --икнока будет полностью закрывать кнопку
    BlzFrameSetAbsPoint(button, FRAMEPOINT_CENTER, x, y)
    BlzFrameSetSize(button, size, size)
    BlzFrameSetTexture(icon, iconPath, 0, false)

    local tooltip = BlzCreateFrameByType("TEXT", "", button, "", 0)
    BlzFrameSetTooltip(button, tooltip)
    BlzFrameSetPoint(tooltip, FRAMEPOINT_BOTTOMLEFT, button, FRAMEPOINT_TOP, 0, 0)
    BlzFrameSetEnable(tooltip, false)
    BlzFrameSetText(tooltip, "|c00FFFF00"..tooltipText.."|r")

    local costFrame = BlzCreateFrameByType("TEXT", "", button, "", 0)
    BlzFrameSetPoint(costFrame, FRAMEPOINT_TOPLEFT, button, FRAMEPOINT_BOTTOMLEFT, 0, 0)
    BlzFrameSetPoint(costFrame, FRAMEPOINT_BOTTOMRIGHT, button, FRAMEPOINT_BOTTOMRIGHT, 0, -0.01)
    BlzFrameSetEnable(costFrame, false)
    BlzFrameSetText(costFrame, cost)
    BlzFrameSetTextAlignment(costFrame, TEXT_JUSTIFY_CENTER, TEXT_JUSTIFY_MIDDLE)

    return button, icon, tooltip, costFrame
end
На джассе примерно то же самое, только хуже.
Результат на видео и в карте.
Загруженные файлы
Принятый ответ
Ответы (3)
0
8
3 недели назад
0
Makeba, теперь вижу почему лучше на Lua мне на хайве на Jass показали там жопа полная.
0
23
3 недели назад
0
лучше на Lua
Lua уже в прошлом, теперь лучше на AngelScript
0
8
3 недели назад
0
Makeba, для меня там лес темный я не особо эти языки понимаю
Чтобы оставить комментарий, пожалуйста, войдите на сайт.