1
23
5 часов назад
1

» Блог Storm'а / Суицидальная атака на Maya API

Видосик
0
23
5 часов назад
0

» Блог Storm'а / Тестим PopcornFX в рефоге

Кстати, постил на хайве краткий "тутор" на эту тему. Скорее в качестве шпаргалки для самого себя, чтобы посмотреть и вспомнить как я это делал, когда забуду
1
23
7 часов назад
1

» WarCraft 3 / импорт карт в blender

осуществить твою задумку вряд ли возможно софтом
Да в принципе ничего в этой задаче нет невыполнимого или даже архисложного. С учётом того, что формат карт разобран, формат моделей разобран, а архивы варкрафта распаковываются в пару кликов.
Другой вопрос, что никто в здравом уме не сядет это пилить, так что да, на практике нереализуемо.
0
23
5 дней назад
0

» WarCraft 3 / как сделать мгновеный поворот юниту

rsfghd, ну так UnitFacing в сделку не входил, поэтому я и обозначил, что не для каждой ситуации способ применим.
Вращение будет видно если таргет двигать плавно, а не просто установить ему нужные конечные координаты
0
23
6 дней назад
0

» WarCraft 3 / как сделать мгновеный поворот юниту

rsfghd, этой скорости действительно недостаточно?
Загруженные файлы
0
23
6 дней назад
Отредактирован Makeba
0

» WarCraft 3 / как сделать мгновеный поворот юниту

только костылить с созданием нового юнита либо использовать
Где-то тут на сайте для мгновенного поворота предлагался костыль с переименованием рут кости модели в turret, и триггерным закрепом кости на цели. На рефе так делал для фиксации модельки героя на курсоре, на 1.26 тоже скорее всего рабочий вариант. Но не для каждой задачи этот способ будет допустим.
1
23
6 дней назад
1

» WarCraft 3 / Заказы на ландшафт

Интересно, oGre_ ещё жив на сайте?) Я бы с удовольствием обратился к нему.
Опоздали на год...
0
23
1 неделю назад
0

» WarCraft 3 / Как прератить tga файл в png файл?

Ввести в гугле "tga to png online"
Первая ссылка по запросу convertio.co/ru/tga-png
0
23
1 неделю назад
0

» IntelliJASS / BLP

Мб тоже полезная ссылка
0
23
2 недели назад
0

» WarCraft 3 / Пак моделей от -Grendel

Галендор Крэйл, похоже, что автор не брезговал заметать проблемы с нормалями под ковёр, путём установки флага Unshaded в материалах
0
23
2 недели назад
0

» WarCraft 3 / Пак моделей от -Grendel

Большинство моделей этого чела (по крайней мере из данного пака, других не видел) имеют косяк с полигонами, а точнее наличие треугольников с дублирующимися вершинами. Не то чтобы претензия, но я не понимаю, как он вообще смог так моделить. У него это встречается буквально везде, где геометрия не является явной копипастой/небольшой доработкой близзовских моделек. В мдлвисе из точек собирал что ли
Пример. Геосет 0 модели NagaWhaler.mdx имеет 16 таких треугольников из 48
NagaWhaler.mdx

Faces with doubles (16):

        Triangle 17: [22, 24, 24]
        Triangle 19: [21, 24, 24]
        Triangle 21: [20, 24, 24]
        Triangle 23: [19, 24, 24]
        Triangle 25: [18, 24, 24]
        Triangle 27: [17, 24, 24]
        Triangle 29: [23, 24, 24]
        Triangle 31: [16, 24, 24]
        Triangle 33: [32, 33, 33]
        Triangle 35: [30, 33, 33]
        Triangle 37: [29, 33, 33]
        Triangle 39: [28, 33, 33]
        Triangle 41: [27, 33, 33]
        Triangle 43: [26, 33, 33]
        Triangle 45: [31, 33, 33]
        Triangle 47: [25, 33, 33]

