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

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

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

MaGoth

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

Вложения

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

Dimus

★★★★★★★★★
Супермодератор
Регистрация
19 Июл 2010
Сообщения
5.574
Благодарности
4.167
Баллы
915
@ Dimmell:
Браво, камрад! Теперь Харад берёт правильное количество мечей даже если ГГ был экипирован одним из них. Кстати, ты немного неправильно объяснил суть идеи: первый вызов функции Npc_RemoveInvItems() не удаляет из инвентаря ГГ экипированный меч, а только убирает его из слота оружия ближнего боя и объединяет в один стек с остальными мечами этого вида. Удаляет мечи из инвентаря ГГ именно второй вызов этой функции. Следовательно, можно убрать из кода лишние проверки:
Код:
func void DIA_Harad_SellBlades_Info()
{
    var C_Item EquipWeap;
    var int anzahl_common;
    var int anzahl_schwert1;
    var int anzahl_schwert4;
    var int anzahl_rubinklinge;
    var int anzahl_elbastardo;
    var int gesamt;
    var string concatText;
    var int lohn;
    AI_Output(other,self,"DIA_Harad_SellBlades_15_00");    //Я хочу продать оружие, выкованное мной.
    EquipWeap = Npc_GetEquippedMeleeWeapon(other);
    anzahl_common = Npc_HasItems(other,ItMw_1H_Common_01);
    if(Hlp_IsItem(EquipWeap,ItMw_1H_Common_01))
    {
        if(anzahl_common > 1)
        {
            Npc_RemoveInvItem(other,ItMw_1H_Common_01);
        };
        anzahl_common -= 1;
    };
    anzahl_schwert1 = Npc_HasItems(other,ItMw_Schwert1);
    if(Hlp_IsItem(EquipWeap,ItMw_Schwert1))
    {
        if(anzahl_schwert1 > 1)
        {
            Npc_RemoveInvItem(other,ItMw_Schwert1);
        };
        anzahl_schwert1 -= 1;
    };
    anzahl_schwert4 = Npc_HasItems(other,ItMw_Schwert4);
    if(Hlp_IsItem(EquipWeap,ItMw_Schwert4))
    {
        if(anzahl_schwert4 > 1)
        {
            Npc_RemoveInvItem(other,ItMw_Schwert4);
        };
        anzahl_schwert4 -= 1;
    };
    anzahl_rubinklinge = Npc_HasItems(other,ItMw_Rubinklinge);
    if(Hlp_IsItem(EquipWeap,ItMw_Rubinklinge))
    {
        if(anzahl_rubinklinge > 1)
        {
            Npc_RemoveInvItem(other,ItMw_Rubinklinge);
        };
        anzahl_rubinklinge -= 1;
    };
    anzahl_elbastardo = Npc_HasItems(other,ItMw_ElBastardo);
    if(Hlp_IsItem(EquipWeap,ItMw_ElBastardo))
    {
        if(anzahl_elbastardo > 1)
        {
            Npc_RemoveInvItem(other,ItMw_ElBastardo);
        };
        anzahl_elbastardo -= 1;
    };
    gesamt = anzahl_common + anzahl_schwert1 + anzahl_schwert4 + anzahl_rubinklinge + anzahl_elbastardo;
    if(gesamt == 0)
    {
        if(Hlp_IsItem(EquipWeap,ItMw_1H_Common_01) || Hlp_IsItem(EquipWeap,ItMw_Schwert1) || Hlp_IsItem(EquipWeap,ItMw_Schwert4) || Hlp_IsItem(EquipWeap,ItMw_Rubinklinge) || Hlp_IsItem(EquipWeap,ItMw_ElBastardo))
        {
            AI_Output(self,other,"DIA_Harad_SellBlades_12_01");    //Все, что у тебя есть - это меч, висящий на поясе. Ты лучше оставь его себе.
        }
        else
        {
            AI_Output(self,other,"DIA_Harad_SellBlades_12_04");    //Тогда сделай его! Я принимаю только обычные мечи.
        };
    }
    else
    {
        AI_Output(self,other,"DIA_Harad_SellBlades_12_02");    //Хорошо - давай сюда.
        Npc_RemoveInvItems(other,ItMw_1H_Common_01,anzahl_common);
        Npc_RemoveInvItems(other,ItMw_Schwert1,anzahl_schwert1);
        Npc_RemoveInvItems(other,ItMw_Schwert4,anzahl_schwert4);
        Npc_RemoveInvItems(other,ItMw_Rubinklinge,anzahl_rubinklinge);
        Npc_RemoveInvItems(other,ItMw_ElBastardo,anzahl_elbastardo);
        concatText = ConcatStrings(IntToString(gesamt),PRINT_ItemsGegeben);
        AI_PrintScreen(concatText,-1,YPOS_ItemGiven,FONT_ScreenSmall,2);
        AI_Output(self,other,"DIA_Harad_SellBlades_12_03");    //Отлично. Держи, что заработал.
        lohn = ((anzahl_common * Value_Common1) + (anzahl_schwert1 * Value_Schwert1) + (anzahl_schwert4 * Value_Schwert4) + (anzahl_rubinklinge * Value_Rubinklinge) + (anzahl_elbastardo * Value_ElBastardo)) / 3;
        B_GiveInvItems(self,other,ItMi_Gold,lohn);
        AI_EquipBestMeleeWeapon(other);
    };
};
 

