scope StormHammer

    globals
        public    constant    integer      ABILITY_ID                             =    'A019'
        public    constant    integer      THUNDERCLAP_ID                         =    'A00K'
        public    constant    string       THUNDERCLAP_ORDER                      =    "thunderclap"
        public    constant    string       EFFECT_PATH                            =    "Abilities\\Spells\\Human\\Thunderclap\\ThunderClapCaster.mdl"
        public    constant    string       LIGHTNING_NAME                         =    "CLPB"
        public    constant    real         LIGHTNING_HEIGHT                       =    9900.0
        public    constant    real         LIGHTNING_LIFE_TIME                    =    0.1
    endglobals

    globals
        public    constant    group       enumUnits           =    CreateGroup()
        public                boolexpr    boolexprForGroup    =    null
    endglobals

    public function Conditions takes nothing returns boolean
        local integer abilityLevel    = GetUnitAbilityLevel( GetAttacker(), ABILITY_ID )
        local real    currentMana     = GetUnitState( GetAttacker(), UNIT_STATE_MANA )
        local real    abilityManaCost = GetAbilityManaCost( ABILITY_ID, abilityLevel )

        local boolean a = ( abilityLevel >= 1 )
        local boolean b = ( currentMana >= abilityManaCost )
        local boolean c = ( not IsAbilityOnCooldown( GetUnitAbility( GetAttacker(), ABILITY_ID ) ) )

        return ( a ) and ( b ) and ( c )
    endfunction

    public function GroupCallback takes nothing returns boolean
        local unit   filterUnit         = GetFilterUnit()
        local unit   attackingUnit      = bj_lastCreatedUnit
        local player attackingUnitOwner = bj_groupEnumOwningPlayer

        local boolean a = not IsUnitType(filterUnit, UNIT_TYPE_STRUCTURE)
        local boolean b = IsUnitEnemy(filterUnit, attackingUnitOwner)
        local boolean c = GetWidgetLife(filterUnit) > 0.405

        if ( a ) and ( b ) and ( c ) then
            call UnitDamageTarget( attackingUnit, filterUnit, 125.0, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null )
        	call CreateFloatingTextTag( null, FLOATING_TEXTTAG_CRITICAL_STRIKE, R2I( 125.0 ), GetUnitX( filterUnit ), GetUnitY( filterUnit ) )
        endif
        
        set filterUnit    = null
        set attackingUnit = null

        return false
    endfunction

    public function Actions takes nothing returns nothing
        local unit    victim          = GetTriggerUnit()
        local unit    attacker        = GetAttacker()

        local real    victimZ         = GetUnitFlyHeight(victim)
        local real    victimX         = GetUnitX(victim)
        local real    victimY         = GetUnitY(victim)

        local integer abilityLevel    = GetUnitAbilityLevel( attacker, ABILITY_ID )
        local integer abilityManaCost = GetAbilityManaCost( ABILITY_ID, abilityLevel )
        local real    abilityCooldown = GetAbilityDataCooldown( GetUnitAbility( attacker, ABILITY_ID ), abilityLevel )

        local real    newManaState    = GetUnitState( attacker, UNIT_STATE_MANA ) - abilityManaCost

        call IssueImmediateOrder( attacker, "stop" )

        call StartAbilityCooldown( attacker, ABILITY_ID, abilityCooldown )
        call SetUnitState( attacker, UNIT_STATE_MANA, newManaState )

        set bj_lastCreatedUnit       = attacker
        set bj_groupEnumOwningPlayer = GetOwningPlayer(attacker)

        call GroupEnumUnitsInRange( enumUnits, victimX, victimY, 675.0, boolexprForGroup )

//      call GroupClear(enumUnits)
        set bj_lastCreatedUnit       = null
        set bj_groupEnumOwningPlayer = null

        call CreateLightningTimed( LIGHTNING_NAME, true, victimX, victimY, LIGHTNING_HEIGHT, victimX, victimY, victimZ, LIGHTNING_LIFE_TIME )
        call CasterCastAbilityImmediate( GetOwningPlayer(attacker), victimX, victimY, victimZ, THUNDERCLAP_ID, 1, THUNDERCLAP_ORDER )
        call DestroyEffect( AddSpecialEffect( EFFECT_PATH, victimX, victimY ) )

        set victim        = null
        set attacker      = null
    endfunction

endscope

