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

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

Вопросы по скриптингу

MaGoth

★★★★★★★★★★★
Администратор
Регистрация
7 Янв 2003
Сообщения
19.367
Благодарности
7.815
Баллы
995
  • Первое сообщение
  • #1
Прежде чем задавать вопросы, ознакомьтесь с документацией..
1) Читать онлайн
2) Архив с офлайн-версией(chm) во вложении
 

Вложения

  • Vam_tutor.rar
    171,6 KB · Просмотры: 572
Последнее редактирование модератором:

D36


Модостроитель
Регистрация
3 Дек 2014
Сообщения
2.178
Благодарности
3.351
Баллы
485
// на НПС есть броня
А если нет?
Daedalus:
var C_ITEM armor;
if(Npc_HasEquippedArmor(self))
{
    armor = Npc_GetEquippedArmor(self);
}
else
{
    armor = NO_ARMOR; //-1
};
B_SetNpcVisual(self,MALE,Hum_Head_Random,Face_L_Random,Rassen,armor);

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

Играя за паладина и добравшись до подвалов монастыря, ГГ находит там НЕ готовые и блестящие паладинские латы, а комплект древних ржавых доспехов теневого воина
Раз уж заговорили про скрипты неофициального обновления - а что там появится при Helmets_Enabled == TRUE?
 

D36


Модостроитель
Регистрация
3 Дек 2014
Сообщения
2.178
Благодарности
3.351
Баллы
485
а если нет то будет нолик :)
Нет, будет null, который для B_SetNpcVisual невалиден, даже если где-то по пути конвертируется в 0. Специально для NPC без доспехов есть константа NO_ARMOR равная -1.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
Специально для этого есть константа NO_ARMOR равная -1.
что там дойдёт в итоге до Mdl_SetVisualBody null или 0 кто его знает. я выложил черновик. мысль простая и понятная. кому надо тот разовьёт: добавит и женский пол и татушки и прочие, в т.ч. NO_ARMOR . в игре работало и без NO_ARMOR у зэков.
 

Slavemaster


Модостроитель
Регистрация
10 Июн 2019
Сообщения
1.078
Благодарности
1.897
Баллы
290

D36


Модостроитель
Регистрация
3 Дек 2014
Сообщения
2.178
Благодарности
3.351
Баллы
485
Тогда так:
Daedalus:
var C_ITEM armor;
var int armorInstance;
if(Npc_HasEquippedArmor(self))
{
    armor = Npc_GetEquippedArmor(self);
    armorInstance = Hlp_GetInstanceID(armor);
}
else
{
    armorInstance = NO_ARMOR;
};
B_SetNpcVisual(self,MALE,Hum_Head_Random,Face_L_Random,Rassen,armorInstance);
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275

Slavemaster


Модостроитель
Регистрация
10 Июн 2019
Сообщения
1.078
Благодарности
1.897
Баллы
290
не обязательно. в B_SetNpcVisual идёт var int armorInstance. он сам возьмёт айдиинстанции.
Неверно.
Daedalus:
func void PrintInt(var int value)
{
    Hlp_PrintConsole(IntToString(value));
};

func void Test()
{
    var C_ITEM gold;
    gold = Wld_FindVob("ITMI_GOLD");
    
    Hlp_PrintConsole(gold.name);
    PrintInt(gold);
    PrintInt(ItMi_Gold);
    PrintInt(Hlp_GetInstanceID(gold));
};
Код:
Золото
74699
6929
6929
 

KirTheSeeker

Участник форума
Регистрация
18 Авг 2017
Сообщения
1.925
Благодарности
556
Баллы
275
Сейчас проверю...
При выбранном изначально разделении доспехов и шлемов, в подвале ГГ ждут соответственно доспех паладина и шлем с опущенным забралом.
Правда у меня шлемы сильно съезжают вперёд и вниз, поэтому видны косичка и затылок как сквозь кольчужный капюшон, так и сквозь тяжёлый "паладинский горшок". Возможно, так получается из-за использования новых моделей головы.
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.300
Благодарности
4.633
Баллы
625
Только вот с товарищами обсуждали null и производные от него баги.
Если кратко: передавать во внешнюю функцию его можно. Во внутреннюю скриптовую - опасно. Так как null есть ни что иное, как 0x00 индекс инстанции, а не нулевой указатель на объект. А нулевая инстанция - это help_inst. То есть там может быть другой объект (npc, item или что-то еще). При передаче такого аргумента или операциях присвоения указатель на инстанцию будет скопирован в целевую переменную и это будет уже нихрена не null.
До ближайшего фикса (он уже сделан) лучше использовать рекомендованный выше (-1).
Union:
#engine [G2A]
    #patch [null instance test fix]
        // Create a null symbol at the memory.
        INT shi_malloc = ImportSymbol("shw32.dll", "shi_malloc")
        #assembler [make_null_symbol]
            push 03Ch        ; sizeof(zCPar_Symbol)
            call $shi_malloc
            mov ecx, eax
            call 0x007A1690  ; zCPar_Symbol ctor
            add esp, 4
            ret
        #/assembler
        INT symbol = make_null_symbol()
        
        // Check the pushed instance index.
        // If this is a zero, it will be replaced
        // to the flag (-2) - a true null symbol.
        #assembler [0x00792695]
            orgcode
            test eax, eax
            jnz return
            mov eax, 0xFFFFFFFE  ; flag null
        return:
        #/assembler
        
        // Detours of the GetSymbol index protection.
        #assembler [0x007A3EF6]
            cmp eax, 0xFFFFFFFE  ; flag null
            jnz return
            mov eax, $symbol
            ret 4
        return:
            mov eax, 0
            ret 4
        #/assembler
    #/patch
