• Уважаемые гости и новички, приветствуем Вас на нашем форуме
    Здесь вы можете найти ответы практически на все свои вопросы о серии игр «Готика» (в том числе различных модах на нее), «Ведьмак», «Ризен», «Древние свитки», «Эра дракона» и о многих других играх. Можете также узнать свежие новости о разработке новых проектов, восхититься творчеством наших форумчан, либо самим показать, что вы умеете. Ну и наконец, можете обсудить общие увлечения или просто весело пообщаться с посетителями «Таверны».

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!

Не стесняюсь спросить....

Orc Hunter


Модостроитель
Регистрация
12 Окт 2013
Сообщения
1.269
Благодарности
1.667
Баллы
305
Приветствую. В Spacer 2 к камере прикреплен источник света, где можно увидеть его свойства?
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.301
Благодарности
4.636
Баллы
625
У меня почему-то получаются только условия вида: если ГГ НАНЁС урон, то ...
А как зафиксировать получение урона?)
AssessDamage и AssessOtherDamage тут почти не помогут. Во-первых потому что первое не работает на гг, а во-вторых потому что оба не срабатывают во время боя.
Как вариант, если речь идет о драке, можно реализовать проверку здоровья через событие Attack для людей и монстров соотвественно:
Daedalus:
var int PlayerCurrentHP;
   
func void ZS_Attack()
{
    ...
   
    // Инициализировать значение здоровья
    // до вступления NPC в бой с героем
    if (Npc_IsPlayer(other))
    {
        Hlp_PrintConsole("Player HP initialized");
        PlayerCurrentHP = other.attribute[ATR_HITPOINTS];
    };
};
   
func int ZS_Attack_Loop()
{
    // Проверка, поменялось ли значение
    // HP для NPC и в какую сторону
    if (Npc_IsPlayer(other))
    {
        var int playerNewHP;
        var int damageTotal;
        var string format;
        playerNewHP = other.attribute[ATR_HITPOINTS];
   
        if (playerNewHP != PlayerCurrentHP)
        {
            if (playerNewHP < PlayerCurrentHP)
            {
                // Твой код тут . . .
                damageTotal = PlayerCurrentHP - playerNewHP;
                format = Str_Format("Урона получено: %i", damageTotal);
                Hlp_PrintConsole(format);
            };
           
            PlayerCurrentHP = playerNewHP;
        };
    };
   
    ...
};

Приветствую. В Spacer 2 к камере прикреплен источник света, где можно увидеть его свойства?
Физически не существует никакого источника света. За интенсивность подсветки полигонов отвечает функция zCPolygon::LightDynCamSpace. Для изменения значения силы света используется глобальная переменная (адрес для G2A) 0x0089EBB4 int playerLightInt
 

Orc Hunter


