Добавлен , опубликован
Дисклеймер!
Я полный нуб/лох/помойка в джассе (называйте как хотите), ничего толком не знаю и короче юзай способность на свой страх и риск. По возможности буду стараться оптимизировать это говно
Цель: мгновенное (без цели)
Тип: АОЕ урон
Суть: наш герой достаёт щиточек прямиком с трущоб моей комнаты и ставит его над головой, сила вони не даёт противникам проникнуть внутрь
Подходит как для обычного юнита, так и для героя
Текущие настройки:
  • Встроение своей хэш-таблицы
  • ID способности
  • ID дамми-юнита
  • Радиус урона барьера
  • Начальный радиус урона барьера
  • Доп. радиус урона барьера с уровнем
  • Скорость роста радиуса
  • Базовый урон барьера
  • Доп. урон барьера с уровнем
  • Скейл урона от силы
  • Скейл урона от ловкости
  • Скейл урона от интеллекта
  • вкл|выкл бонусы к характеристикам
  • Максимальная высота барьера (для летающих юнитов или тех, кто на возвышенности)
  • Доп. высота барьера с уровнем
  • цилиндр|сфера (барьер)
  • Время барьера
  • Доп. время барьера с уровнем
  • вкл|выкл изменение анимации через время
  • Время, через которое изменяется скорость анимации барьера
  • Скорость анимации
  • Тип атаки
  • Тип урона
  • Тип оружия (звук)
  • Максимальный масштаб барьера
  • Начальный мастшаб барьера
  • Доп. мастштаб барьера с уровнем
  • Скорость роста масштаба барьера
  • вкл|выкл эффекты при попадании
  • Эффект при попадании (дамми)
  • Время удаления эффекта
  • Скорость угасания эффекта (255/Время удаления эффекта*0.03, можешь поставить 0, чтобы не было никакого угасания)
  • вкл|выкл дебафф
  • Равкод удаляемого дебаффа
  • Время удаления дебаффа
  • Доп. время удаления дебаффа с уровнем
  • Дамми со способностью, которая накладывает дебафф
  • Время удаления дамми
  • Текст - Порядок строк: включён (Order) способности дебаффа у даммика
  • Свободная ячейка детского ключа юнита
  • Доп. свободная ячейка детского ключа юнита
  • вкл|выкл эффекты при попадании
  • Эффект при попадании
  • Точка крепления эффекта
  • Время удаления эффекта
  • Возвышение барьера над землёй
  • Доп. отталкивание барьера, когда он достигает макс. радиуса (чтобы не получать х2 урон)
Код
scope MySc
globals
define private Hash = udg_Hash // Название твоей хэш-таблицы

define private AbilityID = 'A000' // ID способности
define private DummyID = 'u000' // ID дамми-юнита

define private BarrierMaxRadius = 500.00 // Радиус урона барьера
define private BarrierMinRadius = 200.00 // Начальный радиус урона барьера
define private BarrierMaxRadiusLvl = 100.00 // Доп. радиус урона барьера с уровнем
define private BarrierRadiusGrowth = 15.00 /* Скорость роста радиуса */ *3
define private BarrierDamage = 5.00 // Базовый урон барьера
define private BarrierDamageLvl = 5.00 // Доп. урон барьера с уровнем
define private DamageScaleStr = 0.00 // Скейл урона от силы
define private DamageScaleAgi = 0.00 // Скейл урона от ловкости
define private DamageScaleInt = 1.00 // Скейл урона от интеллекта
define private IncludeBonuses = true // true|false - вкл|выкл бонусы к характеристикам

define private BarrierHeight = 500.00 // Максимальная высота барьера (для летающих юнитов или тех, кто на возвышенности)
define private BarrierHeightLvl = 100.00 // Доп. высота барьера с уровнем
define private BarrierSphereTF = 1 // 0|1 - цилиндр|сфера (барьер)

define private BarrierTime = 3.00 // Время барьера
define private BarrierTimeLvl = 1.00 // Доп. время барьера с уровнем

define private BarrierAnimationTF = 1 // 0|1 - выкл|вкл изменение анимации через время
define private BarrierAnimation = 1.000 // Время, через которое изменяется скорость анимации барьера
define private BarrierAnimationSpeed = 0.09 // Скорость анимации (1.00 = 100%)

define private AttackType = ATTACK_TYPE_NORMAL // Тип атаки
define private DamageType = DAMAGE_TYPE_NORMAL // Тип урона
define private WeaponType = WEAPON_TYPE_WHOKNOWS // Тип оружия (звук)

