Способ реализации:
Версия Warcraft:

Орбитальная бомбардировка

MUI: да
Импорт: иконка, точка, снаряд, радар
Утечки: нет
Требования: JNGP
Описание: Герой сканирует указанное место и наносит урон в случайных точках.

Скриншот

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

Перенос в свою карту
Спообности
  • 'AHob' Орбитальная бомбардировка (герой) "farsight"
Войска
  • 'hobd' Орбитальная бомбардировка (цель)
Заклинания/эффекты
  • 'XHob' Орбитальная бомбардировка (разведка)
Триггеры
  • SpellOrbitalBomb
Импорт
  • Effect\ArtilleryStrike.mdx
  • Effect\PointTarget.mdx
  • Effect\Radar.mdx
  • ReplaceableTextures\CommandButtons\BTNFireStrike.blp
  • ReplaceableTextures\CommandButtonsDisabled\DISBTNFireStrike.blp
Настройка
constant integer AbilityID = 'AHob'; // Равкод способности
constant real StrikeDelay = 2; // Задержка перед ударом

constant integer DummyPoint = 'hobd';
constant player DummyOwner = Player(PLAYER_NEUTRAL_PASSIVE);

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

// Задержка перед взрывом
function getExplodeDelay(unit caster, integer level) -> real {
    return 2.0;
}

// Период появления взрывов
function getStrikePeriod(unit caster, integer level) -> real {
    return 0.25;
}  

// Количество 
function getStrikeCount(unit caster, integer level) -> integer {
    return 5*level;
}

// Радиус сканирования
function getScanRange(unit caster, integer level) -> integer {
    return 400;
}

function getDamageRange(unit caster, integer level) -> integer {
    return 150;
}

// Проверка целей
function checkTarget(unit caster, unit target) -> boolean {
    return (
        !IsUnitType(target, UNIT_TYPE_FLYING) // Не летающий
        &&
        !IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) // Восприимчив к магии
        &&
        IsPlayerEnemy(GetOwningPlayer(caster), GetOwningPlayer(target)) // Враг
    );
}

