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

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

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

MaGoth

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

Вложения

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

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.074
Благодарности
1.030
Баллы
315
π'yavka,
вот так попробуй
Daedalus:
func void B_CheckDeadMissionNPCs(var c_npc slf)
{
    var inst_slf;   
    inst_slf = Hlp_GetInstanceID(slf);
    
    if (inst_slf == Org_844_Lefty)
    {
        if(Lefty_Mission == LOG_RUNNING)
        {
            B_LogEntry(CH1_CarryWater,"Теперь, когда Лефти мертв, вопрос с водой можно считать закрытым. Честно говоря, мне этот парень никогда не нравился.");
            Log_SetTopicStatus(CH1_CarryWater,LOG_SUCCESS);
            LeftyDead = TRUE;
        };
    }
    else if (inst_slf == MOBNEW)
    {
        B_LogEntry(MOBNEWINFO,"TEXT");
    };
};


func void ZS_Dead ()
{
    PrintDebugNpc    (PD_ZS_FRAME, "ZS_Dead" );   
    PrintGlobals    (PD_ZS_CHECK);

    C_ZSInit();

    self.aivar[AIV_PLUNDERED] = FALSE;
 
    //-------- Erfahrungspunkte fьr den Spieler ? --------
    //SN: VORSICHT, auch in B_MagicHurtNpc() vorhanden!
    if    Npc_IsPlayer   (other)
    ||    (C_NpcIsHuman  (other) && other.aivar[AIV_PARTYMEMBER])
    ||    (C_NpcIsMonster(other) && other.aivar[AIV_MM_PARTYMEMBER])
    {
        B_DeathXP();    // vergibt XP an SC
    };
 
    if    C_NpcIsMonster(self)
    {
        B_GiveDeathInv ();     // fьr Monster
    };
    B_CheckDeadMissionNPCs(self);
    B_Respawn (self); 
 
    if (Npc_IsPlayer(other))
    {
        self.aivar[AIV_KilledByPlayer] = TRUE;
    };
};
 

π'yavka

Участник форума
Регистрация
21 Мар 2025
Сообщения
29
Благодарности
2
Баллы
15
ElderGamer,
Здравствуй, можешь, пожалуйста, помочь мне с кодом для G1, чтобы NPC мгновенно уходил на новое расписание?
Сделал так, чтобы менялось расписание при убийстве моба. Заметил, что в определенных зонах после убийства NPC стоит, при чем проверил через MARVIN, что расписание меняется. Если подойти к NPC, то по скрипту он начнет диалог (important1) и как он будет закончен - побежит на свое место по расписанию.
Эмпирическим путем узнал, что есть определенные зоны, где NPC при убийстве моба стоит, а есть зоны где он бежит как задумано (Прикрепил скриншот: NPC - стрелка, 0 - место, где скрипт работает сразу, x - место, где скрипт не работает без диалога или смены времени)
NPCandMOBrountime.jpg
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.506
Благодарности
3.318
Баллы
525
Сделал так, чтобы менялось расписание при убийстве моба. Заметил, что в определенных зонах после убийства NPC стоит, при чем проверил через MARVIN, что расписание меняется. Если подойти к NPC, то по скрипту он начнет диалог (important1) и как он будет закончен - побежит на свое место по расписанию.
Эмпирическим путем узнал, что есть определенные зоны, где NPC при убийстве моба стоит, а есть зоны где он бежит как задумано (Прикрепил скриншот: NPC - стрелка, 0 - место, где скрипт работает сразу, x - место, где скрипт не работает без диалога или смены времени)
Опиши ситуацию детальнее. Перечитал несколько раз, но не понял, что должно происходить.
 

π'yavka