Dimmell

Участник форума
Регистрация
23 Ноя 2008
Сообщения
2.899
Благодарности
111
Баллы
285
Dimus, я знаю что можно покрасивше сделать :D
Но это делалось года 4 тому назад с намного меньшими знаниями и "головой об стену", поэтому и остался кусок кода в рабочем, но неоптимизированном виде. Потому что ждали другие стенки, типа:

почему если создать новый атрибут (допустим интеллект), используя слот под таланты, при повышении этого атрибута больше 100, после загрузки игры он визуально сбрасывается до 1

В Возвращении интеллект прописан как навык, и симптомы были такие же при попытке набрать > 100.
Лечил так:
1. там, где шло изменение интеллекта:
ATR_INTELLECT = ATR_INTELLECT + 1;
Npc_SetTalentSkill(other,NPC_TALENT_INTELLECT,ATR_INTELLECT); //устанавливаем новое значение навыка
2. в циклическом триггере переприсваиваем его
Npc_SetTalentSkill(hero,NPC_TALENT_INTELLECT,ATR_INTELLECT)
Отображается в меню правильно даже после перезагрузок.
Один баг остался - после перезагрузки заклы наносят урон по дефолту, а должны +интеллект. Тоже можно попробовать поправить прописав Npc_SetTalentSkill(hero,NPC_TALENT_INTELLECT,ATR_INTELLECT) при инициализации мира (хотя не гарантирую отсутствие вылетов при загрузке).
Так что много чего можно оптимизировать, только когда голова болит от "ударов о стенку" (бесконечных перекомпиляций и тестов с попытками обмануть движок), уже нет никакого желания оптимизировать и опять тестировать. В том же Ребалансе много чего можно оптимизировать и переделать проще и надежнее - но для этого надо слишком много удалять и заново "красивше" прописывать :)

ЗЫ. и прячьте, ПЛЗ, куски кода под спойлер.
 

Test Level

Участник форума
Регистрация
1 Ноя 2011
Сообщения
1.770
Благодарности
557
Баллы
275
Тогда остаётся вариант циклической функции, в которой периодически контролируется наличие нужного предмета в инвентаре ГГ. Разумеется, предмет должен быть уникальным. Begemot666 сказал(а): ↑ Так вот, как сделать, чтоб запись появлялась только после окончания диалога, а не во время его? Вопрос ещё актуален?

1. Такой зацикленный триггер я делал, но у меня ничего не получилось. К сожалению сейчас не могу выложить скрипт того триггера.

2. Да, вопрос актуален.
 

ElderGamer


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

Не получилось что? Триггер не работает, или наличие предмета в инвентаре не определяется?

Да, вопрос актуален.

Давно хотел реализовать в Г1 выдачу экранного сообщения типа "Получен предмет" в строгом соответствии с произнесением соответствующей фразы. В Г2 для этого появилась AI-функция, а вот в Г1 пришлось плясать с бубном. Идея такова:

1. Прописываем строковую переменную.
Код:
var string ScreenMessage;

2. Создаём инстанцию предмета.
Код:
instance FakeItem(C_Item)
{
    name = "Предмет";
    mainflag = ITEM_KAT_NONE;
    flags = ITEM_MULTI;
    value = 0;
    visual = "ItMi_Nugget_01.3ds";
    material = MAT_LEATHER;
    scemeName = "USEFAKEITEM";
    on_state[0] = UseFakeItem;
    description = name;
};
 
func void UseFakeItem()
{
    PrintScreen(ScreenMessage,-1,40,"FONT_OLD_10_WHITE.TGA",5);
};

3. В файле сценариев анимаций прописываем анимации взаимодействия с этим предметом. Исходник я взял свой, но можно задействовать какой-либо из использующихся в оригинале исходников, например, анимацию простоя.
Код:
ani        ("t_UseFakeItem_Stand_2_S0"        1    "s_UseFakeItem_S0"        0.1    0.1    M.    "Hum_DrawTorch_M01.asc"        F    0    1)
{
                *eventTag    (1    "DEF_INSERT_ITEM"    "ZS_LEFTHAND")
}
ani        ("s_UseFakeItem_S0"                1    "s_UseFakeItem_S0"        0.0    0.0    M.    "Hum_DrawTorch_M01.asc"        F    2    2)
ani        ("t_UseFakeItem_S0_2_Stand"        1    ""                0.1    0.1    M.    "Hum_DrawTorch_M01.asc"        R    0    1)
{
                *eventTag    (1    "DEF_DESTROY_ITEM")
}

