[ИНСТРУКЦИЯ] Как сделать мод "с нуля" самому

Проект создания (не)большого мода и русскоязычной документации по моддингу.

Оказалась ли данная информация полезной лично для вас?

Да, спасибо большое! Я прочитал(а) и мне пригодилось!
7
78%
Да, но не обнаружил(а) нужных мне более глубоких знаний.
1
11%
Да, но хотелось бы информации по другим аспектам (создание анимации, создание локаций и т.д.)
1
11%
Нет, все это я знал(а) и раньше. Я неплохо себя чувствую и с английскими мануалами.
0
Голосов нет
Нет, совершенно бесполезный труд.
0
Голосов нет
WTF? Для чего это вообще нужно?
0
Голосов нет
 
Всего голосов: 9

Аватара пользователя
Prowler
Координатор
Координатор
Сообщения: 2206
Зарегистрирован: 16 май 2010, 23:47
Контактная информация:

Re: [ИНСТРУКЦИЯ] Как сделать мод "с нуля" самому

Сообщение Prowler »

Думаю, такой большой объём вряд ли кто-то возьмётся переводить. Как правило, моддеры изначально знакомы с английским языком на хорошем уровне.

Аватара пользователя
Austin
Переводчик
Переводчик
Сообщения: 1077
Зарегистрирован: 19 май 2010, 19:50

Re: [ИНСТРУКЦИЯ] Как сделать мод "с нуля" самому

Сообщение Austin »

Prowler писал(а):
02 май 2020, 18:18
Думаю, такой большой объём вряд ли кто-то возьмётся переводить. Как правило, моддеры изначально знакомы с английским языком на хорошем уровне.
Имхо, именно потому что до моддинга добираются лишь те, кто знает язык и может разобраться в теме. А многих других, у кого идеи есть, но кто английский знает плохо, именно отсутствие понятного русского мануала останавливает. Будь такой мануал, число русских модов бы стало больше, думаю.

В студенческие годы я занимался созданием мода для игры Fallout 2 и сделал в итоге мод "Убежище 14", хотя ничего не знал ранее об устройстве игры. Но помогло то, что на фан-сайте Teamx были подробные инструкции на русском и люди, которые помогали советом. Иначе я бы не взялся тогда за это, слишком трудно разбираться в новых технических моментах да еще на чужом языке. А благодаря мануалам я, ничего ранее не зная о программировании, смог сделать неплохой мод, которым до сих пор пользуются. Думаю, с BG все аналогично, мануал хотя бы по скриптам бы не помешал.
Сайгон многое сделал, хорошо бы его инструкцию изложить в более кратком варианте и пошагово по всем темам.
https://arcanecoast.ru/mods - Список модов ArcaneCoast

Аватара пользователя
Austin
Переводчик
Переводчик
Сообщения: 1077
Зарегистрирован: 19 май 2010, 19:50

Re: [ИНСТРУКЦИЯ] Как сделать мод "с нуля" самому

Сообщение Austin »

Перевел на русский инструкцию от Kulyok по созданию диалогов с NPC (самую простую и максимально понятную для новичков), добавил ее на сайт в раздел инструкций по моддингу: https://arcanecoast.ru/publication/napi ... nayushchih

Постепенно буду стараться пополнять раздел инструкций, чтобы их могли прочесть все желающие независимо от знания языков.
https://arcanecoast.ru/mods - Список модов ArcaneCoast

Аватара пользователя
Lord_Draconis
Переводчик
Переводчик
Сообщения: 468
Зарегистрирован: 02 дек 2012, 00:40

Re: [ИНСТРУКЦИЯ] Как сделать мод "с нуля" самому

Сообщение Lord_Draconis »

Austin писал(а):
13 май 2020, 18:12
Перевел на русский инструкцию от Kulyok по созданию диалогов с NPC (самую простую и максимально понятную для новичков), добавил ее на сайт в раздел инструкций по моддингу: https://arcanecoast.ru/publication/napi ... nayushchih

Постепенно буду стараться пополнять раздел инструкций, чтобы их могли прочесть все желающие независимо от знания языков.
Переведите гайд, как добавлять свою анимацию в игру. Есть подробная инструкция, когда у тебя есть спрайты персонажа и можно их добавить в игру. Я просил saigon1983 еще давно перевести её, он обещал, но сам откатился до реала)