Модостроитель
Регистрация
12 Окт 2013
Сообщения
1.269
Благодарности
1.667
Баллы
305
Я обнаружил что некоторые объекты, если смотреть против солнца, смотрятся не очень приятно. При этом даже слабый источник света прикрепленный к камере или гг значительно улучшает положение. Подскажите, возможно есть какие-то способы отключить тень на траве, или подсветить ее?
15.png
14.png
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.301
Благодарности
4.636
Баллы
625
Я обнаружил что некоторые объекты, если смотреть против солнца, смотрятся не очень приятно. При этом даже слабый источник света прикрепленный к камере или гг значительно улучшает положение. Подскажите, возможно есть какие-то способы отключить тень на траве, или подсветить ее?
Задавался аналогичным вопросом неделю тому назад. Есть тестовый код, но он не оптимизирован для выхода в массы.
Из-за того, что в свойствах воба отсутствует параметр альтернативного алгоритма освещения, все объекты считаются по умолчанию непросвечивающими. И свет на каждый из них ложится с максимальным затемнением с теневой стороны. Для аутдор локации освещение воба задается в момент рендера. При этом участвуют в этой операции два источника света: 1. направленный солнечный свет 2. эмбиент свет локации.
В реализации ниже для объекта, модель которого имеет в имени подстроку Grass, создается третий источник света, который добавляет светимости траве. Сила третьего источника базируется на значении освещенности полигона, на котором расположен воб.
C++:
    HOOK Hook_zCRenderLightContainer_CollectLights_StatLights AS( &zCRenderLightContainer::CollectLights_StatLights, &zCRenderLightContainer::CollectLights_StatLights_Union );

    bool IsTransparentVob( zCVob* vob ) {
        if( !vob || !vob->visual )
            return false;

        return vob->visual->GetVisualName().HasWordI( "GRASS" );
    }

    zVEC3 GetFloorColorVec3( zCVob* vob ) {
        zCOLOR floorLight = vob->GetLightColorStat();
        return zVEC3( floorLight.r, floorLight.g, floorLight.b );
    }

    bool IsOutDoorSector( const zTRenderContext& renderContext ) {
        zCPolygon* groundPoly = renderContext.vob->groundPoly;
        return !groundPoly || !groundPoly->flags.sectorPoly || renderContext.world->GetBspTree()->bspTreeMode == zBSP_MODE_OUTDOOR;
    }

    void zCRenderLightContainer::CollectLights_StatLights_Union( const zTRenderContext& renderContext ) {
        THISCALL( Hook_zCRenderLightContainer_CollectLights_StatLights )(renderContext);
        if( IsOutDoorSector( renderContext ) && IsTransparentVob( renderContext.vob ) ) {
            zCRenderLight& pmLight = lightList[numLights++];
            zVEC3 floorColor       = GetFloorColorVec3( renderContext.vob );
            pmLight.lightType      = zLIGHT_TYPE_AMBIENT;
            pmLight.colorDiffuse   = floorColor * 0.8f;
        }
    };

Результат:
2021-06-20_14-47-32.png

2021-06-20_14-48-01.png
2021-06-20_14-48-53.png
2021-06-20_14-49-13.png
2021-06-20_14-49-39.png
2021-06-20_14-50-01.png

Проблема пока только в том, чтобы реализовать фильтр, через который без ущерба производительности можно было бы кроме травы добавлять множество других моделей, которые должны освещаться по альтернативному алгоритму. Возможно чуть позже поищу какие-нибудь ненужные поля вобов для записи туда дополнительного флага.
 

Вложения

  • zVobSoftLighting_Test.7z
    6,6 KB · Просмотры: 5

Orc Hunter


Модостроитель
Регистрация
12 Окт 2013
Сообщения
1.269
Благодарности
1.667
Баллы
305
Задавался аналогичным вопросом неделю тому назад. Есть тестовый код, но он не оптимизирован для выхода в массы.
Из-за того, что в свойствах воба отсутствует параметр альтернативного алгоритма освещения, все объекты считаются по умолчанию непросвечивающими. И свет на каждый из них ложится с максимальным затемнением с теневой стороны. Для аутдор локации освещение воба задается в момент рендера. При этом участвуют в этой операции два источника света: 1. направленный солнечный свет 2. эмбиент свет локации.
В реализации ниже для объекта, модель которого имеет в имени подстроку Grass, создается третий источник света, который добавляет светимости траве. Сила третьего источника базируется на значении освещенности полигона, на котором расположен воб.
C++:
    HOOK Hook_zCRenderLightContainer_CollectLights_StatLights AS( &zCRenderLightContainer::CollectLights_StatLights, &zCRenderLightContainer::CollectLights_StatLights_Union );

    bool IsTransparentVob( zCVob* vob ) {
        if( !vob || !vob->visual )
            return false;

        return vob->visual->GetVisualName().HasWordI( "GRASS" );
    }

    zVEC3 GetFloorColorVec3( zCVob* vob ) {
        zCOLOR floorLight = vob->GetLightColorStat();
        return zVEC3( floorLight.r, floorLight.g, floorLight.b );
    }

    bool IsOutDoorSector( const zTRenderContext& renderContext ) {
        zCPolygon* groundPoly = renderContext.vob->groundPoly;
        return !groundPoly || !groundPoly->flags.sectorPoly || renderContext.world->GetBspTree()->bspTreeMode == zBSP_MODE_OUTDOOR;
    }

    void zCRenderLightContainer::CollectLights_StatLights_Union( const zTRenderContext& renderContext ) {
        THISCALL( Hook_zCRenderLightContainer_CollectLights_StatLights )(renderContext);
        if( IsOutDoorSector( renderContext ) && IsTransparentVob( renderContext.vob ) ) {
            zCRenderLight& pmLight = lightList[numLights++];
            zVEC3 floorColor       = GetFloorColorVec3( renderContext.vob );
            pmLight.lightType      = zLIGHT_TYPE_AMBIENT;
            pmLight.colorDiffuse   = floorColor * 0.8f;
        }
    };