#/engine
 

Slavemaster


Модостроитель
Регистрация
10 Июн 2019
Сообщения
1.078
Благодарности
1.897
Баллы
290
значит неверно. тем не менее оно работает без взятия Hlp_GetInstanceID
Так оно бы и с -1 работало бы. Не повод мусор в функции совать - так можно и вылет словить.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
Не повод мусор в функции совать - так можно и вылет словить.
при чём тут мусор то? :) ввиду того что в ряде случаев работает и так и так, картины ясной в голове нет. разъясните лучше с какими внешними функциями что можно использовать и что при этом плохо, что хорошо а что допустимо.
var C_ITEM itmvar int InstanceItmvar C_NPC npcvar int InstanceNpc
Mdl_SetVisualBody
CreateInvItems
Npc_RemoveInvItems
AI_EquipArmor
***
 

Slavemaster


Модостроитель
Регистрация
10 Июн 2019
Сообщения
1.078
Благодарности
1.897
Баллы
290
при чём тут мусор то?
Функция ожидает, что в неё передадут InstanceID предмета. Ты передаёшь НЕ InstanceID. От того, что движок это "проглотил" без видимых негативных эффектов, этот вызов не становится корректным. Можно, конечно, разложить на атомы, что там в движке происходит, но зачем? Просто не делай так. И ещё, в Готике нет по-настоящему локальных переменных, просто компилятор вам не даёт обращаться к переменной извне. А на самом деле, это переменная сохраняет своё значение между вызовами функций. Так что это ещё одна ошибка в твоём коде.

Давай рассмотрим 2 объекта связанных с классом C_ITEM (c C_NPC всё абсолютно аналогично).
Daedalus:
instance ItMi_Gold(C_ITEM) { name = "Золото"; };
var C_ITEM varGold;
Возможно использование объекта ItMi_Gold в двух контекстах:
  1. Как целое число: все предметы, созданные с помощью кода из ItMi_Gold будут иметь instanceID равный ItMi_Gold.
  2. Как указатель на конкретный объект. ItMi_Gold содержит указатель на последний созданный с помощью этого кода предмет. Если ни одного предмета не было создано с помощью этого конструктора или последний из созданных был уничтожен движком, то указатель будет равен нулю.
Объект varGold может быть использован только как указатель на конкретный предмет. В отличие от ItMi_Gold, движок не будет в эту переменную ничего автоматически записывать (только обнулять иногда).

В связи с пунктами 1 и 2, следующее логическое выражение всегда верно:
Daedalus:
Hlp_GetInstanceID(ItMi_Gold) == -1 || Hlp_GetInstanceID(ItMi_Gold) == ItMi_Gold

Mdl_SetVisualBody ожидает число: instanceID предмета-брони, чтобы создать новый экземпляр этой брони и экипировать её на NPC. Поэтому туда можно передавать, например, ItAr_Barkeeper или Hlp_GetInstanceID(Npc_GetEquippedArmor(hero)).
с какими внешними функциями что можно использовать
У меня нет установленного GS. Но, скорее всего, это отражено в объявлении самих внешних функций: если она принимает var instance, или var C_ITEM, то ожидается передача указателя на конкретный игровой объект. Если же функция принимает var int, то ожидается instanceID. Да и по логике, например, если функция создаёт предметы в инвентаре NPC, она это делает для конкретного персонажа, а не для всех персонажей с определённым instanceID. Иначе бы не получилось в инвентаре отдельно взятого волка создать шкуру и т.п.
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
Slavemaster, спасибо за ликбез. теперь становится понятно что Mdl_SetVisualBody при передачи "-1" не "раздент" НПС, а сохранить его текущий "доспех".

то есть для кода выше вместо проверок на то ли одет ли доспех или нет можно всегда отдавать "-1" в Mdl_SetVisualBody .


Daedalus:
var C_ITEM armor;
var int armorInstance;
if(Npc_HasEquippedArmor(self))
{
armor = Npc_GetEquippedArmor(self);
armorInstance = Hlp_GetInstanceID(armor);
}
else
{
armorInstance = NO_ARMOR;
};
B_SetNpcVisual(self,MALE,Hum_Head_Random,Face_L_Random,Rassen,armorInstance);
Код:
B_SetNpcVisual(self, MALE, Hum_Head_Random, Face_L_Random,  Rassen, -1);
 

Парниша с горы

Участник форума
Регистрация
14 Дек 2022
Сообщения
121
Благодарности
41
Баллы
60
А возможно ли вообще прикрутить эффекты частиц(свечение дракона-нежити например) из НВ в классику? Попытался тупо скопировать скрипты, и после начала новой игры вылезла ошибка.
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
Сверху Снизу