Аватара пользователя
Austin
Переводчик
Переводчик
Сообщения: 1077
Зарегистрирован: 19 май 2010, 19:50

Re: [ИНСТРУКЦИЯ] Как сделать мод "с нуля" самому

Сообщение Austin »

Lord_Draconis писал(а):
13 май 2020, 18:35
Переведите гайд, как добавлять свою анимацию в игру. Есть подробная инструкция, когда у тебя есть спрайты персонажа и можно их добавить в игру. Я просил saigon1983 еще давно перевести её, он обещал, но сам откатился до реала)
А ссылки на нее нет? Или на каком сайте она сайте, на G3?
https://arcanecoast.ru/mods - Список модов ArcaneCoast


Аватара пользователя
wooder
Planewalker
Planewalker
Сообщения: 1056
Зарегистрирован: 29 май 2010, 18:53

Re: [ИНСТРУКЦИЯ] Как сделать мод "с нуля" самому

Сообщение wooder »

В веб-архиве есть версия от 19.12.2018г., не думаю, что после этого там что-то менялось.
<3 DS

Аватара пользователя
tipun
Переводчик
Переводчик
Сообщения: 669
Зарегистрирован: 27 май 2016, 06:57

Re: [ИНСТРУКЦИЯ] Как сделать мод "с нуля" самому

Сообщение tipun »

Я добавлял анимацию ИВДшных гоблинов в ЕЕ версии.
INCLUDE ~%MOD_FOLDER%/lib/functions.tph~
COPY ~%MOD_FOLDER%/gob_anim~ ~override~
LAF FIND_FREE_ANIM_SLOT INT_VAR slotMin = 0xE400 RET slot END
LAF TO_HEX_NUMBER INT_VAR value = slot minDigits = 4 RET hexNumber END
COPY_EXISTING ~E400.ini~ ~override/%hexNumber%.ini~
REPLACE_TEXTUALLY ~MGO1 goblin_axe~ ~MGOA goblin_axe_iwd~
REPLACE_TEXTUALLY ~resref=MGO1~ ~resref=MGOA~
APPEND ~ANIMATE.IDS~ ~0x%hexNumber% GOBLIN_AXE_IWD~
OUTER_SET ~goblin_axe~ = ~%slot%~
Спойлер
Показать
DEFINE_PATCH_FUNCTION CREATE_B_BCS_NAME
STR_VAR
namez = ""
prefix = ""
suffix = ""
RET
result
BEGIN
SPRINT ~result~ ~%prefix%%namez%~
SET lng = STRING_LENGTH ~%result%~
SET lngs = STRING_LENGTH ~%suffix%~
PATCH_IF ( lng > 8 ) BEGIN SNPRINT 8 ~result~ ~%result%~ END
PATCH_IF ( lngs > 0 ) BEGIN
SET zzz = 8 - lngs
SNPRINT zzz ~result~ ~%result%~
SPRINT ~result~ ~%result%%suffix%~
END
END

DEFINE_ACTION_FUNCTION CREATE_B_BCS_NAME
STR_VAR
namez = ""
prefix = ""
suffix = ""
RET
result
BEGIN
OUTER_SPRINT ~result~ ~%prefix%%namez%~
OUTER_SET lng = STRING_LENGTH ~%result%~
OUTER_SET lngs = STRING_LENGTH ~%suffix%~
ACTION_IF ( lng > 8 ) BEGIN OUTER_SNPRINT 8 ~result~ ~%result%~ END
ACTION_IF ( lngs > 0 ) BEGIN
OUTER_SET zzz = 8 - lngs
OUTER_SNPRINT zzz ~result~ ~%result%~
OUTER_SPRINT ~result~ ~%result%%suffix%~
END
END

DEFINE_ACTION_FUNCTION repl_textscreen_2da
INT_VAR strr = "-1" rws = 2 nums = 3
STR_VAR file = ""
BEGIN
COPY_EXISTING ~%file%.2da~ ~override~
SET_2DA_ENTRY 1 ~%rws%~ ~%nums%~ ~%strr%~
PRETTY_PRINT_2DA
END

