28

» Блог им. rsfghd / Спеллпак Приватника Ада

Эль_Кин, ахаха, спасибо))
На самом деле на этот прогресс ушло куда больше времени и недоскиллов, но я всё равно не доволен результатом. Типо всё что в этой карте - банальщина, видели миллион раз, так оно ещё и криво написано)
Думаю мне просто нужна конструктивная критика с предложениями как можно сделать лучше
28

» WarCraft 3 / Система создания предметов

Librarian, а, ресурсы в инвентарь в виде предметов кладутся? С зарядами? Я уже делал нечто подобное, но честно говоря, я не помню как и что там устроено)
Могу наклепать позже, если никто не преуспеет
28

» WarCraft 3 / Не срабатывает событие на изменение real var. Игнор строки кода.

NatriY, попробуй на отдельной карте то же самое сделать, так легче понять где именно кроется проблема
28

» WarCraft 3 / Способности и алгоритмы на заказ

Вот, вместо переменной LastCaster можно использовать юнита триггера, а в качестве целей - источник повреждения (искл. прыжок, там только кастер), думаю теперь чуть больше возможностей открылось. Однако для этого в триггер нужно зарегистрировать событие, что юниты получают урон
Загруженные файлы
28

» WarCraft 3 / Способности и алгоритмы на заказ

Простите за абилки, я переделаю под получение юнитом урона, урон можно будет самому настраивать непосредственно при получении нулевого урона, перед нанесением будет выставлено определенное число глобальной переменной, никакого даммикаста, проверять нужно будет только эту целочисленную
28

» WarCraft 3 / Странное поведение функции

map_maiker, тьфу, я думал там наоборот, число 10 это степень. Мда, потопал я отсюда
28

» WarCraft 3 / Странное поведение функции

Загуглил возведение в степень отрицательного числа, там пишут, что при возведении отрицательного числа в четную степень, число станет положительным
28

» WarCraft 3 / Странное поведение функции

Я в математике не силен, но попробуй сначала разницу уровней вычитать, если она минусовая, то 1 опыта дать, если плюсовая, то сделать вот ту твою фигню с Pow
28

» Блог им. rsfghd / Спеллпак Приватника Ада

Готово. Можно было бы ещё добавить деформацию ланда для ульты, но на больших картах оно лагает. Повторюсь, это не для импорта, ибо никаких настроек по использованию и разбора кода я не оставлял. Просто посмотреть на возможности джасса если кому интересно. Мотивация так сказать
хотя кого это говнище мотивировать будет, лол)
upd в видео музыка
Код

