Сообщество Империал: Как делать трейты в Total War Attila - Total War: Attila - Библиотека - Сообщество Империал

  • Поиск
  • Законы
  • Сообщество
  • Репутация
  • Экономика
  • Больше

Информация об авторе

  • Автор: Tryggvi

Информация по статье

  • Добавлено: 21 Апр 2017, 14:45
  • Просмотры: 313

Дополнительно


Репутация: 3
Как делать трейты в Total War Attila

Описание: Редактирование таблиц и создание скриптов
Как делать трейты

Работа с трейтами распадается на два блока: работа с таблицами для создания трейта и работа со скриптами для редактирования/создания триггера (это набор условий, при котором происходит проверка на получение трейта) - и то, и другое в PFM.
Нужна ли нам будет вторая часть, если мы используем ванильный триггер? Толком протестировать я это не смог, но думаю, что да - всё равно придётся дописывать кое-что в скриптах.
Замечу, что также нет смысла приниматься за дело без АКита, поскольку жизненно важная таблица trait_triggers (нужная не для создания трейта как такового, но для получения информации о триггере) в ПФМе просто недоступна.
Я опишу полный цикл создания трейта, включая создание нового триггера. Думаю, после этого работа со старыми трейтами и триггерами станет понятна и так.

Итак, вот полный перечень задействованных таблиц:
character_traits
trait_info
trait_to_included_agents
trait_to_antitraits
character_trait_levels
trait_level_effects
trigger_effects

В character_traits создаётся именно трейт, названия колонок в общем и целом понятны. Обращает на себя внимание колонка no_going_back_level. Видимо, именно это имел в виду rawhide. Я с этим, по крайней мере, не экспериментировал. Остаётся загадкой колонка precedence. Никакого влияния от её параметров я не заметил. Короче говоря, ставьте, как в ванили.

Далее прописывается техническая оснастка трейта. В trait_info выдаётся общая цель трейта. В игре это только agent. Хотя есть ещё опции region и unit (остаётся только гадать, как это выглядит на практике). В trait_to_included_agents задаётся конкретная цель трейта - генерал, жрец и т.д. Чисто теоретически можно обойтись без этой таблицы, задав жёсткие условия в скрипте, но, как говорится, лучше перебдеть. В системе трейтов вообще много такого, что кажется дублирующим или излишним, но приходится всё это исполнять, как обряд.

trait_to_antitraits нужна нам, только если мы делаем трейт, противоположный существующему. Или сразу пару противоположных трейтов. Тут всё понятно - указанные в паре трейты будут друг друга заменять, не встречаясь одновременно. Как понимаю, нужно прописывать отдельно и пару трейтА - трейтБ, и пару трейтБ - трейтА, иначе замена будет работать только "в одну сторону".

Теперь переходим к содержимому трейта. В character_trait_levels мы создаём уровни трейта, создавать уровень нужно даже в том случае, если он у трейта единственный. Тут плюс-минимум всё тоже понятно по названиям колонок. Есть, правда, пустые колонки с манящими названиями вроде epithet_text (уж не кличка ли это?), но они ещё ждут своего исследователя. В этой таблице, однако, задаётся самый загадочный и едва ли не самый главный аспект трейта - threshold (порог). Опытным путём было выявлено, что это количество успешных проверок, которые должен пройти трейт, чтобы получить данный уровень. Т.е., скажем, если у первого уровня threshold = 2, а условие получение трейта - выиграть в битве, вероятность же получения = 100%, то персонаж должен получить трейт только после второй выигранной битвы.
В целом при назначении threshold стоит ориентироваться на ванильные показатели. По крайней мере, поначалу.
Отмечу, что локализация трейта привязывается именно к его уровням (как название, так и описание - coloured text). Никакого общего названия для трейта в локализации не существует.

Таблицу trait_level_effects нет смысла даже комментировать. Стандартная привязка эффектов, величин и скоупов к уровням трейта.

На данной стадии трейт уже готов, и его, например, можно прописать в стартпозе, так что он будет у данного персонажа со старта. Только вот раздавать этот трейт в дальнейшем игра не будет.

