Тёмный ворон

Добавлен , опубликован
Итак заклинания героя Тёмный ворон
Тёмный ворон является магом,но вот беда не логичто иметь дальнюю атаку магу если у него не отнимается при атаке мана,он же как бы стреляет магией поэтому тут сделана не большая системка(а тачнее микро система) что при применение магической атаки у него появляется дальняя атака и отнимается мана при атаке
А теперь о заклинаниях,для просмотра и компиляции карты нужен Jass New Gen Pack эксперементальная сборка так как пишу на cJass.
Библиотеки не нужны так как основная библиотека у меня написанно в нестандартном коде а это
#define int   = integer //короткое названия типа Integer
#define void  = nothing // короткое название типа Nothing
#define bool  = boolean // короткое название типа Boolean
#define h = bj_lastCreatedHashtable 
// я пишу всё на Jass переменные bj не используются,слудовательно для избежания 
//создания переменной Хеш-таблица использую переменную bj_lastCreatedHashtable и вместо этого длинного названия 
//использую h
#define PFG = bj_forceRandomCurrentPick //это переменная bj используется в фильтрах группы и служит только для него,надо 
//как то передовать игрока
теперь о триггере RAW, там написан комментарий о всех используем RAW кодах в карте
Вот такой
/* ТЁМНЫЙ ВОРОН
    A000 - Тёмный ворон (Герой - основная форма)
    B000 - Полёт ворона (Бафф)
    B001 - Аура мудрости (Бафф)
    C000 - Полёт ворона (Спелл - герой)
    C001 - Призыв ворон (Спелл - герой)
    C002 - Аура мудрости (Спелл - герой)
    C003 - Теневые лучи (Спелл - герой)
    d000 - Ворон (Дамми)
    d001 - Полёт ворона (Дамми)
    d002 - Теневой луч (Дамми)
    E000 - Полёт ворона (Дамми - спелл)
    E004 - Посох ворона (Дальняя атака)
    E005 - Потеря маны (Посох ворона)
    F000 - Тёмный ворон (Герой - дальняя атака)
    G000 - Аура мудрости (Эффект - уровень 1)
    G001 - Аура мудрости (Эффект - уровень 2)
    G002 - Аура мудрости (Эффект - уровень 3)
    G003 - Аура мудрости (Эффект - уровень 4)
*/
Наконец-то мы подошли к заклинаниям

1. Полёт ворона (триггер Flight Raven)