library mylib initializer init
    private hashtable H = InitHashtable()
    private trigger trg = CreateTrigger()
    private group TempG = CreateGroup()
    private group TempG1 = CreateGroup()
    private unit CUEX = null
    private real TempR
    private real TempR1
    private real TempR2
    private real TempR3
    private real TempX
    private real TempY
    private integer TF = 0
    private integer TF1 = 0
    private boolean FireID
    private damagetype DamageType
    // Переменные быстрого доступа управления полётом апокалиптического дождя
    private constant real RainFly = 600
    private constant real RainFlyD = 100
    // Воспомогательные функции
    private function Kill takes nothing returns nothing
        call KillUnit(GetEnumUnit())
    endfunction
    
    private function IsUnitDead takes unit u returns boolean
        return IsUnitType(u,UNIT_TYPE_DEAD) or GetUnitTypeId(u) < 1
    endfunction
    
    private function CreateUnitEx takes player id, integer unitid, real x, real y, real face returns unit
        set CUEX = CreateUnit(id,unitid,x,y,face)
        call SetUnitPathing(CUEX,false)
        call SetUnitX(CUEX,x)
        call SetUnitY(CUEX,y)
        return CUEX
    endfunction
    
    private function li takes nothing returns boolean
        return not IsUnitDead(GetFilterUnit()) and GetUnitTypeId(GetFilterUnit()) != 'u000'
    endfunction
    
    private function DBC takes real x, real y, real x1, real y1 returns real
        return SquareRoot((x-x1)*(x-x1)+(y-y1)*(y-y1)) 
    endfunction 
    
    private function IsPointInSector takes real x1, real y1, real x2, real y2, real orientation, real width, real radius returns boolean
        local real lenght = DBC(x1,y1,x2,y2)
        local real angle = Acos(Cos(orientation*bj_DEGTORAD)*(x1-x2)/lenght+Sin(orientation*bj_DEGTORAD)*(y1-y2)/lenght )*bj_RADTODEG
        return angle<=width and lenght<=radius
    endfunction
    
    private function SetUnitPositionEx takes unit u, real x, real y returns nothing
        local item i = CreateItem('spsh',x,y)
        set TempX = GetItemX(i)
        set TempY = GetItemY(i)
        set TempR = DBC(x,y,TempX,TempY)
        if TempR > 10 then
            call SetUnitX(u,TempX)
            call SetUnitY(u,TempY)
        else
            call SetUnitX(u,x)
            call SetUnitY(u,y)
        endif
        call RemoveItem(i)
        set i = null
    endfunction
    
    //===================================================
        // Пламя преисподней
    private function UnderworldFlamesDMG takes nothing returns nothing
        local timer t=GetExpiredTimer()
        local integer timerH=GetHandleId(t)
        local unit caster=LoadUnitHandle(H,timerH,1)
        local unit target=LoadUnitHandle(H,timerH,2)
        local integer casterH=GetHandleId(caster)
        local integer targetH=GetHandleId(target)
        local integer level=LoadInteger(H,timerH,3)
        local integer counter=LoadInteger(H,targetH,casterH)
        local real dmg = LoadReal(H,timerH,0)

        call SaveInteger(H,targetH,casterH,counter-1)
        set TF = 1
        call UnitDamageTarget(caster,target,dmg,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_FIRE,null)
        set TF = 0
        if counter == 1 or IsUnitDead(target) or GetUnitAbilityLevel(target,'B000') < 1 then
            call UnitRemoveAbility(target,'A000')
            call UnitRemoveAbility(target,'B000')
            call RemoveSavedInteger(H,targetH,casterH)
            call FlushChildHashtable(H,timerH)
            call PauseTimer(t)
            call DestroyTimer(t)
        endif
        
        set t=null
        set caster=null
        set target=null
    endfunction
    
    private function UnderworldFlames takes unit u, unit u1 returns nothing
        local integer casterH=GetHandleId(u)
        local integer targetH=GetHandleId(u1)
        local integer lvl=GetUnitAbilityLevel(u,'A005')
        local integer timerH
        local integer counter=LoadInteger(H,targetH,casterH)
        local integer tm
        local timer t
        local real dmg
        
        if lvl == 1 then
            set dmg = 5.
            set tm = 3
        elseif lvl == 2 then
            set dmg = 15.
            set tm = 5
        elseif lvl == 3 then
            set dmg = 20.
            set tm = 6
        endif
        set dmg = dmg+(GetHeroInt(u,true)*.1)
        if counter == 0 then
            call UnitAddAbility(u1,'A000')
            set t = CreateTimer()
            set timerH = GetHandleId(t)
            call SaveReal(H,timerH,0,dmg)
            call SaveUnitHandle(H,timerH,1,u)
            call SaveUnitHandle(H,timerH,2,u1)
            call SaveInteger(H,timerH,3,lvl)
            call TimerStart(t,1.,true,function UnderworldFlamesDMG)
            set t=null
        endif
        
        call SaveInteger(H,targetH,casterH,tm)
    endfunction
    // Планетарное разрушение
    private function PlanetaryDestructionCond takes nothing returns boolean
        set bj_lastReplacedUnit = GetFilterUnit()
        return not IsUnitDead(bj_lastReplacedUnit) and not IsUnitType(bj_lastReplacedUnit,UNIT_TYPE_MAGIC_IMMUNE) and IsUnitEnemy(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit)) and not IsUnitInGroup(bj_lastReplacedUnit,TempG1)
    endfunction
    private function PlanetaryDiscarding takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer i = GetHandleId(t)
        local unit u = LoadUnitHandle(H,i,0)
        local real a = LoadReal(H,i,2)
        local real s = LoadReal(H,i,6)
        local real tm = LoadReal(H,i,4)+.02
        
        call SetUnitPositionEx(u,GetUnitX(u)+s*Cos(a),GetUnitY(u)+s*Sin(a))
        
        if TempR > 10 and not IsUnitDead(u) then
            call DestroyEffect(AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl",GetUnitX(u),GetUnitY(u)))
            set TF = 1
            call UnitDamageTarget(LoadUnitHandle(H,i,3),u,LoadReal(H,i,1),false,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_SONIC,null)
            set TF = 0
            if not IsUnitDead(u) then
                call CreateUnitEx(Player(15),'u007',GetUnitX(u),GetUnitY(u),0)
                call UnitAddAbility(CUEX,'A008')
                call IssueTargetOrder(CUEX,"thunderbolt",u)
                call UnitApplyTimedLife(CUEX,'BTLF',1)
            endif
        endif
        if TempR > 10 or tm > LoadReal(H,i,5) or GetUnitTypeId(u) < 1 then
            call PauseTimer(t)
            call DestroyTimer(t)
            call FlushChildHashtable(H,i)
        else
            call SaveReal(H,i,4,tm)
        endif
        
        set t = null
        set u = null
    endfunction
    private function PlanetaryDestructionDmg takes nothing returns nothing
        local unit u = GetEnumUnit()
        local timer t
        local integer i
        local real x
        local real y
        local real dc
        local real tm
        
        call UnitDamageTarget(bj_lastCreatedUnit,u,TempR1,false,false,ATTACK_TYPE_MAGIC,DamageType,null)
        if not IsUnitDead(u) then
            set x = GetUnitX(u)
            set y = GetUnitY(u)
            call CreateUnitEx(Player(15),'u007',x,y,0)
            if TF1 == 0 then
                call UnitAddAbility(CUEX,'A008')
                call IssueTargetOrder(CUEX,"thunderbolt",u)
                call UnitApplyTimedLife(CUEX,'BTLF',1)
            else
                call UnitAddAbility(CUEX,'A009')
                call IssueTargetOrder(CUEX,"slow",u)
                call UnitApplyTimedLife(CUEX,'BTLF',1)
                set t = CreateTimer()
                set i = GetHandleId(t)
                call SaveUnitHandle(H,i,0,u)
                call SaveReal(H,i,1,TempR1*.5)
                call SaveReal(H,i,2,Atan2(y-TempR3,x-TempR2))
                call SaveUnitHandle(H,i,3,bj_lastCreatedUnit)
                if GetUnitAbilityLevel(u,'A002') > 0 then
                    set tm = .1
                    set dc = 7.5
                elseif GetUnitAbilityLevel(u,'A003') > 0 then
                    set tm = .5
                    set dc = 10.
                else
                    set tm = .5
                    set dc = 15.
                endif
                call SaveReal(H,i,5,tm)
                call SaveReal(H,i,6,dc)
                call TimerStart(t,.02,true,function PlanetaryDiscarding)
                set t = null
            endif
            if FireID then
                call UnderworldFlames(bj_lastCreatedUnit,u)
            endif
            call GroupAddUnit(TempG1,u)
        endif
        
        set u = null
    endfunction
    private function PlanetaryDestructionAct takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer i = GetHandleId(t)
        local unit u = LoadUnitHandle(H,i,1)
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        local real dmg = LoadReal(H,i,4)
        set FireID = LoadBoolean(H,i,3)
        if FireID then
            call KillUnit(CreateUnitEx(Player(15),'u00A',x,y,GetRandomReal(0,360)))
        endif
        set TempR1 = dmg*2
        set TempR2 = x
        set TempR3 = y
        set TF = 1
        
        set DamageType = DAMAGE_TYPE_DEMOLITION
        set bj_lastCreatedUnit = LoadUnitHandle(H,i,0)
        call GroupEnumUnitsInRange(TempG,x,y,200,Condition(function PlanetaryDestructionCond))
        call ForGroup(TempG,function PlanetaryDestructionDmg)
        call GroupClear(TempG)
        
        set TempR1 = dmg
        set TF1 = 1
        set DamageType = DAMAGE_TYPE_SONIC
        call GroupEnumUnitsInRange(TempG,x,y,500,Condition(function PlanetaryDestructionCond))
        call ForGroup(TempG,function PlanetaryDestructionDmg)
        call GroupClear(TempG)
        call GroupClear(TempG1)
        set TF = 0
        set TF1 = 0
        
        call KillUnit(CreateUnitEx(Player(15),'u003',x,y,GetRandomReal(0,360)))
        call KillUnit(CreateUnitEx(Player(15),'u00C',x,y,GetRandomReal(0,360)))
        call KillUnit(CreateUnitEx(Player(15),'u00B',x,y,GetRandomReal(0,360)))
        call KillUnit(CreateUnitEx(Player(15),'u009',x,y,GetRandomReal(0,360)))
        call KillUnit(CreateUnitEx(Player(15),'u008',x,y,GetRandomReal(0,360)))
        call KillUnit(u)
        call KillUnit(LoadUnitHandle(H,i,2))
        
        call DestroyFogModifier(LoadFogModifierHandle(H,i,5))
        call DestroyTimer(t)
        call FlushChildHashtable(H,i)
        
        set bj_lastCreatedUnit = null
        set t = null
        set u = null
    endfunction
    private function PlanetaryDestruction takes nothing returns nothing
        local timer t = CreateTimer()
        local integer i = GetHandleId(t)
        local unit u = GetTriggerUnit()
        local real x = GetSpellTargetX()
        local real y = GetSpellTargetY()
        local real dmg = 300+(GetHeroInt(u,true))
        
        set FireID = GetUnitAbilityLevel(u,'B001') > 0
        if FireID then
            set dmg = dmg+(dmg*(.05*GetUnitAbilityLevel(u,'A005')))
        endif
        
        set bj_groupEnumOwningPlayer = GetOwningPlayer(u)
        set bj_lastCreatedFogModifier = CreateFogModifierRadius(bj_groupEnumOwningPlayer,FOG_OF_WAR_VISIBLE,x,y,1000, true, false)
        call FogModifierStart(bj_lastCreatedFogModifier)
        
        call SaveUnitHandle(H,i,0,u)
        call SaveUnitHandle(H,i,1,CreateUnitEx(bj_groupEnumOwningPlayer,'u006',x,y,bj_RADTODEG*Atan2(y-GetUnitY(u),x-GetUnitX(u))))
        call SaveUnitHandle(H,i,2,CreateUnitEx(bj_groupEnumOwningPlayer,'u006',x,y,bj_RADTODEG*Atan2(y-GetUnitY(u),x-GetUnitX(u))))
        call SaveBoolean(H,i,3,FireID)
        call SaveReal(H,i,4,dmg)
        call SaveFogModifierHandle(H,i,5,bj_lastCreatedFogModifier)
        call TimerStart(t,.9,false,function PlanetaryDestructionAct)
        
        
        set u = null
        set t = null
    endfunction
    
    // Огненный дождь
    private function FieryRainDmgCond takes nothing returns boolean
        set bj_lastReplacedUnit = GetFilterUnit()
        return not IsUnitDead(bj_lastReplacedUnit) and not IsUnitType(bj_lastReplacedUnit,UNIT_TYPE_MAGIC_IMMUNE) and IsUnitEnemy(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit))
    endfunction
    private function FieryRainDmg1 takes nothing returns nothing
        call UnitDamageTarget(bj_lastCreatedUnit,GetEnumUnit(),TempR,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_FIRE,null)
        if FireID then
            call UnderworldFlames(bj_lastCreatedUnit,GetEnumUnit())
        endif
    endfunction
    private function FieryRainDmg takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer i = GetHandleId(t)
        local unit u = LoadUnitHandle(H,i,0)
        set bj_lastCreatedUnit = LoadUnitHandle(H,i,1)
        
        if GetUnitTypeId(bj_lastCreatedUnit) > 0 then
            call GroupEnumUnitsInRange(TempG,GetUnitX(u),GetUnitY(u),LoadReal(H,i,3),Condition(function FieryRainDmgCond))
            set FireID = GetUnitTypeId(u) == 'u004'
            set TempR = LoadReal(H,i,2)
            set TF = 1
            call ForGroup(TempG,function FieryRainDmg1)
            set TF = 0
            call GroupClear(TempG)
        endif
        
        call KillUnit(u)
        call DestroyTimer(t)
        call FlushChildHashtable(H,i)
        
        set u = null
        set t = null
    endfunction
    
    private function FieryRainAct takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local timer t1
        local integer i = GetHandleId(t)
        local unit u = LoadUnitHandle(H,i,0)
        local integer count = LoadInteger(H,i,4)
        local integer count1 = LoadInteger(H,i,5)-1
        local integer count2 = count
        local integer id = LoadInteger(H,i,1)
        local integer i1
        local real a = GetRandomReal(0,360)
        local real x = LoadReal(H,i,7)
        local real y = LoadReal(H,i,8)
        local real sc = LoadReal(H,i,9)
        local real maxr = LoadReal(H,i,3)
        local real minr
        local real ranr
        local real fly
        local real dmg = LoadReal(H,i,2)
        local real rad = LoadReal(H,i,10)
        
        set bj_groupEnumOwningPlayer = GetOwningPlayer(u)
        
        loop
            exitwhen count <= 0
            set minr = GetRandomReal(0,maxr*.2)
            set ranr = GetRandomReal(minr,maxr)
            call CreateUnitEx(bj_groupEnumOwningPlayer,id,x+ranr*Cos(a*bj_DEGTORAD),y+ranr*Sin(a*bj_DEGTORAD),GetRandomReal(0,360))
            set fly = GetRandomReal(RainFly-RainFlyD,RainFly+RainFlyD)
            call UnitAddAbility(CUEX,'Arav')
            call SetUnitFlyHeight(CUEX,fly,0)
            call SetUnitFlyHeight(CUEX,0,RainFly)
            call SetUnitScale(CUEX,sc,sc,sc)
            set t1 = CreateTimer()
            set i1 = GetHandleId(t1)
            call SaveUnitHandle(H,i1,0,CUEX)
            call SaveUnitHandle(H,i1,1,u)
            call SaveReal(H,i1,2,dmg)
            call SaveReal(H,i1,3,rad)
            call TimerStart(t1,fly/RainFly,false,function FieryRainDmg)
            set a = a+(360/count2)
            set count = count-1
        endloop
        set t1 = null
        if count1 <= 0 or GetUnitTypeId(u) < 1 then
            call PauseTimer(t)
            call DestroyTimer(t)
            call FlushChildHashtable(H,i)
        else
            call SaveInteger(H,i,5,count1)
            call TimerStart(t,LoadReal(H,i,6),false,function FieryRainAct)
        endif
        
        set u = null
        set t = null
    endfunction
    
    private function FieryRain takes nothing returns nothing
        local timer t = CreateTimer()
        local integer i = GetHandleId(t)
        local unit u = GetTriggerUnit()
        local integer lvl = GetUnitAbilityLevel(u,GetSpellAbilityId())
        local integer id
        local integer count
        local integer count1
        local real dmg
        local real scale
        local real radius
        local real radius1
        local real periodic
        set FireID = GetUnitAbilityLevel(u,'B001') > 0
        if FireID then
            set id = 'u004'
        else
            set id = 'u005'
        endif
        
        if     lvl == 1 then
            set dmg = 25.
            set scale = 1.
            set radius = 400.
            set radius1 = 80.
            set count = 15
            set count1 = 5
            set periodic = 1.
        elseif lvl == 2 then
            set dmg = 40.
            set scale = 1.25
            set radius = 600.
            set radius1 = 100.
            set count = 20
            set count1 = 7
            set periodic = 1.
        elseif lvl == 3 then
            set dmg = 70.
            set scale = 1.5
            set radius = 1000.
            set radius1 = 120.
            set count = 30
            set count1 = 10
            set periodic = 1.
        endif
        set dmg = dmg+(GetHeroInt(u,true)*.4)
        if FireID then
            set dmg = dmg+(dmg*(.05*GetUnitAbilityLevel(u,'A005')))
        endif
        call SaveUnitHandle(H,i,0,u)
        call SaveInteger(H,i,1,id)
        call SaveReal(H,i,2,dmg)
        call SaveReal(H,i,3,radius)
        call SaveInteger(H,i,4,count)
        call SaveInteger(H,i,5,count1)
        call SaveReal(H,i,6,periodic)
        call SaveReal(H,i,7,GetSpellTargetX())
        call SaveReal(H,i,8,GetSpellTargetY())
        call SaveReal(H,i,9,scale)
        call SaveReal(H,i,10,radius1)
        call TimerStart(t,0.,false,function FieryRainAct)
        
        set u = null
        set t = null
    endfunction
    // Огненная стена
    private function FireWallCond takes nothing returns boolean
        set bj_lastReplacedUnit = GetFilterUnit()
        return not IsUnitDead(bj_lastReplacedUnit) and not IsUnitType(bj_lastReplacedUnit,UNIT_TYPE_MAGIC_IMMUNE) and not IsUnitInGroup(bj_lastReplacedUnit,TempG1) and IsUnitEnemy(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit))
    endfunction
    private function FireWallDamageEx takes nothing returns nothing
        local unit u = GetEnumUnit()
        call UnitDamageTarget(bj_lastCreatedUnit,u,TempR,false,false,ATTACK_TYPE_MAGIC,DAMAGE_TYPE_FIRE,null)
        if not IsUnitDead(u) and FireID then
            call UnderworldFlames(bj_lastCreatedUnit,u)
        endif
        call GroupAddUnit(TempG1,u)
        set u = null
    endfunction
    private function FireWallDamage takes nothing returns nothing
        local unit u = GetEnumUnit()
        call GroupEnumUnitsInRange(TempG,GetUnitX(u),GetUnitY(u),TempR1,Condition(function FireWallCond))
        call ForGroup(TempG,function FireWallDamageEx)
        call GroupClear(TempG)
        set u = null
    endfunction
    private function FireWallDmg takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer i = GetHandleId(t)
        local group g = LoadGroupHandle(H,i,1)
        local real tm = LoadReal(H,i,2)-.25
        
        set bj_lastCreatedUnit = LoadUnitHandle(H,i,0)
        set TempR = LoadReal(H,i,3)
        set FireID = LoadBoolean(H,i,4)
        set TempR1 = 100.
        set TF = 1
        call ForGroup(g,function FireWallDamage)
        call GroupClear(TempG1)
        set TF = 0
        
        if tm <= 0. then
            call ForGroup(g,function Kill)
            call GroupClear(g)
            call DestroyGroup(g)
            call PauseTimer(t)
            call DestroyTimer(t)
            call FlushChildHashtable(H,i)
        else
            call SaveReal(H,i,2,tm)
        endif
        
        set bj_lastCreatedUnit = null
        set g = null
        set t = null
    endfunction
    
    private function FireWall takes nothing returns nothing
        local timer t = CreateTimer()
        local integer i = GetHandleId(t)
        local unit u = GetTriggerUnit()
        local integer lvl = GetUnitAbilityLevel(u,GetSpellAbilityId())
        local integer id
        local boolean b = GetUnitAbilityLevel(u,'B001') > 0
        local group g = CreateGroup()
        local real x = GetSpellTargetX()
        local real y = GetSpellTargetY()
        local real a = bj_RADTODEG*Atan2(y-GetUnitY(u),x-GetUnitX(u))
        local real d
        local real d1
        local real dmg
        local real dmg1
        local real sc
        local real tm
        
        if     lvl == 1 then
            set dmg1 = 80.
            set dmg = 25.
            set d = 300.
            set tm = 5.
            set sc = .5
        elseif lvl == 2 then
            set dmg1 = 150.
            set dmg = 40.
            set d = 400.
            set tm = 7.
            set sc = .75
        elseif lvl == 3 then
            set dmg1 = 225.
            set dmg = 70.
            set d = 500.
            set tm = 10.
            set sc = 1.
        endif
        set dmg = dmg+(GetHeroInt(u,true)*.5)
        set dmg1 = dmg1+(GetHeroInt(u,true)*.65)
        if b then
            set id = 'u002'
            set dmg = dmg+(dmg*(.05*GetUnitAbilityLevel(u,'A005')))
            set dmg1 = dmg1+(dmg1*(.05*GetUnitAbilityLevel(u,'A005')))
        else
            set id = 'u001'
        endif
        set d1 = d/2
        set bj_groupEnumOwningPlayer = GetOwningPlayer(u)
        call GroupAddUnit(g,CreateUnitEx(bj_groupEnumOwningPlayer,id,x,y,GetRandomReal(0,360)))
        call KillUnit(CreateUnitEx(bj_groupEnumOwningPlayer,'u000',x,y,GetRandomReal(0,360)))
        call SetUnitScale(CUEX,sc,sc,sc)
        if b then
            call SetUnitVertexColor(CUEX,0,255,255,100)
        endif
        call KillUnit(CreateUnitEx(bj_groupEnumOwningPlayer,'u000',x+d1*Cos((a-90)*bj_DEGTORAD),y+d1*Sin((a-90)*bj_DEGTORAD),GetRandomReal(0,360)))
        call SetUnitScale(CUEX,sc,sc,sc)
        if b then
            call SetUnitVertexColor(CUEX,0,255,255,100)
        endif
        call KillUnit(CreateUnitEx(bj_groupEnumOwningPlayer,'u000',x+d1*Cos((a+90)*bj_DEGTORAD),y+d1*Sin((a+90)*bj_DEGTORAD),GetRandomReal(0,360)))
        call SetUnitScale(CUEX,sc,sc,sc)
        if b then
            call SetUnitVertexColor(CUEX,0,255,255,100)
        endif
        loop
            exitwhen d1 <= 0.
            call GroupAddUnit(g,CreateUnitEx(bj_groupEnumOwningPlayer,id,x+d1*Cos((a-90)*bj_DEGTORAD),y+d1*Sin((a-90)*bj_DEGTORAD),GetRandomReal(0,360)))
            set d1 = d1-20.
        endloop
        set d1 = d/2
        loop
            exitwhen d1 <= 0.
            call GroupAddUnit(g,CreateUnitEx(bj_groupEnumOwningPlayer,id,x+d1*Cos((a+90)*bj_DEGTORAD),y+d1*Sin((a+90)*bj_DEGTORAD),GetRandomReal(0,360)))
            set d1 = d1-20.
        endloop
        
        set bj_lastCreatedUnit = u
        set TempR = dmg1
        set FireID = b
        set TempR1 = 200.
        set TF = 1
        call ForGroup(g,function FireWallDamage)
        call GroupClear(TempG1)
        set TF = 0
        
        call SaveUnitHandle(H,i,0,u)
        call SaveGroupHandle(H,i,1,g)
        call SaveReal(H,i,2,tm)
        call SaveReal(H,i,3,dmg)
        call SaveBoolean(H,i,4,b)
        call TimerStart(t,.25,true,function FireWallDmg)
        
        set g = null
        set t = null
        set u = null
    endfunction
    
    // Отталкивание юнитов с руки
    private function PassiveCond takes nothing returns boolean
        set bj_lastReplacedUnit = GetFilterUnit()
        return IsUnitEnemy(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit)) and not IsUnitDead(bj_lastReplacedUnit) and IsPointInSector(GetUnitX(bj_lastReplacedUnit),GetUnitY(bj_lastReplacedUnit),GetUnitX(bj_lastCreatedUnit),GetUnitY(bj_lastCreatedUnit),TempR3,80,300.)
    endfunction
    
    private function PassiveMove takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local integer i = GetHandleId(t)
        local unit u = LoadUnitHandle(H,i,0)
        local real tm = LoadReal(H,i,4)+.02
        local real dc = LoadReal(H,i,1)
        local real a = LoadReal(H,i,2)
        
        call SetUnitPositionEx(u,GetUnitX(u)+dc*Cos(a),GetUnitY(u)+dc*Sin(a))
        call IssueImmediateOrder(u,"stop")
        
        if GetUnitTypeId(u) < 1 or tm >= LoadReal(H,i,3) or TempR > 10 then
            call PauseTimer(t)
            call DestroyTimer(t)
            call FlushChildHashtable(H,i)
        else
            call SaveReal(H,i,4,tm)
        endif
        
        set t = null
        set u = null
    endfunction
    
    private function PassiveAct takes nothing returns nothing
        local unit u = GetEnumUnit()
        local timer t
        local integer i
        local real tm1
        local real dc
        
        if u != bj_lastLoadedUnit then
            call UnitDamageTarget(bj_lastCreatedUnit,u,TempR2,false,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,null)
        endif
        
        if not IsUnitDead(u) then
            set t = CreateTimer()
            if GetUnitAbilityLevel(bj_lastCreatedUnit,'B001') > 0 and not IsUnitType(u,UNIT_TYPE_MAGIC_IMMUNE)then
                call UnderworldFlames(bj_lastCreatedUnit,u)
            endif
        
            if GetUnitAbilityLevel(u,'A002') > 0 then
                call DestroyTimer(t)
                set t = null
            elseif GetUnitAbilityLevel(u,'A003') > 0 then
                set tm1 = .05
                set dc = 5.
            else
                set tm1 = .1
                set dc = 10.
            endif
        
            if t != null then
                set i = GetHandleId(t)
                call SaveUnitHandle(H,i,0,u)
                call SaveReal(H,i,1,dc)
                call SaveReal(H,i,2,Atan2(GetUnitY(u)-TempR1,GetUnitX(u)-TempR))
                call SaveReal(H,i,3,tm1)
                call TimerStart(t,.02,true,function PassiveMove)
                set t = null
            endif
        endif
        set u = null
    endfunction
    
    private function Passive takes nothing returns nothing
        set bj_lastLoadedUnit = GetTriggerUnit()
        set bj_lastCreatedUnit = GetEventDamageSource()
        set TempR = GetUnitX(bj_lastCreatedUnit)
        set TempR1 = GetUnitY(bj_lastCreatedUnit)
        set TempR2 = GetEventDamage()
        set TempR3 = Atan2(GetUnitY(bj_lastLoadedUnit)-TempR1,GetUnitX(bj_lastLoadedUnit)-TempR)*bj_RADTODEG
        
        call GroupEnumUnitsInRange(TempG,TempR,TempR1,300.,Condition(function PassiveCond))
        set TF = 1
        call ForGroup(TempG,function PassiveAct)
        set TF = 0
        call GroupClear(TempG)
        
        set bj_lastReplacedUnit = null
        set bj_lastLoadedUnit = null
    endfunction
    
    //=== Каст спеллов ===
    private function SpellsCond takes nothing returns boolean
        local integer i = GetSpellAbilityId()
        if i == 'A001' then
            call ExecuteFunc(SCOPE_PRIVATE+"FireWall")
        elseif i == 'A006' then
            call ExecuteFunc(SCOPE_PRIVATE+"FieryRain")
        elseif i == 'A007' then
            call ExecuteFunc(SCOPE_PRIVATE+"PlanetaryDestruction")
        endif
        return false
    endfunction
    
    //Показ урона + взаимодействие с уроном
    private function trgact takes nothing returns nothing
        local unit u = GetEventDamageSource()
        local unit u1 = GetTriggerUnit()
        local texttag tt = CreateTextTag()
        call SetTextTagText(tt,I2S(R2I(GetEventDamage())),.0276)
        call SetTextTagPosUnit(tt,GetTriggerUnit(),0)
        call SetTextTagColor(tt,255,0,255,0)
        call SetTextTagVelocity(tt,.05325*Cos(1.570788),.05325*Sin(1.570788))
        call SetTextTagPermanent(tt,false)
        call SetTextTagLifespan(tt,.5)
        call SetTextTagFadepoint(tt,.0)
        set tt = null
        
        if TF == 0 and GetUnitAbilityLevel(u,'A004') > 0 then
            call ExecuteFunc(SCOPE_PRIVATE+"Passive")
        endif
        
        set u = null
        set u1 = null
    endfunction
    
    //===================================================
    //---Регистрация события получения урона---
    private function trgcond takes nothing returns boolean
        return GetEventDamage() > 1.
    endfunction

    private function eve takes nothing returns nothing
        call TriggerRegisterUnitEvent(trg,GetEnumUnit(),EVENT_UNIT_DAMAGED)
    endfunction
    
    private function initcond takes nothing returns boolean
        local integer i = GetUnitTypeId(GetTriggerUnit())
        
        if i != 'u000' and i != 'u001' and i != 'u002' and i != 'u004' and i != 'u005' and i != 'u00C'/*
        */ and i != 'u003' and i != 'u00B' and i != 'u009' and i != 'u008' and i != 'u00A' and i != 'u006' and i != 'u007' then
            call TriggerRegisterUnitEvent(trg,GetTriggerUnit(),EVENT_UNIT_DAMAGED)
        endif
        return false
    endfunction
    //Пересборка триггера
    private function reset takes nothing returns nothing
        call DestroyTrigger(trg)
        set trg = CreateTrigger()
        call TriggerAddCondition(trg,Condition(function trgcond))
        call TriggerAddAction(trg,function trgact)
        call GroupEnumUnitsInRect(TempG,bj_mapInitialPlayableArea,Condition(function li))
        call ForGroup(TempG,function eve)
        call GroupClear(TempG)
    endfunction
    
    private function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local region r = CreateRegion()
        local integer i = 0
        //Preload
        call RemoveUnit(CreateUnit(Player(15),'u00C',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u003',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u00B',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u009',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u008',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u00A',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u006',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u000',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u001',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u002',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u004',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u005',0,0,0))
        call RemoveUnit(CreateUnit(Player(15),'u007',0,0,0))
        
        call RegionAddRect(r,bj_mapInitialPlayableArea)
        call TriggerRegisterEnterRegion(t,r,null)
        call TriggerAddCondition(t,Condition(function initcond))
        set t = null
        set r = null
        
        call reset()
        
        set t = CreateTrigger()
        loop
            call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
            set i = i+1
            exitwhen i == bj_MAX_PLAYER_SLOTS
        endloop
        call TriggerAddCondition(t,Condition(function SpellsCond))
        set t = null
        
        call TimerStart(CreateTimer(),600.,true,function reset)
    endfunction

endlibrary

//Счётчик
library HC initializer init
    private leaderboard HB
    private function HCU takes nothing returns nothing
        local integer i = 0
        local integer id
        local location array P
        local real result = 0
        loop
            exitwhen i >= 50
            set i = i+1
            set P[i] = Location(0,0)
            set id = GetHandleId(P[i])
            set result = result+(id-0x100000)
        endloop
        set result = result/i-i/2
        loop
            call RemoveLocation(P[i])
            set P[i] = null
            exitwhen i <= 1
            set i = i-1
        endloop
        call LeaderboardSetItemValue(HB,0,R2I(result))
    endfunction

    private function HCA takes nothing returns nothing
        set HB = CreateLeaderboard()
        call LeaderboardSetLabel(HB,"Handle Counter")
        call PlayerSetLeaderboard(GetLocalPlayer(),HB)
        call LeaderboardDisplay(HB,true)
        call LeaderboardAddItem(HB,"Handles",0,Player(0))
        call LeaderboardSetSizeByItemCount(HB,1)
        call HCU()
        call TimerStart(GetExpiredTimer(),.05,true,function HCU)
    endfunction

    private function init takes nothing returns nothing
        call TimerStart(CreateTimer(),0,false,function HCA)
    endfunction
endlibrary
Загруженные файлы
28

» WarCraft 3 / Способности и алгоритмы на заказ

я ожидал что меня тут на куски разорвут за распространение говнокода)
28

» WarCraft 3 / Тригерное получение золота после атаки

map_maiker
То, что "получает урон" срабатывает чуть раньше урона
?
Если ты про 1.26, то тут событие срабатывает только после получения урона. На рефе есть _DAMAGING, вот оно до урона срабатывает
28

» WarCraft 3 / Даммикаст предметом

ssbbssc, я не велосипед придумываю, а разбираюсь в механиках варкрафта, quq_CCCP много полезной инфы закинул
28

» WarCraft 3 / Тригерное получение золота после атаки

map_maiker, именно)
ssbbssc, думаю мы все бы учли этот факт и уведомили автора об неправильном событии, но у него всё норм)
28