4. В инстанции диалога прописываем использование этого служебного предмета.
Код:
    AI_Output(self,other,"Info_Saturas_ACCEPT_14_07");    //Вот, возьми эту магическую руну. Передай ее Корристо, Верховному Магу Круга Огня, в знак нашего доверия.
    CreateInvItem(other,FakeItem);
    CreateInvItem(other,ItArRuneTeleport2);
    ScreenMessage = "Получена руна.";
    AI_UseItem(other,FakeItem);
    AI_Output(self,other,"Info_Saturas_ACCEPT_14_08");    //С ее помощью он сможет в любой момент, минуя стражу, перенестись сюда, в эту комнату.

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

MoranGrimoff

Участник форума
Регистрация
12 Фев 2013
Сообщения
40
Благодарности
2
Баллы
155
Товарищи! Как создать диалог для монстра, а конкретно для демона? Создал демона по примеру Сеньяка, запихнул его в скрипт со всеми демонами, в игру вставил, создал файл диалога. Сразу этот гад меня мочил, сделал его своим другом. Однако, как заставить его говорить, я так и не понял. Может нужно вставить его как НПС, но в скриптах среди неписей я ни одного монстра не нашел. Памажыте!
 

hell9999

Участник форума
Регистрация
12 Апр 2008
Сообщения
2.048
Благодарности
1.163
Баллы
340
Товарищи! Как создать диалог для монстра, а конкретно для демона? Создал демона по примеру Сеньяка, запихнул его в скрипт со всеми демонами, в игру вставил, создал файл диалога. Сразу этот гад меня мочил, сделал его своим другом. Однако, как заставить его говорить, я так и не понял. Может нужно вставить его как НПС, но в скриптах среди неписей я ни одного монстра не нашел. Памажыте!

Я думаю, поиск по имени XardasDemon в Г1 скриптах даст Вам ответы на все вопросы.
 

MoranGrimoff

Участник форума
Регистрация
12 Фев 2013
Сообщения
40
Благодарности
2
Баллы
155

hell9999

Участник форума
Регистрация
12 Апр 2008
Сообщения
2.048
Благодарности
1.163
Баллы
340

Вложения

  • SolGothic1.7z
    1.012 KB · Просмотры: 113

Test Level

Участник форума
Регистрация
1 Ноя 2011
Сообщения
1.770
Благодарности
557
Баллы
275
Не получилось что? Триггер не работает, или наличие предмета в инвентаре не определяется?

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

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
не определяется наличие предмета

Проверил только что (платформа Г1, локация маленькая). Работает нормально: при поднятии предмета сразу же определяется его наличие, при выбрасывании - его отсутствие.
 

MoranGrimoff

Участник форума
Регистрация
12 Фев 2013
Сообщения
40
Благодарности
2
Баллы
155
Подскажите, граждане, такой момент:
Как заставить созданного мага использовать собственно магию. Вписал ф-ю в скрипт "magic always" или как-то так, точно не помню. Наградил руной. Круг 6-й. А он все равно с кулаками кидается. Даю ему посох - бьет посохом. А руна все так же лежит в кармане.
 

Dimus

★★★★★★★★★
Супермодератор
Регистрация
19 Июл 2010
Сообщения
5.574
Благодарности
4.167
Баллы
915
Скрипт мага для G1 или G2? Если второе, то бесполезно подсовывать ему в инвентарь руны, потому что создание нужной руны и выбор заклинания осуществляется в функции B_SelectSpell() одноимённого скрипта.
 
Последнее редактирование:

MoranGrimoff

Участник форума
Регистрация
12 Фев 2013
Сообщения
40
Благодарности
2
Баллы
155
Скрипт мага для G1 или G2? Если второе, то бесполезно подсовывать ему в инвентарь руны, потому что создание нужной руны и выбор заклинания осуществляется в функции B_SelectSpell() одноимённого скрипта.
Как раз Г2. Т.е. судя по скрипту B_SelectSpell, руна не обязательно должна быть в инвентаре, а создастся сама при необходимости?

И такой вопрос, возможно нубский
При разветвлении диалога при помощи Info_AddChoice варианты развития диалога должны быть взаимозаменяемы. Т.е. если выбираю первый вариант, второй пропадает. У меня почему-то висят оба.
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Т.е. если выбираю первый вариант, второй пропадает. У меня почему-то висят оба.

