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

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

Тутор по изменению диалога MOBSI на примере добавления нового алхимического рецепта

redleha


Модостроитель
Регистрация
26 Фев 2008
Сообщения
735
Благодарности
665
Баллы
245
Решил выложить мой мини-тутор. Может новичкам окажет пользу.
По данному тутору можно вполне догадаться как изменять и Ковку.
Тутор по изменению диалога MOBSI на примере добавления нового алхимического рецепта
Всё рассмотренное ниже проводилось на акелловских скриптах, скачанных из раздела Сообщество.
Изменения проводились с помощью программы GothicSourcer v3.14.

Скрипты рабочие!

Давайте рассмотрим пример «как добавить новый алхимический рецепт».
Предположим, вам захотелось, чтобы какой-нибудь алхимик помог вам изучить Зелье, которое вы придумали сами, и при взаимодействии с алхимическим столом появлялся соответствующий пункт. Навскидку – я придумал зелья, которые представляют собой вытяжки-экстракты из различных растений. Например, рецепт:
«Вытяжка из лечебных растений» - представляет собой что? Берём 10 лечебных растений, выжимаем их в бутылочку и получаем зелье, которое представляет собой эликсир, увеличивающий наши ХитПойнты на 100 очков, то бишь жизнь.
1) Начинаем с конца – создаём сам эликсир. Для этого открываем файл IT_Potions.d в папке Items, и в самый конец файла прописываем следующее:


const int HP_SpecMi_Health_01 = 100; //объявляем константу бонуса – 100 HP
const int Value_HpSpecMi_Health_01 = 100; //объявляем константу стоимости напитка.

instance ItPo_SpecMi_Health_01(C_Item)
{
name = NAME_Trank;
mainflag = ITEM_KAT_POTIONS;
flags = ITEM_MULTI;
value = Value_HpSpecMi_Health_01; //константа - стоимость напитка
visual = "ItPo_Health_01.3ds"; //будет выглядеть как обычная лечебная эссенция.
material = MAT_GLAS;
on_state[0] = UseItPo_SpecMi_Health_01; //здесь имя функции, которая описана ниже, и описывающая бонусы от использования напитка.
scemeName = "POTIONFAST";
wear = WEAR_EFFECT;
effect = "SPELLFX_HEALTHPOTION";
description = "Выжимка из лечебных растений"; //название вашего эликсира
text[1] = NAME_Bonus_HP;
count[1] = HP_SpecMi_Health_01; //константа, объявленная выше (значение бонуса от использования напитка) с присвоенным значением, равным 100 HP.
text[5] = NAME_Value;
count[5] = Value_HpSpecMi_Health_01;
};
func void UseItPo_SpecMi_Health_01() //функция, описывающая бонус.
{
Npc_ChangeAttribute(self,ATR_HITPOINTS,HP_SpecMi_Health_01);
};
//В данном случае при помощи функции Npc_ChangeAttribute мы изменяем себе текущее значение ХитПойнтов(ATR_HITPOINTS) на 100 пунктов(HP_SpecMi_Health_01=100).

Аналогично вставляем второй напиток:

const int HP_SpecMi_Health_02 = 200; //объявляем константу бонуса – 100 HP
const int Value_HpSpecMi_Health_02 = 200; //объявляем константу стоимости напитка.

instance ItPo_SpecMi_Health_02(C_Item)
{
name = NAME_Trank;
mainflag = ITEM_KAT_POTIONS;
flags = ITEM_MULTI;
value = Value_HpSpecMi_Health_02;
visual = "ItPo_Health_02.3ds";
material = MAT_GLAS;
on_state[0] = UseItPo_SpecMi_Health_02;
scemeName = "POTIONFAST";
wear = WEAR_EFFECT;
effect = "SPELLFX_HEALTHPOTION";
description = "Выжимка из лечебных трав";
text[1] = NAME_Bonus_HP;
count[1] = HP_SpecMi_Health_02;
text[5] = NAME_Value;
count[5] = Value_HpSpecMi_Health_02;
};
func void UseItPo_SpecMi_Health_02() //функция, описывающая бонус.
{
Npc_ChangeAttribute(self,ATR_HITPOINTS,HP_SpecMi_Health_02);
};