function InitTrig_StormHammer takes nothing returns nothing
    call PreloadAbility  ( StormHammer_ABILITY_ID     )
    call PreloadAbility  ( StormHammer_THUNDERCLAP_ID )
    call PreloadEffect   ( StormHammer_EFFECT_PATH    )
    call PreloadLightning( StormHammer_LIGHTNING_NAME )

    set StormHammer_boolexprForGroup = Condition(function GroupCallback)
    set gg_trg_StormHammer = CreateTrigger()

    call TriggerRegisterAnyUnitEventBJ( gg_trg_StormHammer, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( gg_trg_StormHammer, Condition( function StormHammer_Conditions ) )
    call TriggerAddAction( gg_trg_StormHammer, function StormHammer_Actions )
endfunction

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

ScopteRectuS, у тебя где то перезаписывается bj_lastCreatedUnit
причём происходит это после первой итерации GroupEnumUnitsInRange
а вообще не стоит юзать стандартные бж переменные
т.к. они могут конфликтовать с другими системами
используй приватные переменные
если после перехода на приватные глобалки проблема останется то скопируй систему на отдельную карту и кинь эту карту сюда
буду тестить разные варианты
0
19
7 лет назад
0
Похожие вопросы:

ответ
нет
no
ответ
Не boolean а booexpr - это фильтр для группы, там никакие локалка не нужны.
Саму группу можно перебирать в цикле что правда дает шанс попасть в лимит операций и грохнуть поток.
Делать нужно примерно вот так :
function OnlyEnemyGroundAlive takes nothing returns boolean
    return GetUnitState( GetFilterUnit(), UNIT_STATE_LIFE )> 0.405 and IsUnitEnemy( GetFilterUnit(), bj_groupEnumOwningPlayer ) and IsUnitType( GetFilterUnit(), UNIT_TYPE_GROUND )
endfunction

function DamageEnemy takes nothing returns nothing
    call UnitDamageTarget( bj_lastReplacedUnit, GetEnumUnit(), 100.00, false, false, ATTACK_TYPE_NORMAL,  DAMAGE_TYPE_COLD, WEAPON_TYPE_WHOKNOWS )
endfunction

function Temp takes nothing returns nothing
    local group grp = CreateGroup( ) //создаём группу юнитов
    local real dx = 0.00   // координата x 
    local real dy = 0.00   // координата y
    
    set bj_groupEnumOwningPlayer == Player(0) // глобальная переменная чтобы передать данные в фильтр
    call GroupEnumUnitsInRange( grp, dx, dy, 512.00, Condition( function OnlyEnemyGroundAlive) )
    set bj_lastReplacedUnit = GetTriggerUnit( )// глобальная переменная чтобы передать данные в другую функцию.
    call ForGroup( grp, function DamageEnemy )
    
    call DestroyGroup( grp )
    
    set grp = null
endfunction
1 строчка бывает только у гуишников.
ответ
проверь настройки A01P, возможно, там кривые данные выше 3-го уровня
ответ
private function Trigger_Conditions takes nothing returns boolean
     return LoadStr(HASHTABLE, GetSpellAbilityId(), StringHash("abil_id")) != null and LoadStr(HASHTABLE, GetSpellAbilityId(), StringHash("abil_id")) != ""
endfunction
попробуйте так, или уберите:
local boolexpr b = Condition(function Trigger_Conditions)
call DestroyBoolExpr(b)
set b = null
Замените call TriggerAddCondition(TRIGGER, b) на call TriggerAddCondition(TRIGGER, Condition(function Trigger_Conditions))

Добавлю
Ещё бывает что значение из хеш-таблицы строкового показывало "(null)";
ответ
У тебя логическая ошибка в цикле. На первом витке, если группа пустая, то i увеличиться на 400! На следующем еще на 400. В итоге, ты при выходе получаешь индекс 400*400+1. Но я не уверен, что до этого дойдет. При 819*, не помню макс размер массива,у тебя просто накроется все. В общем, у тебя логическая ошибка
И, да, ласткриейтедюнит можно занести в локальную переменную, т.к.лайс* - глобалка из common типа unit

0
28
7 лет назад
0
дебаг добавь
0
21
7 лет назад
Отредактирован scopterectus
0
nvc123, дебаг в функции GroupCallback не срабатывает. Кстати, плавающий текст тоже не появляется. Но если в функции call GroupEnumUnitsInRange( enumUnits, victimX, victimY, 675.0, boolexprForGroup ) заменить переменную на Сondition( function GroupCallback ), то плавающий текст начинает появляться, но урона всё также нету.
0
28
7 лет назад
0
ScopteRectuS, не стоит заносить булекспы в переменные
булэкспы кэшируются так что только путаешься с этими переменными
так же функцию инициализации лучше перенести в scope
что касается урона
перед call UnitDamageTarget добавь вывод на экран имён attackingUnit и filterUnit
и функции лучше сделать приватными а не публичными
0
21
7 лет назад
0
nvc123, Имя filterUnit выдает правильно, но имя attackingUnit выдаёт правильно лишь 1 раз, дальше начинает выдавать (null). Даже если где то есть перезапись данной переменной, то такого быть не должно, ведь тут действия происходят без задержек.
0
23
7 лет назад
Отредактирован pro100master
0
...
0
4
7 лет назад
Отредактирован Revenantik
0
геморрой какой то
лучше уж так
call GroupEnumUnitsInRange(enumUnits, victimX, victimY, 675.0,null)
loop
pick = FirstOfGroup(enumUnits)
exitwhen pick==null
if GetWidgetLife(pick)>0.405 and not IsUnitType(pick,UNIT_TYPE_STRUCTURE) and IsUnitEnemy(pick, GetOwningPlayer(victim)) then
call UnitDamageTarget( victim, pick, 125.0, false, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null )
call CreateFloatingTextTag( null, FLOATING_TEXTTAG_CRITICAL_STRIKE, R2I( 125.0 ), GetUnitX( pick ), GetUnitY( pick ) )
endif
GroupRemoveUnit(enumUnits,pick)
endloop
0
28
7 лет назад
0
Revenantik, твой способ и есть геморой
т.к. является велосипедом
ScopteRectuS, 1 раз это при первом запуске системы?
или 1 раз при каждом вызове GroupEnumUnitsInRange?
и убери обнуление бж переменных наподобие bj_lastCreatedUnit
они ведь глобальные
0
21
7 лет назад
0
nvc123, 1 раз при каждом вызове GroupEnumUnitsInRange. А обнуление я сделал специально, если где-нибудь будут использоваться эти переменные, они могут выдать данные из этой функции. Поэтому сделал на всякий случай.
А вообще обнуление убирать пробовал, это ни на что не влияет. По прежнему выдаёт null кроме первого раза.
0
28
7 лет назад
0
ScopteRectuS, у тебя где то перезаписывается bj_lastCreatedUnit
причём происходит это после первой итерации GroupEnumUnitsInRange
а вообще не стоит юзать стандартные бж переменные
т.к. они могут конфликтовать с другими системами
используй приватные переменные
если после перехода на приватные глобалки проблема останется то скопируй систему на отдельную карту и кинь эту карту сюда
буду тестить разные варианты
Принятый ответ
0
21
7 лет назад
Отредактирован scopterectus
0
nvc123, заменил на свои переменные. Пока что всё работает правильно. Но я всё же не могу понять, как могли переменные перезаписаться, если действие происходит очень быстро и нет никаких задержек. Да и одновременно в вк3 ничего не может произойти, насколько я знаю...
2
28
7 лет назад
Отредактирован nvc123
2
Да и одновременно в вк3 ничего не может произойти, насколько я знаю...
а зачем одновременно?
первая итерация нанесла урон
сработал триггер на получение урона и перезаписал переменные
пошла 2 итерация
новые потоки имеют приоритет над ещё работающем
т.е. если на середине кода стартанул 2 поток то будет выполнятся он а только потом 2 половина кода
на этом основаны некоторые фишки в вар3
например выдача невидимых предметов
и вообще я хз кто научил вас юзать бж переменные
как по мне за такое расстреливать надо
0
21
7 лет назад
0
nvc123, хы, лучше не буду говорить кто..)) вы все его знаете.
А за пояснения спасибо.
nvc123, хотел задать ещё один вопрос по выше написанному коду:
Если внутри функции GroupCallback() вызвать функцию GetAttacker(), то она почему-то возвращает того атакующего юнита, которого я пытался передать с помощью глобальных переменных. Это нормально вообще? Если всё и так работает, то зачем передавать данные с помощью глобальных переменных, когда можно получить юнитов с помощью подобных функции?
Чтобы оставить комментарий, пожалуйста, войдите на сайт.