, Гильдия «Черамор»

Заклинание: Похищение Жизни

» опубликован
» Способ реализации: Jass
» Тип: Способность

Похищение Жизни

MUI: да
Импорт: нет
Утечки: нет
Требования: JNGP
Описание: Похищение здоровья жертвы и передача его герою.

Скриншот

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

» Перенос в свою карту
Способности
  • 'AUdl' Похищение жизни (герой)
Триггеры
  • SpellDrainLife
» Настройки
constant integer ABILITY_ID = 'AUdl'; // Равкод способности
constant string LIGHTNING_TYPE = "DRAL"; // Тип молнии
constant real LIGHTNING_Z = 50; // Высота молнии
constant real TIMER_PERIOD = 0.03125; // Период таймера: 1/32 секунды
constant real DAMAGE_PERIOD = 1; // Период нанесения урона: 1 секунда

constant string EFFECT_CASTER_MODEL = "Abilities\\Spells\\Other\\Drain\\DrainCaster.mdl";
constant string EFFECT_CASTER_ATTACH = "chest";
constant string EFFECT_TARGET_MODEL = "Abilities\\Spells\\Other\\Drain\\DrainTarget.mdl";
constant string EFFECT_TARGET_ATTACH = "chest";

hashtable HT = InitHashtable(); // Хэштаблица, можете вписать туда вашу, например:
// hashtable HT = udg_HashTable;
constant integer HO = 0; //

// Время действия
function getExpireTime(unit caster, integer level) -> real {
    return I2R(5+level);
}

// Максимальная дальность
function getMaxDistance(unit caster, integer level) -> real {
    return I2R(1000 + 200*level);
}

