XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
Vadik29
Choice Battle 1.6а
offline
Опыт: 15,845
Активность:
Лимит кода.
Я столкнулся с очень странной проблемой. В моей карте примерно 58к строк кода и когда я начинаю писать еще код, какие-то триггеры не срабатывают, причем код не битый ошибок там нет (проверял в других карта), но если удалить любой старый кусок кода, то как бы освобождается место для нового кода и карта благополучно сохраняется. Не знаете в чем может быть проблема или в редакторе действительно есть такой лимит (стоит JNGP с cJass)?
Старый 17.01.2015, 16:31
Doc

offline
Опыт: 63,163
Активность:
Возможно превышен лимит операций в "потоке".
Попробуй инициализировать часть триггеров по таймеру.
И да, 60к строк скорее всего значит, что в коде тысячи мусора, советую задуматься.
Старый 17.01.2015, 17:33
Vadik29
Choice Battle 1.6а
offline
Опыт: 15,845
Активность:
Doc, Да нет, в карте 77 героев по 5 спелов (у некоторых больше, до 20) + куча разных систем. Но запускать по таймеру, хорошая мысль.
Старый 17.01.2015, 19:11
DioD

offline
Опыт: 45,134
Активность:
77*10 (округлим для тех героев у которых 20 заклинаний, видимо 100500 инвокеров с разноцветными фаерболами лол) == 770 спеллов
60 000 строк кода на 770 заклинаний, получаем каждое заклинание 70 (лол) строк кода.
вот объясните мне уважаемый, что в вашем супер проекте такого, что спелл каждого героя занимает 70 строк
если люди без психических заболеваний, делают одну систему движения снарядов и после только вызывают один метод из этой системы, снижая размер спеллов до 1 строки кода, видимо у вас каждый спелл совершенно уникален и унификация невозможна?
Старый 18.01.2015, 14:39
adic3x

offline
Опыт: 108,439
Активность:
Просто ради интереса, киньте сюда код одного из заклинаний, есть подозрения, что написаны они совсем не рационально.
Старый 18.01.2015, 17:26
ScorpioT1000
Работаем
online
Опыт: отключен
Старый 19.01.2015, 00:50
Vadik29
Choice Battle 1.6а
offline
Опыт: 15,845
Активность:
DioD, как бы карта на аниме тематику и хоть ты извращайся как только можешь, составить закономерность у тебя не получится, потому что у всех абсолютно разные эффекты и стили.
» пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ
scope YatanoKagami initializer YatanoKagamiInit {

    boolean CondYatanoKagami() {
    return GetSpellAbilityId() == 'A0KO' and udg_B == true
    }

    function CastYatanoKagami2 takes void returns void
        timer t = GetExpiredTimer()
        integer id = GetHandleId(t)
        unit u = LoadUnitHandle(h, id, 0)
        real x1 = GetUnitX(u)
        real y1 = GetUnitY(u)
        real x2 = LoadReal(h, id, 4)
        real y2 = LoadReal(h, id, 5)
        real a = LoadReal(h, id, 1)
        group g = LoadGroupHandle(h, id, 3)
        integer idg = GetHandleId(g)
        int lvl = GetUnitAbilityLevel(u, 'A0KO')
        real dmg = 100*lvl + GetHeroAgi(u, true) * lvl
        player p = GetOwningPlayer(u)
        int ide
        real r = LoadReal(h,id,6)+1
        real a3 = LoadReal(h,id,7)
        real a2 = a + a3
        real dist = LoadReal(h,id,100)
        if dist < 1500 {
            SaveReal(h,id,100,dist+35)
            SetUnitX(u, x1 + 65 * Cos(a2))
            SetUnitY(u, y1 + 65 * Sin(a2))
            SetUnitFacing(u, a2 * bj_RADTODEG)
            SetUnitAnimation(u, "walk")
            n = CreateUnit(p, 'e0G5', x1, y1, a2 * bj_RADTODEG)
            UnitApplyTimedLife(n, 'B000', 0.25)
            SetUnitVertexColor(n,255,255,0,100)
            UnitAddAbility(n,'A0KM')
            UnitAddAbility(n,'A0KN')
            SetUnitAnimation(n, "walk")
             n = CreateUnit(p, 'e0G6', x1, y1, a2 * bj_RADTODEG)
            UnitApplyTimedLife(n, 0, 0.65)
            SetUnitTimeScale(n, 0)
            GroupEnumUnitsInRange(G, x1, y1, 175, Base)
            SaveReal(h,id,6,r)
            if r > 5 then
            SaveReal(h,id,7,a3*(-1))
            SaveReal(h,id,6,0)
            endif
            loop
                E = FirstOfGroup(G)
                ide = GetHandleId(E)
                if Condition_Base(p, E) and LoadUnitHandle(h, idg, ide) != E then
                    UnitDamageTarget(u, E, dmg, false, false, null, null, null)
                    SaveUnitHandle(h, idg, ide, E)
                endif
                GroupRemoveUnit(G, E)
                exitwhen E == null
            endloop
        else
            FlushChildHashtable(h, id)
            FlushChildHashtable(h, idg)
            DestroyTimer(t)
            DestroyGroup(g)
            SetUnitInvulnerable(u, false)
            }
            u = null
            p = null
            t = null
            g = null
        endfunction

        function CastYatanoKagami takes void returns void
            unit u = GetTriggerUnit()
            timer t = CreateTimer()
            integer id = GetHandleId(t)
            SaveUnitHandle(h, id, 0, u)
            SaveReal(h, id, 4, GetUnitX(u))
            SaveReal(h, id, 5, GetUnitY(u))
            SaveReal(h, id, 1, Atan2(GetSpellTargetY() - GetUnitY(u), GetSpellTargetX() - GetUnitX(u)))
            SaveGroupHandle(h, id, 3, CreateGroup())
            SetUnitInvulnerable(u, true)
            SaveReal(h,id,6,0)
            SaveReal(h,id,100,0)
            SaveReal(h,id,7,45*bj_DEGTORAD)
            bj_lastPlayedSound = CreateSound("Sound\\Music\\mp3Music\\YatoNoKagami.mp3", false, false, true, 12700, 12700, "")
            StartSound(bj_lastPlayedSound)
            KillSoundWhenDone(bj_lastPlayedSound)
            TimerStart(t, 0.025, true, function CastYatanoKagami2)
            u = null
            t = null
        endfunction


        void YatanoKagamiInit (){
        trigger t = CreateTrigger()
        integer i = 0
        loop
            TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            i++ 
            exitwhen i == bj_MAX_PLAYER_SLOTS
        endloop
        TriggerAddAction(t, function CastYatanoKagami)
        TriggerAddCondition(t, Condition(function CondYatanoKagami))
        t = null
        }
        }
