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

    Чтобы получить возможность писать на форуме, оставьте сообщение в этой теме.
    Удачи!
  • Друзья, доброго времени суток! Спешите принять участие в конкурсе "Таинственные миры" 2024!
    Ждем именно вас!

    Ссылка на конкурсную тему - тык

Union SDK - Инструменты разработчика

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.276
Благодарности
4.579
Баллы
625
  • Первое сообщение
  • #1
UnionProjectIcon.png


Union SDK

инструменты разработчика

Тема находится в состоянии наполнения



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

Рекомендуется смотреть на YouTube, поскольку там имеется сегментированный таймлайн.






Схемы классов движка
1600263933953.png
1600263981919.png
1600264017579.png
 

Вложения

  • sizeof.xlsx
    896,7 KB · Просмотры: 47
  • Union_SDK_1_0m.zip
    20,6 MB · Просмотры: 18
Последнее редактирование:

sam0delk1n

Участник форума
Регистрация
19 Апр 2020
Сообщения
24
Благодарности
1
Баллы
60
Gratt, я заметил такую вещь, что в Видео 2 для объекта миниатюры вызывается Release(). Но те Вобы, которые мы получаем через GetXXX() из других мест, вызова Release() не требуют. Подсчёт ссылок получается реализован наполовину. Я бы следовал концепции целиком, надо прибавлять счётчик на Get()'ах и требовать вызывать Release(). Я бы ещё вместо new использовал Create()'ы как DirectX например. Или можно разрешить new но использовать std::shared_ptr и не использовать счётчик ссылок внутри классов. Жалко что из движка это уже не выпилить.
 

sam0delk1n

Участник форума
Регистрация
19 Апр 2020
Сообщения
24
Благодарности
1
Баллы
60
Как рисовать 3D объекты в интерфейсе? Чтоб как в инвентаре.
Я не нашёл где в иерархии View'ов можно прикрепить Vob или Visual.
Есть какая-то функция oCItem::RenderItem(zCWorld*, zCViewBase*, float) но она вешает игру.
 
Последнее редактирование:

Slavemaster


Модостроитель
Регистрация
10 Июн 2019
Сообщения
1.034
Благодарности
1.798
Баллы
240
Есть какая-то функция oCItem::RenderItem(zCWorld*, zCViewBase*, float) но она вешает игру.
Надо мир специальный создавать.
C++:
zCWorld* rndWorld = new zCWorld();
rndWorld->m_bIsInventoryWorld = true;
item->RenderItem(rndWorld, screen, -2.0f);
rndWorld->Release();
Я бы следовал концепции целиком, надо прибавлять счётчик на Get()'ах и требовать вызывать Release().
Смысла нет, так как часто приходится взаимодействовать с движком, а там нет смартпоинтеров.
Основное правило простое: если создаёшь объект или вызываешь функцию с таким предназначением, то нужно вызывать Release(). А иначе - нет.
Хотя есть и исключения. Например, если передаёшь сообщение в zCEventManager::OnMessage(zCEventMessage*, zCVob*), то релизить не надо. Пираньи сами путались в подсчете ссылок...
 

sam0delk1n

Участник форума
Регистрация
19 Апр 2020
Сообщения
24
Благодарности
1
Баллы
60
Slavemaster, спасибо, в целом работает. Хотя m_bIsInventoryWorld есть только в Gothic_II_Addon. Я пробую делать в Gothic_I_Classic. Без этой переменной объекты рисуются в целом так-же как в инвентаре.

Теперь задача этот объект вращать и приближать/удалять.
Я видел есть oCItem::RenderItemPlaceCamera().
Но вот получается я использую один и тот же объект в инвентаре и в своём окне который рисуется два раза по разному.
Может имеет смысл как-то копировать объект в свой zCWorld, в котором выставлена камера и можно выставить объект как надо (и освещение настроить) и затем рисовать весь мир в zCView как в рендер таргет? Или это требует много лишних действий?
 

Slavemaster


