28

» WarCraft 3 / missing return

code
unit EnemyInGroup (unit u, float x, float y, float range) {
    group enemies = CreateGroup()
    unit u_e
    
    GroupEnumUnitsInRange(enemies, x, y, range, Condition(function SimpleCond))
    loop
        u_e = FirstOfGroup(enemies)
        exitwhen u_e == null
        if IsUnitEnemy(u_e, GetOwningPlayer(u)) then
            DestroyGroup(enemies)
            enemies = null
            return u_e  // утечка переменной u_e, используй глобалку.
            // exitwhen true  // зачем это, когда есть return?
        else
            GroupRemoveUnit(enemies, u_e)
        endif
    endloop
    
    DestroyGroup(enemies)
    enemies = null
    u_e = null
    return null  // нет враждебного юнита.
}

А вообще, что находится в функции SimpleCond? Тут можно всё упростить.
code
globals
    player TransPlayer
    unit LastEnemyUnit
endglobals

function filter takes nothing returns boolean
    if IsUnitEnemy(GetFilterUnit(), TransPlayer) then
        set LastEnemyUnit = GetFilterUnit()
    endif
    return false
endfunction

function EnemyInRange takes unit u, real x, real y, real range return boolean
    set TransPlayer = GetOwningPlayer(u)
    set LastEnemyUnit = null
    call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, range, Filter(function filter))
    return LastEnemyUnit != null
endfunction
замечание от Raised: 1.4 (злоупотребление форматированием) используйте каты
28

» WarCraft 3 / Вылет на полосе загрузки у некоторых игроков

можно подробнее?)
А зачем инициализировать null, "" или 0? Все глобалки, что имеют присвоение в своём определении, выполняются в то время, как игрок кликнул на карту в списке карт. Потому лучше либо вообще ничего не прописывать, либо прописать нормальные значения, например:
globals
    constant trigger TestBuildMase = CreateTrigger()
    constant trigger TestLevelUp = CreateTrigger()
    constant trigger TestPauseTime = CreateTrigger()
    constant trigger TestResumeTime = CreateTrigger()
    constant trigger TestKillMinion = CreateTrigger()
    constant trigger TestCreateHero = CreateTrigger()
endglobals
Однако не для всех это работает. GetLocalPlayer(), CreateRegion(), CreateLeaderboard, CreateMultiboard() нельзя использовать в определении глобалок, они крашнут игру, как только игрок кликнет на карту. А, вот например, InitHashtable(), CreateTimer(), CreateTrigger() карту не крашат, потому можно сделать так:
globals
    constant hashtable Hash  =InitHashtable()
    constant timer Timer = CreateTimer()
endglobals
А ещё присвоение во время определения экономит место и, при использовании с constant, защищает переменную от случайного переназначения.

А что делать, я не совсем понял)
Найти проблемную модель и выяснить, почему она крашит.
28

» WarCraft 3 / Вылет на полосе загрузки у некоторых игроков

я почти всем глобалкам ставлю при объявлении null или 0 или ""
ну это ты зря

Тогда остаётся только инициализацию мультибоарда передвинуть, а также проверить вызовы ExecuteFunc (что имя вызываемой функции точно есть в карте) на всякий случай.
28

» WarCraft 3 / Вылет на полосе загрузки у некоторых игроков

Ещё в начале игры с 0.00 секунды инициализируется мультиборд
Поставь 0.01 хотя бы, это и может крашить, как писалось в некоторых туториалах.

В коде, что показан, всё чисто, но я бы вынес 41 как константную глобалку)

inject на config есть?
Какие глобалки у тебя сразу имеют значение? например constant integer A = 1
28

» WarCraft 3 / Способность которая действует по все карте

Проще простого же. Пусть abil является действием в триггере, который ловит каст твоего спела.
function filter takes nothing returns nothing
    local unit u = GetFilterUnit()
    if /* нужные условия */ then
        // нужные действия
    endif
    set u = null
endfunction

function abil takes nothing returns nothing
    ...
    call GroupEnumUnitsInRect(bj_lastCreatedGroup, bj_mapInitialPlayableArea, Condition(function filter))
    ...
endfunction
28

» WarCraft 3 / Движение, jass

Даешь ему нужную способность волны
Он это не может, потому что карта, скорее всего, ломанная.
28

» WarCraft 3 / Помогите разобраться в карте, в крафтах!

Может лист файл новее надо. У мня tga последний и есть файлы xxx unknown - попробую их пооткрывать.
В MPQ Editor есть сканер карт, он должен такие файлы определить.
28