All geoset Faces (48):

        Triangle 0: [9, 10, 7]
        Triangle 1: [7, 6, 9]
        Triangle 2: [10, 11, 5]
        Triangle 3: [5, 7, 10]
        Triangle 4: [11, 12, 4]
        Triangle 5: [4, 5, 11]
        Triangle 6: [12, 13, 3]
        Triangle 7: [3, 4, 12]
        Triangle 8: [13, 14, 2]
        Triangle 9: [2, 3, 13]
        Triangle 10: [14, 15, 1]
        Triangle 11: [1, 2, 14]
        Triangle 12: [15, 8, 0]
        Triangle 13: [0, 1, 15]
        Triangle 14: [8, 9, 6]
        Triangle 15: [6, 0, 8]
        Triangle 16: [24, 23, 22]
        Triangle 17: [22, 24, 24]
        Triangle 18: [24, 22, 21]
        Triangle 19: [21, 24, 24]
        Triangle 20: [24, 21, 20]
        Triangle 21: [20, 24, 24]
        Triangle 22: [24, 20, 19]
        Triangle 23: [19, 24, 24]
        Triangle 24: [24, 19, 18]
        Triangle 25: [18, 24, 24]
        Triangle 26: [24, 18, 17]
        Triangle 27: [17, 24, 24]
        Triangle 28: [24, 16, 23]
        Triangle 29: [23, 24, 24]
        Triangle 30: [24, 17, 16]
        Triangle 31: [16, 24, 24]
        Triangle 32: [33, 31, 32]
        Triangle 33: [32, 33, 33]
        Triangle 34: [33, 32, 30]
        Triangle 35: [30, 33, 33]
        Triangle 36: [33, 30, 29]
        Triangle 37: [29, 33, 33]
        Triangle 38: [33, 29, 28]
        Triangle 39: [28, 33, 33]
        Triangle 40: [33, 28, 27]
        Triangle 41: [27, 33, 33]
        Triangle 42: [33, 27, 26]
        Triangle 43: [26, 33, 33]
        Triangle 44: [33, 25, 31]
        Triangle 45: [31, 33, 33]
        Triangle 46: [33, 26, 25]
        Triangle 47: [25, 33, 33]
0
23
2 недели назад
0

» StarCraft 2 / .m3 аддон для Blender

Anime Chan, нужен доброволец, который зальёт новый ресурс с новым аддоном
0
23
3 недели назад
0

» WarCraft 3 / Пулемётный огонь веером

EugeAl, весь дискорд хгма уже на AngelScript
1
23
3 недели назад
Отредактирован Makeba
1

» WarCraft 3 / Пулемётный огонь веером

Во-первых, сообщество XGM настоятельно рекомендует перестать использовать эти решения из 2007-го, с даммиками, вызывающими даммиков, сейчас есть возможность сделать лучше.
Во-вторых, сообщество XGM настоятельно рекомендует перейти на Ujapi и AngelScript.

Немного говнокода на эту тему, набросал на луа в рефе за 1 наносекунду
group = CreateGroup()

--всякие параметры
range = 650
dAngle = 30
stepAngle = 15
projVelocity = 100

Timers = {}
Timers.bullets = CreateTimer()

TimerStart(Timers.bullets, 0.25, true, function()
    launchBullets(GetUnitX(hero), GetUnitY(hero)) -- пусть hero это будет пулемётчик
end)