Вы можете изменять, что хотите. Например можно написать следующую функцию:

func void UseItPo_SpecMi_Health_02() //функция, описывающая бонус.
{
Npc_ChangeAttribute(self,ATR_HITPOINTS,HP_SpecMi_Health_02); //Увеличиваем текущие ХП на 100 пунктов.
if(Npc_IsPlayer(self))
{
SpecMiUsing_Bonus = SpecMiUsing_Bonus + 1;
if(SpecMiUsing_Bonus == 10) //если мы использовали напиток 10 раз, то возникает следующее:
{
B_RaiseAttribute(self,ATR_HITPOINTS_MAX,SpecMi_Bonus); //увеличиваем максимум силы на величину константы SpecMi_Bonus
Npc_ChangeAttribute(self,ATR_HITPOINTS,5); // Увеличиваем текущие ХП на 5 пунктов.
Snd_Play("LevelUp");
SpecMiUsing_Bonus = 0;
SpecMiUsing_SuperBonus = SpecMiUsing_SuperBonus + 1;
If(SpecMiUsing_SuperBonus == 10) // если мы использовали напиток 100 раз, то возникает:
{
B_RaiseAttribute(self,ATR_STRENGTH, SpecMi_Bonus); //увеличиваем максимум силы на величину константы SpecMi_Bonus
B_AddFightSkill(self,NPC_TALENT_1H,SpecMi_SuperBonus); //увеличиваем атрибут владения одноручным мечём на величину константы SpecMi_SuperBonus
Snd_Play("LevelUp");
SpecMiUsing_SuperBonus = 0;
};
};
};
};
В этом случае перед строкой instance ItPo_SpecMi_Health_02(C_Item) добавляем строчки:

Const int SpecMi_Bonus = 5;
Const int SpecMi_SuperBonus = 5;

А в файл StoryGlobals.d прописываем следующее:

Var int SpecMiUsing_Bonus;
Var int SpecMiUsing_SuperBonus;

2) Следующий шаг – нужно внести изменения в диалог взаимодействия ГГ с алхимическим столом. Чтобы при выученном навыке «Варить вытяжку» появлялась соответствующая строчка.
Сразу усложним немного задачу и внесем не строчку в диалог, а целый раздел «Изготовить экстракты растений» с внутренними строками: «Вытяжка из лечебных растений» и «Вытяжка из лечебных трав». Всё это аналогично тому, как раздел «Лечебные зелья» содержит в себе строки «Лечебная эссенция», «Лечебный экстракт».
Для этого открываем файл …\Story\Dialog_Mobsis\PotionAlchemy.d и в конец файла добавляем следующее:

Условно разделим вставляемые строки на три логические части(помечены как А, А1 и А2):
Часть А отвечает за раздел в диалоге MOBSI – а именно «Изготовить экстракты растений»
Части А1 и А2 – это как раз те зелья, которые будут в разделе «Изготовить экстракты растений», а именно «Вытяжка из лечебных растений» и «Вытяжка из лечебных трав»
[size=14pt]А[/size]

