Я решил модифицировать вурдалаков, теперь это снорки, ы
Перепрыгивают через препятствия, приоритетная для них цель с самым низким хп, если хп у всех одинаковое, то прыгает на ближайшего
Однако эта системка не поддерживает громадное кол-во вурдалаков, оно начнёт подлагивать, лимиты я не проверял и утечек вроде нет. Начинает лагать с того момента, как юниты уже сами по себе двигаются рывками. Вурдалаки паузятся во время полёта, так что их вроде нельзя продамажить и что-то вообще сделать, в своей карте паузу заменю на морф через руну в стража и отниму абилку атаковать (потом верну на свои места само собой)
Карта с видосом в комментах
код
library mylib initializer init{
    private hashtable H = InitHashtable()
    private location LFZ = Location(0,0)
    private group TempG = CreateGroup()
    private group TempG1 = CreateGroup()
    
    private bool IsUnitDead(unit u){
        return IsUnitType(u,UNIT_TYPE_DEAD) || GetUnitTypeId(u) < 1
    }
    
    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 real GetLocZ(real x, real y){
        MoveLocation(LFZ,x,y); return GetLocationZ(LFZ)
    }
    
    function ParabolaZ takes real h, real d, real x returns real
        return (4 * h / d) * (d - x) * (x / d)
    endfunction
    
    private bool jump1_cond(){
        bj_lastReplacedUnit = GetFilterUnit()
        return !IsUnitDead(bj_lastReplacedUnit) && IsUnitEnemy(bj_lastReplacedUnit,bj_groupEnumOwningPlayer)
    }
    private void jump1(){
        unit u = GetEnumUnit(), u1, u2
        real r, hp, hp1, d, x = GetUnitX(u), y = GetUnitY(u)
        
        bj_groupEnumOwningPlayer = GetOwningPlayer(u)
        GroupEnumUnitsInRange(TempG,x,y,500,Condition(function jump1_cond))
        bj_groupEnumOwningPlayer = null
        
        if FirstOfGroup(TempG) != null{
            r = 501; hp = 999999
            while FirstOfGroup(TempG) != null{
                u1 = FirstOfGroup(TempG)
                d = DistanceBetweenCoordinates(x,y,GetUnitX(u1),GetUnitY(u1))
                hp1 = GetWidgetLife(u1)
                if d < r && hp1 <= hp{
                    r = d; hp = hp1; u2 = u1
                }
                GroupRemoveUnit(TempG,u1); u1 = null
            }
            IssueTargetOrder(u,"thunderbolt",u2); u2 = null
        }
        
       
        u = null
    }
    private bool vurd(){
        bj_lastReplacedUnit = GetFilterUnit(); bj_lastCreatedUnit = null
        /*
        bj_groupEnumOwningPlayer = GetOwningPlayer(bj_lastReplacedUnit)
        GroupEnumUnitsInRange(TempG,GetUnitX(bj_lastReplacedUnit),GetUnitY(bj_lastReplacedUnit),500,Condition(function jump1_cond))
        bj_groupEnumOwningPlayer = null
        bj_lastCreatedUnit = FirstOfGroup(TempG)
        if bj_lastReplacedUnit != null{GroupClear(TempG)}*/ // Попытка оптимизации
        return GetUnitTypeId(bj_lastReplacedUnit) == 'u000' && !IsUnitDead(bj_lastReplacedUnit)// && bj_lastReplacedUnit != null
    }
    private void jump(){
        GroupEnumUnitsInRect(TempG1,bj_mapInitialPlayableArea,Condition(function vurd))
        if FirstOfGroup(TempG1) != null{
            ForGroup(TempG1,function jump1)
            GroupClear(TempG1)
        }
        
    }
    
    //==========
    private void init_act1(){
        timer t = GetExpiredTimer(); int i = GetHandleId(t), tf = 0
        unit u = LoadUnitHandle(H,i,0)
        real s = LoadReal(H,i,4), a = LoadReal(H,i,5), x = GetUnitX(u)+s*Cos(a), y = GetUnitY(u)+s*Sin(a),/*
        */d = LoadReal(H,i,2)-s, d1, x1, y1
        
        if IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY){
            x1 = x; y1 = y; d1 = d; tf = 1
            while d1 > 0 && tf == 1{
                x1 = x1+s*Cos(a); y1 = y1+s*Sin(a); d1 = d1-s
                if !IsTerrainPathable(x1,y1,PATHING_TYPE_WALKABILITY){tf = 0}
            }
        }
        
        if tf == 1 || d+s <= 0 || IsUnitDead(u){
            SetUnitFlyHeight(u,0,500)
            if !IsUnitDead(u){
                PauseUnit(u,false); UnitRemoveAbility(u,'Arav')
                unit u1 = LoadUnitHandle(H,i,1)
                if !IsUnitDead(u1){
                    IssueTargetOrder(u,"attack",u1)
                    DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Critters\\Albatross\\CritterBloodAlbatross.mdl",u1,"chest"))
                    UnitDamageTarget(u,u1,GetRandomReal(15,20),true,false,ATTACK_TYPE_MELEE,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WOOD_MEDIUM_BASH)
                }
                u1 = null
            }
            PauseTimer(t); DestroyTimer(t); FlushChildHashtable(H,i)
        }else{
            SetUnitX(u,x); SetUnitY(u,y)
            SetUnitFlyHeight(u,ParabolaZ(100,LoadReal(H,i,3),d)+(LoadReal(H,i,6)-GetLocZ(x,y)),0)
            SaveReal(H,i,2,d)
        }
        
        t = null; u = null
    }
    private void init_act(){
        timer t = CreateTimer(); int i = GetHandleId(t)
        unit u = GetSpellAbilityUnit(), u1 = GetSpellTargetUnit()
        real x = GetUnitX(u), y = GetUnitY(u), x1 = GetUnitX(u1), y1 = GetUnitY(u1), a = Atan2(y1-y,x1-x),/*
        */d = DistanceBetweenCoordinates(x,y,x1,y1)+50
        
        SetUnitFacing(u,a*bj_RADTODEG)
        UnitAddAbility(u,'Arav')
        PauseUnit(u,true)
        SaveUnitHandle(H,i,0,u); SaveUnitHandle(H,i,1,u1)
        SaveReal(H,i,2,d); SaveReal(H,i,3,d)
        SaveReal(H,i,4,(GetUnitMoveSpeed(u)*.01)+10)
        SaveReal(H,i,5,a)
        SaveReal(H,i,6,GetLocZ(x,y))
        TimerStart(t,.01,true,function init_act1)
        
        t = null; u = null; u1 = null
    }
    private bool init_cond(){return GetSpellAbilityId() == 'A000'}
    private void init(){
        trigger t = CreateTrigger(); int i = 0
        while i < 16{
            TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
            i++
        }
        TriggerAddCondition(t,Condition(function init_cond))
        TriggerAddAction(t,function init_act)
        t = null; t = CreateTrigger()
        TriggerRegisterTimerEvent(t,.5,true)
        TriggerAddAction(t,function jump)
        t = null
    }

}
Карта не планируется для импорта, поэтому никаких настроек я не оставлял, я просто захотел проверить идею, возникшую в моей голове
`
ОЖИДАНИЕ РЕКЛАМЫ...
28
Там музыка в видео если что, звук вырубите
видео со старой версии
4
rsfghd:
Там музыка в видео если что, звук вырубите
видео со старой версии
p.s помянем без защитных работяг. Они небыли готовы к такому...
FFF
28
VuRdaLaK1337, сейчас я бы переделал немного вурдов, с новыми знаниями)
да и вообще абсолютно каждый спелл бы свой переделал, но такой завал по жизни что попросту нет времени
спасибо, что интересуешься моими ресурсами, приятно на душе
Чтобы оставить комментарий, пожалуйста, войдите на сайт.