» WarCraft 3 / Даммикаст предметом

quq_CCCP
(с каналами или молотками бурь не канает в любом случае)
о, вот это спасибо)

Просто вдруг предметы не учитывают задержку реагирования
28

» WarCraft 3 / Тригерное получение золота после атаки

Как вообще такая проблема могла возникнуть? Сокровище же не получает урон если отменять атаку, соответственно и событие не должно срабатывать

Скинь пожалуйста карту с подобной проблемой, у меня не получается её воссоздать
28

» WarCraft 3 / Система создания предметов

Поддерживаю комментатора выше. Можно было бы создавать/удалять юнита если у игрока есть тот или иной ресурс, место, где должны были быть предметы - юниты пустышки, при найме которых выдавать соответствующий предмет герою. У этих юнитов указать, что им нужен юнит-ресурс

возможно в предметах тоже можно указать требования и не извращаться с юнитами, я не особо много работал с ними
28

» WarCraft 3 / Способности и алгоритмы на заказ

Заклинание готово!

Заказчик: Roy Mustang
Способность: Captain's pressence
Выполнено: Да

Может есть какие-то баги или недоработки у системы, но я не обнаружил
Инструкция по импорту:
Просто копируешь либу mylib, можно прямо в шапку карты. Если есть библиотека с таким названием, то можешь переименовать мою
Скопируй способности и установи нужные уровни. Тебе нужно Благословение Элуны и Предмет: повышение защиты с нужным количеством уровней (пользуйся автозаполнением)
Поместить эти абилки в книгу заклинаний, с остальным я думаю сам разберёшься. Я не тестировал эту систему при большом кол-ве юнитов, так что возможны подлаги, снизить их периодичность можно будет таймером. Если рядом 2 юнита с аурой и у одного бафф будет более высокого уровня, то предпочтение отдастся ему
Если нужно что-то переделать или доделать - пиши
Код
library mylib initializer init
private constant integer DummyID = 'hfoo' // Юнит для прелоада способностей
private constant integer AbilityID = 'A000' // Благословение Элуны
private constant integer AbilityID1 = 'A002' // Способность предмета на защиту
private constant integer AbilityID2 = 'A001' // Спеллбук со способностями выше
private constant integer AbilityID3 = 'A003' // Аура
private constant integer AbilityID4 = 'BOae' // Заклинание ауры
private constant integer DefenseLvl = 1 // Фактор константы повышения уровня защиты (+1 защита за уровень)
private constant integer AbilityIDMaxLvl = 10 // Максимальный уровень ауры
private constant integer AbilityID1MaxLvl = 100 // Максимальный уровень способности предмета на защиту
private constant real Radius = 725 // Максимальный радиус для поиска ауры
private constant real AuraPeriodic = 0.25 // Периодичность проверки аур