//BLOCK TO_HEX_NUMBER
DEFINE_ACTION_FUNCTION TO_HEX_NUMBER
INT_VAR
value = 0 // the decimal number
minDigits = 1 // min. number of digits in return value (not counting sign)
prefix = 0 // whether to return number with "0x" prefix
RET
hexNumber // returned as string without prefix
BEGIN
ACTION_IF (minDigits < 1) BEGIN OUTER_SET minDigits = 1 END
ACTION_IF (minDigits > 8) BEGIN OUTER_SET minDigits = 8 END
OUTER_TEXT_SPRINT hexNumber ~~
ACTION_DEFINE_ARRAY digit BEGIN ~0~ ~1~ ~2~ ~3~ ~4~ ~5~ ~6~ ~7~ ~8~ ~9~ ~a~ ~b~ ~c~ ~d~ ~e~ ~f~ END

ACTION_IF (value < 0) BEGIN
OUTER_SET signed = 1
OUTER_SET value = 0 - value
END ELSE BEGIN
OUTER_SET signed = 0
END

OUTER_WHILE (value != 0) BEGIN
OUTER_SET curDigit = value BAND 0xf
OUTER_SET value = value BLSR 4
OUTER_TEXT_SPRINT hexDigit $EVAL digit(~%curDigit%~)
OUTER_TEXT_SPRINT hexNumber ~%hexDigit%%hexNumber%~
END

OUTER_WHILE (STRING_LENGTH ~%hexNumber%~ < minDigits) BEGIN
OUTER_TEXT_SPRINT hexNumber ~0%hexNumber%~
END

ACTION_IF (prefix) BEGIN
OUTER_TEXT_SPRINT hexNumber ~0x%hexNumber%~
END

ACTION_IF (signed) BEGIN
OUTER_TEXT_SPRINT hexNumber ~-%hexNumber%~
END
END

