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

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

Летописи строителей

Статус
В этой теме нельзя размещать новые ответы.

Зорк

Участник форума
Регистрация
29 Дек 2004
Сообщения
3.079
Благодарности
359
Баллы
405

Зорк

Участник форума
Регистрация
29 Дек 2004
Сообщения
3.079
Благодарности
359
Баллы
405
Урок 1: Создание в 3D Studio MAX локации для Готики

Важно! Всё построение производилось в 3D Studio MAX 6, так что могут быть некоторые отличия от предыдущих частей (или новых. - прим. ред.).

План:
1. Основные операции при создании локаций для Готики в 3D Studio MAX
а) Создание ландшафта
б) Создание зданий
в) Наложение текстур (в том числе и с использованием текстурных координат)
2. Создание непосредственно самой “Арены”


1. а) Ландшафт:
Для начала установим метрическую систему на сантиметры
(наблюдается несовпадение с метрической системой Spacera, т.е.
Spacer распознаёт только сантиметры, а при использовании других систем
измерения наблюдается несовпадение размеров)
:
главное меню-> Customize-> Units Setup-> System Units Setup
Создадим поверхность, на которой всё и будет находиться. Можно конечно
взять за основу просто плоскость
панель управления справа: Create-> Geometry-> Plane
, но лучше и реалистичнее будет создать ландшафт.

Тут есть много вариантов, например, создать плоскость (Create-> Geometry->
Plane), поставить нужный размер (Length=+; Width=+ в параметрах ниже),
задать кол-во сегментов (Length Segs=+; Width Segs=+, там же где и размер
плоскости ), щёлкнуть по плоскости правой клавишей (вход в контекстное
меню), применить модификатор Edit Mesh,
контекстное меню-> Convert to:-> Convert to Editable Mesh
выбрать редактирование по вeртексам (вершинам)
панель управления-> Selection-> Vertex
и уже по своему усмотрению перемещать их вверх или вниз.
главное меню вверху-> Select & Move (значок ввиде стрелочек во все
стороны)

Но я предлагаю делать иначе, т.е. с помощью составного объекта (Compound
Object) типа ландшафт (Terrain).
Сделайте две окружности на виде сверху (Top) кривой типа кольца (Donut)
радиус внутреннего- 3000 (сама арена), внешнего- 10000
панель управления: Create-> Shapes-> Donut
Используйте кривые типа линии (Line), чтобы создать заготовки неровностей,
делайте по-больше вершин (для начала нарисуйте линии напроекции сверху).
Затем выберите одну из линий и объедините с остальными (для удобства можно
переходить лишь к одному окну проекции alt+ W)
контекстное меню-> Attach-> щёлкаете по очереди по всем вашим линиям
Перейдите к редактированию
панель управления:-> Modify (следующая вкладка после Create)
Выберите выделение вертексов
панель управления-> Selection-> Vertex
и, выбирая их на проекции сверху, поднимайте или опускайте вершины на
проекции сбоку. Выберите вершины и сделайте сглаживание (Smooth)
контекстное меню-> Smooth
Примените модификатор шум (Noise)
главное меню-> Modifiers-> Parametric Deformers-> Noise
Перейдите к типу редактируемых кривых
контекстное меню-> Convert to:-> Convert to Editable Spline
Теперь надо нормализовать кривую
главное меню-> Modifiers-> Patch/Spline Editing-> Normalize Spline
Если возникнут какие либо проблемы при нормализации, то можно всё поправить
на уровне вершин (у меня не было проблем)
главное меню-> Modifiers-> Patch/Spline Editing-> Edit Spline
Нажмите вкладку Create на панели управления, выберите 2 окружности
(Donut01), что создали в самом начале и создайте составной объект типа
ландшафт
панель управления: Create-> Geometry-> в списке выберите Compound
Objects-> Terrain-> там нажмите Pick Operand и выберите линии, что создали
в начале
Во вкладке Modify на панели управления поставьте Simplification на
Interporale Points * 2 Теперь объект надо сгладить с помощью Mesh Smooth
или HSDS
главное меню-> Modifiers-> Subdivision Surfaces-> MeshSmooth
или
главное меню-> Modifiers-> Subdivision Surfaces-> HSDS Modifier
Примените к объекту разбиение
панель управления: -> Advanced Options-> кнопка Adaptive Subdivision

Итак, ландшафт готов, теперь наложим на него текстуры.
Дадим имя “Ландшафт” нашей поверхности (так будет легче в дальнейшем её
определять)
панель управления:-> Modify (строка названия)
Теперь откройте редактор материалов
главное меню-> Rendering-> Material Editor или клавиша “М”
Выберите 1 шарик для отображения текстур, щёлкните по кнопке (Blinn Basic
Parameters-> Diffuse), из списка выбираем Bitmap и путь к текстуре (я
выбрал …\Gothic II \_work\Data\Textures\Level\NewWorld\
NW_Nature_GreatSea_Sand_01.tga), затем жмёте Assign Material to Selection
(кнопка ввиде кружка и квадратика, соединённых кривой стрелочкой)

Ну вот и всё, поверхность готова.

б) Создание дома:

Создайте плоскость (Create-> Geometry-> Plane), поставьте нужный размер
(Length= 3000; Width= 3000 в параметрах ниже), задайте кол-во сегментов
(Length Segs= 3; Width Segs= 3, там же где и размер плоскости ), щёлкните
по плоскости правой клавишей (вход в контекстное меню), примените
модификатор Edit Poly,
контекстное меню-> Convert to:-> Convert to Editable Poly
выберите редактирование по полигонам (плоскостям)
панель управления-> Selection-> Polygon
выберите центральный полигон и переместитеего вверх на окне проекции сбоку,
чтобы наш будущий дом стоял на холме.
главное меню вверху-> Select & Move (значок ввиде стрелочек во все
стороны)
Затем, не снимая выделение с полигона, примените функцию Extrude
панель управления-> Edit Geometry-> Extrude
и вытените на 300, затем на тот же полигон примените функцию Bevel
панель управления-> Edit Geometry-> Bevel
и поставьте значения Height на 0, Outline Amount на -30, а Bevel Type на By
Polygon и ОК.
На получившийся полигон сделайте Extrude на -300.
Теперь выберите боковую грань нашего здания, где будет дверь, и примените
Bevel со значениями Height на 0, Outline Amount на -30, а Bevel Type на By
Polygon, сделайте Bevel с обеих сторон стенки с одинаковыми значениями.
Получившийся полигон снаружи стены проэкструдьте на -30 и удалите, а
полигон внутри стены просто удалите. Получилась стена, но великоватая для
двери- сейчас исправим.
Выберите выделение вертексов
панель управления-> Selection-> Vertex
Выберите получившиеся вертексы на боковой грани (дверной проём) и
перетяните их на проекции сбоку, так чтобы получился прямоугольник (дверь).
Удобно перемещать сразу 4 полигона с каждого бока (всего 8 ), выделяя с
нажатым Ctrl.Также неплохо убрать и порог, он нам совершенно не нужен.
Просто опустите нижние вершины дверного проёма до уровня пола.
Так, теперь сделаем камин для дома.
Сделайте Box с размерами Length= 300; Width= 100; Height= 200.Преобразуйте
его к Editable Poly. Выберите его грань, где будет топка и примените
функцию Bevel
панель управления-> Edit Geometry-> Bevel
и поставьте значения Height на 0, Outline Amount на -30, а Bevel Type на By
Polygon.
Выберите 4 получившихся вертекса и преобразуйте их к Editable Mesh
контекстное меню-> Convert to:-> Convert to Editable Mesh
Затем примените к 2 верхним вертексам Chamfer Vertex (кромки) 2 раза, чтобы
получились закруглённые углы.
контекстное меню-> Chamfer Vertex
Нижние 2 вертекса опустите пониже, но не до самого пола.
Теперь проэкструдьте центральный полигон на -100 (внимание он состоит из
нескольких Face: панель управления-> Selection-> Face - выбирайте все).
Подиагонали получится лишний полигон- выделите его и удалите, также можно
удалить заднюю стенку камина: она не нужна.

Теперь сделаем дымоход.
Создайте Box с размерами Length= 300; Width= 100; Height= 100, примените
модификатор Edit Mesh, выделите верхний полигон и примените Scale
контекстное меню-> Scale
и сожмите верх до ширины трубы, затем поставьте дымоход точно на камин и
присоедините
контекстное меню-> Attach
Всю печку сделайте Editable Poly. Теперь выберите самый верхний полигон
дымохода (начало трубы) и проэкструдьте его на 350, не снимая выделения с
полигона сделайте Bevel на Height= 0, Outline Amount= -10, а Bevel Type- By
Polygon, затем Extrude на - 300.
Поставьте камин к стене и присоедините к дому
контекстное меню-> Attach
Сделаем ещё прилавок- Box на 200; 500; 100 и присоедините к дому.
Стены есть, дверь есть, окон не надо- в Готике они идут текстурами,
осталась крыша.

Создайте Box с размерами Length=1030; Width=1030; Height= 300 и все
сегменты на 1.
Поставьте его ровно на стены (туда, где будет крыша), примените модификатор
Edit Mesh,
контекстное меню-> Convert to:-> Convert to Editable Mesh
выделите верхний полигон и примените Scale
контекстное меню-> Scale
и сожмите верх крыши по вашему вкусу.
Присоедините крышу ко всему остальному
контекстное меню-> Attach

Теперь откройте редактор материалов
главное меню-> Rendering-> Material Editor или клавиша “М”
Выберите 1 шарик для отображения текстур, щёлкните по кнопке (Blinn Basic
Parameters-> Diffuse), из списка выбираем Bitmap и путь к текстуре (я
выбрал …\Gothic II \_work\Data\Textures\Level\NewWorld\
NW_City_DirtyGround_02.tga), затем жмёте Assign Material to Selection
(кнопка ввиде кружка и квадратика, соединённых кривой стрелочкой).

Кстати, многие меня спрашивали, как сделать башню.
Круглую башню нечего делать: создайте примитив труба (Tybe), проэкструдьте
дверь, вставьте ступеньки
панель управления : Create-> Geometry->…Stairs (в выпадающем меню)->
Spiral Stair
и сделайте крышу. С квадратной почти то же самое, а вот деревянную
смотровую вышку сделать сложнее.
Так вот сделайте Box, разделённый на 3 и более сегментов по высоте, и
примените модификатор Lattice и Edit Mesh
панель управления-> Modifier List-> Lattice
и в Parameters ставите точку около Struts Only From Edges, в Struts-
галочку напротив End Caps.
Поработайте с вершинами, чтобы сделать их менее правильными и сверху
сделайте ещё Box, примените на него Bevel, а затем Extrude, как я уже
раньше описывал- получится платформа с бортиками, соедините всё вместе- вот
вышка и готова.

в) Наложение текстур (в том числе и с использованием текстурных координат)

В 3D Studio MAX есть несколько способов наложения текстур. Начнём с самого простого.
Откройте редактор материалов
главное меню-> Rendering-> Material Editor или клавиша «М»
Выберите 1 шарик для отображения текстур, щёлкните по кнопке (Blinn Basic Parameters-> Diffuse), из списка выбираем а) Checker (шахматная доска), прописываем в Coordinates в графе Tiling U:10 и V:10 или б) Bitmap и путь к текстуре; затем жмёте Assign Material to Selection (кнопка ввиде кружка и квадратика, соединённых кривой стрелочкой). Этот способ уже упомянался при построении объектов, но он обладает существенным недостатком: наблюдается искажение текстур, значит, применять его лучше к плоскостям и неизменённым или малоизменённым примитивам в нашем случае с домом таким способом можно наложить текстуры разве что на площадь рядом с домом.