// Функция, вызываемая при нанесении урона
function onDamage(unit caster, unit target, integer level){
    real damage = level*50;
    UnitDamageTarget(caster, target, damage, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
}
Код заклинания
//! zinc
library SpellOrbitalBomb {
    constant integer AbilityID = 'AHob'; // Равкод способности
    constant real StrikeDelay = 2; // Задержка перед ударом

    constant integer DummyPoint = 'hobd';
    constant player DummyOwner = Player(PLAYER_NEUTRAL_PASSIVE);

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

    // Задержка перед взрывом
    function getExplodeDelay(unit caster, integer level) -> real {
        return 2.0;
    }

    // Период появления взрывов
    function getStrikePeriod(unit caster, integer level) -> real {
        return 0.25;
    }  

    // Количество 
    function getStrikeCount(unit caster, integer level) -> integer {
        return 5*level;
    }

    // Радиус сканирования
    function getScanRange(unit caster, integer level) -> integer {
        return 400;
    }

    function getDamageRange(unit caster, integer level) -> integer {
        return 150;
    }

    // Проверка целей
    function checkTarget(unit caster, unit target) -> boolean {
        return (
            !IsUnitType(target, UNIT_TYPE_FLYING) // Не летающий
            &&
            !IsUnitType(target, UNIT_TYPE_MAGIC_IMMUNE) // Восприимчив к магии
            &&
            IsPlayerEnemy(GetOwningPlayer(caster), GetOwningPlayer(target)) // Враг
        );
    }

    // Функция, вызываемая при нанесении урона
    function onDamage(unit caster, unit target, integer level){
        real damage = level*50;
        UnitDamageTarget(caster, target, damage, false, true, ATTACK_TYPE_MAGIC, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS);
    }
    
    //
    // Заклинание
    //
    function isUnitAlive(unit target) -> boolean {
        return GetWidgetLife(target) > 0.405;
    }
    
    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() == AbilityID;
        }));
        TriggerAddAction(t, function(){
            unit caster = GetTriggerUnit();
            integer level = GetUnitAbilityLevel(caster, AbilityID);
            real r, range = I2R(getScanRange(caster, level));
            real xt = GetSpellTargetX();
            real yt = GetSpellTargetY();
            real x, y, angle;
            integer count = getStrikeCount(caster, level);
            timer t = CreateTimer();
            integer i, pk = GetHandleId(t);
            real period = getStrikePeriod(caster, level);
            real delay = getExplodeDelay(caster, level);
            
            SaveUnitHandle(HT, pk, 0, caster);
            SaveReal(HT, pk, 0, 0); // elapsed
            SaveReal(HT, pk, 1, period); // period
            SaveReal(HT, pk, 2, delay); // delay
            SaveReal(HT, pk, 3, getDamageRange(caster, level)); // damage range
            SaveInteger(HT, pk, 0, level);
            SaveInteger(HT, pk, 1, count);
            SaveInteger(HT, pk, 2, 0); // created
            SaveInteger(HT, pk, 3, 0); // exploaded
            for(0 <= i < count){
                angle = GetRandomReal(0, 360);
                r = GetRandomReal(0, range);
                x = xt + r * Cos(angle * bj_DEGTORAD);
                y = yt + r * Sin(angle * bj_DEGTORAD);
                SaveReal(HT, pk, 10 + i, x);
                SaveReal(HT, pk, 10 + i + count, y);                
            }
            
            TimerStart(t, period, true, function(){
                timer t = GetExpiredTimer();
                integer pk = GetHandleId(t);
                unit caster = LoadUnitHandle(HT, pk, 0);
                integer level = LoadInteger(HT, pk, 0);
                integer count = LoadInteger(HT, pk, 1);
                integer created = LoadInteger(HT, pk, 2); // created
                integer exploaded = LoadInteger(HT, pk, 3); // exploaded
                real elapsed = LoadReal(HT, pk, 0);
                real period = LoadReal(HT, pk, 1);
                real delay = LoadReal(HT, pk, 2);
                real x, y;
                group g = CreateGroup();
                unit u;
                
                SaveReal(HT, pk, 0, elapsed + period);
                
                if (created < count){
                    x = LoadReal(HT, pk, 10 + created);
                    y = LoadReal(HT, pk, 10 + created + count);
                    SaveUnitHandle(HT, pk, 10 + created, CreateUnit(DummyOwner, DummyPoint, x, y, GetRandomReal(0, 360)));
                    SaveInteger(HT, pk, 2, created + 1);
                }
                
                if (elapsed > delay && exploaded < count){
                    x = LoadReal(HT, pk, 10 + exploaded);
                    y = LoadReal(HT, pk, 10 + exploaded + count);
                    SaveInteger(HT, pk, 3, exploaded + 1);
                    RemoveUnit(LoadUnitHandle(HT, pk, 10 + exploaded));
                    DestroyEffect(AddSpecialEffect("Effect\\ArtilleryStrike.mdx", x, y));
                    GroupEnumUnitsInRange(g, x, y, LoadReal(HT, pk, 3), Filter(function() -> boolean {
                        return isUnitAlive(GetFilterUnit());
                    }));
                    while(true){
                        u = FirstOfGroup(g);
                        if (u == null) { break; }
                        if (checkTarget(caster, u)){
                            onDamage(caster, u, level);
                        }
                        GroupRemoveUnit(g, u);
                    }
                }
                
                if (created >= count && exploaded >= count){
                    PauseTimer(t);
                    DestroyTimer(t);
                    FlushChildHashtable(HT, pk);
                }
                
                DestroyGroup(g); g = null;
                u = null;
                caster = null;
                t = null;
            });
            
            t = null;
            caster = null;
        });
    }
}
//! endzinc
`
ОЖИДАНИЕ РЕКЛАМЫ...
26
хорошее сочетание эффектов и реализации)
21
У меня чёт не отображается эффект обстрела
Радар и цели есть
30
У меня чёт не отображается эффект обстрела
Может нужно параметры графики на максимум выставить или компьютер перезагрузить.
21
Может нужно параметры графики на максимум выставить или компьютер перезагрузить.
Графика вроде стояла на максимум
Я позже чекну с перезагрузкой
Если у кого тоже не показывается, скажите плз и как исправили, мне интересно в чём прикол
NazarPunk:
А у тебя не было такого что пропадает отображение выстрелов? в этой наработке
30
А у тебя не было такого что пропадает отображение выстрелов?
Изображение нет, но вот звуки не все проигрываются из-за ограничений вара.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.