private integer TempI = 0
private group TempG = CreateGroup()
private group TempG1 = CreateGroup()

private function AuraCond2 takes nothing returns boolean
    set bj_lastReplacedUnit = GetFilterUnit()
    return not (IsUnitType(bj_lastReplacedUnit,UNIT_TYPE_DEAD) or GetUnitTypeId(bj_lastReplacedUnit) < 1) and GetUnitAbilityLevel(bj_lastReplacedUnit,AbilityID3) > 0 and IsUnitAlly(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit))
endfunction
private function AuraCond takes nothing returns boolean
    return GetUnitAbilityLevel(GetFilterUnit(),AbilityID4) > 0
endfunction
private function SetMaxUnitAura takes nothing returns nothing
    if GetUnitAbilityLevel(GetEnumUnit(),AbilityID3) > TempI then
        set TempI = GetUnitAbilityLevel(GetEnumUnit(),AbilityID3)
    endif
endfunction
private function AddSetBuffs takes nothing returns nothing
    set bj_lastCreatedUnit = GetEnumUnit()
    call GroupEnumUnitsInRange(TempG1,GetUnitX(bj_lastCreatedUnit),GetUnitY(bj_lastCreatedUnit),Radius,Condition(function AuraCond2))
    call ForGroup(TempG1,function SetMaxUnitAura)
    call GroupClear(TempG1)
    if GetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID2) < 1 then
        call UnitAddAbility(bj_lastCreatedUnit,AbilityID2)
    endif
    if TempI == 0 or GetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID) > TempI then
        call UnitRemoveAbility(bj_lastCreatedUnit,AbilityID2)
        call UnitRemoveAbility(bj_lastCreatedUnit,AbilityID4)
    else
        call SetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID,TempI)
        call SetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID1,TempI*DefenseLvl)
    endif
    set TempI = 0
