- Регистрация
- 10 Дек 2017
- Сообщения
- 44
- Реакции
- 28
- Баллы
- 14
- Лучшие ответы
- 0
"Включаем музыку, и читаем текст"(The Bee Gees – Stayin' Alive)
Так как уроки по скриптингу "для чайников" пока прекратились, я решил взять ситуацию в свои руки, и "разжевать" все особенности модостроения. Но, так как, мы будем разбирать уже готовый мод - то это называется "модоломание".
Итак, чтобы "сломать и заново построить" мод, вам нужны несколько программ. Это GothicVDFS - урок по этой программе, уже есть на форуме (Учимся работать с Gothic VDFS). А также, чтобы просматривать все скрипты, и папки с ними - нужна прога Vam'a, а именно Gothic Sourcer V3.15, которую тоже можно скачать на форуме.
Перед чтением данных уроков (да, их будет много), советую прочитать Уроки для чайников от @xterm.
Как только вы станете "чайниками", можно приступать и к более сложным задачам. Я не буду отправлять вас читать тутор Вама, ибо после прочтение этих уроков, тутор вам не нужен будет. Но, советую на полку его не ставить, а держать рядом, ибо к нему мы будет частенько обращаться.
Разберем мод "Ловкач" исходники которого, автор любезно предоставил. Лучше для работы использовать именно исходники, ибо словить баг при компиляции намного сложнее, чем на декомплированном датнике. Но, это не значит что декомпилировать не нужно. Позже, я расскажу как обходить баги при декомпиляции.
"Урок 1 - Характеристика НПС, их движения, их действия"
Урок 2 - "Смотрим и вникаем в диалоги"
Снчала хотел запилить урок про ковку оружия - но решил отложить это на попозже.
Мини-урок #3 "Меняем внешность Главного Героя"
Так как уроки по скриптингу "для чайников" пока прекратились, я решил взять ситуацию в свои руки, и "разжевать" все особенности модостроения. Но, так как, мы будем разбирать уже готовый мод - то это называется "модоломание".
Итак, чтобы "сломать и заново построить" мод, вам нужны несколько программ. Это GothicVDFS - урок по этой программе, уже есть на форуме (Учимся работать с Gothic VDFS). А также, чтобы просматривать все скрипты, и папки с ними - нужна прога Vam'a, а именно Gothic Sourcer V3.15, которую тоже можно скачать на форуме.
Перед чтением данных уроков (да, их будет много), советую прочитать Уроки для чайников от @xterm.
Как только вы станете "чайниками", можно приступать и к более сложным задачам. Я не буду отправлять вас читать тутор Вама, ибо после прочтение этих уроков, тутор вам не нужен будет. Но, советую на полку его не ставить, а держать рядом, ибо к нему мы будет частенько обращаться.
Разберем мод "Ловкач" исходники которого, автор любезно предоставил. Лучше для работы использовать именно исходники, ибо словить баг при компиляции намного сложнее, чем на декомплированном датнике. Но, это не значит что декомпилировать не нужно. Позже, я расскажу как обходить баги при декомпиляции.
"Урок 1 - Характеристика НПС, их движения, их действия"
Итак, вы уже знаете как распаковать мод файл, вытащить оттуда Gothic.dat, как декомпилировать этот датник Соурсером, и как собственно начинать работать. Но поступим проще, скачиваем исходники мода "Ловкач", запускаем GothicSourser. Нажимаем там, "Файл" - "Открыть решение". Открываем файл lovcachnew.gsc. Ждем, когда все загрузится. Обычно, это занимает несколько секунд, или минут.
Когда решение откроется, перед вами предстанет во всей красе, вот такое окно -
Это список всех основных и важный папок. Каждая папка отвечает за свою категорию, и там своия "иерархия".
Так как, в этом уроке будет идти речь о НПС, то нам нужна только одна папка, а именно Story
Далее, тыкаем на NPC. Перед нами откроются, еще две папки и много обычных файлов, каждый который отвечает за своего персонажа. Например, Bau_900_Onar - означает, что этот файлик отвечает за жиробаса Онара.
Итак, я выбрал на "растерзание" товарища Ли - SLD_800_Lee
Давайте, посмотрим что в нем напихано, и какая строчка за что отвечает. Начнем по порядку:
instance SLD_800_Lee - это "название", "гильдия", "порядковый номер", "имя товарища".
Т.е попросту говоря, это 800 наемник под именем Ли..).
name[0] = "Ли"; = опять таки, имя нашего мужчины
guild = GIL_SLD; = гильдия нашего мужчины (наемник)
id = 800; = порядковый номер
voice = 4; = каким голосом говорит наш персонаж
npcType = NPCTYPE_FRIEND; - он друг нашему главному герою
aivar - это особая функция, и ее особенности я расскажу в отдельном уроке.
B_SetAttributesToChapter(self,6); - это аттрибуты нашего НПС. Если вбить в поиск (вы уже знаете как пользоваться поиском ) строчку B_SetAttributesToChapter, то мы найдем отдельный скрипт. Давайте так и сделаем:
Перед нами открылся скрипт, где мы видим "знакомые слова":
slf.level = 3; - уровень
slf.attribute[ATR_STRENGTH] = 10; - сила
slf.aivar[REAL_STRENGTH] = 10;
slf.attribute[ATR_DEXTERITY] = 10; - ловкость
slf.aivar[REAL_DEXTERITY] = 10;
slf.attribute[ATR_MANA_MAX] = 1000; - мана максимальная
slf.aivar[REAL_MANA_MAX] = 1000;
slf.attribute[ATR_MANA] = 1000; - текущая мана
slf.attribute[ATR_HITPOINTS_MAX] = 150; - максимальная жизнь
slf.attribute[ATR_HITPOINTS] = 150; - текущая жизнь
Вот так все просто.
В скрипте Ли, мы видим B_SetAttributesToChapter(self,6);
Т.е у него 6 категория в скрипте B_SetAttributesToChapter.
Ищем эту цифру, и вот она!
Для удобства восприятия, приведу весь "6 номер"
slf.level = 40 = у нашего Ли 40 уровень!
slf.attribute[ATR_STRENGTH] = 300 силы
slf.attribute[ATR_DEXTERITY] = 300 ловкости
slf.attribute[ATR_MANA_MAX] = 1000 мана
slf.aivar[REAL_MANA_MAX] = 1000 максимальная мана
slf.attribute[ATR_MANA] = 1000 текущая мана
slf.attribute[ATR_HITPOINTS_MAX] = 1500 максимальная жизнь
slf.attribute[ATR_HITPOINTS] = 1500 текущая жизнь
Вот такие аттрибуты у Ли. Все просто, так ведь..?.
Можно поменять цифру "6" на любую другую в пределах 7.
Давайте, до конца разберем нашего Ли
EquipItem(self,itmw_lee_axt) = строчка отвечает за экипировку, т.е что "напялено" в данный момент. Если вбить в поиск строчку - itmw_lee_axt то, получим вот это:
B_CreateAmbientInv(self) - данная строчка отвечат за содержимое инвентаря. Данный персонаж не имеет вещей в инвентаре.
B_SetNpcVisual(self,MALE,"Hum_Head_Pony",Face_N_Lee,BodyTex_N,ItAr_Sld_H) - строчка отвечает за внешний вид перса. А именно:
MALE - он мужчина. Так что, у кого были сомнения по этому поводу, то они должны сейчас рухнуть...
Есть две категории MALE и FEMALE, т.е мужчина и женщина.
"Hum_Head_Pony" - вид головы Ли. Сейчас у него сзади головы хвостик, как и у ГГ.
Face_N_Lee - текстура лица
BodyTex_N - тело
ItAr_Sld_H - доспехи, в которые одет Ли. Если вбить в поиск, получим Тяжелые доспехи наемника.
Итак, основу НПС мы разобрали. Осталось еще несколько непонятных строк, которые мы сейчас и разберем..
Rtn_Start_800 - это собственно, отвечает за распорядок дня НПС. Когда мы начинаем игру, все многочисленные НПС, которых просто кишит мир, начинают заниматься своими делами, а именно теми которые им заданы. Именно, поэтому кузнец Харад кует в своей кузнице, и именно поэтому Ватрас читает проповедь всем грешникам Хориниса каждый день - все из за того, что у них такой распорядок.
Отвечает за действие НПС. В данном случае он просто стоит уперев руки в бока.
Время, сколько он так стоит. В данном случае бедняга стоит с 8 утра и до 19 вечера.
И место (вейпойнт) где он данное действие совершает.
Итак, первый урок подошел к концу. Надеюсь, вам будет интересно, а самое главное постарайтесь закрепить данный урок на практике, сделайте все те действия, которые я сделал в этом уроке.
Когда решение откроется, перед вами предстанет во всей красе, вот такое окно -
Так как, в этом уроке будет идти речь о НПС, то нам нужна только одна папка, а именно Story
Итак, я выбрал на "растерзание" товарища Ли - SLD_800_Lee
instance SLD_800_Lee(Npc_Default)
{
name[0] = "Ли";
guild = GIL_SLD;
id = 800;
voice = 4;
flags = 0;
npcType = NPCTYPE_FRIEND;
aivar[93] = TRUE;
aivar[AIV_ToughGuy] = TRUE;
aivar[AIV_ToughGuyNewsOverride] = TRUE;
aivar[AIV_IGNORE_Murder] = TRUE;
aivar[AIV_IGNORE_Theft] = TRUE;
aivar[AIV_IGNORE_Sheepkiller] = TRUE;
B_SetAttributesToChapter(self,6);
fight_tactic = FAI_HUMAN_MASTER;
EquipItem(self,itmw_lee_axt);
B_CreateAmbientInv(self);
B_SetNpcVisual(self,MALE,"Hum_Head_Pony",Face_N_Lee,BodyTex_N,ItAr_Sld_H);
Mdl_SetModelFatness(self,0);
Mdl_ApplyOverlayMds(self,"Humans_Militia.mds");
B_GiveNpcTalents(self);
B_SetFightSkills(self,100);
daily_routine = Rtn_Start_800;
};
{
name[0] = "Ли";
guild = GIL_SLD;
id = 800;
voice = 4;
flags = 0;
npcType = NPCTYPE_FRIEND;
aivar[93] = TRUE;
aivar[AIV_ToughGuy] = TRUE;
aivar[AIV_ToughGuyNewsOverride] = TRUE;
aivar[AIV_IGNORE_Murder] = TRUE;
aivar[AIV_IGNORE_Theft] = TRUE;
aivar[AIV_IGNORE_Sheepkiller] = TRUE;
B_SetAttributesToChapter(self,6);
fight_tactic = FAI_HUMAN_MASTER;
EquipItem(self,itmw_lee_axt);
B_CreateAmbientInv(self);
B_SetNpcVisual(self,MALE,"Hum_Head_Pony",Face_N_Lee,BodyTex_N,ItAr_Sld_H);
Mdl_SetModelFatness(self,0);
Mdl_ApplyOverlayMds(self,"Humans_Militia.mds");
B_GiveNpcTalents(self);
B_SetFightSkills(self,100);
daily_routine = Rtn_Start_800;
};
Т.е попросту говоря, это 800 наемник под именем Ли..).
name[0] = "Ли"; = опять таки, имя нашего мужчины
guild = GIL_SLD; = гильдия нашего мужчины (наемник)
id = 800; = порядковый номер
voice = 4; = каким голосом говорит наш персонаж
npcType = NPCTYPE_FRIEND; - он друг нашему главному герою
aivar - это особая функция, и ее особенности я расскажу в отдельном уроке.
B_SetAttributesToChapter(self,6); - это аттрибуты нашего НПС. Если вбить в поиск (вы уже знаете как пользоваться поиском ) строчку B_SetAttributesToChapter, то мы найдем отдельный скрипт. Давайте так и сделаем:
slf.level = 3; - уровень
slf.attribute[ATR_STRENGTH] = 10; - сила
slf.aivar[REAL_STRENGTH] = 10;
slf.attribute[ATR_DEXTERITY] = 10; - ловкость
slf.aivar[REAL_DEXTERITY] = 10;
slf.attribute[ATR_MANA_MAX] = 1000; - мана максимальная
slf.aivar[REAL_MANA_MAX] = 1000;
slf.attribute[ATR_MANA] = 1000; - текущая мана
slf.attribute[ATR_HITPOINTS_MAX] = 150; - максимальная жизнь
slf.attribute[ATR_HITPOINTS] = 150; - текущая жизнь
Вот так все просто.
В скрипте Ли, мы видим B_SetAttributesToChapter(self,6);
Т.е у него 6 категория в скрипте B_SetAttributesToChapter.
Ищем эту цифру, и вот она!
slf.level = 40 = у нашего Ли 40 уровень!
slf.attribute[ATR_STRENGTH] = 300 силы
slf.attribute[ATR_DEXTERITY] = 300 ловкости
slf.attribute[ATR_MANA_MAX] = 1000 мана
slf.aivar[REAL_MANA_MAX] = 1000 максимальная мана
slf.attribute[ATR_MANA] = 1000 текущая мана
slf.attribute[ATR_HITPOINTS_MAX] = 1500 максимальная жизнь
slf.attribute[ATR_HITPOINTS] = 1500 текущая жизнь
Вот такие аттрибуты у Ли. Все просто, так ведь..?.
Можно поменять цифру "6" на любую другую в пределах 7.
Давайте, до конца разберем нашего Ли
EquipItem(self,itmw_lee_axt) = строчка отвечает за экипировку, т.е что "напялено" в данный момент. Если вбить в поиск строчку - itmw_lee_axt то, получим вот это:
B_SetNpcVisual(self,MALE,"Hum_Head_Pony",Face_N_Lee,BodyTex_N,ItAr_Sld_H) - строчка отвечает за внешний вид перса. А именно:
MALE - он мужчина. Так что, у кого были сомнения по этому поводу, то они должны сейчас рухнуть...
Есть две категории MALE и FEMALE, т.е мужчина и женщина.
"Hum_Head_Pony" - вид головы Ли. Сейчас у него сзади головы хвостик, как и у ГГ.
Face_N_Lee - текстура лица
BodyTex_N - тело
ItAr_Sld_H - доспехи, в которые одет Ли. Если вбить в поиск, получим Тяжелые доспехи наемника.
Итак, основу НПС мы разобрали. Осталось еще несколько непонятных строк, которые мы сейчас и разберем..
func void Rtn_Start_800()
{
TA_Stand_Guarding(8,0,19,0,"NW_BIGFARM_HOUSE_LEE_GUARDING");
TA_Sit_Chair(19,0,22,0,"NW_BIGFARM_HOUSE_UP2_05");
TA_Sleep(22,0,8,0,"NW_BIGFARM_HOUSE_UP2_04");
};
{
TA_Stand_Guarding(8,0,19,0,"NW_BIGFARM_HOUSE_LEE_GUARDING");
TA_Sit_Chair(19,0,22,0,"NW_BIGFARM_HOUSE_UP2_05");
TA_Sleep(22,0,8,0,"NW_BIGFARM_HOUSE_UP2_04");
};
TA_Stand_Guarding
(8,0,19,0,
"NW_BIGFARM_HOUSE_LEE_GUARDING");
Итак, первый урок подошел к концу. Надеюсь, вам будет интересно, а самое главное постарайтесь закрепить данный урок на практике, сделайте все те действия, которые я сделал в этом уроке.
Урок 2 - "Смотрим и вникаем в диалоги"
Снчала хотел запилить урок про ковку оружия - но решил отложить это на попозже.
Итак, что цепляет нас в новых модах? Конечно, же новые квесты. Ну, а чтобы квест мы получили, нам нужно "поговорить" с квестодателем. Для этого как раз нужно и написать диалог, между Нпс который даст нам квест и главным героем.
Урок будет решающий - если вы его поймете, для вас ничего сложного в дальнейшем не будет.
Я не буду писать для урока новый диалог, а просто рассмотрю "по полочкам" уже существующий диалог, где Нпс даст нам квест.
Да, кстати все диалоги находятся в Story/Dialoge.
Итак, у меня тут есть скрипт диалога с крестьянином Вино. Если кто играл в мод "Гильдии", то помнит что этот товарищ, дает нам квест на убийство орка, который мешает ему якобы спать.
Для удобства восприятия приводу скрипт этого диалога:
Разобьем диалог на две части - первая часть это взятие квеста, вторая часть - сдача квеста. Все просто.
Вот первая часть:
Начинаем? Вижу одобрительные кивки головами и влюбленные взгляды.
Итак:
var int - если внимательно изучить тутор Вама и владеть маломалским языком программирования - то понятно, что мы делаем. Обьявляем переменную. Ну а Vino_Gossip_Orks и Vino_Gossip_Bugs - это название нашей переменной, от которых мы собственно и будем отталкиваться при написании диалога.
Внимание!! Обьявлять переменную нужно именно в начале диалога, а не в середине, или в самой заднице конце.
npc = BAU_952_Vino; - диалог проходит с Вино
nr = 10; - строчка расположения диалога, чем больше цифра - тем ниже диалог
condition = DIA_Vino_PERM_Condition; - переменная отвечающая за "техчасть" диалога
information = DIA_Vino_PERM_Info; - за "информационную" часть
permanent = TRUE; - диалог доступен постоянно. Если вместо тру будет стоять FALSE - то диалог доступен один раз
description = "Есть какие-нибудь интересные новости?"; - как выглядит начало в диалоговом окне.
func void DIA_Vino_PERM_Info() (наша переменная которая отвечает за информационную часть)
{
AI_Output(other,self,"DIA_Vino_PERM_15_00"); //Есть какие-нибудь интересные новости? (Собственно, пишем сам диалог. Если other,self то, сначала говорит ГГ, а потом нпс. Если наоборот - то нпс а отвечает ГГ)
if(Vino_Gossip_Orks == FALSE) (Еще одна наша переменная)
{
AI_Output(self,other,"DIA_Vino_PERM_05_01"); //Я могу поклясться, что видел орка вон там, на краю леса, два дня назад.
AI_Output(self,other,"DIA_Vino_PERM_05_02"); //С тех пор я сплю хотя бы с одним открытым глазом.
Vino_Gossip_Orks = TRUE; (Еще одна наша переменная)
Knows_Ork = TRUE; (Орк появился, именно тот который нужен)
Log_CreateTopic(TOPIC_VINO_KILL_ORK,LOG_MISSION); (Топик - запись в дневнике)
Log_SetTopicStatus(TOPIC_VINO_KILL_ORK,LOG_Running);
B_LogEntry(TOPIC_VINO_KILL_ORK,"Крестьянин Вино очень боится того, что ночью на ферму придет орк и убьет его, поэтому он никак не может выспаться."); (Краткое описание квеста в дневнике)
}
Вроде все понятно и просто, верно?
Итак, конец нашего диалога и завершение квеста.
Обьявляем переменную, которая отвечает за выполнение квеста.
instance DIA_VINO_KILLORK(C_Info) (начало диалога)
{
npc = BAU_952_Vino;
nr = 1;
condition = dia_vino_killork_condition; (Смотрим на переменную)
information = dia_vino_killork_info;
permanent = TRUE;
description = "Я убил этого орка!";
};
func int dia_vino_killork_condition() (Смотрим навверх и видим переменную)
{
if(Npc_IsDead(OrcWarrior_Harad)(Убили орка по квесту Харада) && (MIS_KILL_VINO_ORK != 1)(Убили орка по квесту Вино. 1 штуку) && Npc_HasItems(hero,itfo_addon_shnaps_orks)) (В инвентаре ГГ есть орочий шнапс. Можно пробить по поиску itfo_addon_shnaps_orks и узнать что это)
{
return TRUE;
};
};
func void dia_vino_killork_info()(Опять таки смотрим переменную выше)
{
B_GivePlayerXP(50); (Получаем 50 опыта)
AI_Output(other,self,"DIA_Vino_KillOrk_99_01"); //Я убил этого орка!
AI_Output(self,other,"DIA_Vino_KillOrk_99_02"); //Ты шутишь парень? Не верю!
AI_Output(other,self,"DIA_Vino_KillOrk_99_03"); //У меня есть вот этот шнапс, такого больше нигде не достать, кроме как у орков!
B_GiveInvItems(hero,self,itfo_addon_shnaps_orks,1);(Отдаем Вино шнапс)
AI_Output(self,other,"DIA_Vino_KillOrk_99_04"); //Точно! Теперь-то я наконец высплюсь как следует!
AI_UseItem(self,itfo_addon_shnaps_orks);(Изымается из инвентаря шнапс)
AI_Output(self,other,"DIA_Addon_Scatty_Bier_01_01"); //О, как вкусно. Спасибо, мужик. Ты мой герой!
B_LogEntry(TOPIC_VINO_KILL_ORK,"Я убил орка, а Вино теперь может спать спокойно!"); (Запись в дневнике, квест "Бессоница Вино успешно завершен)
AI_Output(self,other,"DIA_Vino_KillOrk_99_05"); //Ну за такую-то работенку можно и заплатить. Правда у меня нет золота, а есть только растения всякие... Держи!
B_GiveInvItems(self,other,ItPl_Temp_Herb,1); (Вино даем нам Полевое растение)
Log_SetTopicStatus(TOPIC_VINO_KILL_ORK,LOG_SUCCESS); (Квест в дневнике переходит из Текущих в Выполненные)
MIS_KILL_VINO_ORK = 1;
};
На этой положительной ноте я завершаю урок. Надеюсь, вы почепнули для себя что то новенькое и интересное. Если вы поняли данный урок - то сможете с легкостью писать квесты в своем моде как электро-веник) Ну и в дальнейшем, знания о написание диалогов поможет вам в более трудных скриптовых задачах.
Урок будет решающий - если вы его поймете, для вас ничего сложного в дальнейшем не будет.
Я не буду писать для урока новый диалог, а просто рассмотрю "по полочкам" уже существующий диалог, где Нпс даст нам квест.
Да, кстати все диалоги находятся в Story/Dialoge.
Итак, у меня тут есть скрипт диалога с крестьянином Вино. Если кто играл в мод "Гильдии", то помнит что этот товарищ, дает нам квест на убийство орка, который мешает ему якобы спать.
Для удобства восприятия приводу скрипт этого диалога:
var int Vino_Gossip_Orks;
var int Vino_Gossip_Bugs;
instance DIA_Vino_PERM(C_Info)
{
npc = BAU_952_Vino;
nr = 10;
condition = DIA_Vino_PERM_Condition;
information = DIA_Vino_PERM_Info;
permanent = TRUE;
description = "Есть какие-нибудь интересные новости?";
};
func int DIA_Vino_PERM_Condition()
{
if(Npc_KnowsInfo(other,DIA_Vino_HALLO) && (Kapitel < 3))
{
return TRUE;
};
};
func void DIA_Vino_PERM_Info()
{
AI_Output(other,self,"DIA_Vino_PERM_15_00"); //Есть какие-нибудь интересные новости?
if(Vino_Gossip_Orks == FALSE)
{
AI_Output(self,other,"DIA_Vino_PERM_05_01"); //Я могу поклясться, что видел орка вон там, на краю леса, два дня назад.
AI_Output(self,other,"DIA_Vino_PERM_05_02"); //С тех пор я сплю хотя бы с одним открытым глазом.
Vino_Gossip_Orks = TRUE;
Knows_Ork = TRUE;
Log_CreateTopic(TOPIC_VINO_KILL_ORK,LOG_MISSION);
Log_SetTopicStatus(TOPIC_VINO_KILL_ORK,LOG_Running);
B_LogEntry(TOPIC_VINO_KILL_ORK,"Крестьянин Вино очень боится того, что ночью на ферму придет орк и убьет его, поэтому он никак не может выспаться.");
}
else if((Vino_Gossip_Bugs == FALSE) && (MIS_AndreHelpLobart == LOG_Running))
{
AI_Output(self,other,"DIA_Vino_PERM_05_03"); //Эти огромные отвратительные насекомые уже всех достали. Они повсюду. Они сожрут все, что мы вырастили, если мы не сделаем что-нибудь.
AI_Output(self,other,"DIA_Vino_PERM_05_04"); //Несколько дней назад я лежал в траве, размышляя о своем, и собирался вздремнуть, когда одна из этих тварей сожрала мой ботинок!
AI_Output(self,other,"DIA_Vino_PERM_05_05"); //Ты бы видел, как я улепетывал. С тех пор я не могу спать спокойно.
Vino_Gossip_Bugs = TRUE;
}
else
{
AI_Output(self,other,"DIA_Vino_PERM_05_06"); //Кроме того, что я уже сказал тебе? Нет.
};
};
var int mis_kill_vino_ork;
instance DIA_VINO_KILLORK(C_Info)
{
npc = BAU_952_Vino;
nr = 1;
condition = dia_vino_killork_condition;
information = dia_vino_killork_info;
permanent = TRUE;
description = "Я убил этого орка!";
};
func int dia_vino_killork_condition()
{
if(Npc_IsDead(OrcWarrior_Harad) && (MIS_KILL_VINO_ORK != 1) && Npc_HasItems(hero,itfo_addon_shnaps_orks))
{
return TRUE;
};
};
func void dia_vino_killork_info()
{
B_GivePlayerXP(50);
AI_Output(other,self,"DIA_Vino_KillOrk_99_01"); //Я убил этого орка!
AI_Output(self,other,"DIA_Vino_KillOrk_99_02"); //Ты шутишь парень? Не верю!
AI_Output(other,self,"DIA_Vino_KillOrk_99_03"); //У меня есть вот этот шнапс, такого больше нигде не достать, кроме как у орков!
B_GiveInvItems(hero,self,itfo_addon_shnaps_orks,1);
AI_Output(self,other,"DIA_Vino_KillOrk_99_04"); //Точно! Теперь-то я наконец высплюсь как следует!
AI_UseItem(self,itfo_addon_shnaps_orks);
AI_Output(self,other,"DIA_Addon_Scatty_Bier_01_01"); //О, как вкусно. Спасибо, мужик. Ты мой герой!
B_LogEntry(TOPIC_VINO_KILL_ORK,"Я убил орка, а Вино теперь может спать спокойно!");
AI_Output(self,other,"DIA_Vino_KillOrk_99_05"); //Ну за такую-то работенку можно и заплатить. Правда у меня нет золота, а есть только растения всякие... Держи!
B_GiveInvItems(self,other,ItPl_Temp_Herb,1);
Log_SetTopicStatus(TOPIC_VINO_KILL_ORK,LOG_SUCCESS);
MIS_KILL_VINO_ORK = 1;
};
var int Vino_Gossip_Bugs;
instance DIA_Vino_PERM(C_Info)
{
npc = BAU_952_Vino;
nr = 10;
condition = DIA_Vino_PERM_Condition;
information = DIA_Vino_PERM_Info;
permanent = TRUE;
description = "Есть какие-нибудь интересные новости?";
};
func int DIA_Vino_PERM_Condition()
{
if(Npc_KnowsInfo(other,DIA_Vino_HALLO) && (Kapitel < 3))
{
return TRUE;
};
};
func void DIA_Vino_PERM_Info()
{
AI_Output(other,self,"DIA_Vino_PERM_15_00"); //Есть какие-нибудь интересные новости?
if(Vino_Gossip_Orks == FALSE)
{
AI_Output(self,other,"DIA_Vino_PERM_05_01"); //Я могу поклясться, что видел орка вон там, на краю леса, два дня назад.
AI_Output(self,other,"DIA_Vino_PERM_05_02"); //С тех пор я сплю хотя бы с одним открытым глазом.
Vino_Gossip_Orks = TRUE;
Knows_Ork = TRUE;
Log_CreateTopic(TOPIC_VINO_KILL_ORK,LOG_MISSION);
Log_SetTopicStatus(TOPIC_VINO_KILL_ORK,LOG_Running);
B_LogEntry(TOPIC_VINO_KILL_ORK,"Крестьянин Вино очень боится того, что ночью на ферму придет орк и убьет его, поэтому он никак не может выспаться.");
}
else if((Vino_Gossip_Bugs == FALSE) && (MIS_AndreHelpLobart == LOG_Running))
{
AI_Output(self,other,"DIA_Vino_PERM_05_03"); //Эти огромные отвратительные насекомые уже всех достали. Они повсюду. Они сожрут все, что мы вырастили, если мы не сделаем что-нибудь.
AI_Output(self,other,"DIA_Vino_PERM_05_04"); //Несколько дней назад я лежал в траве, размышляя о своем, и собирался вздремнуть, когда одна из этих тварей сожрала мой ботинок!
AI_Output(self,other,"DIA_Vino_PERM_05_05"); //Ты бы видел, как я улепетывал. С тех пор я не могу спать спокойно.
Vino_Gossip_Bugs = TRUE;
}
else
{
AI_Output(self,other,"DIA_Vino_PERM_05_06"); //Кроме того, что я уже сказал тебе? Нет.
};
};
var int mis_kill_vino_ork;
instance DIA_VINO_KILLORK(C_Info)
{
npc = BAU_952_Vino;
nr = 1;
condition = dia_vino_killork_condition;
information = dia_vino_killork_info;
permanent = TRUE;
description = "Я убил этого орка!";
};
func int dia_vino_killork_condition()
{
if(Npc_IsDead(OrcWarrior_Harad) && (MIS_KILL_VINO_ORK != 1) && Npc_HasItems(hero,itfo_addon_shnaps_orks))
{
return TRUE;
};
};
func void dia_vino_killork_info()
{
B_GivePlayerXP(50);
AI_Output(other,self,"DIA_Vino_KillOrk_99_01"); //Я убил этого орка!
AI_Output(self,other,"DIA_Vino_KillOrk_99_02"); //Ты шутишь парень? Не верю!
AI_Output(other,self,"DIA_Vino_KillOrk_99_03"); //У меня есть вот этот шнапс, такого больше нигде не достать, кроме как у орков!
B_GiveInvItems(hero,self,itfo_addon_shnaps_orks,1);
AI_Output(self,other,"DIA_Vino_KillOrk_99_04"); //Точно! Теперь-то я наконец высплюсь как следует!
AI_UseItem(self,itfo_addon_shnaps_orks);
AI_Output(self,other,"DIA_Addon_Scatty_Bier_01_01"); //О, как вкусно. Спасибо, мужик. Ты мой герой!
B_LogEntry(TOPIC_VINO_KILL_ORK,"Я убил орка, а Вино теперь может спать спокойно!");
AI_Output(self,other,"DIA_Vino_KillOrk_99_05"); //Ну за такую-то работенку можно и заплатить. Правда у меня нет золота, а есть только растения всякие... Держи!
B_GiveInvItems(self,other,ItPl_Temp_Herb,1);
Log_SetTopicStatus(TOPIC_VINO_KILL_ORK,LOG_SUCCESS);
MIS_KILL_VINO_ORK = 1;
};
Вот первая часть:
var int Vino_Gossip_Orks;
var int Vino_Gossip_Bugs;
instance DIA_Vino_PERM(C_Info)
{
npc = BAU_952_Vino;
nr = 10;
condition = DIA_Vino_PERM_Condition;
information = DIA_Vino_PERM_Info;
permanent = TRUE;
description = "Есть какие-нибудь интересные новости?";
};
func int DIA_Vino_PERM_Condition()
{
if(Npc_KnowsInfo(other,DIA_Vino_HALLO) && (Kapitel < 3))
{
return TRUE;
};
};
func void DIA_Vino_PERM_Info()
{
AI_Output(other,self,"DIA_Vino_PERM_15_00"); //Есть какие-нибудь интересные новости?
if(Vino_Gossip_Orks == FALSE)
{
AI_Output(self,other,"DIA_Vino_PERM_05_01"); //Я могу поклясться, что видел орка вон там, на краю леса, два дня назад.
AI_Output(self,other,"DIA_Vino_PERM_05_02"); //С тех пор я сплю хотя бы с одним открытым глазом.
Vino_Gossip_Orks = TRUE;
Knows_Ork = TRUE;
Log_CreateTopic(TOPIC_VINO_KILL_ORK,LOG_MISSION);
Log_SetTopicStatus(TOPIC_VINO_KILL_ORK,LOG_Running);
B_LogEntry(TOPIC_VINO_KILL_ORK,"Крестьянин Вино очень боится того, что ночью на ферму придет орк и убьет его, поэтому он никак не может выспаться.");
}
else if((Vino_Gossip_Bugs == FALSE) && (MIS_AndreHelpLobart == LOG_Running))
{
AI_Output(self,other,"DIA_Vino_PERM_05_03"); //Эти огромные отвратительные насекомые уже всех достали. Они повсюду. Они сожрут все, что мы вырастили, если мы не сделаем что-нибудь.
AI_Output(self,other,"DIA_Vino_PERM_05_04"); //Несколько дней назад я лежал в траве, размышляя о своем, и собирался вздремнуть, когда одна из этих тварей сожрала мой ботинок!
AI_Output(self,other,"DIA_Vino_PERM_05_05"); //Ты бы видел, как я улепетывал. С тех пор я не могу спать спокойно.
Vino_Gossip_Bugs = TRUE;
}
else
{
AI_Output(self,other,"DIA_Vino_PERM_05_06"); //Кроме того, что я уже сказал тебе? Нет.
};
};
var int Vino_Gossip_Bugs;
instance DIA_Vino_PERM(C_Info)
{
npc = BAU_952_Vino;
nr = 10;
condition = DIA_Vino_PERM_Condition;
information = DIA_Vino_PERM_Info;
permanent = TRUE;
description = "Есть какие-нибудь интересные новости?";
};
func int DIA_Vino_PERM_Condition()
{
if(Npc_KnowsInfo(other,DIA_Vino_HALLO) && (Kapitel < 3))
{
return TRUE;
};
};
func void DIA_Vino_PERM_Info()
{
AI_Output(other,self,"DIA_Vino_PERM_15_00"); //Есть какие-нибудь интересные новости?
if(Vino_Gossip_Orks == FALSE)
{
AI_Output(self,other,"DIA_Vino_PERM_05_01"); //Я могу поклясться, что видел орка вон там, на краю леса, два дня назад.
AI_Output(self,other,"DIA_Vino_PERM_05_02"); //С тех пор я сплю хотя бы с одним открытым глазом.
Vino_Gossip_Orks = TRUE;
Knows_Ork = TRUE;
Log_CreateTopic(TOPIC_VINO_KILL_ORK,LOG_MISSION);
Log_SetTopicStatus(TOPIC_VINO_KILL_ORK,LOG_Running);
B_LogEntry(TOPIC_VINO_KILL_ORK,"Крестьянин Вино очень боится того, что ночью на ферму придет орк и убьет его, поэтому он никак не может выспаться.");
}
else if((Vino_Gossip_Bugs == FALSE) && (MIS_AndreHelpLobart == LOG_Running))
{
AI_Output(self,other,"DIA_Vino_PERM_05_03"); //Эти огромные отвратительные насекомые уже всех достали. Они повсюду. Они сожрут все, что мы вырастили, если мы не сделаем что-нибудь.
AI_Output(self,other,"DIA_Vino_PERM_05_04"); //Несколько дней назад я лежал в траве, размышляя о своем, и собирался вздремнуть, когда одна из этих тварей сожрала мой ботинок!
AI_Output(self,other,"DIA_Vino_PERM_05_05"); //Ты бы видел, как я улепетывал. С тех пор я не могу спать спокойно.
Vino_Gossip_Bugs = TRUE;
}
else
{
AI_Output(self,other,"DIA_Vino_PERM_05_06"); //Кроме того, что я уже сказал тебе? Нет.
};
};
Итак:
var int Vino_Gossip_Orks;
var int Vino_Gossip_Bugs;
var int Vino_Gossip_Bugs;
Внимание!! Обьявлять переменную нужно именно в начале диалога, а не в середине, или в самой заднице конце.
instance DIA_Vino_PERM(C_Info)
{
npc = BAU_952_Vino;
nr = 10;
condition = DIA_Vino_PERM_Condition;
information = DIA_Vino_PERM_Info;
permanent = TRUE;
description = "Есть какие-нибудь интересные новости?";
};
{
npc = BAU_952_Vino;
nr = 10;
condition = DIA_Vino_PERM_Condition;
information = DIA_Vino_PERM_Info;
permanent = TRUE;
description = "Есть какие-нибудь интересные новости?";
};
nr = 10; - строчка расположения диалога, чем больше цифра - тем ниже диалог
condition = DIA_Vino_PERM_Condition; - переменная отвечающая за "техчасть" диалога
information = DIA_Vino_PERM_Info; - за "информационную" часть
permanent = TRUE; - диалог доступен постоянно. Если вместо тру будет стоять FALSE - то диалог доступен один раз
description = "Есть какие-нибудь интересные новости?"; - как выглядит начало в диалоговом окне.
func void DIA_Vino_PERM_Info() (наша переменная которая отвечает за информационную часть)
{
AI_Output(other,self,"DIA_Vino_PERM_15_00"); //Есть какие-нибудь интересные новости? (Собственно, пишем сам диалог. Если other,self то, сначала говорит ГГ, а потом нпс. Если наоборот - то нпс а отвечает ГГ)
if(Vino_Gossip_Orks == FALSE) (Еще одна наша переменная)
{
AI_Output(self,other,"DIA_Vino_PERM_05_01"); //Я могу поклясться, что видел орка вон там, на краю леса, два дня назад.
AI_Output(self,other,"DIA_Vino_PERM_05_02"); //С тех пор я сплю хотя бы с одним открытым глазом.
Vino_Gossip_Orks = TRUE; (Еще одна наша переменная)
Knows_Ork = TRUE; (Орк появился, именно тот который нужен)
Log_CreateTopic(TOPIC_VINO_KILL_ORK,LOG_MISSION); (Топик - запись в дневнике)
Log_SetTopicStatus(TOPIC_VINO_KILL_ORK,LOG_Running);
B_LogEntry(TOPIC_VINO_KILL_ORK,"Крестьянин Вино очень боится того, что ночью на ферму придет орк и убьет его, поэтому он никак не может выспаться."); (Краткое описание квеста в дневнике)
}
Вроде все понятно и просто, верно?
Итак, конец нашего диалога и завершение квеста.
var int mis_kill_vino_ork;
instance DIA_VINO_KILLORK(C_Info) (начало диалога)
{
npc = BAU_952_Vino;
nr = 1;
condition = dia_vino_killork_condition; (Смотрим на переменную)
information = dia_vino_killork_info;
permanent = TRUE;
description = "Я убил этого орка!";
};
func int dia_vino_killork_condition() (Смотрим навверх и видим переменную)
{
if(Npc_IsDead(OrcWarrior_Harad)(Убили орка по квесту Харада) && (MIS_KILL_VINO_ORK != 1)(Убили орка по квесту Вино. 1 штуку) && Npc_HasItems(hero,itfo_addon_shnaps_orks)) (В инвентаре ГГ есть орочий шнапс. Можно пробить по поиску itfo_addon_shnaps_orks и узнать что это)
{
return TRUE;
};
};
func void dia_vino_killork_info()(Опять таки смотрим переменную выше)
{
B_GivePlayerXP(50); (Получаем 50 опыта)
AI_Output(other,self,"DIA_Vino_KillOrk_99_01"); //Я убил этого орка!
AI_Output(self,other,"DIA_Vino_KillOrk_99_02"); //Ты шутишь парень? Не верю!
AI_Output(other,self,"DIA_Vino_KillOrk_99_03"); //У меня есть вот этот шнапс, такого больше нигде не достать, кроме как у орков!
B_GiveInvItems(hero,self,itfo_addon_shnaps_orks,1);(Отдаем Вино шнапс)
AI_Output(self,other,"DIA_Vino_KillOrk_99_04"); //Точно! Теперь-то я наконец высплюсь как следует!
AI_UseItem(self,itfo_addon_shnaps_orks);(Изымается из инвентаря шнапс)
AI_Output(self,other,"DIA_Addon_Scatty_Bier_01_01"); //О, как вкусно. Спасибо, мужик. Ты мой герой!
B_LogEntry(TOPIC_VINO_KILL_ORK,"Я убил орка, а Вино теперь может спать спокойно!"); (Запись в дневнике, квест "Бессоница Вино успешно завершен)
AI_Output(self,other,"DIA_Vino_KillOrk_99_05"); //Ну за такую-то работенку можно и заплатить. Правда у меня нет золота, а есть только растения всякие... Держи!
B_GiveInvItems(self,other,ItPl_Temp_Herb,1); (Вино даем нам Полевое растение)
Log_SetTopicStatus(TOPIC_VINO_KILL_ORK,LOG_SUCCESS); (Квест в дневнике переходит из Текущих в Выполненные)
MIS_KILL_VINO_ORK = 1;
};
На этой положительной ноте я завершаю урок. Надеюсь, вы почепнули для себя что то новенькое и интересное. Если вы поняли данный урок - то сможете с легкостью писать квесты в своем моде как электро-веник) Ну и в дальнейшем, знания о написание диалогов поможет вам в более трудных скриптовых задачах.
Мини-урок #3 "Меняем внешность Главного Героя"
Довольно часто люди спрашивают, как сменить внешность Главного героя, ибо старая физиономия уже надоела. Сделать это не составит никакого труда, если вы не поленились и прочитали серию уроков "для чайников" и "простые уроки модоломания".
Итак, чтобы сменить внешность ГГ (Главный Главнюк Герой) вам нужен скрипт PC_Hero. Он находится по адресу - Story/NPC/PC_Hero
Скрипт мы нашли и видим аттрибуты начальные гг. Можно их заменить на любые другие, например чтобы у ГГ вначале было не 75 хп, а 100. Или по 20 ловкости и силы сразу. Или чтобы он был мастером одноручника или любого другого оружия.
Но, чтобы сменить внешность нам нужна строчка - Mdl_SetVisualBody. Если хоть немного знакомы с ангельским, то из самого названия понятно что это визуализация тела.
Итак:
-Hum_Head_Pony - тип головы. Если надоела косичка, то замените Pony на Bald
-Face_N_Player – лицо. Открывайте, не бойтесь другие скрипты Нпс и смотрите какие у них лица. Например, можно сделать лицо как у Креола, или как у Фалька или как у жиробаса Онара.
-NO_ARMOR - наш герой щеголяет в одном нижнем белье. Можно одеть ему любой доспех. Для того, чтобы узнать инстанцию доспеха, нужно просто пробить по поиску. Поиском в Соурсере вы уже умеете пользоваться.
Как изменили внешность ГГ, компилируйте проект, заменяйте датник и оушник, запаковываете в мод-файл и играйте!
Да, еще одно. Вы можете за игру менять сколько хотите внешность героя - на сейвы это никак не влияет.
Итак, чтобы сменить внешность ГГ (Главный Главнюк Герой) вам нужен скрипт PC_Hero. Он находится по адресу - Story/NPC/PC_Hero
Скрипт мы нашли и видим аттрибуты начальные гг. Можно их заменить на любые другие, например чтобы у ГГ вначале было не 75 хп, а 100. Или по 20 ловкости и силы сразу. Или чтобы он был мастером одноручника или любого другого оружия.
Но, чтобы сменить внешность нам нужна строчка - Mdl_SetVisualBody. Если хоть немного знакомы с ангельским, то из самого названия понятно что это визуализация тела.
Итак:
-Hum_Head_Pony - тип головы. Если надоела косичка, то замените Pony на Bald
-Face_N_Player – лицо. Открывайте, не бойтесь другие скрипты Нпс и смотрите какие у них лица. Например, можно сделать лицо как у Креола, или как у Фалька или как у жиробаса Онара.
-NO_ARMOR - наш герой щеголяет в одном нижнем белье. Можно одеть ему любой доспех. Для того, чтобы узнать инстанцию доспеха, нужно просто пробить по поиску. Поиском в Соурсере вы уже умеете пользоваться.
Как изменили внешность ГГ, компилируйте проект, заменяйте датник и оушник, запаковываете в мод-файл и играйте!
Да, еще одно. Вы можете за игру менять сколько хотите внешность героя - на сейвы это никак не влияет.
Последнее редактирование модератором:
- 14
- Показать все