define private BarrierMaxScale = 4.00 // Максимальный масштаб барьера
define private BarrierMinScale = 0.25 // Начальный мастшаб барьера
define private BarrierMaxScaleLvl = 1.00 // Доп. мастштаб барьера с уровнем
define private BarrierGrowthSpeed = 0.15 /* Скорость роста масштаба барьера */  *3

define private SpecEffectTF = 1 // 0|1 - выкл|вкл эффекты при попадании
define private SpecEffect = 'u001' // Эффект при попадании (дамми)
define private SpecEffectRemoveTime = 1.00 // Время удаления эффекта
define private SpecEffectShowVis = 2.55 // Скорость угасания эффекта (255/Время удаления эффекта*0.01, можешь поставить 0, чтобы не было никакого угасания)
define private SpecEffectThreshold = 50.00 // Дальность спецэффекта от юнита в сторону барьера

define private DebuffTF = 1 // 0|1 - выкл|вкл дебафф
define private DebuffID = 'BPSE' // Равкод удаляемого дебаффа
define private DebuffRemoveTime = 0.50 // Время удаления дебаффа
define private DebuffRemoveTimeLvl = 0.00 // Доп. время удаления дебаффа с уровнем
define private DummyWithDebuffAbility = 'u002' // Дамми со способностью, которая накладывает дебафф
define private DummyLife = 0.50 // Время удаления дамми
define private Order = "thunderbolt" // Текст - Порядок строк: включён (Order) способности дебаффа у даммика
define private H = 0 // Свободная ячейка детского ключа юнита
define private H1 = 1 // Доп. свободная ячейка детского ключа юнита
/* Если ты не помнишь или не знаешь свободные ячейки юнита, если у тебя идёт очистка хэш-таблицы юнита, то лучше
выключить дебафф, иначе значения могут перезаписаться/очиститься и в твоей карте начнутся баги при касте этой абилки*/

define private EffectTF = 0 // 0|1 - выкл|вкл эффекты при попадании
define private Effect = "Abilities\\Spells\\Other\\CrushingWave\\CrushingWaveDamage.mdl" // Эффект при попадании
define private AttachPoint = "origin" // Точка крепления эффекта
define private EffectRemoveTime = 1.00 // Время удаления эффекта

define private BarrierGroundHeight = 300.00 // Возвышение барьера над землёй

define private BarrierDiscardingMaxR = 15.00 // Доп. отталкивание барьера, когда он достигает макс. радиуса (чтобы не получать х2 урон)

private location LocationForGetZ = Location(0,0)
endglobals
//==========================================================================
private function IsUnitDead takes unit u returns boolean
	return IsUnitType(u,UNIT_TYPE_DEAD) or GetUnitTypeId(u) == 0
endfunction

private function myfilt takes nothing returns boolean // Условия кому будет наносится урон, на данный момент: Юнит жив, юнит враг применяющему юниту, юнит не здание
    set bj_lastReplacedUnit = GetFilterUnit()
    return not IsUnitDead(bj_lastReplacedUnit) and IsUnitEnemy(bj_lastReplacedUnit,bj_groupEnumOwningPlayer) and not IsUnitType(bj_lastReplacedUnit,UNIT_TYPE_STRUCTURE)
endfunction

function GetUnitZ takes unit u returns real
    call MoveLocation(LocationForGetZ, GetUnitX(u), GetUnitY(u))
    return GetLocationZ(LocationForGetZ) + GetUnitFlyHeight(u)
endfunction

private function DistanceBetweenCoordinates takes real x, real y, real x1, real y1 returns real
   return SquareRoot((x-x1)*(x-x1)+(y-y1)*(y-y1)) 
endfunction 

private function shw takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer i = GetHandleId(t)
    local real k = LoadReal(Hash,i,1)+SpecEffectShowVis
    local unit u = LoadUnitHandle(Hash,i,0)
    if IsUnitDead(u) or 255-k <= 0 then
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(Hash,i)
    else
        call SetUnitVertexColor(u,255,255,255,R2I(255-k))
        call SaveReal(Hash,i,1,k)
    endif
    set t = null
    set u = null
endfunction

private function remeff takes nothing returns nothing
    local timer t = GetExpiredTimer()
    call DestroyEffect(LoadEffectHandle(Hash,GetHandleId(t),0))
    call FlushChildHashtable(Hash,GetHandleId(t))
    call DestroyTimer(t)
    set t = null