Другой способ и более надёжный состоит в следующем:
Выделите объект, примените модификатор Mesh Select
панель управления : Modify-> Mesh Select (в выпадающем меню Modifier List)
выберите один скат крыши и примените UVW Mapping
панель управления : Modify-> UVW Map (в выпадающем меню Modifier List)
В стоке модификаторов (списке применённых в панели управления) щёлкните по «+» рядом с UVW Mapping и выберите Gizmo. Теперь на виде сбоку (Front) разверните оранжевый прямоугольник (полщадь применения текстуры) так, чтобы он совпал с плоскостью ската крыши, затем отредактируйте его до совпадения по размерам со скатом крыши (Рис.1.6)
панель управления : Alignment-> Fit
Сейчас можете применять текстуру к выделенному (как и в первом случае).
Важно! Для каждой новой плоскости надо заново применять UVW Mapping

Пришло время текстурных координат.
Выделите крышу, назначте в Material Editor текстуру и примените модификатор Unwrap UVW
главное меню-> Modifiers-> UV Coordinates-> Unwrap UVW
войдите в редактор текстурных координат
панель управления-> Parameters-> кнопка Edit
затем в редакторе текстурных координат
меню редактора текстурных координат-> Display-> Filter Selected Faces
Примените плоское текстурирование (Flatten Mapping)
меню редактора текстурных координат-> Mapping-> Flatten Mapping
в параметрах Flatten Mapping поставьте угол <=20 и уберите галочку возле Rotate Clusters
В полученной развёртке поместите полигоны так, чтобы текстуры ложились правильно.
Теперь выберите стены и проделайте то же самое, только с другой текстурой. Аналогично и с остальными поверхностями.

2) Создание «Арены»

Что ж поехали.
Создайте окружность (Circle) на проекции с верху (Top) с радиусом 1500
панель управления : Create-> Shapes-> Circle
Затем на виде сбоку создайте ломанную линию (это собственно будущий контур арены)
панель управления : Create-> Shapes-> Line
(Рис.2.1)
Теперь перейдите к модификатору Loft (не путайте с Лофтом в форуме )
панель управления : Create-> Geometry->…Compound Objects (в выпадающем меню)-> Loft
В Skin Parameters поставьте Shape Steps= 1, а затем щёлкните Get Path во вкладке Creation Method, получится заготовка для арены, но у нас нет дна. Приведите объект к Editable Mesh, затем выделение по вертексам и создайте дно.
контекстное меню-> Create Polyhons
и по-очереди выберите вертексы дна, получился новый полигон.
Теперь создайте 2 Box’a- комнаты за пределами арены напротив друг друга.
Сделайте 2 Box’a- коридоры, примените к ним модификатор Edit Mesh, выдклите верхний полигон п сузьте его
контекстное меню-> Scale
Расположите все объекты, т.е. арена посередине, побокам комнаты, а коридоры соединяют их (Рис.2.2)
Настало время всё соединить. Выделите одну из комнат и примените модификатор Boolean
панель управления : Create-> Geometry->…Compound Objects (в выпадающем меню)-> Boolean
В списке операций (Operation) выберите объединение Union, затем щёлкните Pick Operand B и нажмите на коридор, соответствующий данной комнате. Со второй комнатой сотворите то же самое. Выберите саму арену и присоедините к ней Boolean’ом комнаты.
Отконвертируйте полученный объект к Editable Mesh, выберите полигоны выходов и удалите их.
В дальнейшем при наложении текстур ставьте галочку напротив 2-Sided, чтобы были текстуры и внутри помещений.

Заготовка арены есть.
Теперь можно сделать помещение типа для знатных особ. Сделайте Box, примените на 1 грань Bevel
панель управления-> Edit Geometry-> Bevel
а затем Extrude
панель управления-> Edit Geometry-> Extrude
Чтобы получилось помещение. Дверь можно сделать с помощью модификатора Boolean
панель управления : Create-> Geometry->…Compound Objects (в выпадающем меню)-> Boolean
Создайте примитив с сечением, как у двери и «пронзите» им стенку, где намечается дверь,
в списке операций (Operation) выберите объединение Union, затем щёлкните Pick Operand на этот примитив (сама стена должна быть уже выделена), в итоге примитив исчезнет, а в стене останется проём. Дальше поукрашайте арену по усмотрению.

Теперь наложите текстуры, как было показано в 1.в) из учёта что на примитивы текстуры можно накладывать первым способом, а вот на объекты созданные разными модификаторами (в нашем случае сами кольца арены) лучше с использованием текстурных координат.
 

Зорк

Участник форума
Регистрация
29 Дек 2004
Сообщения
3.079
Благодарности
359
Баллы
405
Урок 2: Скрипты

План:
1. Вставка НПС
2. Создание диалогов



1. Вставка НПС:

instance PAL_9991_Toreodore (Npc_Default) // - Стандартная переменная для всех НПС
{
// —— NSC —— // - просто разделение, чтоб не запутаться. В готовом датнике его нет/
name = “Toreodore”; // - имя
guild = GIL_PAL; // - гильдия (см. в …\_work\Data\Scripts\Content\AI\Human\guilds.d)
) id = 9991; // тот самый ID ,берётся из PAL_***9991***_Toreodore, влияет на определение НПС игрой.
voice = 14; // голос НПС, в нашем случае без разницы какой голос ))
flags = NPC_FLAG_IMMORTAL; // NPC_FLAG_IMMORTAL - НПС бессмертный, ещё есть значение (flags = 0) - НПС смертен.
level = 21; // - уравень НПС
npctype = NPCTYPE_MAIN; // - нужность НПС т.е. друг ,враг, нейтрал, главный (NpcType_Friend, NpcType_Ambient, NpcType_Bl_Main и NpcType_Ocambient , т.е. нужны для миссий)

// —— Attribute —— // - аттрибуты НПС
attribute[ATR_STRENGTH] = 40; // - сила НПС
attribute[ATR_DEXTERITY] = 30; // - ловкость НПС
attribute[ATR_MANA_MAX] = 100; // - Максимальная мана
attribute[ATR_MANA] = 10; // - мана на данный момент
attribute[ATR_HITPOINTS_MAX] = 100; // - максимальная жизнь
attribute[ATR_HITPOINTS] = 46; // - жизнь на данный момент