Модостроитель
Регистрация
10 Июн 2019
Сообщения
1.034
Благодарности
1.798
Баллы
240
sam0delk1n, типа того будет:
C++:
{
    auto camScope = AssignTemp(zCCamera::activeCam, zCCamera::activeCam);

    zCVob* vob = new zCVob();
    vob->SetVisual(item->GetVisual());

    zCView* view = new zCView(0, 0, 2000, 2000);
    screen->InsertItem(view);

    static zCWorld* world = new zCWorld();
    world->m_bIsInventoryWorld = true;
    auto scope = AssignTemp(*(int*)0x0089EBB4, 5000); // light range for G2A (for G1 - 0x0083AB90)
    world->GetBspTree()->bspTreeMode = zBSP_MODE_INDOOR;
    world->GetActiveSkyControler()->SetFillBackground(false);
    world->GetBspTree()->drawVobBBox3D = false;

    zCVob* camVob = new zCVob();
    camVob->SetPositionWorld(zVEC3(0, 0, dist));
    world->AddVob(camVob);

    world->AddVob(vob);
    vob->SetPositionWorld(zVEC3(0, 0, 0));
    vob->RotateLocalZ(dist);

    zCCamera cam;
    cam.connectedVob = camVob;
    cam.SetRenderTarget(view);
    cam.SetFarClipZ(10000.0f);

    {
        auto scope = AssignTemp(zCEventManager::disableEventManagers, 1);
        world->Render(cam);
    }

    world->RemoveVob(camVob);
    world->RemoveVob(vob);
    world->RemoveVobSubtree(vob);

    screen->RemoveItem(view);
    delete view;
    camVob->Release();
    vob->Release();
}
 

sam0delk1n

Участник форума
Регистрация
19 Апр 2020
Сообщения
24
Благодарности
1
Баллы
60
Slavemaster, код то что нужно. Он работает, но вот объект теперь рисуется за view'ом. Если view не прозрачный то он закрывает собой объект. Я подумал может хотя бы родительский view будет под ним, но нет, он тоже сверху. Объект получается под всеми нарисованными окнами.

Ещё AssignTemp у меня кажется нет.
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.276
Благодарности
4.579
Баллы
625
Перед отрисовкой надо для zCView вызвать Blit, чтобы заматчить буфер. Тогда при отрисовке объекта его модель будет сверху.
Однако после блита невозможно будет рисовать текст, поэтому те же пираньи выводят инвентарь в самом конце фрейма.
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.276
Благодарности
4.579
Баллы
625
neromont, ну типа у dx есть буфер выводимого изображения и при рендере объекта в него заносится новая информация, как бы наслаиваясь поверх существующей.
 

zeratul47

Участник форума
Регистрация
10 Янв 2020
Сообщения
21
Благодарности
0
Баллы
60
Подскажите, можно ли как-то добавить эффекты оружия(как в готике 2 нв) через мод в готику 1?
И в какие классы для этого смотреть
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.276
Благодарности
4.579
Баллы
625
zeratul47, тут подход требует комплексных решений. Главная проблема в том, что oCItem в первой готике не имеет части полей, пришедших в ночи ворона. И тут два варианта. Либо написать производный от oCItem, либо немного изменить поля существующего.
Последний чуть быстрее в реализации. Смотри, в скриптах никогда не используются C_ITEM.nameID и C_ITEM.weight, поэтому забираем их в свои нужды.
1589640625935.png
1589640656641.png

Создаем какую-нибудь инстанцию эффекта и присваиваем предмету
1589640895000.png
1589640741948.png

А в плагине делаем привязку эффекта к экземпляру предмета.
C++:
void oCVisualFX::SetPFXShapeVisual_Union( zCVisual* visual );
C++:
  void oCVisualFX::SetPFXShapeVisual_Union( zCVisual* visual ) {
    zCParticleFX* pfx = GetVisual()->CastTo<zCParticleFX>();
    if( !pfx )
      return;

    zCMesh* mesh = visual->CastTo<zCMesh>();
    if( !mesh )
      return;

    if( emAdjustShpToOrigin ) {
      zCParticleEmitter* emitter = pfx->emitter;

      if( emitter->shpMesh == visual )
        return;

      if( emitter->shpMesh ) {
        emitter->shpMesh->Release();
        emitter->shpMesh = Null;
      }

      emitter->shpMesh = mesh;
      mesh->AddRef();
    }
  }

C++:
oCVisualFX* oCItem::InsertEffect();
void oCItem::RemoveEffect();
void oCItem::ThisVobAddedToWorld_Union( zCWorld* world );
void oCItem::ThisVobRemovedFromWorld_Union( zCWorld* world );

C++:
  oCVisualFX* oCItem::InsertEffect() {
    oCVisualFX*& visualFX = (oCVisualFX*&)weight;
    visualFX = Null;

    if( nameID.Length() > 0 ) {
      oCVisualFX* effect = oCVisualFX::CreateAndPlay( nameID, this, Null, 0, 0.0f, 0, 0 );
      if( effect ) {
        visualFX = effect;

        if( visual )
          effect->SetPFXShapeVisual_Union( visual );

        effect->homeWorld->RemoveVob( effect );
        ogame->GetGameWorld()->AddVobAsChild_novt( effect, this );
      }
    }

    return visualFX;
  }

  void oCItem::ThisVobAddedToWorld_Union( zCWorld* world ) {
    THISCALL( oCItem_ThisVobAddedToWorld )(world);
    if( homeWorld == ogame->GetGameWorld() )
      InsertEffect();
  }

  void oCItem::RemoveEffect() {
    oCVisualFX*& visualFX = (oCVisualFX*&)weight;
    if( visualFX ) {
      cmd << "Remove effect" << endl;
      visualFX->Kill();
      //visualFX->Release();
      visualFX = Null;
    }
  }

  void oCItem::ThisVobRemovedFromWorld_Union( zCWorld* world ) {
    if( homeWorld == ogame->GetGameWorld() )
      RemoveEffect();
    THISCALL( oCItem_ThisVobRemovedFromWorld )(world);
  }

