Перейти к контенту

[SoC] Ковыряемся в файлах


Halford

Рекомендуемые сообщения

Арбитр, плохо искал. В LW есть целый файл посвященный таймерам и называется он lwc_timer.script, принцип действия можно посмотреть в их же скриптах.

Также можно посмотреть, как в АМК сделана варка артов по рецептам, там как-раз используется таймеры.

Поделиться этим сообщением


Ссылка на сообщение

Driv3r, а что это за объект у тебя npc? Его ведь как-то определить нужно, либо уже в функцию передать...

И совет на будущее - не занимайся бестолковым копи-пастом.

Поделиться этим сообщением


Ссылка на сообщение

Возник вопрос.

В файле treasure_manager.ltx есть условия на выдачу тайника найденных на убиенных. Условие это задаётся в строке condlist, сами условия ясны как белый день, но вот что означает цифра после, я недоумеваю.

Пример такой строки:

condlist = {=npc_rank(veteran)} 2

Цифра означает сколько необходимо выполнить условие или же это некая вероятность, если так, то в каком отношенни она задаётся, поскольку значения больше 10 в оригинале нет.

Изменено пользователем ColR_iT

Поделиться этим сообщением


Ссылка на сообщение

Немного усидчивости и шевеления извилинами и вот он - алгоритм выдачи тайника в ТЧ.

Начну с лирики...

Лично мне не понятен смысл такой реализации, но в конечном итоге я хоть понял как эта реализация работает и надеюсь, что и вам как-то поможет...

Цифра в конце стоки condlist, в файле treasure_manager.ltx, задающая условие на выдачу тайника, не какая не вероятность и не колличество выполненых условий, как думал я, а это просто цифра, да-да именно цифра и ничего иначе.

По сути, в секциях самих тайников, описанных в файле указанном выше, заданно условие на выдачу, а именно строками condlist и community. Community задаёт группировки с которых можно снять тайник, а в condlist, задаётся условие: сначало следует... ну, назовём это - блок (фигурные скобки {}), затем эта злосчастная цифра, далее возможен ещё один или несколько блоков задающих уже другие условия, идущих через запятую. Пример:

condlist = {=npc_rank(novice) =actor_on_level(l01_escape)} 2, {=npc_rank(novice) =actor_on_level(l02_garbage)} 2

Всё что внутри блока расматривается как "and", т.е. должны выполниться все условия: и НПС должен быть новичок, и локация должна быть "Кордон", это что касается первого блока. Сами же блоки расцениваются как "or": либо этот блок, либо тот.

 

Теперь собственно, сам алгоритм выдачи...

Алгорит описан в файле treasure_manager.script, но вот до принципа его работы ещё нужно догадаться.

 

Для большей наглядности картины, рекомендую открыть файлы treasure_manager.ltx и treasure_manager.script , дабы воочию наблюдать ход событий.

Неже в скобках будут указаны строки, для быстрой навигации по файлу treasure_manager.script

 

При обыске трупа вызывается метод use класса CTreasure (93). Метод считывает все параметры убиенного и сравнивает их с параметрами community и condlist, которые уже инициализированы в конструкторе класса (66 и 77 соответственно). В методе есть оператор for (98), который обрабатывает таблицу treasure_info (54), по элементам которой и происходит сравнение.

При переборе этих элементов, загадочная цифра в конце блока condlist, присваивается переменной treasure_prob (100), при условии, что НПС подходит по заданным условиям, если же условия не выполнились, то присваивается 0. Затем идёт сравнение - равно ли её значение стам:

if tonumber(treasure_prob) == 100 then

Отсюда, вытекает два вывода:

1. Данная проверка всегда в оригинале вернёт false, т.к. значения цифры больше 10 просто нет.

2. Если в condlist поставить число 100 после блока, то такой тайник будет выдан в обязательном порядке, с тем требованием, что условие в блоке выполнились и группировка НПС совпала с community и дальнейшего вычисления не произойдёт.

Как я написал выше, значение переменной treasure_prob, в оригинале, всегда будет меньше 100 и даже меньше 11, поэтому мы переходим дальше.

 