Старый 24.01.2015, 21:06
velmir

offline
Опыт: 8,257
Активность:
Vadik29:
потому что у всех абсолютно разные эффекты и стили.
это все исправимо примерно как сказал DioD:
делают одну систему движения снарядов и после только вызывают один метод из этой системы, снижая размер спеллов до 1 строки кода
Vadik29: просто почитай что такое ооп и поймеш, как оптимизировать однотипные скилы..
зи говоря об однотипных я говорю не о всех в которых одинаковые скилы (ефекты дамики) я говорю об механике, к примеру все скилы создающиее линию из дами, или заставляющие дами двигатся)
Старый 25.01.2015, 10:46
adic3x

offline
Опыт: 108,439
Активность:
Что можно урезать:
// Зачем scope, если мы не пользуемся private?

scope YatanoKagami initializer YatanoKagamiInit {

    boolean CondYatanoKagami() {
    return GetSpellAbilityId() == 'A0KO' and udg_B == true
    }

// ...

        function CastYatanoKagami takes void returns void
// ... Actions
        endfunction


        void YatanoKagamiInit (){
        trigger t = CreateTrigger()
        integer i = 0
        loop
            TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
            i++ 
            exitwhen i == bj_MAX_PLAYER_SLOTS
        endloop
        TriggerAddAction(t, function CastYatanoKagami)
        TriggerAddCondition(t, Condition(function CondYatanoKagami))
        t = null
        }
        }
Меняется на:
// Осторожно, Doc говорил, что с callback могут быть некоторые специфические проблемы
callback onUnitSpellCast ('A0KO') {
    if udg_B {
        // ... Actions
    };
};
Будет сгенерировано немного больше кода, чем тут, но все равно, каждый раз копировать создание триггера - это такая нелепица. Как и проверять boolean через ее сравнение с true, об этом еще Мриз писал (если вы поняли о ком я...).
Далее, в cJass модно не обнулять локальные переменные, он это делает автоматически и в целом адекватно.
Еще очень хочеться надавать по шапке за использование ключей для хеша в виде цифр, линк.
Идем дальше - вопрос про группу. Если я правильно понял алгоритм - группа создается и сохраняется просто для перебора юнитов? Используйте одну глобальную группу (могут быть некоторые проблема, но весьма редко), или используйте глобальную группу для каждого заклинания, или используйте cJass фишку:
// "Лишний код"

        group g = LoadGroupHandle(h, id, 3)
