21

» WarCraft 3 / Как дать герою предмет изначально? (не через Jass)

ClotPh, там свиток даётся только первому юниту, если не изменить значение переменной.
globals
	integer bj_MELEE_MAX_TWINKED_HEROES = 0
endglobals

function MeleeGrantItemsToHero takes unit whichUnit returns nothing
    local integer owner   = GetPlayerId(GetOwningPlayer(whichUnit))

    // If we haven't twinked N heroes for this player yet, twink away.
    if (bj_meleeTwinkedHeroes[owner] < bj_MELEE_MAX_TWINKED_HEROES) then
        call UnitAddItemById(whichUnit, 'stwp')
        set bj_meleeTwinkedHeroes[owner] = bj_meleeTwinkedHeroes[owner] + 1
    endif
endfunction

function MeleeGrantItemsToTrainedHero takes nothing returns nothing
    call MeleeGrantItemsToHero(GetTrainedUnit())
endfunction

function MeleeGrantHeroItems takes nothing returns nothing
    local integer index
    local trigger trig

    // Initialize the twinked hero counts.
    set index = 0
    loop
        set bj_meleeTwinkedHeroes[index] = 0

        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop

    // Register for an event whenever a hero is trained, so that we can give
    // him/her their starting items.
    set index = 0
    loop
        set trig = CreateTrigger()
        call TriggerRegisterPlayerUnitEvent(trig, Player(index), EVENT_PLAYER_UNIT_TRAIN_FINISH, filterMeleeTrainedUnitIsHeroBJ)
        call TriggerAddAction(trig, function MeleeGrantItemsToTrainedHero)

        set index = index + 1
        exitwhen index == bj_MAX_PLAYERS
    endloop

    // Register for an event whenever a neutral hero is hired, so that we
    // can give him/her their starting items.
    set trig = CreateTrigger()
    call TriggerRegisterPlayerUnitEvent(trig, Player(PLAYER_NEUTRAL_PASSIVE), EVENT_PLAYER_UNIT_SELL, filterMeleeTrainedUnitIsHeroBJ)
    call TriggerAddAction(trig, function MeleeGrantItemsToHiredHero)

    // Flag that we are giving starting items to heroes, so that the melee
    // starting units code can create them as necessary.
    set bj_meleeGrantHeroItems = true
endfunction
21

» RenderEdge / [RenderEdge] Memory Hack

Сори за нубский вопрос, только начал разбираться с RenderEdge.
Как задавать координаты, например для функции EditUpperButtonBarButton( ), задаю свои координаты, a кнопка улетает не пойму куда. ANCHOR_TOPRIGHT, ANCHOR_BOTTOM, ANCHOR_RIGHT и т.д. - это точки, откуда отсчитываются координаты?
В прилагаемой карте есть функции FromPixelX( ), FromPixelY( )..., которые используются в функции EditStandardInterface( ). Правильно ли я понял, что эти функции локальные и у каждого игрока кнопки будут настроены относительно их разрешений экрана?
Также карта критует во время загрузки, если в коде есть ! inject main.

UPD: понял, это не координаты, а проценты, как у мультибоарда.
21

» WarCraft 3 / Новый редактор

Darkew, отвечает за то, будет ли урон от предметов учитываться для критического удара.
21

» WarCraft 3 / GetRealId( )

Попробовал return bug, возвращает уникальные значения у real'ов, имеющих 31 символа после запятой, после 32 символа начинает возвращать 0:
function realToInteger takes real r returns integer
    loop
        return r
    endloop
    return 0