Участник форума
Регистрация
21 Мар 2025
Сообщения
29
Благодарности
2
Баллы
15
Опиши ситуацию детальнее. Перечитал несколько раз, но не понял, что должно происходить.
Я реализовал скрипт, чтобы при убийстве моба менялось расписание у NPC (он должен побежать к трупу) . Проблема в том, что после убийства NPC стоит на месте, хотя при проверке видно, что расписание меняется. Как было сказано ранее, я заметил, что есть несколько мест, где при убийстве моба NPC стоит, а есть такие места, где он начинает бежать.
Собственно, как я понял, мне нужен скрипт, который заставит NPC мгновенно выполнять или переходить на новое расписание.
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.506
Благодарности
3.318
Баллы
525
Первое правило, которое должен усвоить скриптер квестов, звучит так: игрок не обязан действовать таким образом, как рассчитывает скриптер. Это так, на будущее. ;)

он должен побежать к трупу
Здесь имеет место большая уязвимость - тебе заранее неизвестно место нахождения трупа. Ты писал про изменение распорядка. Распорядок привязан к вейпоинту. Труп может находиться на существенном удалении от вейпоинта.

Теория. Движок позволяет реализовать два способа передвижения неписей. Первый способ - это движение от точки своего текущего местоположения к другой точке условно "по прямой". При движении непися к неписю (к трупу непися тоже) используется этот способ. При этом движущийся непись не разбирает дороги. Он может упереться в стену или свалиться с высоты и разбиться. Второй способ - это движение вдоль линий путевой сети. В принципе, это доработанный первый способ. Только линии путевой сети расположены в игровом мире с тем расчётом, что непись, движущийся вдоль них, не уткнётся в стену и не свалится с высоты.

Проблема в том, что после убийства NPC стоит на месте, хотя при проверке видно, что расписание меняется.
Каково новое расписание?
 

π'yavka

Участник форума
Регистрация
21 Мар 2025
Сообщения
29
Благодарности
2
Баллы
15
Первый способ - это движение от точки своего текущего местоположения к другой точке условно "по прямой".

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

Каково новое расписание?

В B_CheckDeadMissionNPCs прописано:
Код:
Npc_ExchangeRoutine(VLK_2000_Buddler,"WAIT");

Я создал новый TA, единственное отличие от TA_GUARD в том, что NPC бежит вместо того, чтобы идти пешком .
Код:
func void Rtn_WAIT_2000()
{
TA_GUARD_RUN(10,0,22,0,"MOLERATWAIT");
TA_GUARD_RUN(22,0,10,0,"MOLERATWAIT");
};
 

N1kX

Участник форума
Регистрация
13 Ноя 2009
Сообщения
6.304
Благодарности
5.915
Баллы
940
В B_CheckDeadMissionNPCs прописано:
Код:
Npc_ExchangeRoutine(VLK_2000_Buddler,"WAIT");
Попробуй вместо
Код:
Npc_ExchangeRoutine -> B_ExchangeRoutine

НПС не начинает проигрывать свой новый распорядок дня например из-за активной анимации, поэтому надо делать костыли небольшие, типо очистить очередь этого НПС, прервать текущую анимацию и т.д. Можешь и не менять, но тогда надо будет сделать
Код:
Npc_ClearAIQueue (VLK_2000_Buddler);
AI_ContinueRoutine (VLK_2000_Buddler);
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.074
Благодарности
1.030
Баллы
315
π'yavka, а что он будет делать после этого? если это перфоманс что НПС прибегает к трупу что то делает, а потом возвращается к старому расписанию то можно использовать оверлей. если бежать нужно именно к трупу, тогда можно использовать функцию AI_GotoNpc.
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.506
Благодарности
3.318
Баллы
525
Уже пояснили причину выше.

Не знаю, почему скриптеры Пираний используют в функциях распорядков бесполезные функции-прослойки (TA_Stand, TA_Guard, TA_Smalltalk и др.). У себя для уникальных состояний давно перестал создавать такие прокси. Вместо них в распорядках сразу прописываю нужное состояние в функции TA_Min (если не путаю название, пишу по памяти).

