среда, 21 ноября 2012 г.

Тутор по изменению диалога MOBSI

Решил выложить мой мини-тутор. Может новичкам окажет пользу.
По данному тутору можно вполне догадаться как изменять и Ковку.
Тутор по изменению диалога 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_H  ealth_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 – это как раз те зелья, которые будут в разделе «Изготовить экстракты растений», а именно «Вытяжка из лечебных растений» и «Вытяжка из лечебных трав»
А
Код:
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;

};

А1
Код:
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();

};

А2
Код:
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_T  ALENT_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_AL  CHEMY,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]
В этом случае компиляция проходит

За сим откланиваюсь.

0 коммент.:

Отправить комментарий

Open Panel

Blogroll

Вверх

Вниз