endfunction
    
    
function func_name takes nothing returns nothing
    call BJDebugMsg( I2S( realToInteger( 0.12345 ) ) )                             // return 1039979357
    call BJDebugMsg( I2S( realToInteger( 0.123456 ) ) )                            // return 1039980161
    call BJDebugMsg( I2S( realToInteger( 0.1234567 ) ) )                           // return 1039980256
    call BJDebugMsg( I2S( realToInteger( 0.12345678 ) ) )                          // return 1039980265
    call BJDebugMsg( I2S( realToInteger( 0.123456789 ) ) )                         // return 1039980266
    call BJDebugMsg( I2S( realToInteger( 0.1234567890 ) ) )                        // return ...
    call BJDebugMsg( I2S( realToInteger( 0.12345678901 ) ) )                       // return ...
    call BJDebugMsg( I2S( realToInteger( 0.123456789012 ) ) )                      // return ...
    call BJDebugMsg( I2S( realToInteger( 0.1234567890123 ) ) )                     // return ...
    call BJDebugMsg( I2S( realToInteger( 0.12345678901234 ) ) )                    // return ...
    call BJDebugMsg( I2S( realToInteger( 0.123456789012345 ) ) )                   // return ...
    call BJDebugMsg( I2S( realToInteger( 0.1234567890123456 ) ) )                  // return ...
    call BJDebugMsg( I2S( realToInteger( 0.12345678901234567 ) ) )                 // return ...
    call BJDebugMsg( I2S( realToInteger( 0.123456789012345678 ) ) )                // return ...
    call BJDebugMsg( I2S( realToInteger( 0.1234567890123456789 ) ) )               // return ...
    call BJDebugMsg( I2S( realToInteger( 0.12345678901234567890 ) ) )              // return ...
    call BJDebugMsg( I2S( realToInteger( 0.123456789012345678901 ) ) )             // return ...
    call BJDebugMsg( I2S( realToInteger( 0.1234567890123456789012 ) ) )            // return ...
    call BJDebugMsg( I2S( realToInteger( 0.12345678901234567890123 ) ) )           // return ...
    call BJDebugMsg( I2S( realToInteger( 0.123456789012345678901234 ) ) )          // return ...
    call BJDebugMsg( I2S( realToInteger( 0.1234567890123456789012345 ) ) )         // return ...
    call BJDebugMsg( I2S( realToInteger( 0.12345678901234567890123456 ) ) )        // return ...
    call BJDebugMsg( I2S( realToInteger( 0.123456789012345678901234567 ) ) )       // return ...
    call BJDebugMsg( I2S( realToInteger( 0.1234567890123456789012345678 ) ) )      // return -1065120231
    call BJDebugMsg( I2S( realToInteger( 0.12345678901234567890123456789 ) ) )     // return -1080887466
    call BJDebugMsg( I2S( realToInteger( 0.123456789012345678901234567890 ) ) )    // return  1067220501
    call BJDebugMsg( I2S( realToInteger( 0.1234567890123456789012345678901 ) ) )   // return -1108908349
    call BJDebugMsg( I2S( realToInteger( 0.12345678901234567890123456789012 ) ) )  // return  0
    call BJDebugMsg( I2S( realToInteger( 0.123456789012345678901234567890123 ) ) ) // return  0
ScopteRectuS, также, что удивительно, одинаковые числа, но имеющие разное кол-во введённых символов выдают разные числа:
    call BJDebugMsg( I2S( realToInteger( 0.12345678901234567890123456789 ) ) )     // return -1080887466
    call BJDebugMsg( I2S( realToInteger( 0.123456789012345678901234567890 ) ) )    // return  1067220501
21

» WarCraft 3 / GetRealId( )

Идея со структурой мне показалось очень интересной, но увы, не работает.
раскрыть
	struct timeout
        private real     period
        private thistype prev
        private thistype next

        private static method inStock takes real period returns thistype
            local  thistype  this  =  thistype( 0 ).next
            loop
                exitwhen ( this == thistype( 0 ) ) or ( this.period == period )
                set  this  =  this.next
            endloop
            return this
        endmethod

        static method create takes real period returns thistype
            local thistype this = thistype.inStock( period )
            call BJDebugMsg( "inStock" + I2S( this ) )
            if ( this == thistype( 0 ) ) then
                set this             = thistype.allocate( )
                set this.next        = thistype( 0 )
                set this.prev        = thistype( 0 ).prev
                set this.next.prev   = this
                set this.prev.next   = this
                set this.period      = period
            endif
            return this
        endmethod
    endstruct
В методе inStock, если идёт сравнение 0,03125 и 0,03126, то игра считает, что это одинаковые числа.

Fakov, такая, что максимальный размер массива 8192, что есть четырёхзначное число.
Это неважно, мне не обязательно хранить в массиве, поэтому ограничения 8192 нет. Можно просто:
SaveHandle( hash, randomKey, R2I( real ), handle ), главное, чтобы R2I( ) возвращал уникальные значения для каждого real'a.
21

» WarCraft 3 / GetRealId( )

Clamp, я же написал:
GetLocalPlayer, проверил, R2S( ) округляет. R2S( 0.03125 ) > "0.031"
call BJDebugMsg( I2S( StringHash( R2S( 0.03125 ) ) ) ) == -1331723389
call BJDebugMsg( I2S( StringHash( R2S( 0.03126 ) ) ) ) == -1331723389
21

» WarCraft 3 / GetRealId( )

Clamp, всё равно, даже если это будет более ресурсозатратным, чем простое создание и удаление таймеров, хотелось бы довести свое дело до конца.
Я бы сказал, что мною движет желание это сделать больше, чем оптимизация кода.
21

» WarCraft 3 / GetRealId( )