// —— Kampf-Taktik —— // - Далее описана Характеристика Атаки
fight_tactic = FAI_HUMAN_STRONG; // -(STRONG) характеристика атаки–> МАСТЕР/БОЕЦ/НОВИЧОК—>MASTER / STRONG / COWARD

// —— Equippte Waffen —— // - Вооружение НПС
EquipItem (self, ItMw_1h_Bau_Mace); // - оружие которым вооружён НПС ( в нашем случае **Простой посох**)
EquipItem (self, ItRw_Mil_Crossbow); // -(см.в …\_work\Data\Scripts\Content\Items)

// —— Inventory —— ** - Инвентарь НПС
CreateInvItems (self, ItRw_SLD_Bow); // - оружие в инвентаре НПС ( в данном случае **Салдатский лук**, в основном у НПС здесь лежат деньги, драгоценности и ценные вещи

// —— visuals —— // - Визуализация НПС
B_SetNpcVisual (self, MALE,// - (Мужик, Female-женщина) “Hum_Head_FatBald”,//- (текстура головы НПС) Face_N_OldBald_Jeremiah,// - (лицо НПС) BodyTex_N,// - (текстура тела НПС) ITAR_Vlk_H);// - Броня одетая на НПС
Mdl_SetModelFatness (self, 2); // - жироность НПС )
Mdl_ApplyOverlayMds (self, “Humans_Arrogance.mds”); //- может вместо **Arrogance** быть–> Tired / Militia / Mage / Arrogance / Relaxed это походка НПС- КрутоЙ, уставший пьяный и тд.

// —— NSC-relevante Talente vergeben —— // - Таланты НПС
Npc_SetTalentSkill (self, NPC_TALENT_PICKLOCK, 1); // - НПС обучен взлому замков ( Обучен = 1; Не обучен = 0)

// —— Kampf-Talente —— // - Возможности НПС
B_AddFightSkill (self, NPC_TALENT_1H, 30); // - талант владения одноручем
B_AddFightSkill (self, NPC_TALENT_2H, 30); // - талант владения двуручем
B_AddFightSkill (self, NPC_TALENT_BOW, 50); // - талант владения луком
B_AddFightSkill (self, NPC_TALENT_CROSSBOW, 50); // - талант владения арболетом

// —— TA anmelden —— Рассписание дня
daily_routine = Rtn_Start_9991; // - рассписание дня НПС (само рассписани следует НИЖЕ ===\___/===)
};

FUNC VOID Rtn_Start_9991 ()

{
TA_Sit_Throne (09,00,21,00,”МестО1″); // - Нпс сидит но стуле находящийся около вейпоинта Место1

TA_Sleep (21,00,09,00,”МестО2″); // - НПС спит на кровати, находящийся у вейпоинта Место2
};

1) - (Место1;Место2) - это вейпоинты. создаются в Спайсере, около них должно быть то, на что направлено действие (стул, кровать, дверь)
2) - Потом дописываешь в файле ***NPC_Globals**** (C:\Program Files\Gothic II\_work\data\Scripts\Content\Story\NPC_Globals) строчку (var C_NPC Toreodore; - в начале и
Toreodore = Hlp_GetNpc(PAL_9991_Toreodore); - ,ближе к концу

3)Полный состав (ТА_*****) ( TA_Sleep и т.д.) можно посмотреть в (C:\Program Files\Gothic II\_work\data\Scripts\Content\AI\Human) в разделе ***TA***
4)полный спиок лиц
// Для мужчин и женщин (по 4 штуки)
BodyTex_P = 0; //Бледнокожий
BodyTex_N = 1; //Европеец
BodyTex_L = 2; //Латиноамериканец
BodyTex_B = 3; //Негр
BodyTexBabe_P = 4; //Бледнокожая
BodyTexBabe_N = 5; //Европейка
BodyTexBabe_L = 6; //Латиноамериканка
BodyTexBabe_B = 7; //Негритянка
BodyTex_Player = 8; //ГГ

const int BodyTex_T = 10; //Татуированный мужик
const int BodyTexBabe_F = 11; //Татуированная женщина
const int BodyTexBabe_S = 12; //Чернокожий ребенок

const int NO_ARMOR = -1; //Без доспехов

// Лица мужчин
Face_N_Gomez = 0;
Face_N_Scar = 1;
Face_N_Raven = 2;
Face_N_Bullit = 3;
Face_B_Thorus = 4;
Face_N_Corristo = 5;
Face_N_Milten = 6;
Face_N_Bloodwyn = 7;
Face_L_Scatty = 8;
Face_N_YBerion = 9;
Face_N_CoolPock = 10;
Face_B_CorAngar = 11;
Face_B_Saturas = 12;
Face_N_Xardas = 13;
Face_N_Lares = 14;
Face_L_Ratford = 15;
Face_N_Drax = 16;
Face_B_Gorn = 17;
Face_N_Player = 18;
Face_P_Lester = 19;
Face_N_Lee = 20;
Face_N_Torlof = 21;
Face_N_Mud = 22;
Face_N_Ricelord = 23;
Face_N_Horatio = 24;
Face_N_Richter = 25;
Face_N_Cipher_neu = 26;
Face_B_Cavalorn = 28;
Face_L_Ian = 29;
Face_N_MadPsi = 31;
Face_N_Bartholo = 32;
Face_N_Snaf = 33;
Face_N_Mordrag = 34;
Face_N_Lefty = 35;
Face_N_Wolf = 36;
Face_N_Fingers = 37;
Face_N_Whistler = 38;
Face_P_Gilbert = 39;
Face_L_Jackal = 40;

// Бледнолицые
Face_P_ToughBald = 41;
Face_P_Tough_Drago = 42;
Face_P_Tough_Torrez = 43;
Face_P_Tough_Rodriguez = 44;
Face_P_ToughBald_Nek = 45;
Face_P_NormalBald = 46;
Face_P_Normal01 = 47;
Face_P_Normal02 = 48;
Face_P_Normal_Fletcher = 49;
Face_P_Normal03 = 50;
Face_P_NormalBart01 = 51;
Face_P_NormalBart_Cronos = 52;
Face_P_NormalBart_Nefarius= 53;
Face_P_NormalBart_Riordian= 54;
Face_P_OldMan_Gravo = 55;
Face_P_Weak_Cutter = 56;
Face_P_Weak_Ulf_Wohlers = 57;