Для функций oCItem::ThisVobAddedToWorld и oCItem::ThisVobRemovedFromWorld определяем хуки, чтобы произвести создание эффекта в момент вставки объекта в мир
C++:
  HOOK oCItem_ThisVobAddedToWorld AS( &oCItem::ThisVobAddedToWorld, &oCItem::ThisVobAddedToWorld_Union );
  HOOK oCItem_ThisVobRemovedFromWorld AS( &oCItem::ThisVobRemovedFromWorld, &oCItem::ThisVobRemovedFromWorld_Union );
1589641832187.png


Вооот, это программа минимум. Но когда надеваешь предмет на персонажа, там нужно сделать все тоже самое, но из функций экипировки. Правда есть нюанс, в г1 матрица предмета в слоте всегда будет возвращать 0 0 0, из-за чего эффект будет всегда висеть в нулевой точке координат локации. Сравнивать движки мне пока некогда, возможно Saturas поищет разницу.

И да, важное замечание. Существуют эффекты, частицы которых порождаются на полигонах модели, в г1 такое возможно только для 3ds моделей.
 
Последнее редактирование:

Raven25

Участник форума
Регистрация
18 Дек 2018
Сообщения
186
Благодарности
74
Баллы
190
Screenshot_6.jpg

Подскажите пожалуйста из-за чего может вылазить эта ошибка, и как от неё избавится ?
 

Raven25

Участник форума
Регистрация
18 Дек 2018
Сообщения
186
Благодарности
74
Баллы
190
И снова здрасьте*reverence*.

Вопрос таков, подскажите пожалуйста, как отключить барьер.
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.276
Благодарности
4.579
Баллы
625
Voron25, это вопрос принципиальный или подойдут параметры из SystemPack.ini?
1590322313010.png
 

Raven25

Участник форума
Регистрация
18 Дек 2018
Сообщения
186
Благодарности
74
Баллы
190
Да, принципиален, поскольку для сиквела я данного отдела в систем паке ини не нахожу.
Даже если из системпака первой готики выдергнуть эту строку ничего не изменится, я проверял.
Пост автоматически объединён:

Всё последней версии
 

MaGoth

★★★★★★★★★★★
Администратор
Регистрация
7 Янв 2003
Сообщения
19.371
Благодарности
7.802
Баллы
995
Voron25, СП частично поддерживает Сиквел, вы логи релизов не читаете совсем ?! Это надо отдельно под Сиквел ковырять и настраивать патчингом..
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.276
Благодарности
4.579
Баллы
625
Voron25, ну взял бы оригинальный патч для г1, посмотрел на что он ссылается и сделал бы по аналогии, тупо меняя адреса и одно смещение.
 

Вложения

  • BarrierG2A.7z
    362 байт · Просмотры: 6

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.276
Благодарности
4.579
Баллы
625
Значит объясняю. Читать патч через нотпад++ с установленным синтаксисом из менеджера ресурсов.
Все функции, на которые ссылается патч, абсолютно идентичны что в одном движке, что в другом, поэтому просто ищем теже самые места и подставляем новые адреса.
1590324925782.png


Все байткоды - это обычные условные джампы внутри одной процедуры, поэтому логично что их не трогаем.
А вот последний байткод - это вызов другой процедуры, поэтому смещение придется высчитать по формуле 0x00476038 - (0x006CD0AC + 0x5) = 0xFFDA8F87 , чтобы смещение уткнулось сразу в ее конец и завершилась ничего не делая.
1590325197704.png
 

OsmithREV

Участник форума
Регистрация
17 Мар 2016
Сообщения
117
Благодарности
183
Баллы
230
Можете подсказать как в 1.0h провернуть это (https://worldofplayers.ru/threads/41484/ )? Собственно, хочу пошаманить с боевкой: подцепить класс oCNpcMessages, добавить туда своих ивентов, переписать существующие, ну и добавить пару новых полей в oCNpc. Как понимаю, в тестовой сборке этот процесс изменился (по крайней мере на zCLASS_UNION_DEFINITION ругается), так что прошу хотя бы небольшого разъяснения как нынче все работает, или куда копать. Спасибо :).

p.s. Я понимаю, что oCNpcMessages в боевке это больше аним контроль и управление, но мне это и нужно.
 
Сверху Снизу