Я создал новый TA, единственное отличие от TA_GUARD в том, что NPC бежит вместо того, чтобы идти пешком .
Думаю, создание нового уникального ZS-состояния для более-менее правильного поведения непися в квесте - это оптимальный подход. Но нужно в этом разбираться. В этом состоянии непись может прибежать на вейпоинт, в окрестностях которого предполагается наличие трупа, просканировать окрестности и подойти к трупу, в случае его обнаружения. Подойдя к трупу непись может проиграть анимацию, если это нужно. Если же предполагается диалог с ГГ, то непись может подойти к ГГ. Только здесь есть уязвимость, игрок не обязан стоять и ждать, пока непись подойдёт к нему. Возможно, потребуется временно отнять у игрока возможность управлять ГГ.

Гм, ты правил игровой мир, добавив этот вейпоинт?
 
Последнее редактирование:

π'yavka

Участник форума
Регистрация
21 Мар 2025
Сообщения
29
Благодарности
2
Баллы
15
N1kX,
Спасибо огромное, все заработало как нужно.

а что он будет делать после этого?
В данный момент NPC стоит и ждёт начала диалога. Да, планировал реализовать что-то типа "перфоманса" :D созданием нового TA с командой AI_GotoNpc.

прописываю нужное состояние в функции TA_Min
Очень интересно, но пока не понимаю, как это работает. Сейчас посмотрел, вроде у Стоуна из Г1 в коде как раз через TA_Min в моменте скрипт реализован.
Думаю, создание нового уникального ZS-состояния для более-менее правильного поведения непися в квесте - это оптимальный подход.
Поэтому пока что обхожусь созданием TA.


Гм, ты правил игровой мир, добавив этот вейпоинт?
Да, вейпоинт я добавил. Уже поменял код расписания - всё заработало как надо.
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.506
Благодарности
3.318
Баллы
525
Очень интересно, но пока не понимаю, как это работает.
В классическом варианте в функции распорядка Rtn_XXX_YYY() используется функция-прокладка. У тебя это TA_GUARD_RUN. А уже из неё вызывается целевая функция TA_Min. Но можно обойтись без прокладки, приписав функцию TA_Min непосредственно в функции распорядка Rtn_XXX_YYY(). Пример:

Daedalus:
func void Rtn_OT_239()
{
    TA_Min(self,7,0,20,0,ZS_GuardPathToCellar,"OCC_MERCS_DOWNSTAIRS_3");
    TA_Min(self,20,0,7,0,ZS_GuardPathToCellar,"OCC_MERCS_DOWNSTAIRS_3");
};
 

Сумрак

Участник форума
Регистрация
25 Окт 2021
Сообщения
1.755
Благодарности
742
Баллы
175

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.074
Благодарности
1.030
Баллы
315
Заинтересовался тут флагами, пробуя проходить разные моды. Прочитал Уроки скриптологии, часть 2. Тема первая: Глобальные константы., но или мне кажется, или я видел другие значения флагов НПС, кроме 0, 1, 2. Если я прав, то объясните пожалуйста их значения.
почитай про класс c_npc Класс C_Npc - ZenGin справочник - Gothic Library
если после этого останутся вопросы, пиши.
 

Dimus

★★★★★★★★★
Супермодератор
Регистрация
19 Июл 2010
Сообщения
5.602
Благодарности
4.213
Баллы
915
Сумрак, есть ещё пара значений NPC флагов.
Daedalus:
//
//    NPC FLAGS
//
CONST INT NPC_FLAG_FRIEND                                =  1 << 0                ;    // wird nicht benutzt (wird über aivar geregelt)
CONST INT NPC_FLAG_IMMORTAL                                =  1 << 1                ;    // Unverwundbar
CONST INT NPC_FLAG_GHOST                                =  1 << 2                ;    // Halb-Transparenter NPC (Gothic.ini [INTERNAL] 'GhostAlpha')
const int NPC_FLAG_NFOCUS = 1 << 18;
Предпоследний флаг используется у огненного дьявола и духов Куарходрона и Радемеса.
Последний флаг используется для отключения фокуса на NPC, например, у каменных големов в пещере у пирамид.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.074
Благодарности
1.030
Баллы
315
Код:
//
//    NPC FLAGS
//
CONST INT NPC_FLAG_FRIEND  =  1 << 0                ;    // wird nicht benutzt (wird ьber aivar geregelt)
CONST INT NPC_FLAG_IMMORTAL  =  1 << 1                ;    // Unverwundbar
CONST INT NPC_FLAG_GHOST =  1 << 2                ;    // Halb-Transparenter NPC (Gothic.ini [INTERNAL] 'GhostAlpha')
Код:
const int NPC_FLAG_FRIEND = 1;
const int NPC_FLAG_IMMORTAL = 2;
const int NPC_FLAG_GHOST = 4;
const int NPC_FLAG_NFOCUS = 1 << 18;