» WarCraft 3 / Как сделать возраждение?

не понимаю, почему это без локи можно? и почему не затирается новым юнитом. это получается на поток приписывают
Я же написал выше, что у каждого потока своя DyingUnit, и, возможно, любая другая константная нативка.
28

» WarCraft 3 / Помогите разобраться в карте, в крафтах!

Принятый ответ
компилирует war3map.j какой-то утилитой в составе JNGP
JassHelper эта утилита, её можно через PowerShell отдельно от JNGP запускать.
Так-то можно даже просто pjass.exe (тоже в составе JNGP) запустить (через PowerShell), ведь в war3map.j код уже в JASS.

БОльшая часть строк находится в war3map.wts, его и нужно переводить, там находятся все описания способностей, юнитов, предметов и так далее, иногда даже просто мусор, который редактор забыл убрать.
Дам совет, у способностей нужно переводить только описания, имена в самой игре всё равно не отображаются. А ещё на них может быть завязан код (как у меня в карте), так что лучше их вообще не трогать.
С юнитами и предметами возможна такая же ситуация, но вот тут сложнее, ведь их имена отображаются в игре.
Потому перед переводом, нужно проверить war3map.j на наличие функций GetObjectName, GetItemName, GetUnitName. Если они есть, то понять, для чего они используются, а потом уже переводить.
Часть строк может быть в war3map.j, многие и переводить не нужно (пути к эффектам, например), но вот выводимые на экран сообщения перевести стоит.
28

» WarCraft 3 / Как сделать возраждение?

это получается без локи можно?
Локи в смысле локации или локальной переменной?
Да, без локальной можно.
28

» WarCraft 3 / Варианты границ карты

Кстати, а можно ли сделать карту с различными шириной и длиной?
Да, это можно сделать даже в меню создания новой карты.
Включи среднюю сетку, размер белого квадрата есть 128х128, и именно в них и измеряется размер карты, то есть, выражаясь точнее, когда увеличиваешь или уменьшаешь карту, нужно сделать количество белых квадратов по длине и ширине кратным 32.
28

» WarCraft 3 / Как сделать возраждение?

переменная "Dying Unit" перепишется
А вот и нет, она для каждого вызова триггера своя. Потому вариант 8gabriel8 правильный.
28

» WarCraft 3 / Динамический триггер ?!

Разница между обычным триггером и динамическим в том, что первый создаётся во время инициализации игры, а второй во время самой игры.
28

» WarCraft 3 / Аттач группы триггеров

Надеюсь я объяснил почему именно триггеры, поверь отравление наносящие только урон или какую-нибудь фрост нову я на триггерах бы не делал.
Понял, было интересно. А что по поводу той системы прикрепления, что я предложил? Таймеры в ней не используются, они только в самих баффах.
28

» WarCraft 3 / Как сделать триггер по типу..

Нужен JNPG с включённым UMSWE.
Вот пример без JNGP.
Когда я уже начну верно писать сокращение Jass New Generation Pack.

чистого кода не важна.
Я не про чистый код, а в общем, ГУИ так-то тоже "код".
28

» WarCraft 3 / Как сделать триггер по типу..

Почему?
Делать в if действие только в else плохой тон и просто неудобно для чтения кода. Тут всё равно идёт сравнение логических, потому данное исправление улучшит читаемость кода и никак не повлияет на производительность.
28

» WarCraft 3 / Построение фигур

а оно под любым углом размещает изображение?
Хм, об этом я позабыл, нет, не размещает.
Atesla:
Не поругается ли Варик за то, что не буду использовать BLP?
Не должен, но там есть другие ньюансы, например, тип изображения. в ГУИ их 6, но по факту 4. Также края должны быть прозрачными.
28

» WarCraft 3 / Как сделать триггер по типу..

Принятый ответ
Событие: каждые 20 секунд.
Действия: поставить переменной B значение ноль.
Выбрать все предметы в области Х, равкод которых Z, и для каждого сделать Поставить переменной B значение B + 1.
Если B равно 0 создать предмет иначе ничего не делать.

Нужен JNPG с включённым UMSWE.
28

» WarCraft 3 / Построение фигур

модель полумесяца клепать.
Можно просто текстурку, которую потом нарисовать в нужной точке с помощью CreateImage.
28

» WarCraft 3 / Аттач группы триггеров