Ставь условие на обе опции. При выборе одной опции условие появления второй должно переставать соблюдаться.
Код:
if(условие 1)
{
     Info_AddChoice(...1...)
};
if(условие 2)
{
     Info_AddChoice(...2...)
};
 

Test Level

Участник форума
Регистрация
1 Ноя 2011
Сообщения
1.770
Благодарности
557
Баллы
275
Такой вопрос. Вот взятие квеста
Код:
MIS_Blablabla = LOG_Running;

Код:
MIS_Blablabla = LOG_SUCCESS;
Завершение миссии.

А как отправить квест в проваленные?
 

MaGoth

★★★★★★★★★★★
Администратор
Регистрация
7 Янв 2003
Сообщения
19.367
Благодарности
7.815
Баллы
995
А как отправить квест в проваленные?
Читай тутор Вама там все расписано..
Код:
// Статусы миссий
const int LOG_RUNNING = 1; //Миссия выполняется
const int LOG_SUCCESS = 2; //Миссия успешно завершена
const int LOG_FAILED = 3; //Миссия провалена
const int LOG_OBSOLETE = 4; //Миссия завершена в другом направлении (был выбор вариантов завершения)
 

Test Level

Участник форума
Регистрация
1 Ноя 2011
Сообщения
1.770
Благодарности
557
Баллы
275
Тогда еще вопрос. Допустим кто-то говорит ГГ, чтоб за информацией он приходил через 1-2 дня. Как сделать, чтоб раньше времени нужный диалог не появился?

Как я понимаю, это строчка = Wld_GetDay() ?


P.S. Дайте ссылку на тутор Vam`a. У меня с компом проблемы были и тутор, как и многое другое, пропало.
 
Последнее редактирование модератором:

MaGoth

★★★★★★★★★★★
Администратор
Регистрация
7 Янв 2003
Сообщения
19.367
Благодарности
7.815
Баллы
995
Как сделать, чтоб раньше времени нужный диалог не появился?
Как пример использовать переменную для проверки и где нужно по игре присваивать ей = 1, и по значению активировать этот диалог у Нпс.

По остальному найдешь примеры в оригинальных скриптах Готы, используя поиск по проекту в ГС через: Wld_GetDay()

Дайте ссылку на тутор Vam`a.
Пришпиленный пост этой темы:
http://forum.worldofplayers.ru/showthread.php?t=12544
 

ElderGamer


Модостроитель
Регистрация
16 Апр 2008
Сообщения
4.407
Благодарности
3.232
Баллы
525
Begemot666, завершение квеста нужно понимать в двух плоскостях. Во-первых, это исчезновение диалогов, связанных с этим квестом или появление диалогов, связанных с завершением этого квеста. Переменные типа
MIS_Blablabla как раз и предназначены для того, чтобы их значения учитывались в условиях появления диалогов.

Во-вторых, завершение квеста должно найти отражение в журнале. Для этого существуют функции работы с журналом. С переменными типа MIS_Blablabla эти функции никак не связаны. Для перевода квеста в категорию проваленных используется функци:
Код:
Log_SetTopicStatus(CH4_FindXardas,LOG_FAILED);
Пример из Г1. Здесь CH4_FindXardas - это название топика, созданного в журнале при взятии квеста:
Код:
Log_CreateTopic(CH4_FindXardas,LOG_MISSION);

По поводу появления диалога через несколько дней. В одном диалоге запоминаешь текущий день. Нужна специальная переменная, впрочем, можно использовать и одну из неиспользуемых неписем aivar-переменных. В условии другого диалога проверяешь значение текущего дня, насколько оно больше запомненного значения.
 

Test Level

Участник форума
Регистрация
1 Ноя 2011
Сообщения
1.770
Благодарности
557
Баллы
275
Begemot666, завершение квеста нужно понимать в двух плоскостях. Во-первых, это исчезновение диалогов, связанных с этим квестом или появление диалогов, связанных с завершением этого квеста. Переменные типа
MIS_Blablabla как раз и предназначены для того, чтобы их значения учитывались в условиях появления диалогов.

Во-вторых, завершение квеста должно найти отражение в журнале. Для этого существуют функции работы с журналом. С переменными типа MIS_Blablabla эти функции никак не связаны. Для перевода квеста в категорию проваленных используется функци:
Код:
Log_SetTopicStatus(CH4_FindXardas,LOG_FAILED);
Пример из Г1. Здесь CH4_FindXardas - это название топика, созданного в журнале при взятии квеста:
Код:
Log_CreateTopic(CH4_FindXardas,LOG_MISSION);

По поводу появления диалога через несколько дней. В одном диалоге запоминаешь текущий день. Нужна специальная переменная, впрочем, можно использовать и одну из неиспользуемых неписем aivar-переменных. В условии другого диалога проверяешь значение текущего дня, насколько оно больше запомненного значения.

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