endfunction
private function Aura takes nothing returns nothing
    call GroupEnumUnitsInRect(TempG,bj_mapInitialPlayableArea,Condition(function AuraCond))
    call ForGroup(TempG,function AddSetBuffs)
    call GroupClear(TempG)
endfunction

private function CloseAbility takes nothing returns nothing
    call SetPlayerAbilityAvailable(GetEnumPlayer(),AbilityID2,false)
endfunction
private function init takes nothing returns nothing
    set bj_lastCreatedUnit = CreateUnit(Player(15),DummyID,0,0,0)
    call UnitAddAbility(bj_lastCreatedUnit,AbilityID2)
    call SetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID1,AbilityID1MaxLvl)
    call SetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID,AbilityIDMaxLvl)
    call UnitAddAbility(bj_lastCreatedUnit,AbilityID3)
    call SetUnitAbilityLevel(bj_lastCreatedUnit,AbilityID3,AbilityIDMaxLvl)
    call ForForce(bj_FORCE_ALL_PLAYERS,function CloseAbility)
    call RemoveUnit(bj_lastCreatedUnit)
    set bj_lastCreatedUnit = null
    call TimerStart(CreateTimer(),AuraPeriodic,true,function Aura)
endfunction

endlibrary
Загруженные файлы
28