А дальше и начинается то самае шаманство, которое определяет выдавать нам тайник или нет.

В таблицу avail (113) заносятся данные для каждого тайника подходящего под условия нашего обыскиваемого НПС. Т.е. если condlist вернул true и группировка, та что нужно. Данные заносятся не все, а только имя секции тайника (k) указывается в квадратных скобках в файле treasure_manager.ltx и treasure_prob для этого тайника, т.е. наша непонятная цифра, в таблицу она заносится как prob. По большому счёту, эта таблица хранит в себе имена тех тайников, из которых будет производится выбор, какой именно тайник выдавать.

Далее переменной tr_sum присваивается значение treasure_prob (114) и поскольку всё это происходит в цикле, то данная переменная хранит в себе сумму всех значений treasure_prob для тайников подходящих под условия (нужный НПС, нужное место).

 

Если вы не поняли последнее предложение прочтите его ещё раз и так до тех пор пока не поймёте, потому как это ключевой момент!

 

Дальше, проверка на равенство (120) переменной tr_sum и ноля (такое произойдёт, если за блоком condilst будет стоять значение 100), а также проверяется вернула ли функция math.random значение меньше 65 или нет... вчитайтесь внимательно - функция math.random.

Если что-то одно вернёт true, то тайник выдан не будет.

 

Затем определяется какой именно тайник будет выдан.

Переменной tr_w присваивается случайной число (126) в диапазоне от 1 до значения переменной tr_sum, которая в свою очередь хранит сумму цифр в condlist, тех тайников, которые прошли отбор по community и condlist.

Потом происходит перебор элементов таблицы avail (127), где:

Переменная tr_w уменьшается на значение prob каждого элемента массива. Так происходит до тех пор пока данная переменная не станет отрицательной, как только это произошло, выдаётся тайник, чей prob был вычтен последним.

Всё.

 

Выводы...

Цифра в строке condlist не какая на хрен не вероятность, а просто цифра, и каково её значение особой роли не играет. Вообще GSC вероятно немного не правильно распределили эти цифры, в алгоритме просматривается процентные соотношения, но высчитать их, зная что работает функция random физически не реально.

Можно заметить, что в алгоритме две вероятности: первая определяет будет ли выдан нам тайник вообще (121), вторая определят какай именно тайник будет выдан (126), но опять же таки, просчитать какой именно - крайне трудно, а то и вообще невозможно. Так что, если хотите, чтобы тайники выдавались чаще, измените число 65 в строке 121 на меньшее.

Надеюсь, что эта писанина внесёт хоть кому-нибудь, какую-то ясность в работе данного алгоритма.

Спасибо за внимание.

Поделиться этим сообщением


Ссылка на сообщение

Artos

Моя первостепенная задача была выяснить, что за число в condlist и на кой ляд оно вообще нужно. И я выяснил...

По ходу итерации по таблице treasure_info, где проверялись условия condlist и community, переменная tr_sum хранит в себе сумму treasure_prob всех тайников прошедших валидность по условиям, а treasure_prob это и есть "наша" цифра.

А также в таблицу avail заносятся все тайник у которых подошёл community. Если подошёл и condlist, то prob равняется treasure_prob, иначе 0. Зачем было так без смысленно забивать таблицу, мне не понятно, но ...

В конце-концов таблица avail, при обыске трупа с которого я получил тайник, выглядит следующим образом:

avail = {
{k=esc_secret_anomaly_dead, prob=2},
{k=esc_secret_bandit_cross, prob=5},
{k=esc_secret_nice_place, prob=3},
{k=esc_secret_safe_farm, prob=2},
{k=gar_secret_box_blockpost, prob=3},
{k=esc_secret_village_rucksack, prob=3},
{k=val_secret_0008, prob=1},
{k=gar_secret_bandit_hiding, prob=3},
{k=esc_secret_kpp_tower, prob=2}
}

Все тайники с prob равным 0, я отсёк условием:

if treasure_prob ~= 0 then

ещё на этапе создания этой таблицы, поскольку таковые значения абсолютно ни на что не влияют.