В trigger_effects мы приписываем трейт к определённому триггеру (в нашем случае - придумываем новый). Судя по тестам, колонка value - это тот показатель, который добавляется к threshold после успешного прохождения проверки. Другими словами, если у вас threshold = 3 и value = 1, то трейт появится у персонажа после трёх успешных проверок. А если value = 3, то после первой же успешной проверки. Это проще всего понаблюдать, создав трейт, выдаваемый каждый ход всем персонажам с вероятностью 100, и запустив новую кампанию. В первом случае трейт будет получен на третий ход (каждый ход срабатывала успешная проверка), во втором – на первом же ходу, как только мы запустили кампанию.
Ну а вероятность, как нетрудно догадаться прописывается здесь же, в колонке chance.

На этом с таблицами мы покончили, можно приступать к скриптам, но сперва нам надо поучиться.
Идём в АКите в trait_triggers - это, своего рода, скриптовый файл, разложенный в табличном виде. Настольный учебник по созданию трейтов. Разобравшись в том, что и как там написано, мы усвоим азы синтаксиса скриптов.
Итак, тут у нас есть триггер, список ивентов, при которых триггер срабатывает (там выпадающий список, интуитивно понятный - наступление нового хода, рождение персонажа, взросление персонажа и т.п.). И самое главное - conditions, условия. Это условия, при которых происходит проверка на получение трейта.
В conditions задаётся контекст - какие персонажи, каких фракций, религий, культур, субкультур, на какой территории и при каких других условиях будут проходить проверки на получение данного трейта.

В этой колонке настоящее нагромождение текста, но разобраться в нём довольно легко, если учесть, что каждой команде (уж извините, в терминологии не силён) предшествует технический текст и его можно пропускать (хотя я предполагаю, что можно манипулировать и им, но это надо уже совсем в деле разбираться).
Например, такое условие:
(char_is_general_with_army(context:character()) and context:character():faction():name() == "bel_fact_byzantine_expedition" and context:character():faction():has_technology("bel_roman_civil_gloria_romanorium"
) and not context:character():model():campaign_name("pro_attila")) and not context:character():model():campaign_name("cha_attila")

Переводится это так:
Персонаж - генерал с армией И имя фракции - "Римская экспедиция" И фракция персонажа открыла технологию gloria_romanorium И НЕ кампания-пролог И НЕ гранд-кампания
Т.е. трейт выдаётся генералам и губернаторам Римской экспедиции в кампании Велизария после открытия определённой техи. Всё просто.
Команды типа context:character():faction():name() – это тот самый технический текст. Мы можем присваивать им ключи, взятые из таблиц – названия фракций, религий и прочего (в данном случае - bel_fact_byzantine_expedition).
Есть и самостоятельные функции, например, char_is_general_with_army. На самом деле, под этой функцией уже закодирован определённый контекст, который нам не нужно прописывать (контекст, в общем-то, ясен из названия).
NB. Если открыть пак data через ПФМ, то по адресу lua_scripts / lib_export_triggers.lua можно найти своеобразный сборник этих самых функций с пояснениями от разрабов. Не могу сказать, что я нашёл там что-то экстраординарное, но для человека, который уже разобрался в trait_triggers, может быть полезно.

Копируем в свой пак из той же ветки lua_scripts файл export_triggers.lua. Я бы рекомендовал для редактирования скопировать его содержимое в Notepad++, потому что он куда более удобен для скриптописания, подсвечивает команды и переменные, а тут каждый лишний пробел может стать фатальным.
Просто копируем последний скрипт и начинаем его править. Вот, например, как выглядит один из трейтовых скриптов Шарлеманя:
--[[ cha_trig_character_becomes_faction_leader ]]--

function cha_trig_character_becomes_faction_leader_impl (context)
		return context:character():is_faction_leader() and context:character():faction():is_human() and context:character():model():campaign_name("cha_attila")
end 