Принятый ответ
У меня к каждому юниту крепится ссылка на объект структуры, в которой есть отдельные списки для разных типов баффов. Если же бафф имеет два разных эффекта, то ссылка на него хранится в двух списках. При удалении конфликтов не возникает, потому что при удалении бафф удаляет все ячейки, которые были к нему привязаны, а ячейки удаляются линейно.
Ячейка списка
struct MBSNode
    readonly MinionBuff buf
    readonly integer number
    thistype prev = 0
    thistype next = 0
    
    method basicInit takes MinionBuff buf, integer number returns nothing
        static if ErrorDetectionEnabled_MBSNode then
            if this == 0 then
                call ErrorOccurred("Error: MBSNode struct has run out of indexes. Current amount of indexes is 8190", "MBSNodeError")
            endif
        endif
        set this.buf = buf
        set this.number = number
    endmethod
    
    method removeFromList takes nothing returns nothing
        if prev != 0 then
            set prev.next = next
        endif
        if next != 0 then
            set next.prev = prev
        endif
    endmethod
endstruct

struct MBSNodeReal extends MBSNode
    real value = 0.
endstruct

struct MBSNodeInt extends MBSNode
    integer value = 0
endstruct

struct MBSNodeIntNReal extends MBSNode
    integer value = 0
    real rvalue = 0.
endstruct
Структура, в которой содержится списки, называется MBS, в ней есть счётчик количества баффов, это нужно для определения, какой бафф был добавлен раньше.
Списки в основном задаются таким макросом.
Список
// Name - имя типа баффа
// ntyp - тип ячейки
// values - если есть значения у баффа
// bool - если значения типа boolean
// null - нуль для заданного типа значений.

//! textmacro MBSList takes Name, ntyp, values, type, bool, null
    private MBSNode$ntyp$ head$Name$
    readonly integer buffsAmount$Name$ = 0
    
    method add$Name$Buff takes MinionBuff obj returns MBSNode$ntyp$
        local MBSNode$ntyp$ node = MBSNode$ntyp$.create()
        if buffsAmount$Name$ == 0 then
            set head$Name$ = node
        else
            set node.next = head$Name$
            set head$Name$.prev = node
            set head$Name$ = node
        endif
        set BuffCounter = BuffCounter + 1
        set buffsAmount$Name$ = buffsAmount$Name$ + 1
        call node.basicInit(obj, BuffCounter)
        //call DebugMsg("Current amount of $Name$ buffs is " + I2S(buffsAmount$Name$) + ".")
        return node
    endmethod
    
    method remove$Name$Buff takes MBSNode$ntyp$ node returns nothing
        set buffsAmount$Name$ = buffsAmount$Name$ - 1
        if head$Name$ == node then
            set head$Name$ = node.next
        endif
        static if $values$ then
            static if $bool$ then
                set booleanAmount$Name$ = booleanAmount$Name$ - node.value
                set total$Name$Bonus = booleanAmount$Name$ > 0
            else
                set total$Name$Bonus = total$Name$Bonus - node.value
            endif
        endif
        call node.removeFromList()
        call node.destroy()
        //call DebugMsg("Current amount of $Name$ buffs is " + I2S(buffsAmount$Name$) + ".")
    endmethod
    
    static if $values$ then
        static if $bool$ then
            private integer booleanAmount$Name$ = 0
            readonly boolean total$Name$Bonus = false
        else
            readonly $type$ total$Name$Bonus = $null$
        endif
        
        method change$Name$Value takes MBSNode$ntyp$ node, $type$ value returns nothing
        static if $bool$ then
            local integer v = B2I(value)
            set booleanAmount$Name$ = booleanAmount$Name$ - node.value + v
            set total$Name$Bonus = booleanAmount$Name$ > 0
            set node.value = v
        else
            set total$Name$Bonus = total$Name$Bonus - node.value + value
            set node.value = value
        endif
        endmethod
    endif
//! endtextmacro
В этой же системе определяется текущее кол-во брони, уязвимый ли он или нет, уровень замедления или ускорения, и пр.
При удалении объекта системы удаляются и все навешанные баффы.
Удаление
// Макрос ниже также используется для удаления баффов конкретного типа при каких-то обстоятельствах.
// pos - бафф положительный.
// Ячейки удаляются с удалением баффа.

//! textmacro DeleteBuffs takes Name, first, pos
        static if $first$ then
        local MBSNode node = head$Name$
        local MBSNode temp
        else
        set node = head$Name$
        endif
        loop
            exitwhen node == 0
            set temp = node.next
            $pos$if node.buf.buffdata.negative then
                call node.buf.destroy()
            $pos$endif
            set node = temp
        endloop