Без такового условия, данная таблица имела бы следующий вид, т.е. по сути то, как она выглядет в оригинале:

avail = {
{k=esc_secret_anomaly_dead, prob=2},
{k=bar_secret_0010, prob=0},
{k=gar_secret_concrete_blocks, prob=0},
{k=val_secret_0026, prob=0},
{k=ros_secret_0011, prob=0},
{k=ros_secret_0006, prob=0},
{k=bar_secret_0002, prob=0},
{k=mil_secret_0028, prob=0},
{k=mil_secret_0012, prob=0},
{k=rad_secret_0004, prob=0},
{k=val_secret_0023, prob=0},
{k=val_secret_0022, prob=0},
{k=bar_secret_0006, prob=0},
{k=agr_secret_inventory_schlosser, prob=0},
{k=agr_secret_box_institute, prob=0},
{k=esc_secret_bandit_cross, prob=5},
{k=esc_secret_nice_place, prob=3},
{k=bar_secret_0005, prob=0},
{k=rad_secret_0002, prob=0},
{k=mil_secret_0000, prob=0},
{k=rad_secret_0000, prob=0},
{k=yan_secret_0000, prob=0},
{k=bar_secret_0007, prob=0},
{k=agr_secret_sewers, prob=0},
{k=ros_secret_0022, prob=0},
{k=agr_secret_rotted_log, prob=0},
{k=ros_secret_0020, prob=0},
{k=val_secret_0004, prob=0},
{k=val_secret_0017, prob=0},
{k=ros_secret_0015, prob=0},
{k=ros_secret_0021, prob=0},
{k=esc_secret_safe_farm, prob=2},
{k=gar_secret_metal_hiding, prob=0},
{k=mil_secret_0009, prob=0},
{k=agru_secret_mole_cave, prob=0},
{k=agr_secret_safe_bush, prob=0},
{k=val_secret_0005, prob=0},
{k=mil_secret_0004, prob=0},
{k=agr_secret_box_radiation, prob=0},
{k=yan_secret_0010, prob=0},
{k=val_secret_0003, prob=0},
{k=mil_secret_0003, prob=0},
{k=gar_secret_bus_rucksack, prob=0},
{k=yan_secret_0013, prob=0},
{k=mil_secret_0016, prob=0},
{k=gar_secret_bus_tube, prob=0},
{k=yan_secret_0012, prob=0},
{k=yan_secret_0011, prob=0},
{k=yan_secret_0009, prob=0},
{k=yan_secret_0008, prob=0},
{k=gar_secret_rucksack_noones, prob=0},
{k=yan_secret_0007, prob=0},
{k=bar_secret_0001, prob=0},
{k=yan_secret_0006, prob=0},
{k=bar_secret_0014, prob=0},
{k=gar_secret_south_safe, prob=0},
{k=yan_secret_0005, prob=0},
{k=esc_secret_refuge, prob=0},
{k=yan_secret_0004, prob=0},
{k=yan_secret_0003, prob=0},
{k=gar_secret_box_blockpost, prob=3},
{k=esc_secret_village_rucksack, prob=3},
{k=yan_secret_0002, prob=0},
{k=gar_secret_escavator, prob=0},
{k=yan_secret_0001, prob=0},
{k=rad_secret_0005, prob=0},
{k=agr_secret_agrosafe, prob=0},
{k=val_secret_0032, prob=0},
{k=gar_secret_north_tube, prob=0},
{k=pri_secret_0002, prob=0},
{k=gar_secret_east_tube, prob=0},
{k=bar_secret_0018, prob=0},
{k=agr_secret_cross, prob=0},
{k=bar_secret_0004, prob=0},
{k=val_secret_0025, prob=0},
{k=rad_secret_0003, prob=0},
{k=val_secret_0021, prob=0},
{k=val_secret_0015, prob=0},
{k=agru_secret_box_bloodsucker, prob=0},
{k=agr_secret_rucksack_window, prob=0},
{k=val_secret_0010, prob=0},
{k=agr_secret_safe_wall, prob=0},
{k=ros_secret_0016, prob=0},
{k=val_secret_0008, prob=1},
{k=x16_secret_0001, prob=0},
{k=val_secret_0006, prob=0},
{k=val_secret_0002, prob=0},
{k=pri_secret_0000, prob=0},
{k=agru_secret_bandit_obschak, prob=0},
{k=val_secret_0000, prob=0},
{k=bar_secret_0017, prob=0},
{k=gar_secret_bandit_hiding, prob=3},
{k=gar_secret_cistern_pipe, prob=0},
{k=ros_secret_0000, prob=0},
{k=bar_secret_0012, prob=0},
{k=mil_secret_0014, prob=0},
{k=gar_secret_forest_log, prob=0},
{k=mil_secret_0002, prob=0},
{k=mil_secret_0015, prob=0},
{k=ros_secret_0002, prob=0},
{k=ros_secret_0013, prob=0},
{k=agr_secret_roof_box, prob=0},
{k=bar_secret_0015, prob=0},
{k=ros_secret_0012, prob=0},
{k=x16_secret_0000, prob=0},
{k=ros_secret_0008, prob=0},
{k=agr_secret_safe_tree, prob=0},
{k=ros_secret_0007, prob=0},
{k=ros_secret_0009, prob=0},
{k=esc_secret_kpp_tower, prob=2},
{k=ros_secret_0001, prob=0},
{k=val_secret_0024, prob=0},
{k=bar_secret_0011, prob=0},
{k=rad_secret_0001, prob=0},
{k=agr_secret_gray, prob=0},
{k=mil_secret_0013, prob=0},
{k=agr_secret_box_stairs, prob=0},
{k=val_secret_0027, prob=0},
{k=pri_secret_0001, prob=0},
{k=val_secret_0001, prob=0},
{k=mil_secret_0005, prob=0},
{k=val_secret_0011, prob=0},
{k=pri_secret_0003, prob=0},
{k=bar_secret_0016, prob=0},
{k=mil_secret_0018, prob=0},
{k=bar_secret_0009, prob=0},
{k=ros_secret_0003, prob=0},
{k=gar_secret_car_hiding, prob=0},
{k=ros_secret_0017, prob=0},
{k=esc_secret_thief, prob=0},
{k=mil_secret_0017, prob=0},
{k=pri_secret_0004, prob=0},
{k=mil_secret_0007, prob=0},
{k=bar_secret_0000, prob=0},
{k=gar_secret_rotted_stump, prob=0},
{k=mil_secret_0011, prob=0},
{k=agr_secret_rucksack_laketube, prob=0},
{k=agr_secret_pipe_rucksack, prob=0},
{k=agr_secret_tree_rucksack, prob=0},
{k=mil_secret_0008, prob=0},
{k=mil_secret_0010, prob=0},
{k=gar_secret_avoska, prob=0},
{k=bar_secret_0008, prob=0},
{k=mil_secret_0001, prob=0},
{k=mil_secret_0006, prob=0},
{k=agr_secret_truck, prob=0},
{k=bar_secret_0003, prob=0},
{k=bar_secret_0019, prob=0},
{k=gar_secret_rucksack_ruins, prob=0},
{k=val_secret_0007, prob=0},
{k=agr_secret_box_zavhoz, prob=0},
{k=agr_secret_rucksack_blue, prob=0},
{k=ros_secret_0023, prob=0}
}