» WarCraft 3 / Способности и алгоритмы на заказ

Заказ принят

Заказчик: Roy Mustang
Способность: Captain's pressence
Примерные сроки исполнения: завтра (16.05.21)
28

» WarCraft 3 / Способности и алгоритмы на заказ

Заклинание готово!

Заказчик: Obelick
Способность: Притягивание
Выполнено: Да

Код
function Trig_huk_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000' and udg_Int[GetPlayerId(GetOwningPlayer(GetTriggerUnit()))] == 0
endfunction

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

function IsUnitDead takes unit u returns boolean
    return IsUnitType(u,UNIT_TYPE_DEAD) or GetUnitTypeId(u) < 1
endfunction

function Move takes nothing returns nothing
    local integer ForLoop = 1
    local integer i = 0
    local real speed = 10
    local real radius = 50
    local real a
    local real x
    local real y
    local real x1
    local real y1
    loop
        exitwhen ForLoop > udg_Count
        if not IsUnitDead(udg_Target[ForLoop]) and not IsUnitDead(udg_Caster[ForLoop]) then
            set x = GetUnitX(udg_Target[ForLoop])
            set y = GetUnitY(udg_Target[ForLoop])
            set x1 = GetUnitX(udg_Caster[ForLoop])
            set y1 = GetUnitY(udg_Caster[ForLoop])
            set a = Atan2(y1-y,x1-x)
            call SetUnitX(udg_Target[ForLoop],x+speed*Cos(a))
            call SetUnitY(udg_Target[ForLoop],y+speed*Sin(a))
            if DBC(x1,y1,x+speed*Cos(a),y+speed*Sin(a)) < radius then
                set i = 1
            endif
        else
            set i = 1
        endif
        if i == 1 then
            set udg_Int[GetPlayerId(GetOwningPlayer(udg_Caster[ForLoop]))] = 0
            if udg_Count > 1 then
                set udg_Caster[ForLoop] = udg_Caster[udg_Count]
                set udg_Target[ForLoop] = udg_Target[udg_Count]
                set ForLoop = ForLoop - 1
            else
                call PauseTimer(udg_Timer)
            endif
            call PauseUnit(udg_Target[udg_Count],false)
            set udg_Caster[udg_Count] = null
            set udg_Target[udg_Count] = null
            set udg_Count = udg_Count - 1
            set i = 0
        endif
        set ForLoop = ForLoop + 1
    endloop
endfunction

function Trig_huk_Actions takes nothing returns nothing
    if udg_Count == 0 then
        call TimerStart(udg_Timer,0.03,true,function Move)
    endif
    set udg_Count = udg_Count + 1
    set udg_Caster[udg_Count] = GetTriggerUnit()
    set udg_Target[udg_Count] = GetSpellTargetUnit()
    call PauseUnit(udg_Target[udg_Count],true)
    set udg_Int[GetPlayerId(GetOwningPlayer(udg_Caster[udg_Count]))] = 1
endfunction

//===========================================================================
function InitTrig_huk takes nothing returns nothing
    set gg_trg_huk = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_huk, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_huk, Condition( function Trig_huk_Conditions ) )
    call TriggerAddAction( gg_trg_huk, function Trig_huk_Actions )
endfunction
Загруженные файлы
28

» WarCraft 3 / Способности и алгоритмы на заказ

Заклинание готово!

Заказчик: Roy Mustang
Способность: Дикий Рывок
Выполнено: Да

Инструкция по импорту
Либо счётчик прикалывался, либо я просто не смог найти что у меня там утекает
Копируешь либу mylib в свою карту, если у тебя уже есть библиотека с таким названием - то переименовываешь мою
Дальность применения и перезарядка могут быть любыми, спелл муи, но может произойти перезапись переменной последнего кастера для гуи (ты поймёшь о чем я, когда глянешь как на гуи урон наносится в канал4)
Всё в библиотеке приватное за исключением функции WildDash
Первый раз пролагивает из-за абилок и эффектов, поэтому советую использовать прелоад
Если какие-то абилки тебе не нужны, то можешь выставить 0 и не создавать абилку
Большая часть настроек на гуи, остальные вверху библиотеки
Я так же сделал отдельную переменную где записывается достижение максимальной скорости кастера, ты можешь использовать её, например, для дополнительного урона (я оставил пример)
Если у тебя уже используется название этой переменной, то можешь воспользоваться дефайном и закинуть туда название (я оставил пример)
С последним кастером так же
Расскажу коротко о том, как работает переменная LastCaster. Перед любым нанесением урона, а так же при дамми-касте абилок для гуишных действий, эта переменная выставляется на кастера. Перезапись очень вероятна для гуишных действий (потому что даммикаст с задержкой), поэтому советую пользоваться с осторожностью. На моём примере с гуи уроном толкать юнитов может один кастер, а дамажить в итоге другой, но по коду с ней всё нормально и там есть специальная переменная для настройки урона при расталкивании, стоит на 0.00, если перенесёшь урон туда, то каждый кастер будет именно свои цели дамажить
Если что-то нужно доделать или переделать - пиши
Код
library mylib
private hashtable H = InitHashtable()
//define private H = udg_Hash // если у тебя уже есть хэш-таблица, разкомменти эту строку вписав вместо udg_Hash название своей хэш-таблицы и удали предыдущую строку, если названия совпадают - удали обе строки
//define private udg_CasterSpeed = название твоей переменной
//define private udg_LastCaster = название твоей переменной
private constant attacktype AttackType = ATTACK_TYPE_MAGIC // Тип атаки
private constant damagetype DamageType = DAMAGE_TYPE_NORMAL // Тип урона
private constant integer DummyID = 'u000' // Дамми-юнит для каста способностей
private constant integer ItemID = 'I000' // Предмет для проверки проходимости местности
private constant integer AbilityID = 'A001' // Способность при завершении разбега (для своих действий)
private constant integer AbilityID1 = 'A002' // Способность при столкновении кастера с препятствием
private constant integer AbilityID2 = 'A003' // Способность при столкновении цели с препятствием
private constant integer AbilityID3 = 'A004' // Способность при расталкивании юнитов
private constant integer AbilityID4 = 'A005' // Способность при завершении разбега если был задет таргет, применяемая на кастера
private constant integer AbilityID5 = 'A006' // Способность при завершении разбега если был задет таргет, применяемая на таргета
// Приказ каждой способности должен быть "channel"
//=============================================================================================
private group TempG = CreateGroup()
private real TempR = 0.
private real TempR1 = 0.
private real TempR2 = 0.
private real TempX = 0.
private real TempY = 0.
private timer TempT = null

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

private function IsUnitDead takes unit u returns boolean
    return IsUnitType(u,UNIT_TYPE_DEAD) or GetUnitTypeId(u) < 1
endfunction

private function SetUnitPositionEx takes unit u, real x, real y returns nothing
    local item i = CreateItem(ItemID,x,y)
    set TempR = DBC(GetItemX(i),GetItemY(i),x,y)
    if TempR > 10 then
        call SetUnitX(u,GetItemX(i))
        call SetUnitY(u,GetItemY(i))
    else
        call SetUnitX(u,x)
        call SetUnitY(u,y)
    endif
    call RemoveItem(i)
    set i = null
endfunction