DEFINE_PATCH_FUNCTION TO_HEX_NUMBER
INT_VAR
value = 0
minDigits = 1
prefix = 0
RET
hexNumber
BEGIN
INNER_ACTION BEGIN
LAF TO_HEX_NUMBER INT_VAR value = value minDigits = minDigits prefix = prefix RET hexNumber END
END
END
//BLOCKEND
/*DEFINE_ACTION_FUNCTION ADD_SPLPROT_ENTRY
STR_VAR
label = ~~ // optional entry label (value of first column)
definition = ~~ // definition without label
RET
index // returns -1 if entry could not be added
BEGIN
OUTER_SET index = "-1"
ACTION_IF (NOT ~%definition%~ STR_EQ ~~) BEGIN
COPY_EXISTING ~splprot.2da~ ~override~
COUNT_2DA_COLS numCols
PATCH_IF (numCols = 4) BEGIN
READ_2DA_ENTRIES_NOW table numCols
// use existing entry if available
FOR (row = 0; row < table; ++row) BEGIN
READ_2DA_ENTRY_FORMER table row 1 stat
PATCH_IF (~%stat%~ STRING_COMPARE_REGEXP ~[*+]~ = 0) BEGIN TEXT_SPRINT stat ~\%stat%~ END
READ_2DA_ENTRY_FORMER table row 2 value
PATCH_IF (~%value%~ STRING_COMPARE_REGEXP ~[*+]~ = 0) BEGIN TEXT_SPRINT value ~\%value%~ END
READ_2DA_ENTRY_FORMER table row 3 rel
PATCH_IF (~%rel%~ STRING_COMPARE_REGEXP ~[*+]~ = 0) BEGIN TEXT_SPRINT rel ~\%rel%~ END
TEXT_SPRINT regexp ~[ %TAB%]+%stat%[ %TAB%]+%value%[ %TAB%]+%rel%[ %TAB%]*~
PATCH_IF (~%definition%~ STRING_COMPARE_REGEXP ~%regexp%~ = 0) BEGIN
SET index = row
SET row = table
END
END

// add new definition if needed
PATCH_IF (index < 0) BEGIN
SET index = table
PATCH_IF (~%label%~ STR_EQ ~~) BEGIN TEXT_SPRINT label ~%index%~ END
PATCH_IF (STRING_LENGTH ~%label%~ < 11) BEGIN
TEXT_SPRINT label ~%label% ~
INNER_PATCH_SAVE label ~%label%~ BEGIN DELETE_BYTES 10 (BUFFER_LENGTH - 10) END
END
INSERT_2DA_ROW index numCols ~%label% %definition%~
END
END
BUT_ONLY IF_EXISTS
END
END*/
//BLOCK ADD_SPLPROT_ENTRY
DEFINE_ACTION_FUNCTION ADD_SPLPROT_ENTRY
INT_VAR
stat_hex = 1
value_hex = 0
STR_VAR
label = ~~
definition = ~~
RET
index
exists
label1
BEGIN
OUTER_SET index = "-1"
OUTER_SET exists = 0
ACTION_IF (NOT ~%definition%~ STR_EQ ~~) BEGIN
//extract definition
OUTER_SPRINT ~stat~ ~~
OUTER_SPRINT ~value~ ~~
OUTER_SPRINT ~rel~ ~~
OUTER_INNER_PATCH_SAVE definition ~%definition%~ BEGIN
REPLACE_TEXTUALLY ~[ %TAB%]~ ~*~
SET lng = BUFFER_LENGTH
SET true = 1
SET cmp = 0
FOR ( i = 0 ; i < lng ; ++i ) BEGIN
READ_ASCII i z (1)
PATCH_IF ( ~%z%~ STR_CMP ~*~ ) BEGIN
PATCH_IF ( true = 1 ) BEGIN
PATCH_MATCH cmp WITH
0 BEGIN SPRINT ~stat~ ~%stat%%z%~ END
1 BEGIN SPRINT ~value~ ~%value%%z%~ END
2 BEGIN SPRINT ~rel~ ~%rel%%z%~ END
DEFAULT
END
END ELSE BEGIN
SET true = 1
SET cmp = cmp + 1
PATCH_MATCH cmp WITH
0 BEGIN SPRINT ~stat~ ~%stat%%z%~ END
1 BEGIN SPRINT ~value~ ~%value%%z%~ END
2 BEGIN SPRINT ~rel~ ~%rel%%z%~ END
DEFAULT
END
END
END ELSE BEGIN
SET true = 0
END
END
END
OUTER_SET stat = ~%stat%~
OUTER_SET value = ~%value%~
OUTER_SET rel = ~%rel%~
COPY_EXISTING ~splprot.2da~ ~override~
COUNT_2DA_ROWS 4 table
//find existing entry
FOR ( i = 0 ; i < table ; ++i ) BEGIN
SET true = 0
READ_2DA_ENTRY i 0 4 label1
READ_2DA_ENTRY i 1 4 stat1
PATCH_IF ( IS_AN_INT ~stat1~ ) AND ( stat = stat1 ) BEGIN true = true + 1 END
READ_2DA_ENTRY i 2 4 value1
PATCH_IF ( IS_AN_INT ~value1~ ) AND ( value = value1 ) BEGIN true = true + 1 END
READ_2DA_ENTRY i 3 4 rel1
PATCH_IF ( IS_AN_INT ~rel1~ ) AND ( rel = rel1 ) BEGIN true = true + 1 END
PATCH_IF ( true = 3 ) BEGIN
SET index = i
SET exists = 1
SET i = table
TEXT_SPRINT ~label1~ ~%label1% %stat1% %value1% %rel1%~
END
END
//add_new_string
PATCH_IF ( index < 0 ) BEGIN
SET index = table
PATCH_IF (~%label%~ STR_EQ ~~) BEGIN TEXT_SPRINT label ~%index%~ END
PATCH_IF ( stat >= 0 ) AND ( stat_hex = 1 ) BEGIN
LPF TO_HEX_NUMBER INT_VAR value=stat minDigits=3 prefix=1 RET stat=hexNumber END
END
PATCH_IF ( value >= 0 ) AND ( value_hex = 1) BEGIN
LPF TO_HEX_NUMBER INT_VAR value=value prefix=1 RET value=hexNumber END
END
TEXT_SPRINT ~label1~ ~%label% %stat% %value% %rel%~
INSERT_2DA_ROW index 4 ~%label1%~
PRETTY_PRINT_2DA
END
BUT_ONLY_IF_IT_CHANGES
IF_EXISTS
END
END
//BLOCKEND