//! endtextmacro
...
    method onDestroy takes nothing returns nothing
        //! runtextmacro DeleteBuffs("EoT", "true", "//# ")
        //! runtextmacro DeleteBuffs("Shield", "false", "//# ")
        //! runtextmacro DeleteBuffs("MoveSpeed", "false", "//# ")
        //! runtextmacro DeleteBuffs("Stun", "false", "//# ")
        //! runtextmacro DeleteBuffs("Persistence", "false", "//# ")
        //! runtextmacro DeleteBuffs("PhysArmor", "false", "//# ")
        //! runtextmacro DeleteBuffs("MagcArmor", "false", "//# ")
        //! runtextmacro DeleteBuffs("Armor", "false", "//# ")
        //! runtextmacro DeleteBuffs("PhysImmune", "false", "//# ")
        //! runtextmacro DeleteBuffs("MagcImmune", "false", "//# ")
        //! runtextmacro DeleteBuffs("Protection", "false", "//# ")
        //! runtextmacro DeleteBuffs("Invul", "false", "//# ")
        call DebugMsg("MinionBuffStorage " + I2S(this) + " is deleted.")
    endmethod

Сами баффы.
Каждый бафф - отдельная структура, которая наследуется от общей.
Бафф
struct MinionBuff
    integer typ
    Minion target
    unit source
    CustomPlayer owner
    MinionBuffData buffdata
    integer currticks = 0
    boolean isRunning = false
    MBSNode node1
    MBSNode node2
    MBSNode node3
    
//! runtextmacro CustomTimer("t", "Timer", "MinionBuff", "false")

    method onDestroy takes nothing returns nothing
        call DeleteTimer()
        call RemoveSavedInteger(Hash, target.id, typ)
        call UnitRemoveAbility(target.minion, buffdata.effectid)
        set source = null
        call DebugMsg("MinionBuff " + I2S(this) + " is deleted.")
    endmethod
    
    method basicInit takes Minion host, unit src, CustomPlayer p, integer T returns nothing
        static if ErrorDetectionEnabled_MinionBuff then
            if this == 0 then
                call ErrorOccurred("Error: MinionBuff struct has run out of indexes. Current amount of indexes is 8190", "MinionBuffError")
            endif
        endif
        set typ = T
        set target = host
        set source = src
        set owner = p
        set buffdata = p.minion_buffdata[T]
        call InitTimer()
        call SaveInteger(Hash, target.id, T, this)
        //call DebugMsg("MinionBuff " + I2S(this) + " is created.")
    endmethod

...

endstruct
Может быть всего 3 разных типа эффекта у баффа, пока максимум было 2.
Примеры баффов
struct BuffMultishotDoT extends MinionBuff
    method onCreate takes nothing returns nothing
        set node1 = target.addEoTBuff(this)
    endmethod
    
    method onDestroy takes nothing returns nothing
        call target.removeEoTBuff(node1)
    endmethod

    method tickAction takes nothing returns boolean
        local Tower dd
        if UnitExists(source) then
            set dd = GetUnitUserData(source)
            call dd.dealDamage(target, AbilMultishot(dd.abil).dot, AbilMultishot.dottype, false)
            return currticks == 0
        endif
        return true
    endmethod
    
    static method launch takes Minion m, Tower caster returns nothing
        //                     target,     sourceunit,          owner,           name,    neg,  disabl, chkowne, args
        //! runtextmacro InitBuff("m", "caster.tower", "caster.owner", "MultishotDoT", "true", "false", "false", "")
        call startPeriodic(buffdata.startticks)
    endmethod
endstruct

struct BuffMultishotSlow extends MinionBuff
    method onCreate takes real slow returns nothing
        set node1 = target.addMoveSpeedBuff(this, slow)
    endmethod
    
    method onDestroy takes nothing returns nothing
        call target.removeMoveSpeedBuff(node1)
    endmethod
    
    static method launch takes Minion m, Tower caster, real slow returns nothing
        //! runtextmacro InitBuff("m", "caster.tower", "caster.owner", "MultishotSlow", "true", "true", "false", "slow")
        call start()
    endmethod
endstruct
Макрос InitBuff инициализирует любой бафф, но вопрос не об устройстве баффов, потому опустим его полное устройство. При вызове баффа (метод launch) делаются некоторые проверки, если всё хорошо, то создаётся объект и вызывается его метод onCreate, где сохраняются ссылки на его ячейки.