Добавлен , опубликован
Алгоритмы, Наработки и Способности
Способ реализации:
Zinc
Тип:
Способность
Версия Warcraft:
1.26+

Божественный щит

MUI: да
Импорт: нет
Требования: JNGP
Идея : Bergi_Bear
Описание: Пассивно активируется божественный щит всякий раз, когда здоровье героя падает ниже отметки в 10%. Перезарядка: 20, длительность: 5.

Скринншот

Технические подробности

Перенос в свою карту
Способности
  • 'Asds' Божественный щит (заклинание)
Предметы
  • 'Idsp' Божественный щит
  • 'Idsa' Божественный щит
Триггеры
  • ItemDivineShield
Настройки
constant integer ITEM_ACTIVE = 'Idsa'; // Активный предмет
constant integer ITEM_PASSIVE = 'Idsp'; // Пассивный предмет
constant real ITEM_ABILITY_COOLDOWN = 20; // Перезарядка способности предмета

trigger DAMAGE_DETECT_TRIGGER = CreateTrigger(); // Не трогать
region MAP_REGION;  // Не трогать

hashtable HT = InitHashtable(); // Хэштаблица, можете вписать туда вашу, например:
// hashtable HT = udg_HashTable;
Код заклинания
// !nocjass
//! zinc
library ItemDivineShield {
    
    constant integer ITEM_ACTIVE = 'Idsa'; // Активный предмет
    constant integer ITEM_PASSIVE = 'Idsp'; // Пассивный предмет
    constant real ITEM_ABILITY_COOLDOWN = 20; // Перезарядка способности предмета

    trigger DAMAGE_DETECT_TRIGGER = CreateTrigger(); // Не трогать
    region MAP_REGION;  // Не трогать
    
    hashtable HT = InitHashtable(); // Хэштаблица, можете вписать туда вашу, например:
    // hashtable HT = udg_HashTable;
    
    
    /*
    *
    *
    *
    *
    *
    */
    
    function isUnitAlive(unit target) -> boolean {
        return GetWidgetLife(target) > 0.405;
    }
    
    function itemReplaceInstantly(unit u, integer from, integer to){
        integer i, slot[], slotI = -1;
        item it;
        for(0 <= i < bj_MAX_INVENTORY){
            it = UnitItemInSlot(u, i);
            if (GetItemTypeId(it) == from){
                RemoveItem(it);
                slotI = slotI + 1;
                slot[slotI] = i;
            }
        }
        for(0 <= i <= slotI){
            UnitAddItemToSlotById(u, to, slot[i]);
        }
        it = null;
    }
    
    function itemReplaceDelayed(unit u, integer from, integer to){
        timer t = CreateTimer();
        integer pk = GetHandleId(t);
        SaveUnitHandle(HT, pk, 0, u);
        SaveInteger(HT, pk, 0, from);
        SaveInteger(HT, pk, 1, to);
        TimerStart(t, 0.03125, true, function(){
            timer t = GetExpiredTimer();
            integer pk = GetHandleId(t);
            unit u = LoadUnitHandle(HT, pk, 0);
            if (isUnitAlive(u)){
                itemReplaceInstantly(u, LoadInteger(HT, pk, 0), LoadInteger(HT, pk, 1));
                FlushChildHashtable(HT, pk);
                PauseTimer(t); DestroyTimer(t);
            }
            u = null;
            t = null;
        });
        t = null;
    }
    
    function itemReplace(unit u, integer from, integer to){
        if (isUnitAlive(u)){
            itemReplaceInstantly(u, from, to);
        } else {
            itemReplaceDelayed(u, from, to);
        }
    }
    
    function itemCount(unit u, integer c) -> integer {
        integer i, count = 0;
        item it;
        for(0 <= i < bj_MAX_INVENTORY){
            it = UnitItemInSlot(u, i);
            if(GetItemTypeId(it) == c){
                count = count + 1;
            }
        }
        it = null;
        return count;
    }

    function addUnitToDetect() -> boolean {
        unit u = GetFilterUnit();
        if (IsUnitType(u, UNIT_TYPE_HERO)){
            TriggerRegisterUnitEvent(DAMAGE_DETECT_TRIGGER, u, EVENT_UNIT_DAMAGED);
        }
        u = null;
        return false;
    }
    
    function onInit(){
        trigger t[];
        integer i;
        group g = CreateGroup();
        
        for(0 <= i <= 2){ t[i] = CreateTrigger(); }
        
        MAP_REGION = CreateRegion();
        RegionAddRect(MAP_REGION, bj_mapInitialPlayableArea);
        
        t[0] = CreateTrigger();
        TriggerRegisterEnterRegion(t[0], MAP_REGION, null);
        TriggerAddCondition(t[0], function addUnitToDetect);
        
        GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, function addUnitToDetect);
        GroupClear(g); DestroyGroup(g); g = null;
        
        TriggerAddCondition(DAMAGE_DETECT_TRIGGER, Condition(function() -> boolean {
            unit u = GetTriggerUnit();
            item it;
            integer i, pk;
            real dmg = GetEventDamage();
            timer t;
            if (
                dmg > 0
                &&
                GetUnitCurrentOrder(u) != 851973
                &&
                itemCount(u, ITEM_PASSIVE) > 0
                &&
                GetWidgetLife(u) - dmg <= GetUnitState(u, UNIT_STATE_MAX_LIFE) * 0.1
            ){                
                itemReplace(u, ITEM_PASSIVE, ITEM_ACTIVE);
                for(0 <= i < bj_MAX_INVENTORY){
                    it = UnitItemInSlot(u, i);
                    if(GetItemTypeId(it) == ITEM_ACTIVE){
                        UnitUseItem(u, it);
                        break;
                    }
                }
                
                t = CreateTimer();
                pk = GetHandleId(t);
                SaveUnitHandle(HT, pk, 0, u);
                TimerStart(t, ITEM_ABILITY_COOLDOWN - 0.01, false, function(){
                    timer t = GetExpiredTimer();
                    integer pk = GetHandleId(t);
                    unit u = LoadUnitHandle(HT, pk, 0);
                    itemReplace(u, ITEM_ACTIVE, ITEM_PASSIVE);
                    u = null;
                    FlushChildHashtable(HT, pk);
                    PauseTimer(t); DestroyTimer(t); t = null;
                });
            }
            
            u = null;
            it = null;
            t = null;
            return false;
        }));
        
        for(0 <= i < bj_MAX_PLAYER_SLOTS){
            TriggerRegisterPlayerUnitEvent(t[1], Player(i), EVENT_PLAYER_UNIT_PICKUP_ITEM, null);
            TriggerRegisterPlayerUnitEvent(t[2], Player(i), EVENT_PLAYER_UNIT_DEATH, null);
        }
        TriggerAddCondition(t[1], Condition(function() -> boolean {
            unit u = GetTriggerUnit();
            item it = GetManipulatedItem();
            
            if (GetItemTypeId(it) == ITEM_PASSIVE && itemCount(u, ITEM_ACTIVE) > 0){
                itemReplace(u, ITEM_PASSIVE, ITEM_ACTIVE);
            }
            u = null;
            it = null;
            return false;
        }));
        TriggerAddCondition(t[2], Condition(function() -> boolean {
            unit u = GetTriggerUnit();
            if (itemCount(u, ITEM_ACTIVE) > 0){
                itemReplace(u, ITEM_ACTIVE, ITEM_PASSIVE);
            }
            u = null;
            return false;
        }));
        
        for(0 <= i <= 2){t[i] = null;}
    }
}
//! endzinc
// !endnocjass
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
26
5 лет назад
0
Не сбивая приказ можно вовсе не отдавая юниту приказов
Но тут нет разницы на чём именно делать
0
32
5 лет назад
0
руна неуязвимость да, эффект можно получить, а как вы кд предмету запустить собираетесь?
не только защитный амулет, подменять его, даммиком кидать спелл который собьёт амулет и запустит кд
0
29
5 лет назад
0
не сбивая приказ можно на основе какой нибудь Книги
Пробовал, но таким образом текут хэндлы и пришлось создавать дополнительную способность для кд предмета и дополнительный предмет для вручения герою.
0
11
5 лет назад
0
NazarPunk, люди играют в карты по 1.5-2 часа нонстопом, когда в коде там такая жесть, что про небольшие утечки я вообще молчу (пример та же Дота и всякие Хиро Дефенсы). А каким образом у тебя будут "течь" хэндлы, если все чистить за собой?
0
29
5 лет назад
Отредактирован nazarpunk
0
respect_gg, пусть играют во что им вздумается, я код пишу и он работать должен. Хэндлы утекали когда я добавлял герою руну с божественным щитом, а если бы не текли, то всёравно нужно создвать два дополнительных объекта в РО, что напрягает.
0
11
5 лет назад
0
NazarPunk, Даешь Айтем с абилкой, которая 0 агилити/силы/инты дает, триггерно юзаешь ее и все, в свойствах ставишь, чтобы предмет не кончался и все, офк даешь 'Avul' триггерно, эффект какой надо повесь. Параллельно таймер запускаешь, как таймер истек - свапаешь айтемы обратно. Писать такую кучу триггеров ради этого я хз зачем. По крайней мере так самый важный момент будет работать - не будет сбиваться текущий приказ, а это куда важнее.
0
32
5 лет назад
0
respect_gg, как ты запустишь кд предмет?, в этом сама и соль же!
0
11
5 лет назад
0
Bergi_Bear, Активная способность у ПОвышение ловкости/силы/инты не сбивает приказ
0
32
5 лет назад
0
respect_gg, подробнее...., не сбиает в каком случае ? берсерк тоже не сбивает приказ, но если его триггерно отдать, то сбивает, а тут надо у предмета да ещё и перезарядку запустить
0
26
5 лет назад
Отредактирован Extremator
0
Bergi_Bear:
как ты запустишь кд предмет?, в этом сама и соль же!
Вариант А - каст через руну ладно, тебе оно не нравится
Вариант Б - грёбаный амулет, который запускается с каста даммика
Вариант В - промутить с эксгумацией я на предметах не пробовал, но на юнитах норм, так что не даю 100%
Вариант Г - mh
и чисто кастомная адоптация от меня
Вариант Д - заменять предмет неактивной копией (примерно как у тебя), и отображать числовое КД предмета за счёт уменьшения на нём зарядов (вообще так можно сделать параллельное истечение КД на одинаковых предметах)
Да, заряды это такое себе... но! я делал дотовские транквиллы, которые отрубают от получения героем любого урона на 8 сек, и отображение по-секундного КД никак негативно не сказалось на визуале
0
32
5 лет назад
0
Extremator, я в курсе что ты знаешь, и спрашивал respect_gg, , темболее ты описал всё то что я сам предложил в сообщениях выше, очень смешно, что ты мне в качестве ответа кидаешь, мои же предложения
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.