Clamp, и экономить, и просто сделать. Да и код становится более читабелен, написал одну функцию и всё, не нужно ничего крепить, создавать, запускать...
21

» WarCraft 3 / GetRealId( )

GetLocalPlayer, проверил, R2S( ) округляет. R2S( 0.03125 ) > "0.031"
Clamp, вот небольшая библиотека, которая позволяет использовать один периодический таймер на всю карту.
раскрыть

    function interface callback takes integer this returns nothing defaults nothing


    struct linkedList


        static constant method getListPeriod takes nothing returns real
            return ( 0.03125 )
        endmethod


        private  static  constant  timer     period       =  CreateTimer( )
        private                    thistype  prev
        private                    thistype  next
        private                    callback  handlerFunc


        method destroyList takes nothing returns nothing
            set  this.prev.next  =  this.next
            set  this.next.prev  =  this.prev

            if ( thistype( 0 ).next == thistype( 0 ) ) then
                call PauseTimer( thistype.period )
            endif

            call thistype.deallocate( this )
        endmethod


        private static method iterateList takes nothing returns nothing
            local  thistype  this  =  thistype( 0 ).next

            loop
                exitwhen ( this == thistype( 0 ) )

                call this.handlerFunc.evaluate( integer( this ) )

                set  this  =  this.next
            endloop
        endmethod


        static method createList takes callback handlerFunc returns thistype
            local  thistype  this  =  thistype.allocate( )

            set  this.next         =  thistype( 0 )
            set  this.prev         =  thistype( 0 ).prev
            set  this.next.prev    =  this
            set  this.prev.next    =  this
            set  this.handlerFunc  =  handlerFunc

            if ( this.prev == 0 ) then
                call TimerStart( thistype.period, thistype.getListPeriod( ), true, function thistype.iterateList )
            endif

            return this
        endmethod


    endstruct
Как видно из кода, метод createList( ) берет лишь функцию, которую будет запускать по истечении таймера, а период таймера там статичный. Я же хочу допилить свой код, чтобы этот метод еще и брал период таймера, и, если это новый период таймера, то создаётся новый таймер, если же нет, то действие добавляется к уже существующему таймеру с таким же периодом.
Получилось бы примерно следующее:
static method createList takes real timeout, callback handlerFunc returns thistype
	...
	if timers[ timeout ] == null then
		set timers[ timeout ] = CreateTimer( )
	endif
	...
endmethod
21

» WarCraft 3 / GetRealId( )

Naadir, а как работает функция из мемхака? она же как-то выдаёт разные значения.
Clamp, потому что мне нужно прикрепить объект к real'y
21

» WarCraft 3 / GetRealId( )