Описание:
Герой превращается в ворона и летит в указанную точку,по достижению её превращается обратно нанося всем врагам в радиусе урон и замедляет их
Как устроено:
Проверяем проходимость указаной точки,если не проходима оставляем героя на месте,если проходима переносим его туда,скрываем юнита,создаём дамми-ворона и перемещаем пока не достигнет указаной точки,затем убиваем дамми и показываем юнита,пикаем врагов наносим урон и даём замедление даммиками
Настройка:
Вы всё найдёте в define ,как определить скорость ворона?
ответ легко все учили математику есть Period и Step
Period = .04
Step = 40
Speed = Step / Period = 40/0.04 = 1000
DMG = GetHeroInt(u,true) - это интелект героя тут вы сами можете настроить высчитывая уровень способности или нет
в примере сделано что с уровнем увеличивается дальность применения в РО
cJass
library FlightRaven initializer Init{
    
    define{
        private Trigger = gg_trg_Flight_Raven
        private Event = EVENT_PLAYER_UNIT_SPELL_EFFECT
        private AT = ATTACK_TYPE_NORMAL
        private DT = DAMAGE_TYPE_NORMAL
        private WT = WEAPON_TYPE_WHOKNOWS
        private PT = PATHING_TYPE_WALKABILITY
        private UT = UNIT_TYPE_DEAD
        private sId = 'C000'
        private dId = 'd000'
        private cId = 'd001'
        private bId = 'BTFL'
        private Order = 852075 // "slow"
        private eId = "Abilities\\Spells\\Items\\AIil\\AIilTarget.mdl"
        private eId2 = "Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayTarget.mdl"
        private Attach = "origin"
        private Animation = "spell"
        private TimeLife = .2
        private Period = .04
        private Step = 40.
        private Range = 200.
        private DMG = GetHeroInt(u,true)
    }
    
    
    private bool Cond(){
        return GetSpellAbilityId() == sId
    }
    
    private bool Filter(){
        unit f = GetFilterUnit()
        bool b = IsUnitEnemy(f,PFG) && !IsUnitType(f,UT)
        f = null
        return b
    }
    
    private void GroupAction(group g, unit u){
        unit e = null
        unit d = null
        real damage = DMG
        player p = GetOwningPlayer(u)
        PFG = p
        GroupEnumUnitsInRange(g,GetUnitX(u),GetUnitY(u),Range,Condition(function Filter))
        do{
            e = FirstOfGroup(g)
            exitwhen e == null
            d = CreateUnit(p,cId,GetUnitX(e),GetUnitY(e),0)
            UnitApplyTimedLife(d,bId,TimeLife)
            IssueTargetOrderById(d,Order,e)
            DestroyEffect(AddSpecialEffectTarget(eId2,e,Attach))
            UnitDamageTarget(u,e,damage,false,false,AT,DT,WT)
            GroupRemoveUnit(g,e)
        }
        DestroyGroup(g)
        d = null
        e = null
    }
    
    private void Move(){
        timer t = GetExpiredTimer()
        int id = GetHandleId(t)
        unit u = LoadUnitHandle(h,id,0)
        unit d = LoadUnitHandle(h,id,1)
        real a = LoadReal(h,id,3)
        if !IsUnitInRange(u,d,Step){
            SetUnitPosition(d,GetUnitX(d)+Cos(a)*Step,GetUnitY(d)+Sin(a)*Step)
        }
        else{
            GroupAction(LoadGroupHandle(h,id,2),u)
            PauseUnit(u,false)
            SetUnitPathing(u,true)
            KillUnit(d)
            ShowUnit(u,true)
            DestroyEffect(AddSpecialEffectTarget(eId,u,Attach))
            SetUnitAnimation(u,Animation)
            if GetLocalPlayer() == GetOwningPlayer(u){
                ClearSelection()
                SelectUnit(u,true)
            }
            FlushChildHashtable(h,id)
            DestroyTimer(t)
        }
        d = null
        u = null
        t = null
    }
    
    private void Action(){
        timer t = CreateTimer()
        int id = GetHandleId(t)
        unit u = GetTriggerUnit()
        real x = GetUnitX(u)
        real y = GetUnitY(u)
        real sx = GetSpellTargetX()
        real sy = GetSpellTargetY()
        real a = Atan2(sy - y,sx - x)
        unit d = CreateUnit(GetOwningPlayer(u),dId,x,y,Rad2Deg(a))
        SetUnitColor(d,ConvertPlayerColor(12))
        if !IsTerrainPathable(sx,sy,PT){
            SetUnitPosition(u,sx,sy)
        }
        ShowUnit(u,false)
        PauseUnit(u,true)
        SetUnitPathing(u,false)
        SaveUnitHandle(h,id,0,u)
        SaveUnitHandle(h,id,1,d)
        SaveGroupHandle(h,id,2,CreateGroup())
        SaveReal(h,id,3,a)
        TimerStart(t,Period,true,function Move)
        d = null
        u = null
        t = null
    }
    
    private void Init(){
        Trigger = CreateTrigger() 
        PUEvent(Trigger,Event)
        TriggerAddCondition(Trigger,function Cond)
        TriggerAddAction(Trigger,function Action)
    }
    
}

2. Призыв ворон(триггер SummonCrows)

