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

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

Закрытая тема
 
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
Небольшой глюк препроцессора cjass
Есть следующая библиотека которую ток начал писать
» тык
library PandoraSpellCore
{   
    public unit SysTempUnit = null;
    public group SysTempGroup = CreateGroup();
    public constant int DUMMY_UNIT_ID = 'h004'
    
    #define DummyCastToTarget(u,ut,a,l,o) = 
    {
        unit dummyCaster = CreateUnit(GetOwningPlayer(u),PandoraSpellCore_DUMMY_UNIT_ID,GetUnitX(ut),GetUnitY(ut),0.0)
        UnitAddAbility(dummyCaster,a)
        SetUnitAbilityLevel(dummyCaster,a,l)
        IssueTargetOrderById(dummyCaster,o,ut)
        UnitApplyTimedLife(dummyCaster, 'BTLF',2.0)
        dummyCaster = null
    }

    /// <summary>
    /// Хз как даже эту функцию назвать
    /// </summary>
    /// <param name="caster">Кастер</param>
    /// <param name="xStart">Координата Х начала обработки</param>
    /// <param name="yStart">Координата Y начала обработки</param>
    /// <param name="xEnd">Координата Х конца обработки</param>
    /// <param name="yEnd">Координата Y конца обработки</param>
    /// <param name="width">Ширина выборки</param>
    /// <param name="forEach">код который исполнится для каждого юнита</param>
    /// <param name="onPeroid">код который выполнится в конце каждого прохода</param>
    /// <param name="onEnd">код который выполнится в после всех проходов</param>
    #define LineAction(caster, xStart, yStart, xEnd, yEnd, width, forEach, onPeroid, onEnd) =
    {
        // "выгружаем" аргументы в локальные переменные, т.к. в виде аргументов могут быть переданы функции.
        unit actionUnit = caster;
        float curX = xStart;
        float curY = yStart;
        float xEn##d = xEnd;
        float yEn##d = yEnd;
        float widt##h = width;
        
        // просчитываем дистанцию между указанными координатами
        float dist = 57.295827 * Atan2(yEn##d-curY,xEn##d-curX);
        // просчитываем угол между указанными координатами
        float angle = SquareRoot(curX-xEn##d*curX-xEn##d+curY-yEn##d*curY-yEn##d);
        
        // если не передано инструкций, то группа и тд нам не нужно формировать
        #if (forEach != null)
            // создаем группу для хранения сведений о используемых юнитах
            group selectedUnitGroup = CreateGroup();
            // объявляем переменную для хранения выбранного юнита
            unit curUnit = null;
            PandoraSpellCore_SysTempUnit = actionUnit;
        #endif
        // начинаем проход дистанции
        for(int i = 0; i < 2*dist/widt##h; i++)
        {
            // выбираем юнитов в точке
            // проверяем были ли указаны инструкции по обработке для юнитов 
            #if (forEach != null)
                GroupEnumUnitsInRange(selectedUnitGroup, curX, curY, widt##h, Condition(lambda boolean () 
                {
                    //фильтр юнитов
                    unit filteredUnit = GetFilterUnit();
                    if(!IsUnitInGroup(filteredUnit,PandoraSpellCore_SysTempGroup) &&
                        IsUnitEnemy(filteredUnit,GetOwningPlayer(PandoraSpellCore_SysTempUnit)) &&
                        GetUnitState(filteredUnit,UNIT_STATE_LIFE)>0. &&
                        GetUnitAbilityLevel(filteredUnit,'Avul')<=0 &&
                        !IsUnitType(filteredUnit,UNIT_TYPE_MAGIC_IMMUNE) &&
                        !IsUnitType(filteredUnit,UNIT_TYPE_STRUCTURE))
                        {
                            filteredUnit = null;
                            return true;
                        }
                    filteredUnit = null;
                    return false;
                })));
                // производим выбранных обработку юнитов
                loop 
                {
                    // выбираем первого юнита из группы
                    curUnit = FirstOfGroup(selectedUnitGroup)
                    // если null, значит юнитов в группе нету, можно выйти из цикла
                    exitwhen curUnit==null
                    
                    // добавляем юнита в темп группу, что бы не выполнять для него многократно какие либо действия
                    GroupAddUnit(SysTempGroup, curUnit)
                    // действие которое будет выплнено для каждого юнита 
                    // доступные имена переменных (unit curUnit, float curX, float curY)
                    //===================================================
                    forEach
                    //===================================================
                    // удаляем юнита из группы, так как он более не нужен
                    GroupRemoveUnit(selectedUnitGroup, curUnit)
                }
            #endif
            // просчитываем смещение
            curX+=widt##h/2 * Cos(angle * 0.01745327)
            curY+=widt##h/2 * Sin(angle * 0.01745327)
            // действие которое будет выполненяться при каждом проходе цикла
            // доступные имена переменных (float curX, float curY)
            //===================================================
            #if (onPeroid != null)
                onPeroid
            #endif
            //===================================================
        }
        // финальное действие
        // доступные имена переменных (float curX, float curY)
        //===================================================
        #if(onEnd != null)
            onEnd
        #endif
        //===================================================
        // очищаем мусор 
        #if (forEach != null)
            PandoraSpellCore_SysTempUnit = null;
            DestroyGroup(selectedUnitGroup);
            GroupClear(PandoraSpellCore_SysTempGroup);
            selectedUnitGroup = null;
            curUnit = null;
        #endif
        actionUnit = null;
    }
}
Юзается так:
#define private ForEach = 
{
    CauseDamageUnitX(SPELL_CASTER,curUnit,SPELL_DAMAGE,SPELL_TYPE);
}

#define private OnPeroid = 
{
    CreateOnPoint("Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl", curX, curY)
}

#define private OnEnd = 
{
    CreateOnPoint("Abilities\\Spells\\Orc\\WarStomp\\WarStompCaster.mdl", curX, curY)
}
private void Action()
{
    LineAction(SPELL_CASTER, GetUnitX(SPELL_CASTER), GetUnitY(SPELL_CASTER), GetSpellTargetX(), GetSpellTargetY(), 200., ForEach , OnPeroid , OnEnd)
}
Собсно проблема в том, что
#if (forEach != null)
Такая вот проверка стопорит парсер(он не падает, не зависает, а просто останавливается файнд'n'реплейс если значение является кодом. Если передано значение null, то все ок. Если совсем проверки эти убрать, то все ок.

Отредактировано Faion, 28.07.2012 в 18:31.
Старый 28.07.2012, 17:08
Doc

offline
Опыт: 63,163
Активность:
#define private ForEach =
#if (forEach != null)
м?
Старый 28.07.2012, 19:01
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
Doc, смотри внимательно, я передаю код из ForEach как аргумент в другую дефайн-функцию(да это работает пруф1, пруф2)
Вообще если убрать проверки, то все будет ок, но весь смысл как раз в том, что б дефайн-функция строила функцию в зависимости с указанными параметрами, а все ненужное выпиливала.
Старый 28.07.2012, 19:08
Doc

offline
Опыт: 63,163
Активность:
А ну, так нельзя. Т.к. аргументом в дефайн может быть подана переменная, препроцессор ведь не может сравнить ее с нулем.
Старый 28.07.2012, 19:55
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
Doc, в том то и что дело можно. Другое дело что с проверкой так не прокатывает, в прочем если передать null, то все ок, т.е. если в препроцессоре сделать проверку строк, то все будет ок. Вообще конечно можно просто добавить доп. "булевые" значения для каждой конструкции, тогда по идее все будет ок, но тогда будет не так элегантно код выглядеть.
Старый 28.07.2012, 20:05
Doc

offline
Опыт: 63,163
Активность:
Ну очевидно же что препроц может проверить только константы/дефайны. Так что нет.
Старый 28.07.2012, 20:05
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
Doc, все можно, если есть руки и мозг, нет ничего невозможного.~Faion:
#if (forEach != null)
меняем на:
   #if (!forEach)
и все ок.
Правда теперь другая ошибка посыпалась, но думаю мб где что то пропустил:)
function      cj_anonym__1 takes nothing returns boolean
//# optional
Старый 28.07.2012, 20:15
Doc

offline
Опыт: 63,163
Активность:
#if (!forEach)
тут все правильно, оно всегда будет срабатывать за исключением тех ситуаций когда forEach будет 1 или true.
Старый 28.07.2012, 20:18
Faion
Noblesse Oblige
offline
Опыт: 30,395
Активность:
Doc:
тут все правильно, оно всегда будет срабатывать за исключением тех ситуаций когда forEach будет 1 или true.
Ну да и проблему это вполне решает:)
Faion добавил:
Короче тему можно закрыть, никаких еще извращений я придумывать не буду, оставлю так.
Старый 28.07.2012, 20:37
Закрытая тема

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

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

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

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



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