endfunction

private function remdeb takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local unit u = LoadUnitHandle(Hash,GetHandleId(t),0)
    if LoadReal(Hash,GetHandleId(u),H1) <= 0. then
        call UnitRemoveAbility(LoadUnitHandle(Hash,GetHandleId(t),0),DebuffID)
        call SaveInteger(Hash,GetHandleId(u),H,0)
        call FlushChildHashtable(Hash,GetHandleId(t))
        call PauseTimer(t)
        call DestroyTimer(t)
    else
        call SaveReal(Hash,GetHandleId(u),H1,LoadReal(Hash,GetHandleId(u),H1)-0.01)
    endif
    set t = null
    set u = null
endfunction

private function CopyGroup takes group g returns group
    set bj_groupAddGroupDest = CreateGroup()
    call ForGroup(g, function GroupAddGroupEnum)
    return bj_groupAddGroupDest
endfunction

private function xz takes unit u, unit uu, real H4, group g, real H11, real Hx1, real r returns nothing
    local real x = GetUnitX(uu)
    local real y = GetUnitY(uu)
    local real a = Atan2(y-GetUnitY(u),x-GetUnitX(u))
    local timer tt = null
    local pathingtype pt = null
    
    if IsUnitType(uu,UNIT_TYPE_GROUND) then
        set pt = PATHING_TYPE_WALKABILITY
    else
        set pt = PATHING_TYPE_FLYABILITY
    endif
            
    if not IsTerrainPathable(x+BarrierRadiusGrowth*Cos(a),y+BarrierRadiusGrowth*Sin(a),pt) then
        call SetUnitX(uu,x+BarrierRadiusGrowth*Cos(a))
        call SetUnitY(uu,y+BarrierRadiusGrowth*Sin(a))
        if r < H4 then
            if not IsUnitInGroup(uu,g) then
                call UnitDamageTarget(u,uu,Hx1,true,false,AttackType,DamageType,WeaponType)
                call GroupAddUnit(g,uu)
            endif
        else
            if BarrierDiscardingMaxR > 0.00 then
                if not IsTerrainPathable(x+BarrierDiscardingMaxR*Cos(a),y+BarrierDiscardingMaxR*Sin(a),pt) then
                    call SetUnitX(uu,GetUnitX(uu)+BarrierDiscardingMaxR*Cos(a))
                    call SetUnitY(uu,GetUnitY(uu)+BarrierDiscardingMaxR*Sin(a))
                endif
            endif
            if SpecEffectTF == 1 then
                set tt = CreateTimer()
                set bj_lastCreatedUnit = CreateUnit(GetOwningPlayer(u),SpecEffect,GetUnitX(uu),GetUnitY(uu),a*bj_RADTODEG)
                call SetUnitPathing(bj_lastCreatedUnit,false)
                set a = Atan2(GetUnitY(u)-y,GetUnitX(u)-x)
                call SetUnitX(bj_lastCreatedUnit,GetUnitX(uu)+SpecEffectThreshold*Cos(a))
                call SetUnitY(bj_lastCreatedUnit,GetUnitY(uu)+SpecEffectThreshold*Sin(a))
                call UnitApplyTimedLife(bj_lastCreatedUnit,'BTLF',SpecEffectRemoveTime)
                call UnitAddAbility(bj_lastCreatedUnit,'Arav')
                call SetUnitFlyHeight(bj_lastCreatedUnit,GetUnitZ(uu),0)
                call SaveUnitHandle(Hash,GetHandleId(tt),0,bj_lastCreatedUnit)
                call TimerStart(tt,0.01,true,function shw)
                set tt = null
            endif
            call UnitDamageTarget(u,uu,Hx1,true,false,AttackType,DamageType,WeaponType)
        endif
    endif
            
    if DebuffTF == 1 then
        call SaveReal(Hash,GetHandleId(uu),H1,H11)
        if LoadInteger(Hash,GetHandleId(uu),H) == 0 then
            call SaveInteger(Hash,GetHandleId(uu),H,1)
            set tt = CreateTimer()
            set bj_lastCreatedUnit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DummyWithDebuffAbility,GetUnitX(uu),GetUnitY(uu),GetUnitFacing(uu))
            call SetUnitPathing(bj_lastCreatedUnit,false)
            call UnitApplyTimedLife(bj_lastCreatedUnit,'BTLF',DummyLife)
            call IssueTargetOrder(bj_lastCreatedUnit,Order,uu)
            call SaveUnitHandle(Hash,GetHandleId(tt),0,uu)
            call TimerStart(tt,0.01,true,function remdeb)
            set bj_lastCreatedUnit = null
            set tt = null
        endif            
    endif
        
    if EffectTF == 1 then
        set tt = CreateTimer()
        call SaveEffectHandle(Hash,GetHandleId(tt),0,AddSpecialEffectTarget(Effect,uu,AttachPoint))
        call TimerStart(tt,EffectRemoveTime,false,function remeff)
        set tt = null
    endif
    
    set pt = null