private function SetAnim takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer i = GetHandleId(t)
    call SetUnitAnimationByIndex(LoadUnitHandle(H,i,0),LoadInteger(H,i,1))
    call DestroyTimer(t)
    call FlushChildHashtable(H,i)
    set t = null
endfunction

private function CastAbil takes unit u, integer i returns nothing
    local unit u1 = CreateUnit(Player(15),DummyID,GetUnitX(u),GetUnitY(u),GetUnitFacing(u))
    if i != 0 then
        call UnitAddAbility(u1,i)
        call IssueTargetOrder(u1,"channel",u)
    endif
    call UnitApplyTimedLife(u1,'BTLF',1.)
    set u1 = null
endfunction

private function Dmg takes nothing returns nothing
    local unit u = GetEnumUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real a = Atan2(y-TempY,x-TempX)
    call SetUnitPositionEx(u,x+TempR1*Cos(a),y+TempR1*Sin(a))
    call CastAbil(u,AbilityID3)
    if TempR2 != 0. then
        call UnitDamageTarget(udg_LastCaster,GetEnumUnit(),TempR2,false,false,AttackType,DamageType,null)
    endif
    set u = null
endfunction

private function Discarding takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer i = GetHandleId(t)
    local unit u = LoadUnitHandle(H,i,0)
    local real s = LoadReal(H,i,1)
    local real d = LoadReal(H,i,2)
    local real a = LoadReal(H,i,4)
    local real x = GetUnitX(u)+s*Cos(a)
    local real y = GetUnitY(u)+s*Sin(a)
    local real dd = LoadReal(H,i,6)+s
    
    call SetUnitPositionEx(u,x,y)
    if TempR > 10 then
        set udg_LastCaster = LoadUnitHandle(H,i,5)
        call CastAbil(u,AbilityID2)
        call UnitDamageTarget(udg_LastCaster,u,LoadReal(H,i,3),false,false,AttackType,DamageType,null)
    endif
    if dd >= d or TempR > 10 or GetUnitTypeId(u) < 1 then
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(H,i)
    else
        call SaveReal(H,i,6,dd)
    endif
    
    set t = null
    set u = null
endfunction

private function Move takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer i = GetHandleId(t)
    local unit u = LoadUnitHandle(H,i,0)
    local unit u1 = LoadUnitHandle(H,i,1)
    local real r = LoadReal(H,i,4)
    local real a = Atan2(GetUnitY(u1)-GetUnitY(u),GetUnitX(u1)-GetUnitX(u))
    local real a1 = Atan2(GetUnitY(u)-GetUnitY(u1),GetUnitX(u)-GetUnitX(u1))
    local real ss = LoadReal(H,i,16)
    local real s = LoadReal(H,i,6)+ss
    local real x = GetUnitX(u)+s*Cos(a)
    local real y = GetUnitY(u)+s*Sin(a)
    local real x1 = GetUnitX(u1)+r*Cos(a1)
    local real y1 = GetUnitY(u1)+r*Sin(a1)
    local integer i2 = 0
    local integer i1
    set udg_LastCaster = u
    call SetUnitFacing(u,a*bj_RADTODEG)
    if DBC(x,y,x1,y1)-(r/2) < s then
        call SetUnitPositionEx(u,x1,y1)
        call UnitDamageTarget(u,u1,LoadReal(H,i,2),false,false,AttackType,DamageType,null)
        set TempT = CreateTimer()
        set i1 = GetHandleId(TempT)
        call SaveUnitHandle(H,i1,0,u1)
        call SaveReal(H,i1,1,LoadReal(H,i,11))
        call SaveReal(H,i1,2,LoadReal(H,i,12))
        call SaveReal(H,i1,3,LoadReal(H,i,2))
        call SaveReal(H,i1,4,Atan2(GetUnitY(u1)-GetUnitY(u),GetUnitX(u1)-GetUnitX(u)))
        call SaveUnitHandle(H,i1,5,u)
        call TimerStart(TempT,LoadReal(H,i,10),true,function Discarding)
        set TempT = null
        set i2 = 2
    else
        call SetUnitPositionEx(u,x,y)
        if TempR > 10 then
            call CastAbil(u,AbilityID1)
            set i2 = 1
        endif
    endif
    set TempR2 = LoadReal(H,i,3)
    set TempR1 = LoadReal(H,i,14)
    set TempX = GetUnitX(u)
    set TempY = GetUnitY(u)
    call GroupEnumUnitsInRange(TempG,TempX,TempY,r,LoadBooleanExprHandle(H,i,13))
    call ForGroup(TempG,function Dmg)
    call GroupClear(TempG)
    
    if i2 == 1 then
        set udg_LastCaster = u
        set TempR2 = LoadReal(H,i,7)
        call GroupEnumUnitsInRange(TempG,TempX,TempY,LoadReal(H,i,8),LoadBooleanExprHandle(H,i,13))
        call ForGroup(TempG,function Dmg)
        call GroupClear(TempG)
    endif
    
    if i2 == 1 or i2 == 2 or IsUnitDead(u) or IsUnitDead(u1) then
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(H,i)
        call CastAbil(u,AbilityID)
        if i2 == 2 then
            call CastAbil(u,AbilityID4)
            call CastAbil(u1,AbilityID5)
        endif
        set udg_CasterSpeed = s
    else
        call SaveReal(H,i,16,ss+LoadReal(H,i,5))
    endif
    
    set u = null
    set u1 = null
    set t = null
endfunction

function WildDash takes unit caster, unit target, integer animation, real dmg, real dmg1, real radius, real sspeed, real speed, real dmg2, real radius1, real tmper, real dcper, real dc, real dd, real dc1, boolexpr b returns nothing
    local timer t = CreateTimer()
    local integer i = GetHandleId(t)
    
    call SaveUnitHandle(H,i,0,caster)
    call SaveUnitHandle(H,i,1,target)
    call SaveReal(H,i,2,dmg)
    call SaveReal(H,i,3,dmg1)
    call SaveReal(H,i,4,radius)
    call SaveReal(H,i,5,sspeed)
    call SaveReal(H,i,6,speed)
    call SaveReal(H,i,7,dmg2)
    call SaveReal(H,i,8,radius1)
    call SaveReal(H,i,9,tmper)
    call SaveReal(H,i,10,dcper)
    call SaveReal(H,i,11,dc)
    call SaveReal(H,i,12,dd)
    call SaveBooleanExprHandle(H,i,13,b)
    call SaveReal(H,i,14,dc1)
    call TimerStart(t,tmper,true,function Move)
    
    set t = CreateTimer()
    call SaveUnitHandle(H,GetHandleId(t),0,caster)
    call SaveInteger(H,GetHandleId(t),1,animation)
    call TimerStart(t,0.00,false,function SetAnim)
    
    set t = null
endfunction

endlibrary

так же поправил прыжок, теперь вместо предмета там тоже даммикаст и убрал удаление условия кому наносить урон, сорян за это))
Загруженные файлы
28

» WarCraft 3 / Даммикаст предметом

map_maiker:
Предметом в смысле руной?
Предметом в смысле предметом, запихиваешь туда абилку канала и кастуешь её
И ради интереса, как замерялась скорость?
Визуально обратил на это внимание и стало интересно
28

» WarCraft 3 / Способности и алгоритмы на заказ

Заклинание готово!

Заказчик: Roy Mustang
Способность: Прыжок
Выполнено: Да

