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

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

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

MaGoth

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

Вложения

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

neromont


Модостроитель
Регистрация
12 Мар 2011
Сообщения
675
Благодарности
662
Баллы
245
Привет всем.
Не могу понять логику работы скрипта:
func void B_CheckDeadMissionNPCs ()
{
// Получаем ссылку на Лефти (При этом, я так понимаю, в self записывается ссылка на Лефти) .
// Таким образом, они вероятно, равны друг другу.
// Какая здесь логика? Почему при выполнении этого условия персонаж считается мертвым?

if (Hlp_GetInstanceID(Org_844_Lefty) == Hlp_GetInstanceID(self))
{
if (Lefty_Mission == LOG_RUNNING)
{
B_LogEntry (CH1_CarryWater, "Теперь, когда Лефти мертв, вопрос с водой можно считать закрытым. Честно говоря, мне этот парень никогда не нравился");
Log_SetTopicStatus (CH1_CarryWater, LOG_SUCCESS);
LeftyDead = True;
};
};
};
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.301
Благодарности
4.636
Баллы
625
Привет всем.
Не могу понять логику работы скрипта:
func void B_CheckDeadMissionNPCs ()
{
// Получаем ссылку на Лефти (При этом, я так понимаю, в self записывается ссылка на Лефти) .
// Таким образом, они вероятно, равны друг другу.
// Какая здесь логика? Почему при выполнении этого условия персонаж считается мертвым?

if (Hlp_GetInstanceID(Org_844_Lefty) == Hlp_GetInstanceID(self))
{
if (Lefty_Mission == LOG_RUNNING)
{
B_LogEntry (CH1_CarryWater, "Теперь, когда Лефти мертв, вопрос с водой можно считать закрытым. Честно говоря, мне этот парень никогда не нравился");
Log_SetTopicStatus (CH1_CarryWater, LOG_SUCCESS);
LeftyDead = True;
};
};
};
Потому что функция вызывается из состояния ZS_Dead. Еще перед вызовом предполагается что персонаж мертв.
 

neromont


Модостроитель
Регистрация
12 Мар 2011
Сообщения
675
Благодарности
662
Баллы
245
Функция

Daedalus:
Wld_SetObjectRoutine (0,00,"EVT_AM_LOB_GATE_BIG",1)

Изменяет распорядок для объекта до конца игры?
Ее ведь не нужно вызывать каждый раз при инициализации мира?
P.S. Судя по всему, до конца игры.
 
Последнее редактирование:

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Wld_SetObjectRoutine (0,00,"EVT_AM_LOB_GATE_BIG",1)
Насколько я знаю, эта функция работает только для костров, факелов, светильников. Для муверов не работает. В Г1 разрабы так пытались закрыть ворота СШ после её "обрушения", и они, понятное дело, не закрывались.
 

Jr13San


Модостроитель
Регистрация
1 Апр 2010
Сообщения
449
Благодарности
266
Баллы
230
Ее ведь не нужно вызывать каждый раз при инициализации мира?
Я считаю, что нужно. Потому что "список рутин" очищается, например, после сохр.->загрузки, или при переходе на другой зен (этого достаточно).
Функции: "Wld_SetObjectRoutine()" и "Wld_SetMobRoutine()" схожи, только первая для воб-объектов, а вторая чисто для интерактивных объектов. И не зря функция "Wld_SetMobRoutine()" пишется в "INIT_" функции инициализации локации.
Для использования функции "Wld_SetObjectRoutine()" имя объекта должно быть уникальным, иначе она выполнится для первого попавшегося объекта.
А функция "Wld_SetMobRoutine()" выполнится для всех одноимённых рутин (по названию сцены). Думаю так.
 
Последнее редактирование:

neromont


Модостроитель
Регистрация
12 Мар 2011
Сообщения
675
Благодарности
662
Баллы
245
Я так понимаю, что инициализация глобальных переменных выполняется после вставки Npc?
Снимаю вопрос. Разобрался.
 
Последнее редактирование:

neromont


Модостроитель
Регистрация
12 Мар 2011
Сообщения
675
Благодарности
662
Баллы
245
Существует две анимации: MAP - свитки, книги и пр.
Daedalus:
// ---------------------------------------------------------------------------------------------------------------
// Чтение свитка (MAP)
 
        ani         ("t_MAP_Stand_2_S0"         1   "s_MAP_S0"      0.1 0.0 M.  "Hum_MapRead_M01.asc"       F   1   24)
        {
            *eventTag   (18 "DEF_INSERT_ITEM"   "ZS_RIGHTHAND")
            *eventSFX   (18 "Scroll_Unfold")
        }
        ani         ("s_MAP_S0"                 1   "s_MAP_S0"      0.0 0.0 M.  "Hum_MapRead_M01.asc"       F   25  25)
        ani         ("t_MAP_S0_2_Stand"         1   ""              0.0 0.1 M.  "Hum_MapRead_M01.asc"       R   1   24)
        {
            *eventTag   (18 "DEF_REMOVE_ITEM")
            *eventSFX   (18 "Map_Unfold"    R:1000)
        }