Описание:
Призывает ворон которые атакую указанную цель
Как устроенно:
Генерируем случайную точку в нужном радиусе и с нужным углом,затем создаём циклом сколько нужно ворон и отдаём приказ атаковать цель
Примечание:
Вороны не атакуемы(москиты) и жизнь ворон настраиваеться в define
Хотел сначала сделать после нанесения урона убивать птицу,но потом возник бы бафф что если цель умерла то птица бы оставалась поэтому просто даёться таймер жизни.
Настройка:
TimeLife = время жизни
NCrows = кол-во птиц,стоит 2 * Уровень способности,урон у птицы настраиваем в РО у юнита Ворон ('d000')
cJass
library SummonCrows initializer Init{

    define{
        private Trigger = gg_trg_Summon_Crows
        private Event = EVENT_PLAYER_UNIT_SPELL_EFFECT
        private sId = 'C001'
        private dId = 'd000'
        private bId = 'BTFL'
        private Order = 851983 // "attack"
        private TimeLife = 3.
        private NCrows = 2*GetUnitAbilityLevel(u,sId)
        private Dist = 200.
    }
    
    private bool Cond(){
        return GetSpellAbilityId() == sId
    }
    
    private void Action(){
        unit u = GetTriggerUnit()
        unit d = GetSpellTargetUnit()
        unit e = null
        real x = GetUnitX(u)
        real y = GetUnitY(u)
        real a = Atan2(GetUnitY(d) - y,GetUnitX(d) - x)
        int lvl = NCrows
        real r = 0.
        real step = 0.
        int i = 0
        whilenot i == lvl{
            r = GetRandomReal(0.,6.2832)
            step = GetRandomReal(0.,Dist)
            e = CreateUnit(GetOwningPlayer(u),dId,x+step*Cos(r),y+step*Sin(r),Rad2Deg(a))
            SetUnitColor(e,ConvertPlayerColor(12))
            IssueTargetOrderById(e,Order,d)
            UnitApplyTimedLife(e,bId,TimeLife)
            i = i + 1
        }
        d = null
        u = null
        e = null
    }
    
    private void Init(){
        Trigger = CreateTrigger()
        PUEvent(Trigger,Event)
        TriggerAddCondition(Trigger,function Cond)
        TriggerAddAction(Trigger,function Action)
    }
    
}

3.​Аура мудрости(триггер ​Wisdom ​Aura)

Описание:
Всем юнитам в радиусе даётся дополнительное максимальное здоровье
Как устроенно:
Ауры вообще сложно делать,так как надо отслеживать носителя,что тут и сделанно, сперва отслеживается носитель затем юниты в радиусе и если урвоень полученной неообходимой способности не совпадает или меньше то мы даём спелл, при большем радиусе проверяем что нет бафф ауры и удаляем эту способность, что бы не затирать спеллы если етсь другие юниты с этой аурой,сложновато было оформить всё
Примечание:
радиус укзаный в код должен быть приблизительно равный радиусу в РО,так как удаление дополнительного здоровье идёт првоеркой на бафф, а добавление в проверке радиуса
Настройка:
Вся настройка идёт в РО у заклинаний Мудрость(Уровень 1...N) так указываем дополнительное здоровье,также если вы хотите сделать свои навыки то использовать спеллы необходимо с подряд идущими равкодами,как тут
G000 G001 G002 G003
указав в коде в define первый из них в пункте aId так как там идёт счёт так
cJass
library WisdomAura initializer Init{
    
    define{
        private Trigger = gg_trg_Wisdom_Aura
        private UT = UNIT_TYPE_HERO
        private UT2 = UNIT_TYPE_DEAD
        private sId = 'C002'
        private aId = 'G000'
        private bId = 'B001'
        private Range = 601.
        private MaxLvl = 4
    }
    
    private bool Filter(){
        return GetUnitAbilityLevel(GetFilterUnit(),sId) > 0
    }
    
    private bool Filter2(){
        unit f = GetFilterUnit()
        bool b = IsUnitAlly(f,PFG) && IsUnitType(f,UT) && !IsUnitType(f,UT2)
        f = null
        return b
    }
    
    private void ClearAbility(unit u){
        int i = 0
        whilenot i > MaxLvl-1{
            UnitRemoveAbility(u,aId+i)
            i = i + 1
        }
    }
    
    private int GetUnitAura(unit u){
        int i = 0
        whilenot i > MaxLvl-1{
            if GetUnitAbilityLevel(u,i+aId) > 0{
                return i+1
            }
        i = i + 1
        }
        return 0
    }
    
    private void GroupAction(unit e,int lvl){
        unit u = null
        group g = CreateGroup()
        GroupEnumUnitsInRect(g,bj_mapInitialPlayableArea,Condition(function Filter2))
        do{
            u = FirstOfGroup(g)
            exitwhen u == null
            if IsUnitInRange(u,e,Range){
                if lvl != GetUnitAura(u) && GetUnitAbilityLevel(u,sId) <= lvl{
                    ClearAbility(u)
                    UnitAddAbility(u,lvl+aId-1)
                    UnitMakeAbilityPermanent(u,true,lvl+aId-1)
                }
            }else{
                if GetUnitAbilityLevel(u,bId) == 0{
                    ClearAbility(u)
                }
            }
            GroupRemoveUnit(g,u)
        }
        DestroyGroup(g)
        g = null
        u = null
    }
    
    
    private void Action(){
        unit u = null
        group g = CreateGroup()
        GroupEnumUnitsInRect(g,bj_mapInitialPlayableArea,Condition(function Filter))
        do{
            u = FirstOfGroup(g)
            exitwhen u == null
            int lvl = GetUnitAbilityLevel(u,sId)
            if lvl > 0{
                PFG = GetOwningPlayer(u)
                GroupAction(u,lvl)
            }
            GroupRemoveUnit(g,u)
        }
        DestroyGroup(g)
        g = null
        u = null
    }
    
    private void Init(){
        timer t = CreateTimer()
        TimerStart(t,1.,true,function Action)
        t = null
    }
    
}