Результат:

Проблема пока только в том, чтобы реализовать фильтр, через который без ущерба производительности можно было бы кроме травы добавлять множество других моделей, которые должны освещаться по альтернативному алгоритму. Возможно чуть позже поищу какие-нибудь ненужные поля вобов для записи туда дополнительного флага.
Отлично работает! Люди пытались написать на Икарусе, но результатов я не нашел. Я тоже пытался. Насколько я понял за это отвечает _zCVob_lightColorStat и _zCVob_lightDirectionStat? У меня обрабатываются все модели травы после загрузки сохранения, я думал сделать их ярче в этот момент.
Код:
    var zCArray vobList;
    vobList = _^(vobArrayPtr);
    repeat(i, vobList.numInArray);
    var int i;
    var int vobPtr; vobPtr = MEM_ArrayRead(vobArrayPtr, i);
    var oCMobInter mob;
    mob = _^ (vobPtr);
    mob._zCVob_lightColorStat
 
Последнее редактирование:

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.301
Благодарности
4.636
Баллы
625
Насколько я понял за это отвечает _zCVob_lightColorStat и _zCVob_lightDirectionStat?
Скорее помогают. Статический свет считается по разному для меша локации и вобов. В первом случае информация о цвете вертекса пишется непосредственно в сам зен, а вот цвета вертексов у вобов приходится пересчитывать каждый кадр.
Ключевым моментом является тип статических источников света, которые я перечислил выше:
1. Направленный свет от солнца с флагом zLIGHT_TYPE_DIR - освещенность полигона будет зависеть от угла, которым он повернут к источнику.
2. Эмбиент свет с флагом zLIGHT_TYPE_AMBIENT - освещенность распределяется равномерно на все полигоны согласно заданному цвету. Этот источник значительно темнее первого, из-за чего мы видим такие темные участки на траве.
Всего можно задействовать до 8 источников света, которые будут как бы суммироваться при конечном расчете. В аутдоре используется 2, в индоре 1 (только эмбиент, а роль первого играет генерация карт теней).
Но если мы говорим о 3м эмбиент-источнике для аутдора из реализации выше, то мы не можем применять его ко всем объектам в мире, иначе пропадет игра света и картинка станет максимально плоской.

Вот смотри. Добавил пару опций в Gothic.ini, теперь можно более конкретно поиграть с вобами и уровнем освещения:
INI:
[ZVOBSOFTLIGHT]
Visuals=*grass*, *farn*, *weed*, *clover*, *bush*, *lupine*, *plant*, *webs*
; ... строки, которые содержат модели, которые следует подсветить.
; * - означает, что в этом месте может быть любая подстрока.

Intensity=0.7
; ... значение дополнительного освещения. По умолчанию - 0.7

Дллка при входе в мир перебирает все дерево вобов и по фильтру добавляет в сортированный массив подходящие модели. Далее эти модели бинарно проверяются в функции CollectLights_StatLights, соответственно на производительность это не влияет. И еще можно кнопкой KEY_0 посмотреть ДО и ПОСЛЕ.
По ощущениям будто напрашивается каждому из указанных типов добавить собственную настройку яркости. Некоторые объекты сильно пересвечивает. Либо мне кажется... Во всяком торчащие из воды тентакли можно и потемнее сделать.