и BRUSH - щетка для мытья полов.

Daedalus:
// Мойка полов (BRUSH)
 
        ani         ("t_BRUSH_Stand_2_S0"   1   "s_BRUSH_S0"    0.1 0.0 M.  "Hum_BrushFloor_A01.asc"            F   0   2)
        {
            *eventTag   (1  "DEF_INSERT_ITEM"   "ZS_RIGHTHAND")
        }
        ani         ("s_BRUSH_S0"           1   "s_BRUSH_S0"    0.0 0.0 M.  "Hum_BrushFloor_A01.asc"            F   3   3)
        ani         ("t_BRUSH_S0_2_Stand"   1   ""              0.0 0.1 M.  "Hum_BrushFloor_A01.asc"            R   0   2)
        {
            *eventTag   (1  "DEF_REMOVE_ITEM")
        }
        ani         ("t_BRUSH_S0_2_S1"      1   "s_BRUSH_S1"    0.0 0.0 M.  "Hum_BrushFloor_A01.asc"            F   4   39)
        ani         ("s_BRUSH_S1"           1   "s_BRUSH_S1"    0.0 0.0 M.  "Hum_BrushFloor_A01.asc"            F   40  120 FPS:12.5)
        {
            *eventPFX   (43 1   "SOAPFOAM"  "BIP01 L Finger0"   ATTACH  )
            *eventPFX   (46 2   "SOAPFOAM"  "BIP01 R Finger0"   ATTACH  )
            *eventPFXStop   (112    1   )
            *eventPFXStop   (115    2   )           
        }
        aniAlias    ("t_BRUSH_S1_2_S0"      1   "s_BRUSH_S0"    0.0 0.0 M.  "t_BRUSH_S0_2_S1"           R)

Как я понимаю разница в количестве состояний. В первом случае: 1, во-втором: 2.

Внимание вопрос: Почему в случае с листом бумаги функция Wld_PlayEffect() и некоторые другие работают.

Daedalus:
INSTANCE StandardBrief        (C_Item)
{
    //...
scemeName   = "MAP";
    on_state[0]            =   UseStandardBrief;
    //...
};
func void UseStandardBrief ()
{
    Wld_PlayEffect("spellFX_Teleport_RING",  hero  , hero    , 0, 0, 0, FALSE );
    //...
    }

А в случае с щеткой нет?

Daedalus:
INSTANCE ItMi_Broom (C_Item)
{
 //...
 scemeName   = "BROOM";
 on_state[0]   =  Use_Broom;
 //...
 TEXT[5]    =  NAME_Value;
 COUNT[5]   =  value;
};
func void Use_Broom()
{
 Wld_PlayEffect("spellFX_Teleport_RING",  hero  , hero , 0, 0, 0, FALSE );
    }
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Насколько я знаю, если состояний больше, чем 1, то функция on_state[0] вызывается при переходе из состояния "1" в состояние "0". Это не начало, а конец взаимодействия с предметом.
 

neromont


Модостроитель
Регистрация
12 Мар 2011
Сообщения
675
Благодарности
662
Баллы
245
Я вроде пробовал прописать для onstate[1] = funcName, но ничего не изменилось. Сейчас еще потестю.
Извиняюсь. Код изменил для ItMi_Broom, а в игре проверял ItMi_Brush. Старею...
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.854
Благодарности
6.733
Баллы
1.625

Jr13San


Модостроитель
Регистрация
1 Апр 2010
Сообщения
449
Благодарности
266
Баллы
230
Внимание вопрос: Почему в случае с листом бумаги функция Wld_PlayEffect() и некоторые другие работают.
А в случае с щеткой нет?
И с щёткой и с метлой всё работает. Возможно просто число частиц в сцене зашкаливает, поэтому некоторые частицы не успевают рендериться. Попробуй сделать тест в "чистом поле".
Brush_PFX_Test.jpg
 

neromont


Модостроитель
Регистрация
12 Мар 2011
Сообщения
675
Благодарности
662
Баллы
245
Использую PrintGlobals(), но в zSpy ничего не выводится.
В MARVIN включил Debug режим клавишами Alt + O.
Что нужно еще чтобы вывести в zSpy нужную информацию?
Использовал канал №2.
GothicStarter ► Сообщения zSpy ► 4
 
