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

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

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

MaGoth

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

Вложения

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

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Анимации может не случиться и в случае, если randomize_mob равен единице, а непись относится к подгруппе боссов. И если в случае с нулём не ясно, что думали разрабы, то тут всё вполне очевидно. И не совсем правильно, как по мне.
 

MW 7


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

Код:
func int b_arena_getgladiatorranking(var int gladiatorinstance)
{
    var int rank;       rank = 0;
    if(b_arena_getgladiatorvictoryranking(AMZ_900_THORA) == 1)
    {
        rank += 1;
        if(gladiatorinstance == amz_900_thora)        {   return rank;    };
    };
    if(b_arena_getgladiatorvictoryranking(dmh_1302_malgar) == 1)
    {
        rank += 1;
        if(gladiatorinstance == dmh_1302_malgar)        {            return rank;        };
    };

такая же проверка некорректная ? очень странные конечно скрипты в сиквел местами.
думаю можно просто проверять по айди неписи.
Код:
    var C_Npc npc;    npc = Hlp_GetNpc(gladiatorinstance);
   
    if(b_arena_getgladiatorvictoryranking(AMZ_900_THORA) == 1)
    {
        rank += 1;
        //if(gladiatorinstance == amz_900_thora)        {   return rank;    };
        if (npc.id == 900)        {   return rank;    };
    };
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
попробовал раскрыть условия, но в скобках подзапутался.. :)
Daedalus:
        if (GRIM_CHALLENGED || BRUTUS_CHALLENGED || THORA_CHALLENGED) && (NPC_GETDISTTOWP(HERO, ARENA_WP_LEFT_START) < 200) || (GOLIATH_CHALLENGED || MALGAR_CHALLENGED) && (NPC_GETDISTTOWP(HERO, ARENA_WP_RIGHT_START) < 200)
        {
            return TRUE;
        };



правильно ли получилось?
Daedalus:
 [S]       if (Npc_GetDistToWP(hero,ARENA_WP_LEFT_START) < 200)
        {
            if GRIM_CHALLENGED          { return TRUE; };
            if BRUTUS_CHALLENGED        { return TRUE; };
            if THORA_CHALLENGED         { return TRUE; };
        };
        if (Npc_GetDistToWP(hero, ARENA_WP_RIGHT_START) < 200)
        {
            if GOLIATH_CHALLENGED       { return TRUE; };
            if MALGAR_CHALLENGED        { return TRUE; };
        };[/S]

upd
какая то хрень.гладиаторы путаются в кружках и оттого поединок не начинается.
1706003076880.png

upd2
шизойдная история. проще переписать по русски, чем распутывать клубок условий.

