WE + свободная минутка + лень

Добавлен , опубликован
Захотелось сделать чего-нибудь в старом, добром варике...
Через часик-два, лень стала брать верх, я "наелся" и сомневаюсь что мне снова захочется (в ближайшее время) что-нибудь делать...
Не сделал и половины того что задумал, но все же решил выложить. Исполнено более-менее нормально.
Этот спелл, примерно то же самое что и огненное лассо. Сначала я хотел сделать систему запрещающую юниту выходить за определенный радиус от какой-нибудь точки, но в процессе разработки я растерял свое вдохновение и стал думать как урезать спелл.
Отличия от стокового "огненного лассо" лишь в том, что кастовать можно на одного и того же юнита, а так же у юнита-кастера и у цели "равные права". Т. е. цель может тянуть кастера, а кастер может тянуть цель, оба юнита подвижны. Решил сделать небольшой прикол с молниями, хоть как-то привлекающий интерес к способности.
Прикрепляю карту-пример. Для импорта нужно всего-лишь создать свои два спелла для включения\выключения способности и указать в дефайнах ID созданных способностей, если они отличаются от моих.
Потом скопировать мой триггер (по желанию можно удалить вспомогательную функцию CreateUnits и избавиться от некоторых дефайнов)
Настройки есть как в дефайнах так и в глобалках.
Ясное дело, для повторной компиляции нужен JNGP.
код
    library link initializer Init{
    /*
    © XGM.RU (10.02.2014)
                        By Buulichkaa
    */
        define{
        //Keywords
            int = integer
            void = nothing
            bool = boolean
            func = function
            const = constant
            class = struct
        //***************************************************************************
        //Functions
            msg(s) = DisplayTimedTextToPlayer(Player(0), 0, 0, 10, "|cFF00FFFFDEBUG|r " + s)
            Sqrt(r) = SquareRoot(r)
            GetX(u) = GetUnitX(u)
            GetY(u) = GetUnitY(u)
            SetXY(u, x, y) = { SetUnitX(u, x); SetUnitY(u, y) }
            DistBtwXY(x1, y1, x2, y2) = SquareRoot((x2-x1) * (x2-x1) + (y2-y1) * (y2-y1))
            AngBtwXY(x1, y1, x2, y2) = Atan2(y2 - y1, x2 - x1)
            Pyth(cathetus) = SquareRoot(max_dist2 - (cathetus*cathetus))
            SaveInt(u, data) = SetUnitUserData(u, data)
            GetInt(u) = GetUnitUserData(u)
        //***************************************************************************
        //Values
            Pi = 3.14159
            Pi_2 = Pi/2
            l_type = "DRAM" // lightning type
            add_height = 0 //additional lightning height
            create_id = 0x41303033
            destroy_id = 0x41303034
        //***************************************************************************
        }

        globals
            private const real max_dist = 500 //Maximum possible distance from caster to target
            private const real max_dist2 = max_dist * max_dist
            private const real max_dist_2 = max_dist / 2

            private int con_stack[]
            private int con_top = -1 
            private int lin_stack[]
            private int lin_top = -1 
            private location loc = Location(0, 0)
            
            private timer t = CreateTimer()
        endglobals

        private real GetZ(real x, real y){
            MoveLocation(loc, x, y);
            return GetLocationZ(loc);
        }
        
        private class vec{
            real x
            real y
            
            static method Set takes vec v, real ax, real ay, real bx, real by returns void
                v.x = bx - ax;
                v.y = by - ay;
            endmethod
            
            method Add takes vec a returns void
                .x = .x + a.x;
                .y = .y + a.y;
            endmethod
            
            method Multiply takes real n returns void
                .x = .x * n;
                .y = .y * n; 
            endmethod
            
            method Normalize takes nothing returns nothing
                real mod = Sqrt(.x * .x + .y * .y);
                .x = .x / mod;
                .y = .y / mod;
            endmethod
        }
        private class connection{
            unit Leader
            real l_x
            real l_y
            unit Target
            real t_x
            real t_y
            bool active
            vec v

            static method Create takes unit L, unit T returns connection
                connection newCon = connection.create();
                newCon.Leader = L;
                newCon.Target = T;
                newCon.v = vec.create();
                newCon.l_x = GetX(L);
                newCon.l_y = GetY(L);
                newCon.t_x = GetX(T);
                newCon.t_y = GetY(T);
                con_top++;
                con_stack[con_top] = newCon;
                newCon.active = true;
                return newCon;
            endmethod
            
            method Destroy takes void returns void
                .Leader = null;
                .Target = null;
                .v.destroy();
                .destroy();
                if((lin_top == -1) and (con_top == 0)){
                    PauseTimer(t);
                }
            endmethod
            
            method Exec takes void returns void
                real l_x = GetX(.Leader);
                real l_y = GetY(.Leader);
                real t_x = GetX(.Target);
                real t_y = GetY(.Target);
                if (DistBtwXY(l_x, l_y, t_x, t_y) > max_dist){
                    if ((.t_x != t_x) or (.t_y != t_y)){
                        if ((.l_x != l_x) or (.l_y != l_y)){
                            vec.Set(.v, l_x, l_y, t_x, t_y);
                            .v.Multiply(0.5);
                            real x = l_x + .v.x;
                            real y = l_y + .v.y;
                            .v.Normalize();
                            .v.Multiply(max_dist_2);
                            SetXY(.Target, x + .v.x, y + .v.y);
                            SetXY(.Leader, x - .v.x, y - .v.y);
                        }else{
                            vec.Set(.v, t_x, t_y, l_x, l_y);
                            .v.Normalize();
                            .v.Multiply(max_dist);
                            l_x = t_x + .v.x;
                            l_y = t_y + .v.y;
                            SetXY(.Leader, l_x, l_y);
                        }
                    }//((.t_x != t_x) or (.t_y != t_y))
                    elseif ((.l_x != l_x) or (.l_y != l_y)){
                            vec.Set(.v, l_x, l_y, t_x, t_y);
                            .v.Normalize();
                            .v.Multiply(max_dist);
                            t_x = l_x + .v.x;
                            t_y = l_y + .v.y;
                            SetXY(.Target, t_x, t_y);
                    }//((.l_x != l_x) or (.l_y != l_y))
                }//(DistBtwXY(l_x, l_y, t_x, t_y) > max_dist)
                .t_x = GetX(.Target);
                .t_y = GetY(.Target);
                .l_x = GetX(.Leader);
                .l_y = GetY(.Leader);
            endmethod
        }
        
        class link{
            unit caster
            unit target
            lightning l_main1
            lightning l_main2
            lightning l_1
            lightning l_2
            bool active
            connection con
            
            static method Create takes unit uc, unit ut returns link
                real ut_x = GetX(ut);
                real ut_y = GetY(ut);
                real ut_z = GetZ(ut_x, ut_y);
                real uc_x = GetX(uc);
                real uc_y = GetY(uc);
                real uc_z = GetZ(uc_x, uc_y);
                UnitRemoveAbility(uc, create_id);
                UnitAddAbility(uc, destroy_id);
                link newLink = link.create();
                newLink.caster = uc;
                newLink.target = ut;
                newLink.l_main1 = AddLightningEx(l_type, false, uc_x, uc_y, uc_z + add_height, uc_x, uc_y, uc_z + add_height);
                newLink.l_main2 = AddLightningEx(l_type, false, uc_x, uc_y, uc_z + add_height, uc_x, uc_y, uc_z + add_height);
                newLink.l_1 = AddLightningEx(l_type, false, uc_x, uc_y, uc_z + add_height, uc_x, uc_y, uc_z + add_height);
                newLink.l_2 = AddLightningEx(l_type, false, uc_x, uc_y, uc_z + add_height, uc_x, uc_y, uc_z + add_height);
                newLink.con = con.Create(uc, ut);
                newLink.active = true;
                return newLink;
            endmethod
            
            method Destroy takes void returns void
                .con.active = false;
                UnitRemoveAbility(.caster, destroy_id);
                UnitAddAbility(.caster, create_id);
                .caster = null;
                .target = null;
                DestroyLightning(.l_main1);
                DestroyLightning(.l_main2);
                DestroyLightning(.l_1);
                DestroyLightning(.l_2);
                .l_main1 = null;
                .l_main2 = null;
                .l_1 = null;
                .l_2 = null;
                .destroy();
            endmethod
            
            method Exec takes void returns void
                if IsUnitType(.target, ConvertUnitType(1)){//if trgt dead
                    .active = false;
                }else{
                    real uc_x = GetX(.caster);
                    real uc_y = GetY(.caster);
                    real uc_z = GetZ(uc_x, uc_y);
                    real ut_x = GetX(.target);
                    real ut_y = GetY(.target);
                    real ut_z = GetZ(ut_x, ut_y);
                    real dist = DistBtwXY(uc_x, uc_y, ut_x, ut_y);
                    real PythDist = Pyth(dist);
                    real ang = AngBtwXY(uc_x, uc_y, ut_x, ut_y)+(Pi_2);
                    real l_m_x1 = uc_x + PythDist * Cos(ang);
                    real l_m_y1 = uc_y + PythDist * Sin(ang);
                    real l_m_z1 = GetZ(l_m_x1, l_m_y1);
                    real l_m_x2 = uc_x + PythDist * Cos(ang+Pi);
                    real l_m_y2 = uc_y + PythDist * Sin(ang+Pi);
                    real l_m_z2 = GetZ(l_m_x2, l_m_y2);
                    MoveLightningEx(this.l_main1, false, uc_x, uc_y, uc_z + add_height, l_m_x1, l_m_y1, l_m_z1 + add_height);
                    MoveLightningEx(this.l_main2, false, uc_x, uc_y, uc_z + add_height, l_m_x2, l_m_y2, l_m_z2 + add_height);
                    MoveLightningEx(this.l_1, false, l_m_x1, l_m_y1, l_m_z1 + add_height, ut_x, ut_y, ut_z + add_height);
                    MoveLightningEx(this.l_2, false, l_m_x2, l_m_y2, l_m_z2 + add_height, ut_x, ut_y, ut_z + add_height);
                }
            endmethod
            
        }
        
        private void main(){
            int i = 0;
            loop{ //connection engine
                connection c;
                exitwhen i > con_top
                c = con_stack[i];
                if (c.active){
                    c.Exec();
                    i++;
                }else{
                    c.Destroy();
                    con_stack[i] = con_stack[con_top];
                    con_stack[con_top] = 0;
                    con_top--;
                }
            }
            
            i = 0;
            
            loop{ //link engine
                link l;
                exitwhen i > lin_top
                l = lin_stack[i];
                if (l.active){
                    l.Exec();
                    i++;
                }else{
                    l.Destroy();
                    lin_stack[i] = lin_stack[lin_top];
                    lin_stack[lin_top] = 0;
                    lin_top--;
                }
            }
        }
        
        private void events(){
            int spell = GetSpellAbilityId();
            unit uc;
            link newLink;
            if (spell == create_id){
                if (lin_top < 8191){
                    uc = GetSpellAbilityUnit();
                    newLink = link.Create(uc, GetSpellTargetUnit());
                    lin_top++;
                    lin_stack[lin_top] = newLink;
                    SaveInt(uc, newLink);
                    if(lin_top == 0){
                        TimerStart(t, .025, true, func main);
                    }
                }//top < 8191
            }//spell == create_id
            elseif (spell == destroy_id){
                newLink = GetInt(GetSpellAbilityUnit());
                newLink.active = false;
            }
        }
        private void OnDeath(){
            link newLink = GetInt(GetDyingUnit());
            newLink.active = false;
        }
        void CreateUnits(int i_p, int n, int i_t){
            int i = 0;
            loop{;
                exitwhen i > n;
                CreateUnit(Player(i_p), i_t, GetRandomReal(GetRectMinX(bj_mapInitialPlayableArea), GetRectMaxX(bj_mapInitialPlayableArea)), GetRandomReal(GetRectMinY(bj_mapInitialPlayableArea), GetRectMaxY(bj_mapInitialPlayableArea)), GetRandomReal(0, 360));
                i++;
            }
        }

        private void Init(){
            int i = 0;
            trigger t = CreateTrigger();
            loop{
                TriggerRegisterPlayerUnitEvent(t, Player(i++), ConvertPlayerUnitEvent(274), null); //spell
                exitwhen i == 16;
            }
            TriggerAddAction(t, func events);
            i = 0;
            trigger t1 = CreateTrigger();
            loop{
                TriggerRegisterPlayerUnitEvent(t1, Player(i++), ConvertPlayerUnitEvent(20), null); //death
                exitwhen i == 16;
            }
            TriggerAddAction(t1, func OnDeath);
            CreateUnits(0, 5, 'h000');
        }
    }
//***************************************************************************
`
ОЖИДАНИЕ РЕКЛАМЫ...