// Animation slots reserved by vanilla or mod-added game creatures (in hexadecimal format)
// Supported mods:
// - Bearwalker + extended Werebear animation
// - Pack Mule
<<<<<<<< .../inlined/creature/animation/slots.txt
"0410" "1000" "1003" "1004" "1100" "1101" "1102" "1103" "1104" "1105" "1200" "1201" "1202" "1203" "1204" "1205" "1206" "1207" "1208" "1300" "2000" "2100" "2200" "2300" "3000" "3001" "4000" "4001" "4002" "4010" "4012" "4100" "4101" "4102" "4110" "4112" "4200" "4300" "4400" "4410" "4500" "4600" "4700" "4710" "4800" "5000" "5001" "5002" "5003" "5010" "5011" "5012" "5013" "5100" "5101" "5102" "5103" "5110" "5111" "5112" "5113" "5200" "5201" "5202" "5210" "5211" "5212" "5300" "5301" "5302" "5303" "5310" "5311" "5312" "5313" "6000" "6001" "6002" "6003" "6004" "6005" "6010" "6011" "6012" "6013" "6014" "6015" "6100" "6101" "6102" "6103" "6104" "6105" "6110" "6111" "6112" "6113" "6114" "6115" "6200" "6201" "6202" "6204" "6205" "6210" "6211" "6212" "6214" "6215" "6300" "6301" "6302" "6303" "6304" "6305" "6310" "6311" "6312" "6313" "6314" "6315" "6400" "6401" "6402" "6403" "6404" "6405" "6406" "6500" "6510" "6621" "7000" "7001" "7100" "7101" "7200" "7201" "7202" "7203" "7300" "7301" "7302" "7310" "7311" "7312" "7313" "7314" "7320" "7321" "7400" "7401" "7402" "7500" "7501" "7600" "7601" "7602" "7603" "7604" "7700" "7701" "7702" "7703" "7800" "7801" "7802" "7900" "7901" "7902" "7903" "7904" "7a00" "7a01" "7a02" "7a03" "7a04" "7b00" "7b01" "7b02" "7b03" "7b04" "7b05" "7b06" "7c00" "7c01" "7d00" "7d01" "7d02" "7d03" "7d04" "7d05" "7d06" "7d07" "7d08" "7e00" "7e01" "7f00" "7f01" "7f02" "7f03" "7f04" "7f05" "7f06" "7f07" "7f08" "7f09" "7f0a" "7f0b" "7f0c" "7f0d" "7f0e" "7f0f" "7f10" "7f11" "7f12" "7f13" "7f14" "7f15" "7f16" "7f17" "7f18" "7f19" "7f20" "7f21" "7f22" "7f23" "7f24" "7f27" "7f28" "7f29" "7f2a" "7f2b" "7f2c" "7f2d" "7f2e" "7f2f" "7f30" "7f31" "7f32" "7f33" "7f34" "7f35" "7f36" "7f37" "7f38" "7f39" "7f3a" "7f3b" "7f3c" "7f3d" "7f3e" "7f3f" "7f40" "7f41" "7f42" "7f43" "7f44" "7f45" "7f46" "7f47" "7f48" "7f49" "7f4a" "7f4b" "7f4c" "7f4d" "7f4e" "7f4f" "7f50" "7f51" "7f52" "7f53" "7f54" "7f55" "7f56" "7f57" "7f58" "7f59" "7f5a" "7f5b" "7f5c" "7f5d" "7f5e" "7f5f" "7f60" "7f61" "7f62" "8000" "8100" "8200" "9000" "a000" "a100" "a200" "a201" "a202" "b000" "b100" "b200" "b210" "b300" "b310" "b400" "b410" "b500" "b510" "b600" "b610" "b700" "c000" "c100" "c200" "c300" "c400" "c500" "c600" "c610" "c700" "c710" "c800" "c810" "c900" "c910" "ca00" "ca10" "cb00" "cc00" "cc01" "cc02" "cc04" "d000" "d100" "d200" "d300" "d400" "e000" "e010" "e020" "e040" "e050" "e060" "e070" "e080" "e090" "e0a0" "e0b0" "e0c0" "e0d0" "e0e0" "e0f0" "e0f1" "e0f2" "e200" "e210" "e220" "e230" "e240" "e241" "e242" "e243" "e244" "e245" "e246" "e247" "e248" "e249" "e24a" "e24b" "e24c" "e24d" "e24e" "e24f" "e250" "e251" "e252" "e253" "e254" "e255" "e256" "e257" "e258" "e259" "e25a" "e25b" "e25c" "e25d" "e25e" "e25f" "e260" "e261" "e262" "e263" "e264" "e265" "e266" "e267" "e26a" "e26b" "e26d" "e26e" "e26f" "e270" "e271" "e272" "e273" "e274" "e276" "e279" "e27d" "e27e" "e27f" "e280" "e281" "e282" "e283" "e288" "e289" "e28a" "e28b" "e28c" "e28d" "e28e" "e28f" "e290" "e291" "e292" "e293" "e294" "e300" "e310" "e320" "e330" "e400" "e410" "e420" "e430" "e440" "e441" "e442" "e443" "e444" "e500" "e510" "e520" "e600" "e610" "e6fe" "e700" "e710" "e720" "e800" "e810" "e820" "e830" "e840" "e900" "e910" "ea00" "ea10" "ea20" "eb00" "eb10" "eb20" "ec00" "ec10" "ec20" "ed00" "ed10" "ed20" "ee00" "ee10" "ef10"
>>>>>>>>
OUTER_TEXT_SPRINT animationSlotsPath ".../inlined/creature/animation/slots.txt"