events.CharacterBecomesFactionLeader[#events.CharacterBecomesFactionLeader+1]
 =
function (context)
	if cha_trig_character_becomes_faction_leader_impl(context) then
		effect.trait("cha_trait_leader_influence", "agent", 1, 100, context)
		return true
	end
	return false
end

Схематически это будет выглядеть так (извиняюсь, табуляция пропадает, но её тоже надо блюсти):

--[[ <Название скрипта, думаю, чисто для красоты> ]]--

function <Название триггера>_impl (context)
return <набор контекстов>
end

events.<название ивента - из trait_triggers>[#events.<то же самое название ивента>+1] =
function (context)
if <название триггера>_impl(context) then
effect.trait("<название трейта>", "<категория из trait_info>", <показатель value из trigger_effects>, <показатель chance из trigger_effects>, context)
return true
end
return false
end

Нетрудно догадаться, что всё, что не вошло в скобки <>, трогать не стоит.

Но самое сердце (и источник всех глюков) трейтового скрипта - это набор условий, или контекстов.
Синтаксис его довольно прост - его мы уже наблюдали в trait_triggers. Ровно те же самые команды и функции мы из него и берём.
У нас есть несколько логических операторов (капсом - для наглядности):
- AND - "и"
- OR - "или"
- NOT - оператор отрицания для функций (у которых нет значка присвоения ==). Обычно идёт в комбинации с AND или OR. Т.е. если мы хотим задать условие "все, кроме генералов, командующих армией", то мы пишем not char_is_general_with_army(context:character())
- ~= - оператор отрицания для команд со значком присвоения ==. Собственно, этот значок он и заменяет. Т.е., если мы хотим задать условие "любая фракция, кроме фракции гаутов", то мы пишем context:character():faction():name() ~= "att_fact_gauti". Ни в коем случае не используйте NOT в данном случае. Весь скрипт просто перестанет работать.
- и наконец, обычные скобки (). Как в формулах Экселя. С помощью них можно задавать довольно сложные условия, группируя контексты. Скажем, условие вида

Цитата

(context:character():is_faction_leader() and context:character():faction():name() == "att_fact_mauri") or context:character():faction():name() == "att_fact_gaetuli"

- позволяет нам воздействовать конкретно на лидера фракции мавров ИЛИ на всех персонажей фракции гетулов. Но не на рядовых персонажей фракции мавров.
Тут логика - наше всё. Короче говоря, если вы не понимаете, каковы будут последствия у условия ЕСЛИ (А И Б), а какие - у условия ЕСЛИ (А ИЛИ Б), то лучше вообще не подходите к триггерам.

На закуску ряд полезных условий для создания трейта (из тех, что я лично проверял или использовал):
- context:character():is_faction_leader() - персонаж - лидер фракции
- char_is_general(context:character()) - персонаж - генерал (любой не женский персонаж и не агент)
- char_is_governor(context:character()) - персонаж - губернатор
- context:character():faction():name() == "ВАШ ТЕКСТ" - фракция персонажа
- context:character():model():campaign_name("ВАШ ТЕКСТ") - определить кампанию (пролог, основная, Велизарий, Карл)
- context:character():faction():state_religion() == "ВАШ ТЕКСТ" - гос. религия персонажа
- context:character():has_trait("ВАШ ТЕКСТ") - персонаж имеет определённый трейт
- context:character():faction():culture() == "ВАШ ТЕКСТ" - культура фракции персонажа
- context:character():faction():subculture() == "ВАШ ТЕКСТ" - субкультура фракции персонажа
- context:character():age() > ВАШ ТЕКСТ - возраст персонажа больше заданного числа (ну или меньше, если знак перевернуть)
А есть ещё контексты, связанные с битвами... :0182:

И последнее. Если вы просто добавляете триггеры, то нет смысла засовывать в свой пак весь ванильный export_triggers.lua.
Можно переименовать его как-нибудь, удалить содержимое и писать всё с нуля.
Но, чтобы этот файл заработал, его надо прописать в той же ветке в файле all_scripted.lua по образцу:
local triggers = require "data.lua_scripts.ИМЯ_СКРИПТОВОГО_ФАЙЛА"
Copyright © «Империал». Копирование информации с этой страницы возможно только при указании прямых ссылок на эту страницу.

Будем благодарны, если Вы поделитесь этой публикацией:





    Воспользуйтесь одной из социальных сетей для входа на форум:


    Внимание: Реклама отключена для зарегистрированных посетителей

    Сообщество Империал > Библиотека > Total War: Attila > Как делать трейты в Total War Attila Обратная Связь
      Стиль:
        27 Май 2017, 07:24
    © 2017 «Империал». Условия предоставления. Ответственность сторон. Рекрутинг на Империале. Лицензия зарегистрирована на: «Империал». Счётчики