// Европейцы
Face_N_Important_Arto = 58;
Face_N_ImportantGrey = 59;
Face_N_ImportantOld = 60;
Face_N_Tough_Lee_дhnlich = 61;
Face_N_Tough_Skip = 62;
Face_N_ToughBart01 = 63;
Face_N_Tough_Okyl = 64;
Face_N_Normal01 = 65;
Face_N_Normal_Cord = 66;
Face_N_Normal_Olli_Kahn = 67;
Face_N_Normal02 = 68;
Face_N_Normal_Spassvogel = 69;
Face_N_Normal03 = 70;
Face_N_Normal04 = 71;
Face_N_Normal05 = 72;
Face_N_Normal_Stone = 73;
Face_N_Normal06 = 74;
Face_N_Normal_Erpresser = 75;
Face_N_Normal07 = 76;
Face_N_Normal_Blade = 77;
Face_N_Normal08 = 78;
Face_N_Normal14 = 79;
Face_N_Normal_Sly = 80;
Face_N_Normal16 = 81;
Face_N_Normal17 = 82;
Face_N_Normal18 = 83;
Face_N_Normal19 = 84;
Face_N_Normal20 = 85;
Face_N_NormalBart01 = 86;
Face_N_NormalBart02 = 87;
Face_N_NormalBart03 = 88;
Face_N_NormalBart04 = 89;
Face_N_NormalBart05 = 90;
Face_N_NormalBart06 = 91;
Face_N_NormalBart_Senyan = 92;
Face_N_NormalBart08 = 93;
Face_N_NormalBart09 = 94;
Face_N_NormalBart10 = 95;
Face_N_NormalBart11 = 96;
Face_N_NormalBart12 = 97;
Face_N_NormalBart_Dexter = 98;
Face_N_NormalBart_Graham = 99;
Face_N_NormalBart_Dusty = 100;
Face_N_NormalBart16 = 101;
Face_N_NormalBart17 = 102;
Face_N_NormalBart_Huno = 103;
Face_N_NormalBart_Grim = 104;
Face_N_NormalBart20 = 105;
Face_N_NormalBart21 = 106;
Face_N_NormalBart22 = 107;
Face_N_OldBald_Jeremiah = 108;
Face_N_Weak_Ulbert = 109;
Face_N_Weak_BaalNetbek = 110;
Face_N_Weak_Herek = 111;
Face_N_Weak04 = 112;
Face_N_Weak05 = 113;
Face_N_Weak_Orry = 114;
Face_N_Weak_Asghan = 115;
Face_N_Weak_Markus_Kark = 116;
Face_N_Weak_Cipher_alt = 117;
Face_N_NormalBart_Swiney = 118;
Face_N_Weak12 = 119;

// Латиноамериканцы
Face_L_ToughBald01 = 120;
Face_L_Tough01 = 121;
Face_L_Tough02 = 122;
Face_L_Tough_Santino = 123;
Face_L_ToughBart_Quentin = 124;
Face_L_Normal_GorNaBar = 125;
Face_L_NormalBart01 = 126;
Face_L_NormalBart02 = 127;
Face_L_NormalBart_Rufus = 128;

// Негры
Face_B_ToughBald = 129;
Face_B_Tough_Pacho = 130;
Face_B_Tough_Silas = 131;
Face_B_Normal01 = 132;
Face_B_Normal_Kirgo = 133;
Face_B_Normal_Sharky = 134;
Face_B_Normal_Orik = 135;
Face_B_Normal_Kharim = 136;

FaceBabe_N_BlackHair = 137;
FaceBabe_N_Blondie = 138;
FaceBabe_N_BlondTattoo = 139;
FaceBabe_N_PinkHair = 140;
FaceBabe_L_Charlotte = 141;
FaceBabe_B_RedLocks = 142;
FaceBabe_N_HairAndCloth = 143;
FaceBabe_N_WhiteCloth = 144;
FaceBabe_N_GreyCloth = 145;
FaceBabe_N_Brown = 146;
FaceBabe_N_VlkBlonde = 147;
FaceBabe_N_BauBlonde = 148;
FaceBabe_N_YoungBlonde = 149;
FaceBabe_N_OldBlonde = 150;
FaceBabe_P_MidBlonde = 151;
FaceBabe_N_MidBauBlonde = 152;
FaceBabe_N_OldBrown = 153;
FaceBabe_N_Lilo = 154;
FaceBabe_N_Hure = 155;
FaceBabe_N_Anne = 156;
FaceBabe_B_RedLocks2 = 157;
FaceBabe_L_Charlotte2 = 158;

// Лицо Фортуно
Face_N_Fortuno = 159;

// Лица пиратов
Face_P_Greg = 160;
Face_N_Pirat01 = 161;
Face_N_ZombieMud = 162;

5) - Советую поставить!G2MDK(63метра) (без него никуда)!

Теперь о том, как вставить этот самый НПС в игру:

ШАГ 1-ый

Копируем наш *.d файл в папку со всеми неписями у Gothic II\_work\Data\Scripts\Content\Story\NPC

ШАГ 2-ой

В файле Gothic II\_work\data\Scripts\Content\Story\NPC_Globals.d находим строчку var C_NPC Lester; и дописываем под ней var C_NPC Vendigo;(имя вашего НПС). Теперь в этом же файле находим Lester = Hlp_GetNpc(PC_Psionic); и дописываем ниже Vendigo = Hlp_GetNpc(PAL_9991_Toreodore); где PAL_9991_Toreodore название файла Вашего непися.
Почему именно под этой строчкой. Важно не под какой строчкой, а в каком разделе файла, в какой функции. Лестер, так же как и наш новенький непись попадает в в функцию, которая вставляет персов в окрестностях башни ксардаса. А так как нашего перса мы вставляем именно у его башни, то соответственно прописывать нужно именно здесь.(вместо строчки МестО1/2 нужно написать NW_XARDAS_PATH_FARM1_08 или любой другой вуапоинт,их можно посмтреть,открым zen файл в спайсере.)