//
            GroupEnumUnitsInRange(G, x1, y1, 175, Base)
//
            loop
                E = FirstOfGroup(G)
// Actions...
                GroupRemoveUnit(G, E)
                exitwhen E == null
            endloop
//
            DestroyGroup(g)
//
            SaveGroupHandle(h, id, 3, CreateGroup())
Меняется на:
for (unit u; UnitsInRange (x1, y1, 175) {
    // Actions...
};
Сейчас еще посмотрю...
ADOLF добавил:
Ах да, анонимные функции:
callback onUnitSpellCast ('A0KO') {
    if udg_B {
        // ... 
        timer t = CreateTimer ();
        Timer Start (t, .025, true, lambda nothing () {

        };)
    };
};
Старый 25.01.2015, 12:06
DioD

offline
Опыт: 45,134
Активность:
если логика не верна, не важно сколько сахара будет вбито в код, код всё равно останется дерьмом, даже пусть сладким, но всё равно дерьмом.
да и раковый сижас только скрывает реальный код от пользователя, не изменяя его суть.
в ряде случаев раздувает его и делает совершенно абсурдные конструкции которые нормальный программист никогда бы не сделал сам.
Старый 25.01.2015, 12:45
adic3x

offline
Опыт: 108,439
Активность:
Теперь поговорим про алгоритм - я крайне советую использовать 1 структуру (на крайний случай ее можно наследовать, хотя я вполне уверен, что в vJass это сделано через одно место, так что проще просто добавлять максимум для всех заклинаний), которая является универсальным заклинанием. Я так делал в морлоках ;)
Обычно, данные заклинания - это наборы координат (четыре real, две точки), еще несколько значений, будь то урон, дистанция, угол и т. д., несколько юнитов (владелец заклинания, цель), игрок, иногда группа (чтобы в нее помещать уже пораженных заклинанием юнитов), несколько целочисленных (уровень, счетчик) и т. д.
Так вот, вы просто присобачиваете эту структуру к таймеру, и пользуете ее, описывается она всего 1 раз.
» click
#include "cj_types.j"

hashtable hash = InitHashtable ();

struct spell extends array {
    real x1, y1, x2, y2, f, damage, angle, distance, r1, r2;
    int i, lvl;
    unit caster, target;
    player owner;
    group g;
};

// Простой аллокатор

spell spell_stack [];
int spell_stack_pointer = -1;
int spell_max = -1;

spell NewSpell () {
    if (spell_stack_pointer < 0) {
        if (spell_max < 8190) {
            return ++spell_max;
        } else {
            return -1;
        }
    } else {
        return spell_stack[spell_stack_pointer--];
    };
};

nothing SpellFree (spell s) {
    spell_stack[++spell_stack_pointer] = s
};

bool udg_B = true;

// Само заклинание