endfunction

private function move takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local timer tt = null
    local integer i = GetHandleId(t)
    local unit u = LoadUnitHandle(Hash,i,0)
    local unit uu = null
    local real tm = LoadReal(Hash,i,3)+0.03
    local real r = LoadReal(Hash,i,7)+BarrierRadiusGrowth
    local real q = LoadReal(Hash,i,8)+BarrierGrowthSpeed
    local group g = LoadGroupHandle(Hash,i,10)
    local group gg = CreateGroup()
    
    if BarrierAnimationTF == 1 and tm >= BarrierAnimation and LoadInteger(Hash,i,9) == 0 then
        call SetUnitTimeScale(u,BarrierAnimationSpeed)
        call SaveInteger(Hash,i,9,1)
    endif
    
    if BarrierMinScale+q < LoadReal(Hash,i,6) then
        call SetUnitScale(u,BarrierMinScale+q,BarrierMinScale+q,BarrierMinScale+q)
    endif
    
    set bj_groupEnumOwningPlayer = GetOwningPlayer(u)
    if BarrierMinRadius+r <= LoadReal(Hash,i,4) then
        call GroupEnumUnitsInRange(gg,GetUnitX(u),GetUnitY(u),BarrierMinRadius+r,Condition(function myfilt))
    else
        call GroupEnumUnitsInRange(gg,GetUnitX(u),GetUnitY(u),LoadReal(Hash,i,4),Condition(function myfilt))
    endif
    set bj_groupEnumOwningPlayer = null
    
    loop
        set uu = FirstOfGroup(gg)
        exitwhen uu == null
        if GetUnitZ(uu) <= (LoadReal(Hash,i,12)-DistanceBetweenCoordinates(GetUnitX(u),GetUnitY(u),GetUnitX(uu),GetUnitY(uu)))/LoadReal(Hash,i,12)*LoadReal(Hash,i,12) and BarrierSphereTF == 1 then
            call xz(u,uu,LoadReal(Hash,i,4),g,LoadReal(Hash,i,11),LoadReal(Hash,i,1),r)
        elseif BarrierSphereTF != 1 then
            call xz(u,uu,LoadReal(Hash,i,4),g,LoadReal(Hash,i,11),LoadReal(Hash,i,1),r)
        endif
        call GroupRemoveUnit(gg,uu)
        set uu = null
    endloop
    
    if tm >= LoadReal(Hash,i,2) then
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(Hash,i)
        call GroupClear(g)
        call DestroyGroup(g)
        if BarrierAnimationTF == 1 then
            call SetUnitTimeScale(u,1.)
        endif
        call KillUnit(u)
    else
        call SaveReal(Hash,i,3,tm)
        call SaveReal(Hash,i,8,q)
        call SaveReal(Hash,i,7,r)
    endif
    
    call DestroyGroup(gg)
    set g = null
    set gg = null
    set u = null
    set t = null
endfunction