2021-06-21_02-16-49.png

2021-06-21_02-17-11.png

2021-06-21_02-17-50.png

2021-06-21_02-18-13.png
 

Вложения

  • zVobSoftLighting.7z
    8,7 KB · Просмотры: 5

Orc Hunter


Модостроитель
Регистрация
12 Окт 2013
Сообщения
1.269
Благодарности
1.667
Баллы
305
Скорее помогают. Статический свет считается по разному для меша локации и вобов. В первом случае информация о цвете вертекса пишется непосредственно в сам зен, а вот цвета вертексов у вобов приходится пересчитывать каждый кадр.
Ключевым моментом является тип статических источников света, которые я перечислил выше:
1. Направленный свет от солнца с флагом zLIGHT_TYPE_DIR - освещенность полигона будет зависеть от угла, которым он повернут к источнику.
2. Эмбиент свет с флагом zLIGHT_TYPE_AMBIENT - освещенность распределяется равномерно на все полигоны согласно заданному цвету. Этот источник значительно темнее первого, из-за чего мы видим такие темные участки на траве.
Всего можно задействовать до 8 источников света, которые будут как бы суммироваться при конечном расчете. В аутдоре используется 2, в индоре 1 (только эмбиент, а роль первого играет генерация карт теней).
Но если мы говорим о 3м эмбиент-источнике для аутдора из реализации выше, то мы не можем применять его ко всем объектам в мире, иначе пропадет игра света и картинка станет максимально плоской.

Вот смотри. Добавил пару опций в Gothic.ini, теперь можно более конкретно поиграть с вобами и уровнем освещения:
INI:
[ZVOBSOFTLIGHT]
Visuals=*grass*, *farn*, *weed*, *clover*, *bush*, *lupine*, *plant*, *webs*
; ... строки, которые содержат модели, которые следует подсветить.
; * - означает, что в этом месте может быть любая подстрока.

Intensity=0.7
; ... значение дополнительного освещения. По умолчанию - 0.7

Дллка при входе в мир перебирает все дерево вобов и по фильтру добавляет в сортированный массив подходящие модели. Далее эти модели бинарно проверяются в функции CollectLights_StatLights, соответственно на производительность это не влияет. И еще можно кнопкой KEY_0 посмотреть ДО и ПОСЛЕ.
По ощущениям будто напрашивается каждому из указанных типов добавить собственную настройку яркости. Некоторые объекты сильно пересвечивает. Либо мне кажется... Во всяком торчащие из воды тентакли можно и потемнее сделать.


Gothic 3.jpg
 

Trazege

Участник форума
Регистрация
20 Фев 2008
Сообщения
1.760
Благодарности
1.394
Баллы
340
У меня почему-то получаются только условия вида: если ГГ НАНЁС урон, то ...
А как зафиксировать получение урона?)

Потому что в скриптах нет функции которая отвечала бы за урон нанесенный именно по гг. Это только через костыли возможно и расширители.
 

WoOliN

Участник форума
Регистрация
13 Окт 2012
Сообщения
347
Благодарности
196
Баллы
210
Ага, разобрались уже. Гратт подсказал костыль)
 

Trazege

Участник форума
Регистрация
20 Фев 2008
Сообщения
1.760
Благодарности
1.394
Баллы
340
Ага, разобрались уже. Гратт подсказал костыль)

Как вариант, но будет много нюансов. Если вдруг урон тебе будет прилетать без участия рутины атаки нпс. Просто по опыту скажу, что уже проходили все эти танцы с бубнами, и решились они только с вводом внешки из расширителя. Но если у тебя все по "канону", то наверное да сойдет.
 

WoOliN

Участник форума
Регистрация
13 Окт 2012
Сообщения
347
Благодарности
196
Баллы
210
Там примитив, как раз подходит (шанс на активацию состояния временной неуязвимости при получении любого урона).
 