Daedalus:
    if (ARENA_PLAYERFIGHT)      // на арене стоит герой
    {
        // получаем инстанцию соперника
        var int npcint;     npcint = C_ARENA_NPCCOMBO(0);
 
 
        // если соперник стоит слева
        if (C_Npc_GetDistToWP(npcint,ARENA_WP_LEFT_START) < 200)
        {
            // то герой справо
            if (NPC_GETDISTTOWP(hero, ARENA_WP_RIGHT_START) < 200)
            {
                return true;
            };
            return false;
        };
 
        // если соперник стоит ...
        if (C_Npc_GetDistToWP(npcint,ARENA_WP_RIGHT_START) < 200)
        {
            // то герой ...
            if (NPC_GETDISTTOWP(hero, ARENA_WP_LEFT_START) < 200)
            {
                return true;
            };
            return false;
        };
   
        return false;
 

Вложения

  • 1706003058523.png
    1706003058523.png
    12,7 KB · Просмотры: 15
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
а чем отличаются проверки?

if Npc_IsOnFP(npc,wp2) if (Hlp_StrCmp(npc.wp,wp2))
 

MEG@VOLT

★★★★★★★★★
ТехАдмин
Регистрация
24 Мар 2006
Сообщения
9.839
Благодарности
6.725
Баллы
1.625
а чем отличаются проверки?

if Npc_IsOnFP(npc,wp2) if (Hlp_StrCmp(npc.wp,wp2))
Одна проверяет находится ли НПС в радиусе 100 см от фрипоинта, а вторая сравнивает текст. В твоем случае - не факт что она вообще что-то вернет.

Не, вторая функция тебе вернет что-нить, т.к. оба параметра возвращают текст.
А вот первая не должна сработать, т.к. wp != fp. В ней проверка именно на fp идет.
 

D36


Модостроитель
Регистрация
3 Дек 2014
Сообщения
2.177
Благодарности
3.347
Баллы
485
а чем отличаются проверки?

if Npc_IsOnFP(npc,wp2) if (Hlp_StrCmp(npc.wp,wp2))
Первая проверяет, находится ли npc на точке FP с именем wp2.
Вторая проверяет, является ли точка WP с именем wp2 точкой текущего расписания npc.
 

MW 7


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

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Обычно такая проверка происходит в состояниях распорядков для определения того факта, что непись находится в точке выполнения своего текущего распорядка. Определяется ближайший вейпоинт и сравнивается с тем, который назначен неписю распорядком. Если проверка не возвращает TRUE, неписю предписывается идти или бежать к точке выполнения распорядка.

В определённых случаях проверка такого типа может работать не совсем правильно с точки зрения логики поведения непися. Например, если при выполнении распорядка неписю приходится занять фрипоинт, то после занятия фрипоинта ближайшим вейпоинтом может оказаться уже не тот вейпоинт, на котором непись выполняет свой распорядок. Если заговорить с таким неписем, то диалог начнётся на фрипоинте, но после завершения диалога непись потопает к "своему" вейпоинту и только потом снова вернётся на фрипоинт. Я предпочитаю для описанной выше цели использовать проверку на расстояние до "своего" вейпоинта. Если расстояние меньше, скажем, 5м, то непись считается находящимся в точке выполнения своего распорядка.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
а есть аналог функции func c_item Npc_GetInvItem(var c_npc self, var int iteminstance) для моб объекта?
 

D36


Модостроитель
Регистрация
3 Дек 2014
Сообщения
2.177
Благодарности
3.347
Баллы
485
а есть аналог функции func c_item Npc_GetInvItem(var c_npc self, var int iteminstance) для моб объекта?
Daedalus:
var string detMob;
detMob = Npc_GetDetectedMob(self);
Print(detMob);
if(Hlp_StrCmp(detMob,"CHESTBIG")
{
  ...

Берется из названия модели:
Screenshot_2.png
 
Последнее редактирование:

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
D36, я имею ввиду можно ли получить ссылку на предмет который лежит в сундуке. то есть получить item что бы его отредактировать, например поменять название.
 

MW 7


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

if(Hlp_StrCmp(Npc_GetNearestWP(self),"OW_CAVE1_OREWOLF_4"))if Npc_IsOnFP(npc,wp2)

В коде идёт проверка Npc_GetNearestWP что бы определить находится ли герой на точке возле MOBa. но мне субъективно кажется что проверка Npc_IsOnFP будет правильнее в таком случае.
1706406049081.png


что лучше в данном случае и почему?
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Для этого, как минимум, нужен фрипоинт в игровом мире.

В коде идёт проверка Npc_GetNearestWP что бы определить находится ли герой на точке возле MOBa.
Почему привязка идёт к конкретному вейпоинту? В чём авторская задумка?

Не знаю, как в движке Сиквела, но в движке Г1 поиск объектов для взаимодействия производится криво. По идее, должен выбираться самый ближайший объект, если есть несколько объектов, доступных для взаимодействия. В движке Г2 так и сделано. Но в Г1 контроль расстояния не производится. Может быть выбран не тот объект, который находится рядом с неписем. Например, тот, что находится у соседнего вейпоинта на скрине выше.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
ElderGamer, есть что то похожее в Готике 1?
Daedalus:
func int C_WantItem()
{

    PrintDebugNpc(PD_ZS_DETAIL,"C_WantItem");
    
    if(!Hlp_IsValidItem(item))
    {
        PrintDebugNpc(PD_ZS_DETAIL,"...'item' ist ungьltig -> NEIN!");
        return FALSE;
    };
    
    PrintDebugString(PD_ZS_DETAIL,"...'item': ",item.name);
    PrintDebugNpc(PD_ZS_DETAIL,"...'item' gehцrt NSC oder seiner Gilde -> JA!");

    if Npc_OwnedByNpc(item,self)        {    return TRUE;        };
        
    var int selfGuild;  selfGuild = Npc_GetTrueGuild(self);
    if Npc_OwnedByGuild(item,selfGuild) {   return TRUE;        };

    if(item.flags == ITEM_MISSION)        {    return FALSE;        };
        
        
    
    if (item.mainflag == ITEM_KAT_ARMOR)
    {
        var int bodyGuild;  bodyGuild = Npc_GetTrueGuild(other);
        var int itemGuild;    itemGuild = item.ownerGuild;
        PrintDebugNpc(PD_ZS_DETAIL,"...'item' ist Rьstung und geht micht nichts an -> NEIN!");
        if (bodyGuild == itemGuild)        {    return FALSE; };
        if (selfGuild != itemGuild)        {    return FALSE; };
    };
        
    if((item.mainflag == ITEM_KAT_RUNE) && !C_NpcIsMage(self))
    {
        PrintDebugNpc(PD_ZS_DETAIL,"...'item' ist eine Rune/Scroll und Nsc ist kein Magier -> NEIN!");
        return FALSE;
    };
        
 
    if(Hlp_IsItem(item,itmi_silver))
    {
        PrintDebugNpc(PD_ZS_DETAIL,"...'item' ist Erz -> JA!");
        return TRUE;
    };

    var int itemvalue;          itemvalue = item.value;
    var int levelbewertung;     levelbewertung = self.level * 10;
    
    PrintDebugInt(PD_ZS_DETAIL,"...itemvalue: ",itemvalue);
    PrintDebugInt(PD_ZS_DETAIL,"...levelbewertung: ",levelbewertung);
    
    if(itemvalue > levelbewertung)
    {
        PrintDebugNpc(PD_ZS_DETAIL,"...'item' ist wertvoll genug um interessant zu sein -> JA!");
        return TRUE;
    };
        
    PrintDebugNpc(PD_ZS_DETAIL,"...'item' ist zu billig -> NEIN!");
    return FALSE;
};
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Неписи в Г1 умеют распознавать личное оружие (но не доспехи), которое экипировано у ГГ, или которое ГГ держит в руках. Они умеют требовать возврата этого оружия. То, что оружие является личным, определяется параметром owner в инстанции предмета, где прописана инстанция владельца. И это, понятное дело, касается уникальных предметов. Также в скриптах Г1 сделана попытка, не доведённая до ума, реализовать требование возврата украденных вещей. Но как это должно было работать по задумке авторов, я не понимаю. Я не вижу способа отличить украденный предмет от не украденного. Если предмет попал в инвентарь ГГ, то это уже обычный предмет, который мог присутствовать в инвентаре ГГ ещё ДО совершения кражи. Для реализации подобной фичи в скриптах нужно, чтобы движок умел каким-то образом помечать украденные предметы, вообще, и запоминать инстанцию обворованного непися, в частности. Также нужны функции, позволяющие найти такие предметы в инвентаре ГГ. Сомневаюсь, честно говоря, что подобное реализовано в движке Сиквела.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
судя по коду C_WantItem подразумевается что нпс проверяет все предметы героя. а это значит что герой скорее всего лежит бессознания, то есть получил люлей.

таким образом можно предположить что условный стражник бьёт героя условно обыскивает героя и забирает у него часть лута. значит сначала надо сформировать чёрный список что у героя не должно забираться, то есть вынести это вперёд. затем белый список это owner , то есть личная вещь НПС и вещи гильдии Npc_OwnedByGuild, например оружие милиции / паладинов ну и потом всё остальное: всё серебро и просто дорогие шмотки.

а есть именно аналог похожей функции в скриптах Готики 1 ?
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Прямо в таком виде - нет. В скриптах Г1 предполагалось, что у побитого ГГ будет забираться куча вещей, но там всё было построено на месте в списке предметов в соответствующей категории инвентаря. Не помню точно, но должны были забираться несколько "верхних" предметов в списке. Впрочем, разрабы кое-в-чём накосячили, и в результате не забиралось ничего.
 

MW 7


Модостроитель
Регистрация
26 Мар 2004
Сообщения
1.992
Благодарности
967
Баллы
275
@MW 7, Npc_RemoveInvItem(s) ?
Чур меня... Для одной инстанции это еще подходит, а если их тыщи, да и если инвентарь не постоянный....

1. чистка всего инвентаря кроме флага одетый и миссия Npc_clearInventory
2. чистка всего инвентаря по твоим собственным критериям можно написать самому на скриптах с помощью функции Npc_GetInvItemBySlot. в таком случае можно настраивать более "тонко" и ситуативно.

например чистка конкретной категории по флагу mainflag
Daedalus:
func int B_Del_KAT_InvItems(var C_Npc slf,var int ItemBySlot,var int item_mainflag)
{
    if(Npc_GetInvItemBySlot(slf,0,ItemBySlot))
    {
        if (item.mainflag & item_mainflag) // проверка на категорию
        {
            var string msg;
            msg = Str_Format("              [%s] %s", slf.name, item.name);


            if (item.flags & ITEM_ACTIVE)
            {
               // активный предмет(броня, кольца и прочее) ->  пропускаем
                msg = Str_Format("%s = ITEM_ACTIVE", msg);
                ItemBySlot += 1;
            }
            else if(item.flags & ITEM_MISSION)
            {
                // Квестовый предмет ->  пропускаем
                msg = Str_Format("%s = ITEM_MISSION", msg);
                ItemBySlot += 1;
            }
            else
            {
                // удаляем ПРЕДМЕТ
               // твой код по удалением
                msg = Str_Format("%s  - del", msg);
           
            };
       
            Hlp_PrintConsole(msg);
        };
   
        // Повторный вызов функции для проверки следующего предмета в данной категории.
        return B_Del_KAT_InvItems(slf, (ItemBySlot),item_mainflag);
    };

    // В текущем слоте нет предметов -> завершение работы функции.
    return false;
};
 

KirTheSeeker

Участник форума
Регистрация
18 Авг 2017
Сообщения
1.925
Благодарности
556
Баллы
275
Приветствую всех. Порекомендуйте, пожалуйста, как можно оптимизировать данный код:
Daedalus:
func int b_getlearncostattribute(var C_NPC oth,var int attribut)
{
    var int kosten;
    if((attribut == ATR_STRENGTH) || (attribut == ATR_DEXTERITY) || (attribut == ATR_MANA_MAX))
    {
//        if((oth.guild == GIL_KDF) || (oth.guild == GIL_NOV))
        if(Npc_GetTalentSkill(other,NPC_TALENT_MAGE) >= 1)
        {
            if(attribut == ATR_STRENGTH)
            {
                kosten = 1;
            };
            if(attribut == ATR_DEXTERITY)
            {
                kosten = 1;
            };
            if(attribut == ATR_MANA_MAX)
            {
                kosten = 1;
            };
        }
        else
        {
            if(attribut == ATR_STRENGTH)
            {
                kosten = 1;
            };
            if(attribut == ATR_DEXTERITY)
            {
                kosten = 1;
            };
            if(attribut == ATR_MANA_MAX)
            {
                kosten = 2;
            };
        };
    };
    return kosten;
};
Суть - чтобы ГГ поднимал ману по 2 lp зо 1 ед. атрибута, пока не обучен первому кругу магии.
 
Сверху Снизу