private function Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local integer i = GetHandleId(t)
    local unit u = GetSpellAbilityUnit()
    local integer lvl = GetUnitAbilityLevel(u,AbilityID)
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local group g = CreateGroup()
    
    set bj_lastCreatedUnit = CreateUnit(GetOwningPlayer(u),DummyID,x,y,0)
    call SetUnitPathing(bj_lastCreatedUnit,false)
    call UnitAddAbility(bj_lastCreatedUnit,'Arav')
    call SetUnitFlyHeight(bj_lastCreatedUnit,BarrierGroundHeight,0.)
    call SetUnitScale(bj_lastCreatedUnit,BarrierMinScale,BarrierMinScale,BarrierMinScale)
    call SaveUnitHandle(Hash,i,0,bj_lastCreatedUnit)
    call SaveReal(Hash,i,1,BarrierDamage+(lvl*BarrierDamageLvl)+(GetHeroStr(u,IncludeBonuses)*DamageScaleStr)+(GetHeroAgi(u,IncludeBonuses)*DamageScaleAgi)+(GetHeroInt(u,IncludeBonuses)*DamageScaleInt))
    call SaveReal(Hash,i,2,BarrierTime+(BarrierTimeLvl*lvl))
    call SaveReal(Hash,i,4,BarrierMaxRadius+(BarrierMaxRadiusLvl*lvl))
    call SaveReal(Hash,i,5,((BarrierMaxRadius+(BarrierMaxRadiusLvl*lvl))-BarrierMinRadius)*0.02)
    call SaveReal(Hash,i,6,BarrierMaxScale-BarrierMinScale+(BarrierMaxScaleLvl*lvl))
    call SaveReal(Hash,i,11,DebuffRemoveTime+(DebuffRemoveTimeLvl*lvl))
    call SaveReal(Hash,i,12,BarrierHeight+(BarrierHeightLvl*lvl))
    call SaveGroupHandle(Hash,i,10,g)
    call TimerStart(t,0.03,true,function move)
    
    set bj_lastCreatedUnit = null
    set g = null
    set t = null
    set u = null
endfunction

//===========================================================================
private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == AbilityID
endfunction

function InitTrig_Phoenix takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer index = 0
    loop
        call TriggerRegisterPlayerUnitEvent(t,Player(index),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    call TriggerAddCondition(t,Condition(function Conditions))
    call TriggerAddAction(t,function Actions)
    set t = null
endfunction
endscope
26.12.2020 - обновленная карта в комментах
В планах:
Заменить SetUnitX|Y на SetUnitPosition (это должно очень сильно облегчить код)
Если при запуске карты через редактор тебя выбивает в главное меню, то включи JassHelper (если он выключен) и просто нажми Ctrl+S в редакторе, если возникнет ошибка, пожалуйста, сделай скрин и пришли мне, если ошибки не будет, то после этого карта должна запустится
`
ОЖИДАНИЕ РЕКЛАМЫ...
28
Планирую добавить отключение зданий внутри этого барьера
28
Нашел много недоработок, например то, что барьер откидывает вне радиуса юнитов
Так же планирую сделать особенность для летающих юнитов, барьер всё-таки сферический, а не цилиндрический
28
Обнова (кому она нужна в принципе)
+ Переменные в дефайны (это типо оптимизация)
+ Исправлена ошибка с отталкиванием при росте барьера
+ Максимальная высота барьера (для сферического (и то, я не уверен, что у меня правильная формула))
+ Барьер может быть теперь земноводным, полёт настраивается в самом триггере
+ "Исправлена" ошибка с двойным уроном, таймер увеличен и добавлены настройки с дополнительным отталкиванием (юниты всё равно могут получить двойной урон, если оттолкнутся один в другого)
+ Юнитов не отталкивает в непроходимые зоны
+ Юниты, которых нельзя выкинуть с барьера, не получают кучу урона, вместо этого обновляется время дебаффа
- Специальный эффект (дамми) может криво спавнится на горах
- Очень сложно настроить барьер до оптимального значения, всё делается на ощупь (из-за плохого кода)
- Я не проверял все настройки, поэтому что-то может не работать (оч извиняюсь, но это рили много времени жрёт (исправлю, если кто-то напишет))
- Нет возможности добавить собственные условия без малейшего знания джасса (постараюсь что-нибудь придумать с этим в будущем)
- Некоторые значения лучше не ставить ниже единицы
- Минусовое значение урона не будет хилять (в будущем добавлю)
- Минусов больше, чем плюсов, я забыл остальные)
Код и настройки обновил в посте
Загруженные файлы
32
Ну мб взять для начала тетрадный листик, описать все что ты хочешь, а потом по шагам воплотить в виде кода, тогда не будет мешанины и говнокода.
28
quq_CCCP, точно, но идеи приходят не сразу, да и в принципе нужно учить вектора. К сожалению, не справляюсь, очень разочарован в себе)
18
rsfghd:
Заменить SetUnitX|Y на SetUnitPosition
SetUnitPosition сбивает приказы, я бы на координатах оставил. Но, с другой стороны, сбитый приказ можно считать эффектом от удара щита)
28
Maniac_91, вау
Мне даже как-то на душе теплее, что тут такие гости)
Чтобы оставить комментарий, пожалуйста, войдите на сайт.