Добавлен , опубликован
Дисклеймер!
Я полный нуб/лох/помойка в джассе (называйте как хотите), ничего толком не знаю и короче юзай способность на свой страх и риск. По возможности буду стараться оптимизировать это говно
Цель: мгновенное (без цели)
Тип: АОЕ урон
Суть: наш герой достаёт щиточек прямиком с трущоб моей комнаты и ставит его над головой, сила вони не даёт противникам проникнуть внутрь
Подходит как для обычного юнита, так и для героя
Текущие настройки:
  • Встроение своей хэш-таблицы
  • 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 в редакторе, если возникнет ошибка, пожалуйста, сделай скрин и пришли мне, если ошибки не будет, то после этого карта должна запустится
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
27
3 года назад
0
Планирую добавить отключение зданий внутри этого барьера
0
27
3 года назад
Отредактирован rsfghd
0
Нашел много недоработок, например то, что барьер откидывает вне радиуса юнитов
Так же планирую сделать особенность для летающих юнитов, барьер всё-таки сферический, а не цилиндрический
0
27
3 года назад
Отредактирован rsfghd
0
Обнова (кому она нужна в принципе)
+ Переменные в дефайны (это типо оптимизация)
+ Исправлена ошибка с отталкиванием при росте барьера
+ Максимальная высота барьера (для сферического (и то, я не уверен, что у меня правильная формула))
+ Барьер может быть теперь земноводным, полёт настраивается в самом триггере
+ "Исправлена" ошибка с двойным уроном, таймер увеличен и добавлены настройки с дополнительным отталкиванием (юниты всё равно могут получить двойной урон, если оттолкнутся один в другого)
+ Юнитов не отталкивает в непроходимые зоны
+ Юниты, которых нельзя выкинуть с барьера, не получают кучу урона, вместо этого обновляется время дебаффа
- Специальный эффект (дамми) может криво спавнится на горах
- Очень сложно настроить барьер до оптимального значения, всё делается на ощупь (из-за плохого кода)
- Я не проверял все настройки, поэтому что-то может не работать (оч извиняюсь, но это рили много времени жрёт (исправлю, если кто-то напишет))
- Нет возможности добавить собственные условия без малейшего знания джасса (постараюсь что-нибудь придумать с этим в будущем)
- Некоторые значения лучше не ставить ниже единицы
- Минусовое значение урона не будет хилять (в будущем добавлю)
- Минусов больше, чем плюсов, я забыл остальные)
Код и настройки обновил в посте
Загруженные файлы
1
32
3 года назад
1
Ну мб взять для начала тетрадный листик, описать все что ты хочешь, а потом по шагам воплотить в виде кода, тогда не будет мешанины и говнокода.
0
27
3 года назад
0
quq_CCCP, точно, но идеи приходят не сразу, да и в принципе нужно учить вектора. К сожалению, не справляюсь, очень разочарован в себе)
2
18
3 года назад
2
rsfghd:
Заменить SetUnitX|Y на SetUnitPosition
SetUnitPosition сбивает приказы, я бы на координатах оставил. Но, с другой стороны, сбитый приказ можно считать эффектом от удара щита)
0
27
3 года назад
0
Maniac_91, вау
Мне даже как-то на душе теплее, что тут такие гости)
Чтобы оставить комментарий, пожалуйста, войдите на сайт.