Как можно заметить она существенно больше...

Причем таковая таблица, для одинаковых по рангу и группировке НПС, формируется идеинтичная, причем в непонятном для меня порядке, почему перебор идёт не в том порядке, в котором тайники прописаны в treasure_manager.ltx?

 

Дальше, у нас идёт условие выдачи тайника впринципе:

if tr_sum == 0 or
    math.random(100) < 65
then
    return
end

Как видно, тайник действительно выдастся с вероятностью 35%.

А вот далее идёт выбор самого тайника:

1:local tr_w = math.random(tr_sum)
2:for k,v in pairs(avail) do
3:      tr_w = tr_w - v.prob
4:      if tr_w <= 0 then
5:          --' Выдать тайник
6:          self:give_treasure(v.k)
7:          break
8:      end
9:end

Первая строчка данного кусочка кода, записывает в переменную tr_w случайное число от 1 до значения переменной tr_sum, которая, в свою очередь, хранит в себе сумму treasure_prob всех тайников прошедших валидность, или можно сказать, что tr_sum равна сумме всех prob, из таблице avail, это одно и тоже.

Затем ещё один цикл, в котором переменная tr_w уменьшается на значение prob, каждого тайника из таблицы. Как только эта переменная становиться отрицательной, то выдаём тайнкци с именем k, чей prob оказался последним (строки 4,6 приведённого "кусочка").

 