// Функция, вызываемая при нанесении урона
function onDamage(unit caster, unit target, integer level){
    real damage = 20 + level*20; // 40/60/80
    UnitDamageTarget(caster, target, damage, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
    SetWidgetLife(caster, GetWidgetLife(caster) + damage);
}
» Код заклинания
// !nocjass
native UnitAlive takes unit u returns boolean

//! zinc
library SpellDrainLife {
    constant integer ABILITY_ID = 'AUdl'; // Равкод способности
    constant string LIGHTNING_TYPE = "DRAL"; // Тип молнии
    constant real LIGHTNING_Z = 50; // Высота молнии
    constant real TIMER_PERIOD = 0.03125; // Период таймера: 1/32 секунды
    constant real DAMAGE_PERIOD = 1; // Период нанесения урона: 1 секунда
    
    constant string EFFECT_CASTER_MODEL = "Abilities\\Spells\\Other\\Drain\\DrainCaster.mdl";
    constant string EFFECT_CASTER_ATTACH = "chest";
    constant string EFFECT_TARGET_MODEL = "Abilities\\Spells\\Other\\Drain\\DrainTarget.mdl";
    constant string EFFECT_TARGET_ATTACH = "chest";
    
    hashtable HT = InitHashtable(); // Хэштаблица, можете вписать туда вашу, например:
    // hashtable HT = udg_HashTable;
    constant integer HO = 0; //
    
    // Время действия
    function getExpireTime(unit caster, integer level) -> real {
        return I2R(5+level);
    }
    
    // Максимальная дальность
    function getMaxDistance(unit caster, integer level) -> real {
        return I2R(1000 + 200*level);
    }
    
    // Функция, вызываемая при нанесении урона
    function onDamage(unit caster, unit target, integer level){
        real damage = 20 + level*20; // 40/60/80
        UnitDamageTarget(caster, target, damage, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
        SetWidgetLife(caster, GetWidgetLife(caster) + damage);
    }
    
    /*
    *
    */
    constant integer HO_CASTER_DRAIN = HO;
    
    // Polar: https://xgm.guru/p/wc3/polar
        location LOCZ = Location(0, 0);
        function GetTerrainZ(real x, real y) -> real {
            MoveLocation(LOCZ, x, y);
            return GetLocationZ(LOCZ);
        }
        function GetUnitZ(unit target) -> real {
            return GetTerrainZ(GetUnitX(target), GetUnitY(target)) + GetUnitFlyHeight(target);
        }
        function DistanceBetweenCoords3D(real x1, real y1, real z1, real x2, real y2, real z2) -> real {
            real dx = x2 - x1;
            real dy = y2 - y1;
            real dz = z2 - z1;
            return SquareRoot(dx*dx + dy*dy + dz*dz);
        }
    // endPolar
    struct drain {
        unit caster, target;
        real period, time, expire, maxDist;
        integer level;
        lightning lighting;
        timer tymer;
        effect effectCaster, effectTarget;
    
        static method create(unit caster, unit target) -> drain {
            drain this = drain.allocate();
            integer pk = GetHandleId(caster);
            this.tymer = CreateTimer();
            SaveInteger(HT, pk, HO_CASTER_DRAIN, this);
            this.caster = caster;
            this.target = target;
            this.level = GetUnitAbilityLevel(caster, ABILITY_ID);
            this.period = 0;
            this.time = 0;
            this.maxDist = getMaxDistance(this.caster, this.level);
            this.expire = getExpireTime(this.caster, this.level);
            
            this.lighting = AddLightningEx(
                LIGHTNING_TYPE,
                true,
                GetUnitX(caster),
                GetUnitY(caster),
                GetUnitZ(caster) + LIGHTNING_Z,
                GetUnitX(target),
                GetUnitY(target),
                GetUnitZ(target) + LIGHTNING_Z
            );
            
            this.effectCaster = AddSpecialEffectTarget(EFFECT_CASTER_MODEL, caster, EFFECT_CASTER_ATTACH);
            this.effectTarget = AddSpecialEffectTarget(EFFECT_TARGET_MODEL, target, EFFECT_TARGET_ATTACH);
            
            SaveInteger(HT, GetHandleId(this.tymer), 0, this);
            TimerStart(this.tymer, TIMER_PERIOD, true, function drain.callback);
            return this;
        }
        
        method destroy(){
            RemoveSavedInteger(HT, GetHandleId(this.caster), HO_CASTER_DRAIN);
            PauseTimer(this.tymer); DestroyTimer(this.tymer); this.tymer = null;
            DestroyLightning(this.lighting); this.lighting = null;
            DestroyEffect(this.effectCaster); this.effectCaster = null;
            DestroyEffect(this.effectTarget); this.effectTarget = null;
            this.caster = null;
            this.target = null;
            this.deallocate();
        }
        
        static method callback(){
            timer t = GetExpiredTimer();
            integer pk = GetHandleId(t);
            real xc, yc, zc, xt, yt, zt;
            drain this = LoadInteger(HT, pk, 0);
            t = null;
            
            this.period = this.period + TIMER_PERIOD;
            if (this.period >= DAMAGE_PERIOD){
                this.period = 0;
                onDamage(this.caster, this.target, this.level);
            }
            
            xc = GetUnitX(this.caster);
            yc = GetUnitY(this.caster);
            zc = GetUnitZ(this.caster) + LIGHTNING_Z;
            xt = GetUnitX(this.target);
            yt = GetUnitY(this.target);
            zt = GetUnitZ(this.target) + LIGHTNING_Z;
            
            MoveLightningEx(this.lighting, true, xc, yc, zc, xt, yt, zt);
            
            this.time = this.time + TIMER_PERIOD;
            if (
                !UnitAlive(this.caster)
                ||
                !UnitAlive(this.target)
                ||
                this.time >= this.expire
                ||
                DistanceBetweenCoords3D(xc, yc, zc, xt, yt, zt) >= this.maxDist
                ||
                GetUnitCurrentOrder(this.caster) == 851973
            ) {
                FlushChildHashtable(HT, pk);
                this.destroy();
            }
        }
    }

    function onInit(){
        integer i;
        trigger t;
        
        t = CreateTrigger();
        for (0 <= i < bj_MAX_PLAYER_SLOTS){
            TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null);
        }
        TriggerAddCondition(t, Filter(function() -> boolean {
            return GetSpellAbilityId() == ABILITY_ID;
        }));
        TriggerAddAction(t, function(){
            unit caster = GetTriggerUnit();
            integer pk = GetHandleId(caster);
            drain current;
            if (HaveSavedInteger(HT, pk, HO_CASTER_DRAIN)){
                current = LoadInteger(HT, pk, HO_CASTER_DRAIN);
                current.destroy();
            }
            drain.create(caster, GetSpellTargetUnit());
            caster = null;
        });
    }
}
//! endzinc
// !endnocjass


Просмотров: 922

» Лучшие комментарии


Rockmaf #1 - 6 месяцев назад -7
Это специально то что они приближаюся к друг - друг?
8gabriel8 #2 - 6 месяцев назад 2
Да, высасывание жизни работает при движении, его просили в вопросах.
Hodor #3 - 6 месяцев назад 0
NazarPunk, могу идею подкинуть)

последний комментарий
у меня просто времени нету)
Bergi_Bear #4 - 6 месяцев назад 0
UrsaBoss, он вроде бы сделал этот триггер, я помогал ему в дискорде и потом ещё захождение на этот дом
quq_CCCP #5 - 6 месяцев назад 8
А че эффект молнии идет откуда то из жопы? Неужели бд нельзя было с высотой сделать?
NazarPunk #6 - 6 месяцев назад 0
Неужели бд нельзя было с высотой сделать?
А к ней в придачу бд с масштабированием?
quq_CCCP #7 - 6 месяцев назад 0
NazarPunk, проверка на маштаб есть и так GetUnitScale или мемхак.
NazarPunk #8 - 6 месяцев назад 0
quq_CCCP, не уверен, что она показывает масштаб от способностей.
pro100master #9 - 6 месяцев назад (отредактировано ) 0
...