function launchBullets(x, y) -- выпускаем очередь из пулемёта
    local angle = GetUnitFacing(hero)

    SetUnitAnimation(hero, "attack")
    local segments = getSegments(x, y, range, angle - dAngle, angle + dAngle, stepAngle) --находим конечные точки отрезков, по которым пустим снаряды

    local t = CreateTimer()
    TimerStart(t, 0.03, true, function()
        local p = table.remove(segments, math.random(1, #segments))
        launchBullet(x, y, p.x, p.y) --для красоты пускаем выстрелы с небольшой задержкой

        if #segments <= 0 or IsUnitDeadBJ(t) then
            DestroyTimer(t)
            return
        end
    end)
end

function launchBullet(x, y, x1, y1)
    -- выпускаем "снаряд" и ищем цель
    local eff = AddSpecialEffect("bullets", x, y)
    BlzSetSpecialEffectZ(eff, 60)
    BlzSetSpecialEffectYaw(eff, getAngle(x, y, x1, y1))

    local t = CreateTimer()
    local isProjectileAlive = true
    local xEffect, yEffect = x, y
    TimerStart(t, 0.015, true, function()
        GroupEnumUnitsInRange(group, xEffect, yEffect, 120)
        while true do
            local target = FirstOfGroup(group)
            if target == nil then break end
            GroupRemoveUnit(group, target)
            if UnitAlive(target) and target ~= hero and IsUnitInRangeXY(target, xEffect, yEffect, 50) --ищем юнитов в ренже, кроме пулемётчика
            then
                DestroyEffect(eff)
                isProjectileAlive = false --после первого столкновения уничтожим снаряд, чтобы он не летел дальше
                UnitDamageTargetBJ(hero, target, 20.00, ATTACK_TYPE_PIERCE, DAMAGE_TYPE_NORMAL) -- наносим те самые 20 дальнего урона
            end
        end

        -- двигаем снаряд в нужном направлении
        local sin, cos = getSinCos(xEffect, yEffect, x1, y1)

        xEffect = xEffect + cos * projVelocity
        yEffect = yEffect + sin * projVelocity

        if getDistance(x, y, xEffect, yEffect) >= range or not isProjectileAlive then
            DestroyTimer(t)
            DestroyEffect(eff)
            return
        end
        BlzSetSpecialEffectPosition(eff, xEffect, yEffect, 60)
    end)
end

function getSegments(cx, cy, r, angle1, angle2, angle_step)
    local segments = {}
    local n = math.floor((angle2 - angle1) / angle_step) + 1

    for i = 0, n - 1 do
        local angle = angle1 + i * angle_step
        local x = cx + r * math.cos(math.rad(angle))
        local y = cy + r * math.sin(math.rad(angle))
        table.insert(segments, {x = x, y = y})
    end

    return segments
end

function getSinCos(x1, y1, x2, y2)
    local dX = x2 - x1
    local dY = y2 - y1
    local dist = math.sqrt(dX*dX + dY*dY)
    local sin = dY / dist
    local cos = dX / dist

    return sin, cos
end

function getAngle(x1, y1, x2, y2)
    local deltaX = x2 - x1
    local deltaY = y2 - y1

    local angle
    if deltaX == 0 then
        if deltaY > 0 then
            angle = math.pi / 2
        else
            angle = -math.pi / 2
        end
    else
        angle = math.atan(deltaY / deltaX)
        if deltaX < 0 then
            angle = angle + math.pi
        end
    end

    return angle
end

function getDistance(x1, y1, x2, y2)
    local deltaX = x2 - x1
    local deltaY = y2 - y1

    return math.sqrt(deltaX^2 + deltaY^2)
end

Пример использования, с эффектами и набигающими врагами
Загруженные файлы
0
23
3 недели назад
0

» WarCraft 3 / Массив в магазине.

лучше на Lua
Lua уже в прошлом, теперь лучше на AngelScript
2
23
3 недели назад
2

» WarCraft 3 / Где находятся спецэффекты, появляющиеся на земле

Уберсплаты. Путь в архиве что-то типа ReplaceableTextures/splats
0
23
3 недели назад
0

» WarCraft 3 / Оптимизация Выполнения Последовательности Кода

где-то я это уже видел
В первом ответе то же самое предложено
1
23
3 недели назад
Отредактирован Makeba
1

» WarCraft 3 / Оптимизация Выполнения Последовательности Кода

Раз уж мы всем хгмом делаем наработку для крафтов, то вкачусь тоже В луа я бы сделал так. Ну, если все предметы разные, без повторений.
RequiredItems = {0x6F646566, 0x6F736C6F, 0x6F666972, 0x6F636F72, 0x6F76656E, 0x4930304C}

function checkItems(u)
    for _, v in ipairs(RequiredItems) do
        if not UnitHasItemOfTypeBJ(u, v) then
            return false
        end
    end
    return true
end
Результат
Загруженные файлы
1
23
3 недели назад
Отредактирован Makeba
1

» WarCraft 3 / Массив в магазине.

Сразу хочу сказать, что события фреймов в рефе багованные, после патча 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
На джассе примерно то же самое, только хуже.
Результат на видео и в карте.
Загруженные файлы
1
23
3 недели назад
Отредактирован Makeba
1

» Блог Storm'а / Суицидальная атака на Maya API

Переключение между клипами чёт вообще колхозноватенько реализовано в майе, по сравнению с тем же блендером. Хотя может это я неправильно делаю, ибо в интерфейсе майи разбирался по шортсам с ютуба, кек

Ещё неожиданным приколом оказалось, что Майа не умеет в 3дмаксовский TCB, который в основном близзы использовали в варкрафте, так что либо безье, либо линейная интерполяция.

Этот эйлер сломался, несите следующего
0
23
3 недели назад
0

» Администрация XGM / XGM предлагает проиграть однокадровые гифки

MpW, коммьюнити попросило, получается
Автозагрузка видосов с ютуба раздражает, кстати
0
23
4 недели назад
0

» Администрация XGM / XGM предлагает проиграть однокадровые гифки

А нафига их вообще делать с кнопкой?
0
23
4 недели назад
0

» Администрация XGM / XGM предлагает проиграть однокадровые гифки

Результат
Чёт вопрос отредачить не могу
Загруженные файлы