var int SpecialMiskStart;
instance PC_SpecialMisk_Start(C_Info) //функция вставляющая соответствующий раздел «Изготовить экстракты растений»
{
npc = PC_Hero;
nr = 12;
condition = PC_SpecialMisk_Start_Condition;
information = PC_SpecialMisk_Start_Info;
permanent = TRUE;
description = "Изготовить экстракты растений";
};
func int PC_SpecialMisk_Start_Condition() //условия, при которых будет вставлен раздел
{
if((PLAYER_MOBSI_PRODUCTION == MOBSI_PotionAlchemy) && (TabakStart == FALSE) && (BoozeStart == FALSE) && (HealthStart == FALSE) && (ManaStart == FALSE) && (SpecialStart == FALSE) && (SpecialMiskStart == FALSE))
{
return TRUE;
};
};
func void PC_SpecialMisk_Start_Info() //итоговое значение функции – то, что мы перешли в этот раздел к напиткам.
{
SpecialMiskStart = TRUE;
};
instance PC_SpecialMisk_Stop(C_Info)
{
npc = PC_Hero;
nr = 99;
condition = PC_SpecialMisk_Stop_Condition;
information = PC_SpecialMisk_Stop_Info;
permanent = TRUE;
description = Dialog_Back;
};
func int PC_SpecialMisk_Stop_Condition()
{
if((PLAYER_MOBSI_PRODUCTION == MOBSI_PotionAlchemy) && (SpecialMiskStart == TRUE))
{
return TRUE;
};
};
func void PC_SpecialMisk_Stop_Info()
{
SpecialMiskStart = FALSE;
};

[size=14pt]А1[/size]


instance PC_ItPo_SpecMi_Health_01(C_Info)
{
nr = 10;
npc = PC_Hero;
condition = PC_ItPo_SpecMi_Health_01_Condition;
information = PC_ItPo_SpecMi_Health_01_Info;
permanent = TRUE;
description = “Вытяжка из лечебных трав”;
};
func int PC_ItPo_SpecMi_Health_01_Condition()
{
if((PLAYER_MOBSI_PRODUCTION == MOBSI_PotionAlchemy) && (SpecialMiskStart == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_SpecMi_Health_01] == TRUE))
{
return TRUE;
};
};
func void PC_ItPo_SpecMi_Health_01_Info()
{
if(Npc_HasItems(hero,ItPl_Health_Herb_01) >= 10)
{
Npc_RemoveInvItems(hero,ItPl_Health_Herb_01,10);
CreateInvItem(hero,ItPo_SpecMi_Health_01);
Print(PRINT_AlchemySuccess);
}
else
{
Print(PRINT_ProdItemsMissing);
CreateInvItems(self,ItMi_Flask,1);
};
b_endproductiondialog();
};

[size=14pt]А2[/size]

instance PC_ItPo_SpecMi_Health_02(C_Info)
{
nr = 11;
npc = PC_Hero;
condition = PC_ItPo_SpecMi_Health_02_Condition;
information = PC_ItPo_SpecMi_Health_02_Info;
permanent = TRUE;
description = "Вытяжка из лечебных растений";
};
func int PC_ItPo_SpecMi_Health_02_Condition()
{
if((PLAYER_MOBSI_PRODUCTION == MOBSI_PotionAlchemy) && (SpecialMiskStart == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_SpecMi_Health_02] == TRUE))
{
return TRUE;
};
};
func void PC_ItPo_SpecMi_Health_02_Info()
{
if(Npc_HasItems(hero,ItPl_Health_Herb_02) >= 10)
{
Npc_RemoveInvItems(hero,ItPl_Health_Herb_02,10);
CreateInvItem(hero,ItPo_SpecMi_Health_02);
Print(PRINT_AlchemySuccess);
}
else
{
Print(PRINT_ProdItemsMissing);
CreateInvItems(self,ItMi_Flask,1);
};
b_endproductiondialog();
};

Теперь практически всё, осталось только по всему файлу изменить строки, содержащие выражение:

if((PLAYER_MOBSI_PRODUCTION == MOBSI_PotionAlchemy) && (TabakStart == FALSE) && (BoozeStart == FALSE) && (HealthStart == FALSE) && (ManaStart == FALSE) && (SpecialStart == FALSE))
на
if((PLAYER_MOBSI_PRODUCTION == MOBSI_PotionAlchemy) && (TabakStart == FALSE) && (BoozeStart == FALSE) && (HealthStart == FALSE) && (ManaStart == FALSE) && (SpecialStart == FALSE) && (SpecialMiskStart == FALSE))