Если честно, то даже не понял, что это за слова вы мне написали.(

Думаю, будет лучше, если я объясню для чего мне это нужно.
Мне нужно прикрепить к real'y handle, но все способы, что мне известны, реализованы через integer (структуры, массивы переменных, хеш-таблицы).

Сперва думал, что смогу сделать через параллельные массивы:
reals[ index ] = 0.056465
handle[ index ] = whichTimer
но как то не получилось, да и к циклам приходится постоянно прибегать. А если сделать через GetRealId( ), то получилось бы всё очень просто:
handle[ GetRealId( 0.056465 ) ] = whichTimer
всё очень просто, таймер хранится в ячейке 0.056465.
21

» WarCraft 3 / Как правильно импортировать

8gabriel8, карта должна открываться и без JNGP, но если не сохраняется без JNGP, то отключите все триггеры (так должно сохранится).
(xgm.guru/files/100/213449/comments/394737/[4]KamokTD.w3x)
Загруженные файлы
21

» WarCraft 3 / Как правильно импортировать

8gabriel8, так в игровом интерфейсе этого всего нету. И шрифтов тоже нету. По крайней мере у меня нету.
21

» WarCraft 3 / Кель из Heroes of the Storm

PT153, IsUnitType(u, UNIT_TYPE_DEAD) вернет false, если u == null. То есть функция скажет, что несуществующий юнит еще живой.
21

» WarCraft 3 / Наш рудник обрушился...

quq_CCCP, благодарю, почти не пользуюсь GUI, поэтому не знал, что есть такие нативки.
KingMaximax, добавлять золото перед обрушением - не подходит. Мне нужен рудник с 0 золотом, который не обрушится, если в него войдёт рабочий.
21

» WarCraft 3 / Наш рудник обрушился...

Если создать на его месте рудник без золота, то любой рабочий, что войдёт внутрь, обрушит его.
А также можно ли как-то влиять на кол-во золота в руднике? Там добавить 10 золота или отнять 124.
21

» WarCraft 3 / WESTRING_SCRIPTERR UNCLARED_IDENTIFIER

call SetTextTagVisibility(tt, GetLocalPlayer()== Player (plr_num))
endif
можно заменить на
if (GetLocalPlayer()== Player (plr_num)) then
call SetTextTagVisibility(tt, true)
21

» WarCraft 3 / Проблемы с постройкой зданий

Благодарю за помощь. Но от морфа пришлось отказаться, так как он имеет ряд недостатков: создание двух строителей; возможность создать лишь два окна, для выбора построек. В то время как с помощью блокирования построек не нужно создавать второго строителя, можно сделать несколько окошек для выбора списка доступных заданий (больше двух, просто создав еще одну способность-пустышку, при использовании которой, будет создаваться новый список).
А насчёт моего первого утверждения, что нельзя использовать на нескольких строителях > я ошибался. Так как невозможно открыть окно построек сразу у нескольких рабочих, всегда будет открыто только одно окно, соответственно, всё будет работать как надо.
раскрыть
scope Buildings initializer onInit


    function EnableBuildings takes player whichPlayer, integer int returns nothing
        if ( int == 0 ) then
            call SetPlayerTechMaxAllowed( whichPlayer, 'T000', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T001', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T002', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T003', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T004', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T005', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T006', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T007', -1 )
            

        elseif ( int == 1 ) then
            call SetPlayerTechMaxAllowed( whichPlayer, 'h002',  1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h004', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h005', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h006', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h007', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h008', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h009', -1 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'n000', -1 )
        endif
    endfunction


    function DisableBuildings takes player whichPlayer, integer int returns nothing
        if ( int == 0 ) then
            call SetPlayerTechMaxAllowed( whichPlayer, 'T000', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T001', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T002', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T003', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T004', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T005', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T006', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'T007', 0 )

        elseif ( int == 1 ) then
            call SetPlayerTechMaxAllowed( whichPlayer, 'h002', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h004', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h005', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h006', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h007', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h008', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'h009', 0 )
            call SetPlayerTechMaxAllowed( whichPlayer, 'n000', 0 )
        endif
    endfunction


    function DisableAllBuildings takes nothing returns nothing
        local integer index = 0

        loop
            if (GetPlayerSlotState(Player(index)) == PLAYER_SLOT_STATE_PLAYING) then
                call DisableBuildings(Player(index), 0)
                call DisableBuildings(Player(index), 1)
            endif

            set index = index + 1
            exitwhen index == bj_MAX_PLAYERS
        endloop
    endfunction


    globals
        private unit builder = null
    endglobals


    function onUnitSpellFinish takes nothing returns nothing
        if (GetSpellAbilityId() == 'A000') then
            set builder = GetSpellAbilityUnit()

            call DisableBuildings(GetOwningPlayer(builder), 0)
            call EnableBuildings (GetOwningPlayer(builder), 1)

            call IssueImmediateOrderById(builder, 851994)
            call UnitRemoveAbility(builder, 'BOwk')

        elseif (GetSpellAbilityId() == 'A001') then
            set builder = GetSpellAbilityUnit()

            call DisableBuildings( GetOwningPlayer(builder), 1)
            call EnableBuildings ( GetOwningPlayer(builder), 0)

            call IssueImmediateOrderById(builder, 851994)
            call UnitRemoveAbility(builder, 'Bbsk')
        endif
    endfunction


    function onInit takes nothing returns nothing
        call DisableAllBuildings()

        call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_SPELL_FINISH, function onUnitSpellFinish)
    endfunction


endscope
21

» WarCraft 3 / Крепление места вылета снаряда к модели

Steal nerves, а можно откуда-нибудь взять эти параметры для каждой боевой единицы? Я изменил Графика - Масштабирование (usca) у многих юнитов и теперь они стреляют из не из того места. На глаз делать, мне кажется, будет не совсем правильно.
Steal nerves:
Значение "ноль" является исходным значением.
Ставил на 0, но насколько я понял, это не дофолтное значение, а просто центр координатной сетки.
21

» WarCraft 3 / Fatal при отлове завершения строительства

Сори, ребзя. Так как это у меня здание-герой, я и совсем забыл, что башня является героем. А функции GetUnitGoldCost(), GetUnitWoodCost() не работают с героями, об этом я писал ранее:
ScopteRectuS:
Есть же функции:
native GetUnitGoldCost        takes integer unitid                    returns integer
native GetUnitWoodCost        takes integer unitid                    returns integer
Правда нелbзя использовать на воинов, у которых равкод начинается с прописной буквы (на героев).
Idency всё верно сказал. Всем спасибо за помощь.