/** FREE_ANIM_SLOT
* Returns the first free creature animation slot in the range defined by slotMin and slotMax.
* INT_VAR slotMin Lowest available creature animation slot for the animation.
* INT_VAR slotMax Highest available creature animation slot for the animation.
* INT_VAR slotSteps How many slots to skip after each iteration, starting from slotMin.
* Setting this parameter is useful if compatible animation slots are always
* a fixed distance apart (e.g. at a distance of 0x10 each)
* RET slot A free animation slot. Returns -1 if none found.
*/
DEFINE_ACTION_FUNCTION FIND_FREE_ANIM_SLOT
INT_VAR
slotMin = 0
slotMax = (slotMin BAND 0xf000) + 0x1000
slotSteps = 1
RET
slot
BEGIN
OUTER_SET slot = "-1"
ACTION_IF (slotSteps < 1) BEGIN OUTER_SET slotSteps = 1 END
ACTION_IF (slotMin < 0) BEGIN OUTER_SET slotMin = 0 END
ACTION_IF (slotMax < 0) BEGIN OUTER_SET slotMax = 0 END
ACTION_IF (slotMax < slotMin) BEGIN
OUTER_SET tmp = slotMin
OUTER_SET slotMin = slotMax
OUTER_SET slotMax = tmp
END

// animslots.txt contains reserved creature animation slots
COPY - ~%animationSlotsPath%~ ~%animationSlotsPath%~
READ_ASCII 0 slotList (SOURCE_SIZE)
FOR (idx = slotMin; idx < slotMax; idx += slotSteps) BEGIN
LOOKUP_IDS_SYMBOL_OF_INT name ~animate~ idx
PATCH_IF (~%name%~ STRING_EQUAL ~%idx%~) BEGIN
LPF TO_HEX_NUMBER INT_VAR value = idx minDigits = 4 RET hexNumber END
PATCH_IF (NOT FILE_EXISTS_IN_GAME ~%hexNumber%.ini~ AND
~%slotList%~ STRING_CONTAINS_REGEXP ~"%hexNumber%"~ != 0) BEGIN
SET slot = idx
SET idx = slotMax
END
END
END
END

DEFINE_PATCH_FUNCTION FIND_FREE_ANIM_SLOT
INT_VAR
slotMin = 0
slotMax = (slotMin BAND 0xf000) + 0x1000
slotSteps = 1
RET
slot
BEGIN
INNER_ACTION BEGIN
LAF FIND_FREE_ANIM_SLOT INT_VAR slotMin = slotMin slotMax = slotMax slotSteps = slotSteps RET slot END
END
END