флагов может быть несколько.

Daedalus:
INSTANCE NONE_ADDON_111_Quarhodron (Npc_Default)
{
    // ------ NSC ------
    name         = "Quarhodron";
    guild         = GIL_NONE;
    id             = 111;
    voice         = 11;
    flags       = NPC_FLAG_GHOST|NPC_FLAG_IMMORTAL;                                                                   
    npctype        = NPCTYPE_FRIEND;
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
2.074
Благодарности
1.030
Баллы
315
Последний флаг используется для отключения фокуса на NPC, например, у каменных големов в пещере у пирамид.
вот кстати... Вопрос знатокам: а в чём принципиальная разница между flags = NPC_FLAG_NFOCUS и
noFocus = true ?

Daedalus:
CLASS C_NPC
{
    VAR INT     id                                ;        //    absolute ID des NPCs
    VAR STRING     name            [5]                ;        //    Namen des NPC
    VAR STRING     slot                            ;           
    VAR STRING    effect;
    VAR INT        npcType                            ;           
    VAR INT        flags                            ;           
    VAR INT     attribute        [ATR_INDEX_MAX]    ;           
    var int     HitChance        [MAX_HITCHANCE] ;
    VAR INT        protection        [PROT_INDEX_MAX];           
    VAR INT        damage            [DAM_INDEX_MAX] ;           
    VAR INT        damagetype                        ;
    VAR INT        guild,level                        ;           
                                                            
    VAR FUNC    mission            [MAX_MISSIONS]    ;           
    var INT        fight_tactic                    ;           
    VAR INT        weapon                            ;           
                                                            
    VAR INT        voice                            ;           
    VAR INT        voicePitch                        ;           
    VAR INT        bodymass                        ;           
                                                            
    VAR FUNC    daily_routine                    ;        //    Tagesablauf
    VAR FUNC    start_aistate                    ;        //    Zustandsgesteuert
                                                            
    // **********************                   
    // Spawn                                   
    // **********************                   
    VAR STRING    spawnPoint                        ;        //    Beim Tod, wo respawnen ?
    VAR INT        spawnDelay                        ;        //    Mit Delay in (Echtzeit)-Sekunden
                                                            
    // **********************                   
    // SENSES                                   
    // **********************                   
    VAR INT     senses                            ;        //    Sinne
    VAR INT     senses_range                    ;        //    Reichweite der Sinne in cm
                                                            
    // **********************                   
    // Feel free to use                           
    // **********************                   
    // FIXME: TODO: bei goldmaster auf das benцtigte minimum reduzieren
    VAR INT        aivar            [100]            ;                       
    VAR STRING    wp                                ;           
    
    // **********************                   
    // Experience dependant                       
    // **********************                   
    VAR INT        exp                                ;        // EXerience Points
    VAR INT        exp_next                        ;        // EXerience Points needed to advance to next level
    VAR INT        lp                                ;       // Learn Points   

    // If this is set to TRUE, the Npc can't be interrupted in any action (e.g. BS_FLAG_INTERRUPTABLE for anis is being ignored)
    VAR INT        bodyStateInterruptableOverride                ;       
    // if "noFocus" is set to TRUE, the focus name and health bar will not be drawn of this nsc (hi, stefan!)
    var int     noFocus;                           
};
 

Gratt


Модостроитель
Регистрация
14 Ноя 2014
Сообщения
3.346
Благодарности
4.670
Баллы
625
Видимо флаг завели по аналогии с ITM_FLAG_NFOCUS, только у npc он не используется никак и нигде.
Чему равен этот флаг в определении скриптов?
 
Сверху Снизу