Последнее редактирование:

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.301
Благодарности
4.636
Баллы
625
Использую PrintGlobals(), но в zSpy ничего не выводится.
В MARVIN включил Debug режим клавишами Alt + O.
Что нужно еще чтобы вывести в zSpy нужную информацию?
Использовал канал №2.
GothicStarter ► Сообщения zSpy ► 4
Во-первых что такое канал. Канал определяется как битовое поле размером 4 байта (от 0 до 31).
В случае передачи номера канала используется обычный int, указывая на номер бита в поле. ( PrintDebugInstCh( int, string ); )

Во-вторых активные каналы необходимо настроить. Например через ini файл:
1558085927148.png
Где debugAllChannels == 1 -> включает все каналы, что соответствует 0xFFFFFFFF.
иначе debugChannels указывает все нужные каналы через , или ;

Еще можно через марвин вводом команд:

set alldebugchannels разрешает слушать все каналы одновременно.
clear alldebugchannels запрещает слушать все каналы одновременно.
toggle alldebugchannels переключает значение прослушки всех каналов одновременно на противоположное.

set debugchannels разрешает слушать заданный канал.
clear debugchannels запрещает слушать указанный канал.
toggle debugchannels переключает значение прослушки на противоположное.
 
Последнее редактирование:

neromont


Модостроитель
Регистрация
12 Мар 2011
Сообщения
675
Благодарности
662
Баллы
245
Я так понимаю, если мы вставляем Npc для которого установлен распорядок дня...

Wld_InsertNpc(BAU_2020_Onar,"NW_FARM1_INHOUSE_02");

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

Можно просто писать:

Wld_InsertNpc(BAU_2020_Onar,"");
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.301
Благодарности
4.636
Баллы
625
Не обязательно указывать точку вставки, так как Npc вставляется в мир в точку, где он должен находится согласно распорядку.
Не совсем. Если ты не указываешь явную точку спауна (имя вейпоинта или воба), то нпс вставляется в нулевую точку координат. А вставка в рутину произойдет в тот момент, когда камера приблизится на минимальное видимое расстояние до нее.
Если указать куда вставить персонажа, то там отработает функция спаунменеджера с последующим вызовом Enable (подробнее тут), не игнорируй этот параметр без видимых причин.
 

N1kX


Модостроитель
Регистрация
13 Ноя 2009
Сообщения
6.113
Благодарности
5.605
Баллы
910
Чем чревато использование не правильного аргумента, например в функции или в любой другой:
AI_Teleport(var C_NPC npc, var string waypoint);
Здесь указана инстанция NPC, телепорт в WP будет осуществлен (Хоть и неправильный аргумент)
AI_Teleport(VLK_494_Attila,"NW_CITY_BANDA_8");
Здесь ссылка на класс этого NPC, телепорт в WP будет осуществлен (Аргумент правильный)
var C_NPC Attila;
Attila = Hlp_GetNpc(VLK_494_Attila);
AI_Teleport(Attila,"NW_CITY_BANDA_8");
Движок хоть и ругается, но все равно выполняет эту работу.
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.854
Благодарности
6.733
Баллы
1.625
N1kX, тут все правильно.
разве движек ругается?
 

N1kX


Модостроитель
Регистрация
13 Ноя 2009
Сообщения
6.113
Благодарности
5.605
Баллы
910
Более нагляднее на функции
Npc_IsDead(var C_NPC npc);

Daedalus:
func int dia_xardas_pacckaz_condition()
{
    //if((Kapitel >= 3) && Npc_IsDead(KDF_679_FALER) && (FALERKILL == TRUE) && (Npc_HasItems(other,svitokfalera) >= 1))
    if((Kapitel >= 3) && Npc_IsDead(Faler) && (FALERKILL == TRUE) && (Npc_HasItems(other,svitokfalera) >= 1))
    {
        return TRUE;
    };
};
Если проверять инстанцию, то будет сообщение:
20:44 Warn: 0 C: SCRIPT: Npc_IsDead(): illegal param: "KDF_679_FALER" is NULL. .... <oGameExternal.cpp,#252>
20:44 Warn: 0 C: SCRIPT: last parser func-name: DIA_XARDAS_PACCKAZ_CONDITION .... <oGameExternal.cpp,#262>
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.854
Благодарности
6.733
Баллы
1.625
N1kX, ну а было где нить:
Daedalus:
var C_Npc Faler;

Faler = Hlp_GetNpc(KDF_679_FALER);
?
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.854
Благодарности
6.733
Баллы
1.625
а ну и попробуй
(Npc_IsDead(Faler) == TRUE)
Daedalus:
    if(MIS_KilledDragons == 4)
    {
        MIS_AllDragonsDead = TRUE;
        if((DJG_BiffParty == TRUE) && (Npc_IsDead(Biff) == FALSE))
        {
            DJG_BiffSurvivedLastDragon = TRUE;
        };
    };
 
Сверху Снизу