"Весовой эквивалент" - да, возможно так и есть. Поскольку таблица avail формируется одинаковая для одной и той же группировки, то впринципе, можно вычислить и процентное соотношение данного числа, естественно, что в разных случаях (ранг НПС, локация на которой мы сейчас) это соотношение будет разным, поэтому задать одинаковую вероятность для нескольких, вроде как, подходящих НПС, заранее неполучится...

Поделиться этим сообщением


Ссылка на сообщение
Wookie, в теме "Справочник по функциям и классам" есть подробное описание скриптовой составляющей диалогов, в том числе в третьей части рассказывается и о расстоянии на котором можно открыть диалоговое окно: "Диалоги. Часть 3"

Поделиться этим сообщением


Ссылка на сообщение

Касательно первого пункта из вопросов MIDERY.

Ребята, всё намного проще. Инфопоршень который стоит в качестве проверки:

<dont_has_info>escape_volk_ак74u_done</dont_has_info>

и инфопоршень который выдаётся:

<give_info>escape_volk_ak74u_done</give_info>

просто напросто разные. В первом случае буквосочетание "ак" написано кириллицей и только.

 

Artos

Чтобы диалог не появлялся нужно чтобы стояла общая проверка (прекондишен) для диалога, а не в самм диалоге. Это или в скриптах или в логике НПС делается.
Вовсе не обязательно. Тег <precondition> используется для проверки функции, MIDERY же в своём диалоге использовал наличие одного инфопоршня и отсутствие другого, в качестве условия появления диалога в целом.

 

gruber, а о каком собственно лимите идёт речь?

Изменено пользователем ColR_iT

Поделиться этим сообщением


Ссылка на сообщение
gruber, а можно по подробнее об этом, поскольку мне казалось, что ограничения как такового нет, а инфопоршни читаются при каждой загрузке игры. Изменено пользователем ColR_iT

Поделиться этим сообщением


Ссылка на сообщение
CON, для ГГ что ли? Ответ прост, как и сам вопрос: в all.spawn убрать из секции спавна актора строку device_torch.

Поделиться этим сообщением


Ссылка на сообщение

CON, конечно можно - скриптом. Приблизительно вот так:

local obj_torch = db.actor:object("device_torch")
if obj_torch then
    db.actor:drop_item(obj_torch)
end

Я выбросил предмет, можешь его удалить в последствии.

 

SWoBoDoWeTH, загляни в шапку этой темы:"The new weapon and its addition in S.T.A.L.K.E.R", там есть ответ на твой вопрос.

Поделиться этим сообщением


Ссылка на сообщение

MIDERY.

Найди отдельно для себя: проверка на поднятие предмета и вывод сообщения (собственно это у тебя есть), и посмотри как это сделано в принципе.

P.S. Извини, если обидно прозвучит, но по моему ты пытаешься прыгать выше головы...

Поделиться этим сообщением


Ссылка на сообщение

Boofer, спавн происходит далее через скрипт, т.е. с использованием переменных lvid, gvid и pos или руками вписываешь?

Если руками и уверен в правильности скрипта, то делай выводы...

Поделиться этим сообщением


Ссылка на сообщение
Artos, почему именно нет пакеты? Ведь есть методы
function turn_on();
function turn_off();

для класса hanging_lamp. Это рудимент?

Поделиться этим сообщением


Ссылка на сообщение

Nic101

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

А теперь по твоему посту:

Файла release_body_manager.script в игре просто не существует, не по тому, что ты неправильно написал расширение файла, а потому, что разработчики просто такового не создавали. Поэтому и комментировать в файле xr_motivator.script, будет нечего, и открывать собственно также нечего.

Всё бы ничего, но ты не ошибся, т.е. решение действительно рабочее. Но вот есть одна большая проблема: ты не в изначальном вопросе, не в посте выше не указал версию игры, хотя пишешь ты в тему по ковырянию ТЧ (Тень Чернобыля), а не в тему по Зову Припяти, где твой ответ будет актуальным и то с некоторыми оговорками.

Итого:

1. Правильно выбирай тему;

2. Правильно задавай вопрос;

3. Нашёл решение - поделись, а не бросайся полученными знаниями;

4. И пиши, пожалуйста, грамотнее.

Спасибо за понимание.

Изменено пользователем ColR_iT

Поделиться этим сообщением


Ссылка на сообщение

MIDERY

Во-первых, из рестриктора можно вызывать и функцию напрямую, но она должна быть в файле xr_effects.script, вот так:

on_actor_inside = %=tester%

И функцию измени, чтобы не принимала никаких аргументов, вот так:

function tester()
    news_manager.send_tip(db.actor, "%c[255,255,128,128]Блаблабла:\n%c[default]Проверка", nil, nil, 30000)
end

Во-вторых, ты темой ошибся.

Поделиться этим сообщением


Ссылка на сообщение
Сообщение от модератора ColR_iT
Ребята, перемещаемся с вопросами о косяках моделей, костях, конвертации из одного формата в другой, в соответствующие темы.

Поделиться этим сообщением


Ссылка на сообщение

Вольт

В файле esc_trader_door.ltx замени вторую строчку на вот эту:

active = ph_door@closed

Поделиться этим сообщением


Ссылка на сообщение

fzz

Ох, ну и следопыт же ты.

Десять раз говоришь искал!? А что именно ты искал?

2.jpeg 1.jpeg

 

 

Поделиться этим сообщением


Ссылка на сообщение

FANAT

Универсальные гулаги (general_lager).

По своей сути это вид гулага, который задаёт все значения для схем по умолчанию. А работы распределяет исходя из наличия путей на уровне, где находится таковой гулаг. Т.е. он автоматически соберет все точки путей на уровне начинающиеся на имя смарта и "парсит" их названия следующим образом: (имя смарта)_(схема)_(номер схемы)_(поднастройка схемы)_(состояние гулага). И компонует всё это дело в работы. Работой будет по сути путь вида esc_gen_lager_walker_1_walk_1 и esc_gen_lager_walker_1_look_1, здесь:

esc_gen_lager - имя смарта;

walker - схема;

1 - номер схемы. Если нужно например, несколько однотипных схем, то просто задаём несколько номеров;

walk - поднастройка схемы, т.е. что именно это за точка;

1 - состояние гулага. 1 - день, 0 - ночь.

С одной стороны всё это упрощает создание гулага, с другой же ИМХО наоборот. Но тут уже кому как.

-------------

tonloon

Как раз таки дело в "параметрах этих ogg файликов". Комментариям для звуковых файлов в игре отведена отдельная роль, при помощи них, НПС адекватно будут реагировать на звуки. Звуки нужно прогонять через СДК, только тогда из консоли исчезнут надписи Missing ogg-comment. Собственно эта надпись сама за себя говорит, что не правильные комментарии в файле.

Изменено пользователем ColR_iT

Поделиться этим сообщением


Ссылка на сообщение

wikreznowНа самом деле всё гораздо проще.

... fixed_bones = link - где link имя кости, которую фиксируешь. Для оружия это может быть wpn_body ...
Вместо link нужно вписывать любую кость, которая есть у объекта, который ты спавнишь, именно за эту кость будет зафиксирован предмет. Для оружия это wpn_body, например, для ведра это может быть bone01 и т.д. Посмотреть наличие и название костей можно в SDK в Actor Editore.

Как нанести предмету хит можно посмотреть вот в этом посте: Наносим хит предмету (третий спойлер снизу).

Почитать о классе hit можно вот здесь: hit (спойлер с именем "Далее").

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...