Подчеркнул изменения. Надеюсь понятно - почему.

3) Далее открываем файл …/Story/B_Story/b_teachplayertalentalchemy –
В этом файле содержится функция:

func int B_TeachPlayerTalentAlchemy(var C_Npc slf,var C_Npc oth,var int potion)

Её роль – обучение ГГ искусству алхимии и соответственно каждому из рецептов.
Теперь вставляем после строки:

B_LogEntry(TOPIC_TalentAlchemy,"Чтобы сварить зелье, мне нужна пустая мензурка и необходимые для этого зелья ингредиенты. Из этих ингредиентов, я могу приготовить зелье на столе алхимика.");
Наши строки:

if(potion == POTION_SpecMi_Health_01)
{
PLAYER_TALENT_ALCHEMY[POTION_Health_01] = TRUE;
B_LogEntry(TOPIC_TalentAlchemy,"Ингредиенты для 'Выжимки из лечебных растений': 10 лечебных растений.");
};
if(potion == POTION_SpecMi_Health_02)
{
PLAYER_TALENT_ALCHEMY[POTION_Health_02] = TRUE;
B_LogEntry(TOPIC_TalentAlchemy,"Ингредиенты для 'Выжимки из лечебных трав': 10 лечебных растений.");
};
На этом всё.

4) Далее открываем файл …/Story/B_Story/b_getlearncosttalent.d –
В этом файле содержится функция:

func int B_GetLearnCostTalent(var C_Npc oth,var int talent,var int skill)

Её роль – определение очков обучения, которые будут потрачены на обучение какому-либо навыку всех талантов ГГ, как то рецепты алхимии, кузнечного и охотничьего дела и т.д.
Ищем строки:

else if(skill == POTION_MegaDrink)
{
kosten = 20;
};
И после них вставляем следующее, предварительно удалив точку с запятой. Получаем следующее:
else if(skill == POTION_MegaDrink)
{
kosten = 20;
}
else if(skill == POTION_SpecMi_Health_01)
{
kosten = 2;
}
else if(skill == POTION_SpecMi_Health_02)
{
kosten = 2;
};
Здесь kosten – кол-во очков обучения, которые ГГ потратит на изучение соответствующего рецепта.

5) Самое главное теперь прописать эти рецепты в файл …/Intern/Constants.d
Ищем строки:

var int player_talent_alchemy[MAX_POTION]; //массив размеров равным константе MAX_POTION, объявленной ниже.
const int POTION_Health_04 = 14;
const int MAX_POTION = 15;

И изменяем размер массива и вставляем строки так, как показано ниже:

var int player_talent_alchemy[MAX_POTION];
const int POTION_Health_04 = 14;
const int POTION_SpecMi_Health_01 = 15;
const int POTION_SpecMi_Health_02 = 16;
const int MAX_POTION = 17;
На этом подготовительная часть закончена. Осталось только добавить обучение этим рецептам кому-то из алхимиков.

6) Возьмем, например Константино.
Открываем файл …/Story/Dialoge/dia_vlk_417_constantino.d
Ищем строки:

func void DIA_Constantino_TEACH_Info()
{
AI_Output(other,self,"DIA_Constantino_TEACH_15_00"); //Каким рецептам ты можешь обучить меня?
if((PLAYER_TALENT_ALCHEMY[POTION_Health_01] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Health_02] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Health_03] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Perm_Health] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Mana_01] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Mana_02] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Perm_STR] == TRUE))
{
AI_Output(self,other,"DIA_Constantino_TEACH_10_01"); //Извини. Я больше ничему не могу научить тебя.
}
else
{
AI_Output(self,other,"DIA_Constantino_TEACH_10_02"); //Есть несколько - выбирай.
Info_ClearChoices(DIA_Constantino_TEACH);
Info_AddChoice(DIA_Constantino_TEACH,Dialog_Back,DIA_Constantino_Teach_BACK);
};
};
И изменяем следующим образом (изменения подчёркнуты):
func void DIA_Constantino_TEACH_Info()
{
AI_Output(other,self,"DIA_Constantino_TEACH_15_00"); //Каким рецептам ты можешь обучить меня?
if((PLAYER_TALENT_ALCHEMY[POTION_Health_01] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Health_02] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Health_03] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Perm_Health] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Mana_01] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Mana_02] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_Perm_STR] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_SpecMi_Health_01] == TRUE) && (PLAYER_TALENT_ALCHEMY[POTION_SpecMi_Health_02] == TRUE))
{
AI_Output(self,other,"DIA_Constantino_TEACH_10_01"); //Извини. Я больше ничему не могу научить тебя.
}
else
{
AI_Output(self,other,"DIA_Constantino_TEACH_10_02"); //Есть несколько - выбирай.
Info_ClearChoices(DIA_Constantino_TEACH);
Info_AddChoice(DIA_Constantino_TEACH,Dialog_Back,DIA_Constantino_Teach_BACK);
};
};
И вставляем после них сразу:

if(PLAYER_TALENT_ALCHEMY[POTION_SpecMi_Health_01] == FALSE)
{
Info_AddChoice(DIA_Constantino_TEACH,B_BuildLearnString("Выжимка из лечебных растений",B_GetLearnCostTalent(other,NPC_TALENT_ALCHEMY,POTION_SpecMi_Health_01)),DIA_Constantino_TEACH_SpecMi_Health_01);
};
if(PLAYER_TALENT_ALCHEMY[POTION_SpecMi_Health_02] == FALSE)
{
Info_AddChoice(DIA_Constantino_TEACH,B_BuildLearnString("Выжимка из лечебных трав",B_GetLearnCostTalent(other,NPC_TALENT_ALCHEMY,POTION_SpecMi_Health_02)),DIA_Constantino_TEACH_SpecMi_Health_02);
};

Далее после строк:
func void DIA_Constantino_Teach_BACK()
{
Info_ClearChoices(DIA_Constantino_TEACH);
};
Прописываем следующее:
func void DIA_Constantino_TEACH_SpecMi_Health_01()
{
if(B_TeachPlayerTalentAlchemy(self,other,POTION_SpecMi_Health_01))
{
AI_Output(self,other,"DIA_Constantino_TEACH_SpecMi_Health01_10_00"); //Ингредиенты для "Выжимки из лечебных растений" - 10 лечебных растений.
};
Info_ClearChoices(DIA_Constantino_TEACH);
};
func void DIA_Constantino_TEACH_SpecMi_Health_02()
{
if(B_TeachPlayerTalentAlchemy(self,other,POTION_SpecMi_Health_02))
{
AI_Output(self,other,"DIA_Constantino_TEACH_SpecMi_Health02_10_00"); ////Ингредиенты для "Выжимки из лечебных трав" - 10 лечебных трав.
};
Info_ClearChoices(DIA_Constantino_TEACH);
};

7) Теперь самое главное – не компилируем наш изменённый проект, а сохраняем все изменения и закрываем его.
Затем вновь запускаем GS3.14 и открываем наш проект. После этого компилируем.
С чем это связано? Просто если компилировать сразу, то вы наткнётесь на ошибку
«Неопределённый идентификатор POTION_SPECMI_HEALTH_01» в файле dia_vlk_417_constantino.d
Чем это объясняется. В моём понимании – ответ таков:
В момент открытия проекта идет анализ в том числе файла Constants.d.
Можно компилировать и сразу, но тогда нужно сделать следующую замену:

PLAYER_TALENT_ALCHEMY[POTION_SpecMi_Health_01]
на
PLAYER_TALENT_ALCHEMY[15],
а
PLAYER_TALENT_ALCHEMY[POTION_SpecMi_Health_02]
На PLAYER_TALENT_ALCHEMY[16]
В этом случае компиляция проходит

За сим откланиваюсь.
 
Последнее редактирование модератором:
Сверху Снизу