4. Теневые лучи(триггер Shadow Beams)

Описание:
Вокруг юнита создаются теневые лучи и атакую все цели вокруг нанося урон
Как устроенно:
Сложность заклинания в том что создаются даммики и летят в каждого пикнутого юнита пока не достигнут цели,при касте делаем расчёт сколько целей попало под заклинание создаём даммиков,заносим их на хендл кастера и цели на хендл группы,а на хендл таймера я заношу кастера группу и число даммиков и целей(оно одинаоковое)
далее мы таймеров двигаем каждого дамми к целе при достижении убиваем и когда все даммики достигнут цели удаляем таймер и группу и всё очищаем
Настройка:
Настройка как всегда в define
DMG это урон который я сделал (5+(5*Уровень способности)*кол-во целей) + Разум героя = он равен получилось
10/15/20 урона за цель + разум героя
скорость снаряда равна всё по тойже формуле Step/Period = 30/0.03 = 1000
cJass
library ShadowBeams initializer Init{
    
    define{
        private Trigger = gg_trg_Shadow_Beams
        private Event = EVENT_PLAYER_UNIT_SPELL_EFFECT
        private AT = ATTACK_TYPE_NORMAL
        private DT = DAMAGE_TYPE_NORMAL
        private WT = WEAPON_TYPE_WHOKNOWS
        private UT = UNIT_TYPE_DEAD
        private dId = 'd002'
        private sId = 'C003'
        private eId = "Abilities\\Spells\\Undead\\DeathandDecay\\DeathandDecayTarget.mdl"
        private attach  = "origin"
        private Step = 30.
        private Range = 900.
        private Period = .03
        private DMG = ((5.+(5.*GetUnitAbilityLevel(u,sId)))*i)+GetHeroInt(u,true)
    }
    
    private bool Cond(){
        return GetSpellAbilityId() == sId
    }
    
    private bool Filter(){
        unit f = GetFilterUnit()
        bool b = IsUnitEnemy(f,PFG) && !IsUnitType(f,UT)
        f = null
        return b
    }
    
    private void Move(){
        timer t = GetExpiredTimer()
        int id = GetHandleId(t)
        unit u = LoadUnitHandle(h,id,0)
        int uid = GetHandleId(u)
        group g = LoadGroupHandle(h,id,1)
        int gid = GetHandleId(g)
        int i = LoadInteger(h,id,2)
        int nulled = 0
        real dmg = DMG
        unit array dummy
        unit array target
        int n = 1
        whilenot n > i{
            dummy[n] = LoadUnitHandle(h,uid,n)
            target[n] = LoadUnitHandle(h,gid,n)
            if dummy[n] != null{
                real x = GetUnitX(dummy[n])
                real y = GetUnitY(dummy[n])
                real a = Atan2(GetUnitY(target[n]) - y,GetUnitX(target[n]) - x)
                SetUnitPosition(dummy[n],x + Cos(a)*Step,y + Sin(a)*Step)
                if IsUnitInRange(dummy[n],target[n],Step){
                    UnitDamageTarget(u,target[n],dmg,false,false,AT,DT,WT)
                    DestroyEffect(AddSpecialEffectTarget(eId,target[n],attach))
                    RemoveUnit(dummy[n])
                    SaveUnitHandle(h,uid,n,null)
                    SaveUnitHandle(h,gid,n,null)
                }
            }
            n = n + 1 
        }
        n = 1
        whilenot n > i{
            if dummy[n] == null{
                nulled = nulled + 1
            }else{
                dummy[n] = null
            }
            target[n] = null
            n = n + 1
        }
        if nulled == i{
            FlushChildHashtable(h,uid)
            FlushChildHashtable(h,gid)
            FlushChildHashtable(h,id)
            DestroyGroup(g)
            DestroyTimer(t)
        }
        t = null
        u = null
        g = null
    }
    
    private int GroupAction(group g,unit u){
        real x = GetUnitX(u)
        real y = GetUnitY(u)
        int uid = GetHandleId(u)
        int gid = GetHandleId(g)
        player p = GetOwningPlayer(u)
        unit e = null
        int i = 0
        PFG = p
        GroupEnumUnitsInRange(g,x,y,Range,Condition(function Filter))
        do{
            e = FirstOfGroup(g)
            exitwhen e == null
            i = i + 1
            SaveUnitHandle(h,uid,i,CreateUnit(p,dId,x,y,0.))
            SaveUnitHandle(h,gid,i,e)
            GroupRemoveUnit(g,e)
        }
        e = null
        return i
    }
    
    private void Action(){
        unit u = GetTriggerUnit()
        timer t = CreateTimer()
        group g = CreateGroup()
        int id = GetHandleId(t)
        SaveUnitHandle(h,id,0,u)
        SaveGroupHandle(h,id,1,g)
        SaveInteger(h,id,2,GroupAction(g,u))
        TimerStart(t,Period,true,function Move)
        t = null
        g = null
        u = null
    }
    
    private void Init(){
        Trigger = CreateTrigger()
        PUEvent(Trigger,Event)
        TriggerAddCondition(Trigger,function Cond)
        TriggerAddAction(Trigger,function Action)
    }
    
}
На этом вроде всё
Пользуйтесь на здоровье
Если вы нашли баги пишите, как улучшить что исправить также пишите,буду рад
Спеллы не сложные и выполнены на хорошем уровне(не иделаьном,я не знаю что значит идеал,но считаю что сделанно не плохо)
Вопросы также задавайте как,что исправить или что настроить
1
29
12 лет назад
1
Всё слишком просто.
минут за 30 написал?
я имел ввиду код
1
18
12 лет назад
1
ну я не делаю всё сверх естесвенно просто и красиво
с аурой долго мучался а так не долго)
1
29
12 лет назад
1
ну вообще... оформлено красиво
у меня с отступами всегда все ужасно :3
1
18
12 лет назад
1
таб в помощь))
1
29
12 лет назад
1
а с табом еще хуже.. именно в условиях и циклах)
плюсанул короч
1
18
12 лет назад
1
Msey, у меня все отступы табуляцией сделаны, в JNGP норм, это в блокноте какие то отступы большие делает)
1
15
12 лет назад
1
Klop, статья зашибись, постараюсь раскурить. Имхо - делал бы кто-нибудь подобное для ск2, цены б ему небыло.
1
18
12 лет назад
1
Амбидекстрия, это не статья это готовые спеллы) и герой там описано настройка и работа спеллов)
0
15
12 лет назад
0
Klop, я всёравно рассматриваю это как пособие
карту бы получше оформил
0
18
12 лет назад
0
зачем? там скилет всё что надо для теста спелла бугры вода границы и враги)
Чтобы оставить комментарий, пожалуйста, войдите на сайт.