// Adds a new entry for a conversable item
DEFINE_PATCH_FUNCTION ADD_ITEM_DIALOG
INT_VAR
button_strref = 5689 // Default: "Converse"
name_strref = "-1" // not used outside of PSTEE
STR_VAR
itm_resref = ~~
dlg_resref = ~~
BEGIN
PATCH_IF (NOT ~%itm_resref%~ STR_EQ ~~) BEGIN
PATCH_IF (~%dlg_resref%~ STR_EQ ~~) BEGIN TEXT_SPRINT dlg_resref ~%itm_resref%~ END
COUNT_2DA_COLS numCols
COUNT_2DA_ROWS numCols numRows
TEXT_SPRINT entry ~%itm_resref% %button_strref% %dlg_resref%~
PATCH_IF (numCols > 3) BEGIN
TEXT_SPRINT entry ~%entry% %name_strref%~
FOR (idx = 4; idx < numCols; ++idx) BEGIN TEXT_SPRINT entry ~%entry% *~ END
END
INSERT_2DA_ROW numRows numCols ~%entry%~
END
END


//BLOCK REPLACE_MULTILINE
//Patch function that replaces set or all occurrences of the given regexp pattern in the file with the given string.
//Use EVAL to perform variable substitution on the string and/or the regexp pattern.
//Unlike REPLACE_TEXTUALLY the pattern can be multi-line text, even without using regexp.
//Just like REPLACE_BCS_BLOCK the function ignores pattern whitespace.
//The function can be also used as a COUNT_REGEXP_INSTANCES alternative with the above mentioned features.
//Optional PATCH_WARN message is printed if the task could not be performed (pattern not found or different amount of pattern matches than expected).

DEFINE_PATCH_FUNCTION REPLACE_MULTILINE
INT_VAR
num = "-1" //amount of times the pattern should be replaced with string (-1 by default which is at least 1 but without max limit)
strict = 0 //set to 1 to enable strict checking (auto escapes $^.*+?[]\ special characters)
verbose = 1 //set to 0 to skip printing patching message
warn = 1 //set to 0 to skip printing warning message if the function can't do what you ask it to do
only_count = 0 //set to to 1 to skip pattern replacing and just return num_matches (COUNT_REGEXP_INSTANCES alternative)
STR_VAR
pattern = "" //pattern that you want to replace
string = "" //string that the pattern will be replaced with
RET
num_matches //amount of times the pattern has been found
BEGIN
TEXT_SPRINT percent ~%~
INNER_PATCH_SAVE textToReplace ~%pattern%~ BEGIN
PATCH_IF strict = 1 BEGIN
REPLACE_TEXTUALLY ~\\~ ~\\\\~
REPLACE_TEXTUALLY ~\[~ ~\[~
REPLACE_TEXTUALLY ~\]~ ~\]~
REPLACE_EVALUATE ~\([\$\^\.\*\+\?]\)~ BEGIN END ~\%MATCH1%~
END
REPLACE_TEXTUALLY ~[%WNL%%LNL%%MNL%%TAB% ]+~ ~[%WNL%%LNL%%MNL%%TAB% ]+~
END
SET num_matches = 0
PATCH_IF only_count = 0 BEGIN
REPLACE_EVALUATE CASE_INSENSITIVE ~%textToReplace%~ BEGIN
SET num_matches = num_matches + 1
INNER_PATCH_SAVE string ~%string%~ BEGIN
REPLACE_TEXTUALLY ~%percent%MATCH\([0-9]+\)%percent%~ ~%MATCH\1%~
END
END ~%string%~
SET warned = 0
PATCH_IF num_matches != num BEGIN
PATCH_IF num_matches = 0 BEGIN
PATCH_IF warn = 1 BEGIN
PATCH_WARN ~WARNING %SOURCE_FILESPEC% - pattern not found:%LNL%%pattern%~
END
SET warned = 1
END ELSE PATCH_IF num >= 0 AND (num_matches > num OR num_matches < num) BEGIN
PATCH_IF warn = 1 BEGIN
PATCH_WARN ~WARNING %SOURCE_FILESPEC% - pattern replaced %num_matches% time(s) instead of %num%:%LNL%%pattern%~
END
SET warned = 1
END
END
PATCH_IF verbose = 1 AND warned = 0 BEGIN
PATCH_PRINT ~Patching %SOURCE_FILESPEC% - pattern replaced %num_matches% time(s):%LNL%%pattern% => %string%~
END
END ELSE BEGIN
COUNT_REGEXP_INSTANCES ~%textToReplace%~ num_matches
END
END
//BLOCKEND