Trazege

Участник форума
Регистрация
20 Фев 2008
Сообщения
1.760
Благодарности
1.394
Баллы
340
Там примитив, как раз подходит (шанс на активацию состояния временной неуязвимости при получении любого урона).
Тогда это лучше отслеживать циклическим тригером, а не рутиной нпс.
 

WoOliN

Участник форума
Регистрация
13 Окт 2012
Сообщения
347
Благодарности
196
Баллы
210
В принципе да, там же, где цикл отслеживает длительность неуязвимости можно всунуть и этот костыль на отслеживание изменений в ХП)
 

Trazege

Участник форума
Регистрация
20 Фев 2008
Сообщения
1.760
Благодарности
1.394
Баллы
340
Комрады, подскажите кто шарит в чем ошибка. Суть - провести линию к от гг ко всем итемам в радиусе n готических попугаев.

1624370409302.png
 

N1kX


Модостроитель
Регистрация
13 Ноя 2009
Сообщения
6.129
Благодарности
5.626
Баллы
910
Комрады, подскажите кто шарит в чем ошибка. Суть - провести линию к от гг ко всем итемам в радиусе n готических попугаев.

TopLayer же делал это в своем плагине, который поднимает предметы.
Вот часть кода, которая рисует линии к предметам, которые поднялись
C++:
    void Lift::Debug()
    {
        screen->PrintCX(1000, string::Combine("Items checked: %i", itemsTraversed).GetVector());
        screen->PrintCX(1200, string::Combine("Items affected: %i", oldPositions.size()).GetVector());

        //интересующая часть
        for (auto it = oldPositions.begin(); it != oldPositions.end(); it++)
        {
            zlineCache->Line3D(GetFocus(player), GetFocus(it->first), zCOLOR(255, 0, 0), true);
        }

        if (!player->GetFocusVob())
        {
            return;
        }
    }
Liftitem
 

Slavemaster


Модостроитель
Регистрация
10 Июн 2019
Сообщения
1.082
Благодарности
1.901
Баллы
320
Первый элемент списка всегда пустые данные содержит.
Пишу по памяти:
C++:
for (zCListSort<oCItem>* node = ogame->GetGameWorld()->voblist_items->GetNextInList(); node; node = node->GetNextInList())
    // use node->GetData()
Вот часть кода, которая рисует линии к предметам, которые поднялись
Тут используются итераторы, которые, вроде, только в моих проектах реализованы
 

Trazege

Участник форума
Регистрация
20 Фев 2008
Сообщения
1.760
Благодарности
1.394
Баллы
340
Первый элемент списка всегда пустые данные содержит.
Пишу по памяти:
C++:
for (zCListSort<oCItem>* node = ogame->GetGameWorld()->voblist_items->GetNextInList(); node; node = node->GetNextInList())
    // use node->GetData()

Тут используются итераторы, которые, вроде, только в моих проектах реализованы

Все разобрался, спс. А кроме линий, например жирную точку или круг можно нарисовать? Есть подобные классы?
 

Trazege

Участник форума
Регистрация
20 Фев 2008
Сообщения
1.760
Благодарности
1.394
Баллы
340
У предмета есть флаг, который описывает его состояние в момент использования неписями - например метла или щетка?
 

Xeдин


Модостроитель
Регистрация
3 Дек 2008
Сообщения
1.448
Благодарности
1.976
Баллы
365
Trazege, у игрока есть player->interactItem, я с ним сравнивал предметы из инвентаря, что бы определить взаимодействует ли игрок с этим предметом.
 

Trazege

Участник форума
Регистрация
20 Фев 2008
Сообщения
1.760
Благодарности
1.394
Баллы
340
Trazege, у игрока есть player->interactItem, можно с ним сравнить.

Спасибо! Но тут именно интересует момент использования предмета не ГГ, а неписем. Переписал внешку, вроде работает, но просто думаю мб что то более нормальное есть. без этих костылей.
 
Сверху Снизу