callback onUnitSpellCast ('A0KO') {
    if udg_B {
        spell s = NewSpell ();
        s.caster = GetTriggerUnit ();
        s.x1 = GetUnitX (s.caster);
        s.y1 = GetUnitY (s.caster);
        s.damage = (GetHeroAgi(s.caster, true) + 100. ) * GetUnitAbilityLevel (s.caster, 'A0KO') 
        s.angle = Atan2 (GetSpellTargetY() - s.y1 , GetSpellTargetX() - s.x1);
        s.distance = 0.
        s.owner = GetOwningPlayer (s.caster)
        SetUnitInvulnerable(s.caster, true);
        
        sound a = CreateSound ("Sound\\Music\\mp3Music\\YatoNoKagami.mp3", false, false, true, 12700, 12700, "");
        StartSound (a);
        KillSoundWhenDone (a);
        
        timer t = CreateTimer ();
        SaveInteger (hash, GetHandleId(t), 0, s);
        TimerStart (t, .025, true, lambda nothing () {
            timer t = GetExpiredTimer ();
            spell s = LoadInteger (hash, GetHandleId (t), 0);
            if (s.distance < 1500.) {
                s.distance += 35.;
// Я не понял, что вы творите с углами
//                s.r2 +=1;
// ...
                SetUnitX(s.caster, s.x1 + 65. * Cos(s.angle));
                SetUnitY(s.caster, s.y1 + 65. * Sin(s.angle));
                SetUnitFacing(s.caster, s.angle * .017453); // fuck bj
                SetUnitAnimation(s.caster, "walk");
                
                unit n = CreateUnit(s.owner, 'e0G5', s.x1, s.y1, 0.);
                UnitApplyTimedLife(n, 'B000', 0.25);
                SetUnitVertexColor(n, 255, 255, 0, 100);
                UnitAddAbility(n, 'A0KM');
                UnitAddAbility(n, 'A0KN');
                SetUnitAnimation(n, "walk");
                n = CreateUnit(s.owner, 'e0G6', s.x1, s.y1, 0.);
                UnitApplyTimedLife(n, 0, 0.65);
                SetUnitTimeScale(n, 0);
                
                for (unit u; UnitsInRange (s.x1, s.y1, 175.) {
                    UnitDamageTarget (s.caster, u, s.damage, false, false, null, null, null);
// Опять-же, какое-то добавление в группы, но функции нет                    
                };
            } else {
                FlushChildHashtable (hash, GetHandleId (t));
                DestroyTimer (t);
                SpellFree (s);
                SetUnitInvulnerable (s.caster, false);
            };            
        };);        
    };
};
ADOLF добавил:
Я пока набирал...
ADOLF добавил:
если логика не верна, не важно сколько сахара будет вбито в код, код всё равно останется дерьмом, даже пусть сладким, но всё равно дерьмом.
Я согласен, но это не повод писать не сахарно, но тупо.
да и раковый сижас только скрывает реальный код от пользователя, не изменяя его суть.
Ой-ли, раковый Си скрывает реальные опкоды и машинные команды. Мы что,место 1 команды должны каждый раз писать 10? Хотя я не спорю про то, что программист должен понимать, как работает та или иная команда, и что в нее завернуто.
в ряде случаев раздувает его и делает совершенно абсурдные конструкции которые нормальный программист никогда бы не сделал сам.
Больше про vJass, с cJass я фанател от низкоуровневой оптимизации, он там максимум скобочку где-то добавит. Никакого мусора.
Старый 25.01.2015, 13:17
Clamp
Lost in space
offline
Опыт: 71,158
Активность:
ADOLF:
Как и проверять boolean через ее сравнение с true, об этом еще Мриз писал
local bool Check
if(Check == true)&&(Check != false)
{
	DoNothing()
}

Отредактировано Кет, 25.01.2015 в 15:37.
Старый 25.01.2015, 13:30
DioD

offline
Опыт: 45,134
Активность:
стоит отойти от "ява для чайников" и делать чтото не предусмотренное базовым курсом - добро пожаловать в те самые опкоды и имплементацию нативных методов на си.
стоит отойти от си для чайников и например написать драйвер какойнить экзотической фигни, добро пожаловать в ассемблер с опкодами уже процессора.
про то что было много случаев когда находили баги в коде процессора (особенно касается графических карт) тоже можно не говорить.
человек должен понимать как выполняется код, скрывая от него те самые опкоды за сотней обёрток язык не делает ничего хорошего.
система движения 2д рисуется на коленках за 5 минут на любом языке, и всегда это будет массивом или таблицей по которой будет бегать таймер, поток, итератор или еще чтонить такое в бесконечном цикле.
3д рисуется на коленках за час, там будут углы и прочие радости, но опять таки это будет массив зарегистрированных снарядов которые будут двигаться некоторым методом.
Старый 25.01.2015, 17:58
adic3x

offline
Опыт: 108,439
Активность:
стоит отойти от "ява для чайников" и делать чтото не предусмотренное базовым курсом - добро пожаловать в те самые опкоды и имплементацию нативных методов на си.
стоит отойти от си для чайников и например написать драйвер какойнить экзотической фигни, добро пожаловать в ассемблер с опкодами уже процессора.
про то что было много случаев когда находили баги в коде процессора (особенно касается графических карт) тоже можно не говорить.
А что, часто приходится? А как же черные ящики? А должен ли я знать конкретно архитектуру процессора? А должен ли я понимать, как там электрический заряд скачет? Это все конечно интересно, но в излишнем уходе в "низкий" уровень толка мало. Все выше перечисленное - специфические области, и зачем программисту, который пишет код исключительно под виртуальные машины понимать архитектуру железа? Нет, это конечно полезно, но фишка языков высокого уровня в том и состоит, что позволяет делать что-либо легче.
Старый 25.01.2015, 20:24
DioD

offline
Опыт: 45,134
Активность:
архитектуру железа нет, архитектуру виртуальной машины очень даже не помешает.
натипные методы вара в данном случае это второй уровень абстракции, первый это тот код который будет передан вару, нулевой это всякие раковые надстройки и гуи.
Старый 26.01.2015, 10:06
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 17:32.