/* GET_BIT */
DEFINE_PATCH_FUNCTION GET_BIT
INT_VAR
number = 0
nth_bit = 0
RET
bit_value
BEGIN
SET bit_value = (number >> nth_bit) & 1
END

/* GET_SCRIPT_BLOCK

* Returns the first available script block containing the specified search string (as regular expression).
* INT_VAR start_offset Optional offset where to start searching. (Default: 0)
* INT_VAR reverse Specify zero to apply a forward search, or non-zero to apply a backwards seearch from "start_offset". (Default: 0)
* STR_VAR search_regexp The search string as regular expression. Must be non-empty.
* RET script_block The full script block as string when found, empty string otherwise.
* RET start_offset Start offset of the script block when found, -1 otherwise.
* RET end_offset End offset (directly behind closing "END") of the script block when found, -1 otherwise.
*/
DEFINE_PATCH_FUNCTION GET_SCRIPT_BLOCK
INT_VAR
start_offset = 0
reverse = 0
STR_VAR
search_regexp = ~~
RET
script_block
start_offset
end_offset
BEGIN
SET offset = start_offset
PATCH_IF (offset < 0) BEGIN SET offset = 0 END
PATCH_IF (offset > BUFFER_LENGTH) BEGIN SET offset = BUFFER_LENGTH END

TEXT_SPRINT script_block ~~
SET start_offset = "-1"
SET end_offset = "-1"

PATCH_IF (NOT ~%search_regexp%~ STR_EQ ~~) BEGIN
PATCH_IF (reverse) BEGIN
SET offset = RINDEX_BUFFER(~%search_regexp%~ offset)
END ELSE BEGIN
SET offset = INDEX_BUFFER(~%search_regexp%~ offset)
END

PATCH_IF (offset >= 0) BEGIN
SET ofsStart = RINDEX_BUFFER(~^IF$~ offset)
PATCH_IF (ofsStart >= 0) BEGIN
SET ofsEnd = INDEX_BUFFER(~^END$~ offset)
PATCH_IF (ofsEnd >= 0) BEGIN
SET ofsEnd += 3
READ_ASCII ofsStart script_block (ofsEnd - ofsStart)
SET start_offset = ofsStart
SET end_offset = ofsEnd
END
END
END
END
END
Про ИНИ файлы чуть позже напишу. В спойлере functions.tph
Там еще есть некоторое количество макросов, которые делают очень полезные вещи. Все никак не собирусь отправить argent77 свой вариант патча splprot. Его вариант бобавляет копии, а не возвращает значение, если данная запись уже существует.
Изображение
Жираф большой - ему видней...

Gorion
Сообщения: 351
Зарегистрирован: 24 июн 2011, 00:54

Re: [ИНСТРУКЦИЯ] Как сделать мод "с нуля" самому

Сообщение Gorion »

wooder писал(а):
14 май 2020, 13:20
В веб-архиве есть версия от 19.12.2018г., не думаю, что после этого там что-то менялось.
Вот , только жалко картинки канули в лето. Кому интересно можете собрать мануал и перевести. Но все же кто захочет взяться обязательно отпишитесь сюда.
http://www.shsforums.net/topic/60392-te ... ia-update/
Я добавлял анимацию ИВДшных гоблинов в ЕЕ версии.
Тут вопрос , а с модом Infinity Animations ты не будешь взаимодействовать?

Аватара пользователя
Austin
Переводчик
Переводчик
Сообщения: 1077
Зарегистрирован: 19 май 2010, 19:50

Re: [ИНСТРУКЦИЯ] Как сделать мод "с нуля" самому

Сообщение Austin »

Перевел еще одну инструкцию от Kulyok по диалогам - о правильной установке времени срабатывания бантеров, с примерами кода и комментариями: https://arcanecoast.ru/publication/Kak_ ... ogo_hotite
https://arcanecoast.ru/mods - Список модов ArcaneCoast

Ответить