ШАГ 3-ий

Открываем файл Gothic II\_work\Data\Scripts\Content\Story\StartUp.d Находим в нём строку Wld_InsertNpc (PC_Psionic, “NW_XARDAS_TOWER_PATH_01″); И дописываем ниже Wld_InsertNpc (PAL_9991_Toreodore, “”NW_XARDAS_PATH_FARM1_08″);

ШАГ 4-ый

Открываем Spacer, прогу, поставляющуюся из Девелопменкита или вместе с игрой. Экзешник в папке System. Нажимаем World\Repare Script(Мир – заменить скрипты), выбираем Gothic.scr и нажимаем открыть. После чего начнётся компиляция скриптов. Продолжаться она может достаточно долго. В идиале не должно выскочить ни одной ошибки. Если они всё-таки повыскакивали, не отчаивайтесь, персонаж и с ними может вставиться. Конец компиляции выдаст окно Аутпут-Юнитс, которе заменится на окно Материалз.

ШАГ 5-ый

Теперь заходим в игру и начинаем новую (обязательно! не загружаем!). Проверяем, стоит ли персонаж на месте. Если же персонажа на указанном вайпоинте не оказалось, детально, по строчечке проверте правильность ваших скриптов (везде ли стоят ‘;’ и “{”, нету ли описок в словах и т.д.).

Написание Миссий

INSTANCE DIA_Alex_MIS(C_INFO)
{
npc = bau_999_Alex;Код нпс, который будет доватьь миссию
nr = 2;Важность,месть положение в меню
condition = DIA_Alex_MIS_Condition;// название переменной
information = DIA_Alex_MIS_Info;// название переменной
permanent = FALSE;// то что диалог повторяется бесконечно, если = TRUE, если =False, то один раз
important = TRUE; // нпс начинает говорить первым =TRUE, если =False, то нечего не происходит
description = “ХХХ”; // здесь то о чём будет написанно в меню
};

FUNC INT DIA_Mager_MIS_Condition() //функция переменной, которая записана выше
{
if () //Тут записывается условие,условия можно посмотреть в других миссиях
{
return TRUE;
};
};
FUNC VOID DIA_Alex_MIS_Info() //функция переменной которая записана выше

{
AI_Output (other, self, “DIA_Alex_MIS_15_00″);// //Тут идет диалог отображается в субтитрах,если (other, self) , то начинает ГГ к НПС, если наоборот, то НПС к ГГ
AI_Output (self, other, “DIA_Alex_MIS_04_01″);//
AI_Output (self, other, “DIA_Alex_MIS_04_02″);//
AI_Output (self, other, “DIA_Alex_MIS_04_03″);//
AI_Output (self, other, “DIA_Alex_MIS_04_04″);//
AI_Output (self, other, “DIA_Alex_MIS_04_05″);//
AI_Output (other, self, “DIA_Alex_MIS_15_06″);//

Log_CreateTopic (Topic_Alex,LOG_MISSION); //создаётся запись в дневнике, в теме активных заданий……(Topic_Alex) создаёшь в (Gothic II\_work\data\Scripts\Content\Story\Log_Entries)в (LOG_Constants_Mattes)
Log_SetTopicStatus (Topic_Alex,LOG_RUNNING); // миссия НАЧАЛАСЬ
B_LogEntry (Topic_Alex,”ХХХ.”); //То, что написано в дневнике

};

сохраняем в (Gothic II\_work\data\Scripts\Content\Story\Dialoge)
Внимание : если вы нашли и исправили ошибку, нужно снова компилить Gothic.src

©francisc,помогал VenDigo, использовались уроки скриптологии Вама

Создание диалогов:


В папке Gothic II\_work\Data\Scripts\Content\Story\Dialoge

создаём файл DIA_NONE_1000_Dedroit.d(создадим далог допустим убить кого-нибудь)!

Вот содержимое этого файла:

instance DIA_Dedroit_q (C_Info)

{
npc = NONE_1000_Dedroit; //ваш нпс
nr = 2;
condition = dia_Dedroit_q_condition;
information = dia_Dedroit_q_info;
permanent = FALSE;
important = FALSE; //если false то диалог начмнаете вы,если TRUE нпс начинает разговор с вами!
description = “Я могу чем нибудь помочь?”;
};
func int dia_Dedroit_q_condition()
{
return TRUE;
};
func void dia_Dedroit_q_info()
{
AI_Output(other,self,”DIA_Dedroit_q_15_00″); //Я могу чем нибудь помочь?
AI_Output(self,other,”DIA_Dedroit_q_3_01″); //Да ты можешь мне почь!Ты бы мог бы убить Вино?
Info_ClearChoices(DIA_Dedroit_q);
Info_AddChoice(dia_Dedroit_q,”Нет я не буду тебе помогать.”,dia_Dedroit_q_w); //Это варианты ответом,которые будут отображаться в главном меню!
Info_AddChoice(dia_Dedroit_q,”Хорошо я убью Вино”,dia_Dedroit_q_e); //Это второй вариант ответа!
};
Если он отказывается помогать ,то

func void dia_Dedroit_q_w()
{
AI_Output(other,self,”dia_Dedroit_q_w_15_00″); //Я не буду помогать тебе!
AI_Output(self,other,”dia_Dedroit_q_w_03_01″); //Тогда не жди и отменя помощи.
};
Если игрок соглашается,то

func void dia_Dedroit_q_e()
{
AI_Output(other,self,”dia_Dedroit_q_e_15_00″); //Хорошо я погу тебе.
AI_Output(self,other,”dia_Dedroit_q_e_03_01″); //Вот и отлично,еслт ты его убьёшь я щедро вознагрожу тебя!
Log_CreateTopic(TOPIC_KillVino,LOG_MISSION);
Log_SetTopicStatus(TOPIC_KillVino,LOG_Running); //дневник
B_LogEntry(TOPIC_KillVino,”Арес попросил меня убить Вино.”); //запись в дневнике
MIS_KillVino = LOG_Running; //Это означает,что миссия началась!
};

instance DIA_Dedroit_q2 (C_Info)
{
npc = NONE_1000_Dedroit;
nr = 1;
condition = dia_Dedroit_q2_condition;
information = dia_Dedroit_q2_info;
permanent = FALSE;
important = FALSE;
description = “Я убил Вино.”;
};

func int dia_Dedroit_q2_condition()
{
if(Npc_IsDead(Vino) && (MIS_KillVino == LOG_Running)) //это означает,что если Вино мёртв то начинается этот диалог!
{
return TRUE;
};
};
func void dia_Dedroit_q2_info()
{
AI_Output(other,self,”dia_Dedroit_q2_info_15_00″); //Я убил вино.
AI_Output(self,other,”dia_Dedroit_q2_info_3_01″); //Великолепно,как я и обещал мой подарок!
MIS_KillVino=LOG_SUCCESS; //миссия завершена
Log_SetTopicStatus(TOPIC_KillVino,LOG_SUCCESS);
B_LogEntry(TOPIC_KillVino,”Я убил вино,а арес как и обещал дал мне подарок.”); //запись в дневнике
B_GivePlayerXP(500); //количество получаевомого опыта,в даном случаи 500!
b_giveinvitems(self,other,ItMW_Addon_Stab03,1); //непись даёт нам подарок посох воды!
};

instance NONE_1000_Dedroit_EXIT(C_Info)
{
npc = NONE_1000_Dedroit;
nr = 999;
condition = NONE_1000_Dedroit_EXIT_Condition;
information = NONE_1000_Dedroit_EXIT_Info;
permanent = TRUE;
description = “Конец”;
};
func int NONE_1000_Dedroit_EXIT_Condition()
{
return TRUE;
};
func void NONE_1000_Dedroit_EXIT_Info()
{
AI_StopProcessInfos(self);
};

Вот так должен выглядеть наш диалог:

instance DIA_Dedroit_q (C_Info)
{
npc = NONE_1000_Dedroit;
nr = 2;
condition = dia_Dedroit_q_condition;
information = dia_Dedroit_q_info;
permanent = FALSE;
important = FALSE;
description = “Я могу чем нибудь помочь?”;
};

func int dia_Dedroit_q_condition()
{
return TRUE;
};
func void dia_Dedroit_q_info()
{
AI_Output(other,self,”DIA_Dedroit_q_15_00″); //Я могу чем нибудь помочь?
AI_Output(self,other,”DIA_Dedroit_q_3_01″); //Да ты можешь мне почь!Ты бы мог бы убить Вино?
Info_ClearChoices(DIA_Dedroit_q);
Info_AddChoice(dia_Dedroit_q,”Нет я не буду тебе помогать.”,dia_Dedroit_q_w);
Info_AddChoice(dia_Dedroit_q,”Хорошо я убью Вино”,dia_Dedroit_q_e);
};
func void dia_Dedroit_q_w()
{
AI_Output(other,self,”dia_Dedroit_q_w_15_00″); //Я не буду помогать тебе!
AI_Output(self,other,”dia_Dedroit_q_w_03_01″); //Тогда не жди и отменя помощи.
AI_StopProcessInfos(self);
};
func void dia_Dedroit_q_e()
{
AI_Output(other,self,”dia_Dedroit_q_e_15_00″); //Хорошо я погу тебе.
AI_Output(self,other,”dia_Dedroit_q_e_03_01″); //Вот и отлично,еслт ты его убьёшь я щедро вознагрожу тебя!
Log_CreateTopic(TOPIC_KillVino,LOG_MISSION);
Log_SetTopicStatus(TOPIC_KillVino,LOG_Running);
B_LogEntry(TOPIC_KillVino,”Арес попросил меня убить Вино.”);
MIS_KillVino = LOG_Running;
AI_StopProcessInfos(self);
};

instance DIA_Dedroit_q2 (C_Info)
{
npc = NONE_1000_Dedroit;
nr = 1;
condition = dia_Dedroit_q2_condition;
information = dia_Dedroit_q2_info;
permanent = FALSE;
important = FALSE;
description = “Я убил Вино.”;
};
func int dia_Dedroit_q2_condition()
{
if(Npc_IsDead(Vino) && (MIS_KillVino == LOG_Running))
{
return TRUE;
};
};
func void dia_Dedroit_q2_info()
{
AI_Output(other,self,”dia_Dedroit_q2_info_15_00″); //Я убил вино.
AI_Output(self,other,”dia_Dedroit_q2_info_3_01″); //Великолепно,как я и обещал мой подарок!
MIS_KillVino=LOG_SUCCESS;
Log_SetTopicStatus(TOPIC_KillVino,LOG_SUCCESS);
B_LogEntry(TOPIC_KillVino,”Я убил вино,а арес как и обещал дал мне подарок.”);
B_GivePlayerXP(500);
b_giveinvitems(self,other,ItMW_Addon_Stab03,1);
};

instance NONE_1000_Dedroit_EXIT(C_Info)
{
npc = NONE_1000_Dedroit;
nr = 999;
condition = NONE_1000_Dedroit_EXIT_Condition;
information = NONE_1000_Dedroit_EXIT_Info;
permanent = TRUE;
description = “Конец”;
};

func int NONE_1000_Dedroit_EXIT_Condition()
{
return TRUE;
};

func void NONE_1000_Dedroit_EXIT_Info()
{
AI_StopProcessInfos(self);
};

Дальше заходим в Story_Globals и в самом конце прописываем var int MIS_KillVino; Потом заходим допустим в LOG_Constants_Yoly(находится в папке \Story\Log_Entries) и всамом конце прописываем const string TOPIC_KillVino= “Убийство Вино”;
Потом заходим в спайсер2 нажимаем world->Reparse Script->gothic.src потом выбираем окно Output-units->update->refresh(ждем,удаляем Ou.bin и Ou.csl)->save. Ou.bin и Ou.csl->находятся в Gothic II\_work\Data\Scripts\Content\Cutscene!
Если вы пользуетесь прогой от вама то просто нужно прописать диалог в Gothic.src и закомпилировать! Ну вот и всё!

Итак продолжаем:

Давайте создадим миссию допустим что-то принести:

В том файле пишем:

instance DIA_DEDEROIT_q3 (C_Info)

{

npc = NONE_1000_Dedroit;//имя непися

nr = 1; //важность,т.е в где будет стоять строка в начале в конце в середине.

condition = dia_DEDEROIT_q3_condition;

information = dia_DEDEROIT_q3_info;

permanent = FALSE;

important = FALSE;

description = “Я могу ещё чем нибудьпомочь”;//То что отображается в меню дилога

};

func int dia_DEDEROIT_q3_condition()

{

if(Npc_KnowsInfo(other, DIA_DEDROIT_q2)) //условие когда начнётся диалог,в нашем случаи после разговора о убийстве Вино

{

return TRUE;

};

};

func void dia_DEDEROIT_q3_info()

{

AI_Output(other,self,”DIA_DEDEROIT_q_15_00″); //Я могу ещё чем нибудьпомочь

AI_Output(self,other,”DIA_DEDEROIT_q_03_01″); //Да ты бы мог мне принести кольцо защиты от пламени!

Info_ClearChoices(DIA_DEDEROIT_q3);

Info_AddChoice(dia_DEDEROIT_q3,”Хорошо я принесу.”,dia_DEDEROIT_q3_w); //Варианты ответов

Info_AddChoice(dia_DEDEROIT_q3,”Нет, забудь”,dia_DEDEROIT_q3_e); //Варианты ответов

Info_AddChoice(dia_DEDEROIT_q3,”Ты мне уже надоел.”,dia_DEDEROIT_q3_r); //Варианты ответов

};

Если игрок соглашается

func void dia_DEDEROIT_q3_w()

{

AI_Output(other,self,”dia_DEDEROIT_q3_w_15_00″); //Хорошо я принесу тебе кольцо.

AI_Output(self,other,”dia_DEDEROIT_q3_w_03_01″); //Вот и отлично!

AI_StopProcessInfos (self);

Log_CreateTopic(TOPIC_q_r,LOG_MISSION);//дневник.

Log_SetTopicStatus(TOPIC_q_r,LOG_Running);//дневник(миссия началась)!

B_LogEntry(TOPIC_q_r,”Нужно принести кольцо для Ареса”); //запись в дневнике.

};

если игрок отказывается

func void dia_DEDEROIT_q3_e()

{

AI_Output(other,self,”dia_DEDEROIT_q3_e_15_00″); //Нет, забудь.

AI_Output(self,other,”dia_DEDEROIT_q3_e_03_01″); //Ну и ладно!

AI_StopProcessInfos (self);

};

Если игрок говорит третий вариант ответа

func void dia_DEDEROIT_q3_r()

{

AI_Output(other,self,”dia_DEDEROIT_q3_r_15_00″); //Забудь!

AI_Output(self,other,”dia_DEDEROIT_q3_r_03_01″); //Тогда умри!

AI_StopProcessInfos (self);

B_Attack(self,other,AR_NONE,1);//функция атаки,после разговора непись будет вас атаковать

};

instance DIA_DEDEROIT_q4 (C_Info)

{

npc = NONE_1000_Dedroit;//опятьже имя

nr = 1;

condition = dia_DEDEROIT_q4_condition;

information = dia_DEDEROIT_q4_info;

permanent = FALSE;

important = FALSE;

description = “Вот, я прнёс тебе кольцо”;//отображение в меню диалога

};

func int dia_DEDEROIT_q4_condition()

{

if(Npc_HasItems(other, ItRi_Prot_Fire_01)>= 1) //он начнётся если привас будет это кольцо

{

return TRUE;

};

};

func void dia_DEDEROIT_q4_info()

{

AI_Output(other,self,”DIA_DEDEROIT_q4_15_00″); //Вот, я прнёс тебе кольцо!

AI_Output(self,other,”dia_DEDEROIT_q4_03_01″); //Отлично!

b_giveinvitems(other,self, ItRi_Prot_Fire_01,1);//вы отдаёте это кольцо!

B_GivePlayerXP(250);//это сеолько опыта вы получили

Log_SetTopicStatus(TOPIC_q_r,LOG_SUCCESS);//миссия закончена

B_LogEntry(TOPIC_q_r,”Я отдал Арксу кольцо.”);//запись в дневнике

};

TOPIC_q_r прописываем в \Story\Log_Entries\LOG_Constants_Yoly.d

и в конце прописываем const string TOPIC_q_r= “Кольцо для Ареса”;

А дальше тоже самое со спайсером или прогой от Vama(написано выше)!

Создать новую,полноценную гильдию нельзя,можно только переделать под свои нужды существующие!

Давайте сделам допустим гильдию сектатнтов.

Чтобы её сделать:

1)заходим в _Intern\Constants.d

там заменяем допустим

const int GIL_EMPTY_D= 15; на const int GIL_SEC= 15;(где SEC->сокращёное название гильдии)!

2)Заходим в Scripts\Content\Story\TEX.d

и в разделе const string TXT_GUILDS[66] =

парописываем вместо “D”,ставим “Сектант”,

3)заходим в _work\data\Scripts\_decompiled\AI\Human\Guilds.d

Там вместо этого

/* D */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, /* D */ ATT_NEUTRAL, ATT_NEUTRAL, /* D */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, /* D */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, /* D */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL

};

ставим

/* SEC */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, /* SEC */ ATT_NEUTRAL, ATT_NEUTRAL, /* SEC */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, /* SEC */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, /* SEC */ ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL, ATT_NEUTRAL

};

Потом всё это дело компилируем и вооля,у нас новая гильдия!

Писал быстро так что могут быть ошики.Если кто найдёт говорите я исправлю.Приятного обучения.


©DEDROIT
 
Статус
В этой теме нельзя размещать новые ответы.
Сверху Снизу