Инструкция по импорту:
Просто импортируешь либу mylib в свою карту (можно прямо в шапку)
Дальность применения и перезарядка могут быть любыми, спелл муи
Копируй все созданные на гуи переменные
Сам спелл юзается через функцию
function Jump takes unit caster, unit target, real dmg, real speed, real height, real tmper, boolexpr b, real radius, real dbtm returns nothing
Ты увидишь её на кастомскрипте, всё что тебе там в принципе можно поменять это периодичность таймера и названия переменных на свои
Замедление реализовано через ауру, чтобы с другими твоими замедлениями не конфликтовать
Ты можешь использовать свою хэш-таблицу, не создавая новой (их лимит 255 по моему), но учти, ради ауры мне пришлось взять одну ячейку юнита, то бишь если ты там что-то записываешь в юнита и не помнишь последнюю свободную ячейку, то лучше новую хэш-таблицу создать, чтобы спелл тебе ничего там не сломал. Ах да, использовать свою хэш-таблицу нужно через дефайн, я оставил там комментарии, но опять же, дефайн может вызвать какие-то непонятки и конфликтовать с кодом других людей. Если название твоей хэш-таблицы соответствует моей и ты хочешь её подставить, то просто удали private hashtable H = InitHashtable()
По коду лишь пару переменных тебе нужно изменить:
private constant attacktype AttackType = ATTACK_TYPE_MAGIC // Тип атаки
private constant damagetype DamageType = DAMAGE_TYPE_NORMAL // Тип урона
private constant integer AbilityID = 'A001' // Равкод ауры замедления
private constant integer AbilityID1 = 'Basl' // Равкод заклинания из ауры замедления
private constant integer UnitH = 0 // Свободная ячейка юнита для ауры
private constant integer ItemID = 'I000' // Получение предмета после завершения прыжка для своих действий
Я добавил показательный триггер пример, где юнит после приземления создаёт кратер, там можешь делать свои действия на гуи. Например выбрать всех юнитов вокруг юнита и повесить спецэффект. Ах да, если тебе не нужно замедление именно с ауры и ты предпочтёшь какой-нибудь даммикаст, то можешь в коде указать равкод ауры 0.
Всё в либе приватное и не должно конфликтовать с чужим кодом, исключение сама функция Jump.
Если нужно что-то переделать или доделать, то пиши
Код
library mylib initializer init
private hashtable H = InitHashtable()
//define private H = udg_Hash // если у тебя уже есть хэш-таблица, разкомменти эту строку вписав вместо udg_Hash название своей хэш-таблицы и удали предыдущую строку
//Внимание! Используется ячейка юнита в хэш-таблице, чтобы не сбивались ауры, если ты записывал какие-то значения в юнита и не помнишь ячейку, лучше создать ещё одну хэш-таблицу
private constant attacktype AttackType = ATTACK_TYPE_MAGIC // Тип атаки
private constant damagetype DamageType = DAMAGE_TYPE_NORMAL // Тип урона
private constant integer AbilityID = 'A001' // Равкод ауры замедления
private constant integer AbilityID1 = 'Basl' // Равкод заклинания из ауры замедления
private constant integer UnitH = 0 // Свободная ячейка юнита для ауры
private constant integer ItemID = 'I000' // Получение предмета после завершения прыжка для своих действий

private location LFZ = Location(0,0)
private group TempG = CreateGroup()
private group DebuffG = CreateGroup()
private real TempR = 0.
private real TempR1 = 0.
private timer DebuffT = CreateTimer()

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

private function ParabolaZ takes real h, real d, real x returns real
    return (4 * h / d) * (d - x) * (x / d)
endfunction

private function GetLocZ takes real x, real y returns real
    call MoveLocation(LFZ,x,y)
    return GetLocationZ(LFZ)
endfunction

private function RemoveF takes nothing returns nothing
    local unit u = GetEnumUnit()
    local integer i = GetHandleId(u)
    local real r = LoadReal(H,i,UnitH)-.01
    if r <= 0. then
        call RemoveSavedReal(H,i,UnitH)
        call GroupRemoveUnit(DebuffG,u)
        call UnitRemoveAbility(u,AbilityID)
        call UnitRemoveAbility(u,AbilityID1)
    else
        call SaveReal(H,i,UnitH,r)
    endif
    set u = null
endfunction
private function Remove takes nothing returns nothing
    call ForGroup(DebuffG,function RemoveF)
endfunction

private function Dmg takes nothing returns nothing
    local unit u = GetEnumUnit()
    call UnitDamageTarget(bj_lastCreatedUnit,GetEnumUnit(),TempR,false,false,AttackType,DamageType,null)
    if not IsUnitType(u,UNIT_TYPE_DEAD) then
        if LoadReal(H,GetHandleId(u),UnitH) <= 0. and AbilityID != 0 then
            set bj_groupCountUnits = 0
            call ForGroup(DebuffG,function CountUnitsInGroupEnum)
            call GroupAddUnit(DebuffG,u)
            call UnitAddAbility(u,AbilityID)
            if bj_groupCountUnits == 0 then
                call TimerStart(DebuffT,.01,true,function Remove)
            endif
        endif
        call SaveReal(H,GetHandleId(u),UnitH,TempR1)
    endif
    set u = null
endfunction

private function Move takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local integer i = GetHandleId(t)
    local unit u = LoadUnitHandle(H,i,0)
    local real s = LoadReal(H,i,2)
    local real a = LoadReal(H,i,4)
    local real x = GetUnitX(u)+s*Cos(a)
    local real y = GetUnitY(u)+s*Sin(a)
    local real d = LoadReal(H,i,5)-s
    local real d1 = LoadReal(H,i,9)+s
    local real d2 = LoadReal(H,i,7)
    
    call SetUnitX(u,x)
    call SetUnitY(u,y)
    call SetUnitFlyHeight(u,LoadReal(H,i,12)+ParabolaZ(LoadReal(H,i,6),d2,d)+(LoadReal(H,i,8)-GetLocZ(x,y)),0)
    
    if d2-d1 < s then
        set s = d2-d1
        set x = GetUnitX(u)+s*Cos(a)
        set y = GetUnitY(u)+s*Sin(a)
        call SetUnitX(u,x)
        call SetUnitY(u,y)
        call SetUnitFlyHeight(u,LoadReal(H,i,12),0)
        call PauseUnit(u,false)
        call SetUnitPathing(u,true)
        call UnitRemoveAbility(u,'Arav')
        set bj_lastCreatedUnit = u
        set TempR = LoadReal(H,i,1)
        set TempR1 = LoadReal(H,i,13)
        call GroupEnumUnitsInRange(TempG,x,y,LoadReal(H,i,10),LoadBooleanExprHandle(H,i,11))
        call ForGroup(TempG,function Dmg)
        call GroupClear(TempG)
        call DestroyBoolExpr(LoadBooleanExprHandle(H,i,11))
        call PauseTimer(t)
        call DestroyTimer(t)
        call FlushChildHashtable(H,i)
        call UnitAddItem(u,CreateItem(ItemID,0,0))
    else
        call SaveReal(H,i,5,d)
        call SaveReal(H,i,9,d1)
    endif
    
    set u = null
    set t = null
endfunction

function Jump takes unit caster, unit target, real dmg, real speed, real height, real tmper, boolexpr b, real radius, real dbtm returns nothing
    local timer t = CreateTimer()
    local integer i = GetHandleId(t)
    local real d = DBC(GetUnitX(caster),GetUnitY(caster),GetUnitX(target),GetUnitY(target))
    call SaveUnitHandle(H,i,0,caster)
    call SaveReal(H,i,1,dmg)
    call SaveReal(H,i,2,speed)
    call SaveReal(H,i,3,tmper)
    call SaveReal(H,i,4,Atan2(GetUnitY(target)-GetUnitY(caster),GetUnitX(target)-GetUnitX(caster)))
    call SaveReal(H,i,5,d)
    call SaveReal(H,i,6,height)
    call SaveReal(H,i,7,d)
    call SaveReal(H,i,8,GetLocZ(GetUnitX(caster),GetUnitY(caster)))
    call SaveReal(H,i,10,radius)
    call SaveBooleanExprHandle(H,i,11,b)
    call SaveReal(H,i,12,GetUnitFlyHeight(caster))
    call SaveReal(H,i,13,dbtm)
    call TimerStart(t,tmper,true,function Move)
    call UnitAddAbility(caster,'Arav')
    call SetUnitPathing(caster,false)
    call PauseUnit(caster,true)
    
    set t = null
endfunction

private function Res takes nothing returns nothing
    set bj_groupCountUnits = 0
    call ForGroup(DebuffG,function CountUnitsInGroupEnum)
    if bj_groupCountUnits == 0 then
        call PauseTimer(DebuffT)
    endif
endfunction

private function init takes nothing returns nothing
    call TimerStart(CreateTimer(),1,true,function Res)
endfunction

endlibrary
Загруженные файлы
28

» WarCraft 3 / Способности и алгоритмы на заказ

Заказ принят

Заказчик: Roy Mustang
Способность: Прыжок
Примерный срок выполнения: Спелл закину сегодня ближе к вечеру

Заказ принят

Заказчик: Roy Mustang
Способность: Дикий Рывок
Примерный срок выполнения: Либо вместе с предыдущей абилкой, либо на следующий день