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

Внимание. На форуме проводятся технические работы с боковым меню.

_Val_ _Val_

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

Тема для обсуждения скриптов всего и всех в серии игр STALKER.


Задавая вопрос (!):
1. Внимательно изучите суть вопроса. Вопрос должен соответствовать выбранной Вами темы. Это поможет сохранить порядок и читабельность темы, а также облегчит поиск и понимание сего;
2. Изучите то, что уже есть в теме (пролистайте "руками", воспользуйтесь поиском на форуме);
3. Изучите информацию которая может вам помочь:

 
 

Stalkerin. Там есть много хороших статей касательно данной темы.
Уроки по модостроению. Есть рабочие примеры готовых скриптов различного назначения.

 

Справочное руководство по языку Lua 5.1
https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual/ru
Справочник по функциям и классам. Собрано много информации по функциям и классам, не всем, но по основные сведения предоставлены.

4. Дабы не превращать обсуждение в "кашу" разной информативной направленности, задавайте несколько вопросов по порядку (в разных постах) после того, как получите ответ на предыдущий вопрос;
5. "Спасибо" и тому подобное - будьте так любезны в ПМ. Если не любите писать в ПМ, в конце вопроса напишите фразу: "Заранее спасибо!" - или что-то в этом духе;
6. ПОЖАЛУЙСТА! Указывайте, для какой игры Вам необходима информация (ТЧ, ЧН, ЗП), если стоит мод - укажите название мода;
7. Если Вы что-то сделали и результат не такой, какой Вами задумывался, то, пожалуйста, приводите коды которые Вы изменяли/писали целиком! Это поможет другим правильно ответить на Ваш вопрос, а также оградит Вас от лишней писанины.
8. Оформляйте сообщение. Пользуйтесь тегами для того, чтобы отделить код от текста. Пишите грамотно - ПОЛЬЗУЙТЕСЬ ЗНАКАМИ ПРЕПИНАНИЯ.
9. И помните: «Правильно заданный вопрос – половина ответа».

 

Какие вопросы следует задавать, а какие нет...

 

Задавайте вопросы, которые касаются непосредственно скриптов и их работы, т.е. Вы что-то делаете, а у Вас что-то не получается, при этом у Вас на руках должен быть хотя бы какой-то код, свидетельствующий о Вашей причастности к вопросу.

 

Вопросы которые будут удалятся, следовательно их задавать не нужно:
-- Где находится та или иная функция?
Для ответа используем поиск по словам среди файлов оригинальной игры или мода, если объект поиска относится к нему, при помощью программы, которая Вам наиболее симпатизирует;
-- Как сделать что-то/то-то?
С подобными вопросами, либо в "ковырялки", где Вам вероятнее всего так же не ответят, либо выдвигаем мысли, подкреплённые теорией, практикой (идеальный вариант) и здравым рассудком;
-- Вопросы со смыслом: "сделайте", "совместите" и подобными глаголами повелительного наклонения.
-- К тому же удалению будут подвергаться вопросы, в которых масштабно не используются теги, для отделения кода и цитат от основного текста, а также не вписан в спойлер код размером превышающие семь строк.
Ответ на возможно возникший вопрос: В какую тему можно обратиться по поводу логики и спавна объектов?
В тему "ковырялок" соответствующей версии игры, для которой Вы задаёте вопрос.

И последнее: очень рекомендовано к прочтению Правила форума
 


  • Спасибо 1
  • Полезно 2
Ссылка на комментарий
https://www.amk-team.ru/forum/topic/6185-skriptovanie/
  • Неравнодушный сталкер

Всем доброго. Есть сильные в регулярках? Вычищаю скрипты в ЧН, есть  две функции
 

Скрытый текст
function parse_names( s )
		local t = {}
		for name in string.gfind( s, "([%w_\\]+)%p*" ) do
				table.insert( t, name )
		end

		return t
end

 

 

Скрытый текст
function parse_names(s)
		local t = {}
		for name in string.gfind( s, "([%w_%-.\\]+)%p*" ) do
				table.insert( t, name )
		end
		return t
end

 

 

Делаю насколько я понял одно и тоже, вопрос собственно в том можно ли первую функцию 1 безопасно заменить на функцию 2 (или наоборот)?

Вернулся получается...

@vampirnik77 вторая универсальнее, не делит строчку по тире и точкам (для всяких патронов нужно). Надо смотреть, где используется первая функция, нужно ли там такое разделение.

  • Спасибо 1

Доброго времени суток. Есть ещё пара вопросов - первый, не знаю насчёт реализации(возможно ли это) , нужно сделать музыку в виде клипа - т.е. Подходишь к приёмнику например(База долга или Сталкеров НИИ), на определённую дистанцию и появляется изображение(проще говоря клип). Отходишь и он исчезает, но звук остаётся. Это движок вообще сможет сделать ? И второй: "До выброса осталось NN минут"". Таймер на ПДА, в ближайшей точке схрона от него же. Которая синхронно перемещается с ГГ, до ближайшего убежища. Хотелось бы вывести на экран это время, ибо какой от него толк в ПДА. Ну не бегать же по локации не видя куда, зная сколько осталось времени. 

Безглючная работа компа и модов, зависит от присутствия у юзера драйверов mozgi.sys и pryami_hands.vxd.

 

Всех приветствую! Нужна помощь. Имеется движок OGSR 2.1.417. В нём я включил функцию для включения отключенных + новых слотов(самое главное, слот противогаза). Мне необходимо сделать так,чтобы при нажатии клавиши ПНВ, скрипт проверил, есть ли в слоте шлем с секцией ПНВ, если есть то включить его. Заранее благодарю.

Помогите с функцией. Пытаюсь вернуть часть денег Актору, но функция срабатывает с 2 раза.... почему?

сама функция

local actor_last_money = 0

function round(amount)
    return math_floor(amount + 0.5)
end

function on_trade(item, sell_bye, money)
    local money = db.actor:money()
    local cashback = round((actor_last_money - money) * 0.3)
    if cashback < 1 then
    actor_last_money = money
    return
end

    db.actor:give_money(cashback)
    local news_text = gts(tostring(cashback))
    local msg = "\\n"..gts("general_in_money").." "..news_text
    local money_texture, money_ico = get_texture_info("ui_coal_air_iconstotal_money_in")
    db.actor:give_game_news(msg, money_texture, money_ico, 0, 3000)
end

 

Изменено пользователем Colder
3 часа назад, Colder сказал:

почему?

Потому что при первом вызове actor_last_money = 0, а это значит, что разность actor_last_money - money имеет отрицательное значение, которое меньше единицы, из-за чего и следует выход из функции. А вот при втором вызове actor_last_money имеет уже не нулевой показатель и, вероятно, больше значения money, так что условие выхода не срабатывает.
Но вообще здесь вся логика неправильная какая-то. Учитывая, что функция on_trade вызывается при торговле столько раз, сколько всего продаётся/покупается предметов, кешбэк будет перечисляться при каждом вызове нарастающим итогом, при этом будет зависеть не от цены продажи конкретного примера, а исключительно от наличности в кармане актора (идёт подмена входящего параметра money вычисляемым).

Также мне кажется, что кешбэк имеет смысл начислять актору только при покупке, то есть при входящем параметре sell_bye = false.

Резюмируя всё вышесказанное, я сделал бы просто: вместо

function on_trade(item, sell_bye, money)
  local money = db.actor:money()
  local cashback = round((actor_last_money - money) * 0.3)
  if cashback < 1 then
    actor_last_money = money
    return
  end
  db.actor:give_money(cashback)
  -- всё остальное
end

написал что-то вроде такого

function on_trade(item, sell_bye, money)
  if sell_bye == false then
    local cashback = round(money * 0.3) -- здесь 0.3 - 30% кешбэка от потраченной на приобретение предмета суммы
    db.actor:give_money(cashback)
    -- всё остальное
  end
end

 

  • Спасибо 1

Свои работы и совместные проекты: Инструмент, OGSM CS, Final Stroke, HARDWARMOD

Полезное: модули Артоса, XML парсер

Подскажите как отследить что ГГ получил хит от аномалии(любой). Искал на форуме, но к сожалению не нашёл. 

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

@Colder Попробуй в bind_stalker добавить hit callback, и в нём уже проверять clsid нанёсшего хит. Если clsid совпадает с clsid аномалии(примерный список приведу ниже), то урон нанесён ею.

 

Список классов(приблизительно)

anoms_classes = {
    [clsid.zone_buzz_s] = true,
    [clsid.zone_bfuzz_s] = true,
    [clsid.zone_electra_s] = true,
    [clsid.zone_galant_s] = true,
    [clsid.zone_ice_s] = true,
    [clsid.zone_mbald_s] = true,
    [clsid.zone_mincer_s] = true,
    [clsid.zone_zharka_s] = true,
    [clsid.zone_radioactive] = true,
    [clsid.zone_radioactive_s] = true
}

 

Реализация в ОП 2.2

if who and amk_anoms.is_anomaly(who:clsid()) then -- Оказывается, актор погиб от аномалии.
        set_death_count("anoms", get_death_count("anoms")+1) -- Некие действия.
end

Код из файла scripts\archievements.script -> on_actor_death.

Правда, это вызывается на смерть актора, но по идее с хитом должна быть схожая история.

 

  • Спасибо 1
  • Полезно 1

Жить стало лучше, жить стало веселей. А когда веселей живётся, то работа скорится.

img.php?nick=Balavnik&sert=2&text=t6

Всем привет. Имеется такая функция(список группировок) в GUI окне:

Заголовок спойлера (редактируемый)

local loadout_cost = {
    "st_loadout_1",
    "st_loadout_2",
    "st_loadout_3",
    "st_loadout_4",
    "st_loadout_5"
}

 

function ui_mm_faction_select:FillList()
    local add = nil
    for k,v in pairs(loadout_cost) do
    add = ui_mm_faction_list()

    local item_text = gts(v)
    add.item_name:SetText(item_text)
    add.item_count:SetText(k)

    if add and self.st_items_list then
    self.st_items_list:AddItem(add)
end
end
end

 

function ui_mm_faction_select:OnListItemClicked()
    local list_box = self:GetListWnd("list_window")
    if list_box:GetSize() == 0 then return end
    local itm_index = list_box:GetSelectedItem()
    local item = list_box:GetItem(itm_index)
    if item == nil then return end

---------------------------------------- >> здесь

    self.descr:SetText(gts("st_ui_tool"))
end
end

 

Как по клику из списка узнать, что была выбрана, например 4?

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

Уважаемые коллеги, товарищи, все здравствуйте!

Отдельная большая благодарность за одобрение моей регистрации с немного странным, мягко-говоря email (думаю тот, кто одобрил, точно увидит  ). Основная причина, но не единственная, регистрации - это некоторые вопросы о правках скриптов в ОП 2.2. 

Точнее говоря вопрос один, подскажите, пожалуйста, как сделать условный "честный" рандом для групп предметов, которые выдаются в качестве наград по цикличкам? Имею ввиду группы предметов "обычные патроны" "ствол", "пистолетные патроны" и т.д. Под "честным" рандомом имею ввиду разную награду при перезагрузке (да это не честно, простите).

Я нашел предположительное место выдачи награды, но уперся в непонимание работы текущего рандома. Если все правильно нашел, то за выдачу случайной награды по группам предметов отвечает функция function CCycleTask:task_reward(vendor, actor, p1, p2) из файла \scripts\cycle_task.script, а именно секция:

-' Рандомные предметы
            if self.task_ini:line_exist(task_id, "reward_random") then
                local reward_random = string.key_value_num(self.task_ini:r_string(task_id, "reward_random"))
                for kk,vv in pairs(reward_random) do
                    for ii = 1,vv do
                        got(self:get_random_item(kk,task_desc.vendor),1)
                    end
                end
            end

Сам рандом реализуется в функции function CCycleTask:get_random_item(random_level,vendor_id) таким образом:

   repeat
		next_val=queue:get_next()
		result, id, value = self.task_ini:r_line("random_"..random_level, 
		--preview and queue:get_next_preview() or queue:get_next(), 
		next_val,"", "")
		-- log("! "..(self.task_ini:line_count("random_"..random_level)-1))
		-- log("random_"..random_level.." "..tostring(result).." "..next_val.." ["..tostring(id).."]")
		if not result then
			rman:remove_queue(quuid)
			quuid=rman:new_queue(self.task_ini:line_count("random_"..random_level)-1)
			self.task_info.rqueues[vendor_queue_id]=quuid
			queue=rman:get_queue(quuid)
			next_val=queue:get_next()
			result, id, value = self.task_ini:r_line("random_"..random_level, next_val,	"", "")
			-- log("random_"..random_level.." "..tostring(result).." "..next_val.." ["..tostring(id).."]")
		end
	until value == "" or has_info(value)	--' Не выдаем награду, если не выдан прикрывающий поршень

Как я понял рандом реализован через queue:get_next(), но как вместо данной функции использовать, к примеру math.random(), к сожалению не понял 

 

Обсуждение данной темы нашел, но, как я понял, продолжения обсуждения не было. Подскажите, пожалуйста, если кто знает, как работают или где найти информацию про rman:get_queue(). Я бы хотел сохранить всю логику, которая есть, добавить только, что бы можно было при перезагрузке получить другую награду из "разрешенных" (те, для которых нужные поршни уже выданы).

Буду очень признателен за помощь. Спасибо, что прочитали.

  • Жуть! 1

@Blum спасибо большое за помощь!

 

@shahvkit, простите, да, надо было в данной теме спрашивать :(. @_Val_ спасибо большое за перенос! 

 

@Im-not и Вас спасибо большое за помощь! Способ хороший.

 

Так же в процессе размышления над ситуацией нашел еще следующий вариант:

 

В функции CCycleTask:get_random_item вместо получения порядкового номера "случайного" предмета из очереди, получаю его через math.random(). Все остальное оставил, как было, получилось:

 

Код функции CCycleTask:get_random_item вместе с правками

function CCycleTask:get_random_item(random_level,vendor_id)
	local elem_count=self.task_ini:line_count("random_"..random_level)-1
	local quuid
	local rman=pr_queues()
	if not self.task_info.rqueues then
		abort("! ERROR invalid internal data for cycle tasks! place:rqueues.")
	end
	local vendor_queue_id=vendor_id.."_"..random_level
	if not self.task_info.rqueues[vendor_queue_id] then
		abort("! ERROR invalid internal data for cycle tasks! place:rqueues [%s].",vendor_queue_id)
	else
		quuid=self.task_info.rqueues[vendor_queue_id]
	end
	local queue=rman:get_queue(quuid)
	if not queue then
		abort("! ERROR invalid internal calls and data for cycle tasks! pr[%s]",tostring(quuid))
	end	
	local result, id, value,next_val
	repeat
	    countTreasures = self.task_ini:line_count("random_"..random_level)-1
		next_val=math.random(1,countTreasures)
		result, id, value = self.task_ini:r_line("random_"..random_level, 
		-- preview and queue:get_next_preview() or queue:get_next(), 
		 next_val,"", "")
		-- log("! "..(self.task_ini:line_count("random_"..random_level)-1))
		-- log("random_"..random_level.." "..tostring(result).." "..next_val.." ["..tostring(id).."]")
		if not result then
			rman:remove_queue(quuid)
			quuid=rman:new_queue(self.task_ini:line_count("random_"..random_level)-1)
			self.task_info.rqueues[vendor_queue_id]=quuid
			queue=rman:get_queue(quuid)
			next_val = math.random(1,countTreasures)
			result, id, value = self.task_ini:r_line("random_"..random_level, next_val,	"", "")
			-- log("random_"..random_level.." "..tostring(result).." "..next_val.." ["..tostring(id).."]")
		end
	until value == "" or has_info(value)	--' Не выдаем награду, если не выдан прикрывающий поршень
	return id
end

 

 

1 час назад, drMiha сказал:

вместо получения порядкового номера "случайного" предмета из очереди, получаю его через math.random()

Криво он работает, одно значение всегда выпадает из пула, причём даже в последующих таких же наградах оно так же отсутствует. Видимо, связано с текущим состоянием очереди. Проверял на выборке величиной 1000: и на паре вариантов, и на полных пулах один и тот же элемент выпадает. Делай подменой, проверил свой вариант, там всё чётко рандомно :grin2: И работает быстрее.

  • Спасибо 1

А вот это интересно! @Im-not, спасибо большое! Я проверил, чисто в игре: получал награды за два квеста и пистолетные патроны выпали новые, которые никогда еще не выпадали, но в пуле были, но, похоже из-за малой выборки, проблемы не увидел.

 

Странно, конечно, что состояние очереди частично блокирует работу math.random(), но это вполне возможно. Переделаю на Ваш вариант, заодно уберу все лишнее, кроме пересоздание очереди, если она не создана (вдруг это тоже на что-то влияет в дальнейшем на другие скрипты и т.д.).

 

Если вдруг записали, те предметы, что никогда не выпадают, не первый и последний из пулов?.. И пока я писал этот вопрос, я понял, где "собака зарыта", проблема.

 

Проблема вот тут:

 

countTreasures = self.task_ini:line_count("random_"..random_level)-1

 

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

 

Огромное спасибо за тесты! Переделаю.

1 час назад, Im-not сказал:
3 часа назад, drMiha сказал:

math.random()

Криво он работает

Советуют предварительно запускать: math.randomseed(os.time())

В _g.script есть пример: random_number

  • Спасибо 1
3 минуты назад, h0N0r сказал:

Советуют предварительно запускать: math.randomseed(os.time())

В _g.script есть пример: random_number

Спасибо большое! Добавлю!

 

Точно, можно будет добавить в функцию инициализации цикличек.

@drMiha 

self.task_ini:line_count

возвращает количество, если 0 ,то это пустая таблица. А у нас есть элемент с индексом  0.

поэтому

 

self.task_ini:line_count("random_"..random_level)-1

-1 приводит индексы в порядок..начиная с 0. Так что выпадал предмет с индексом 0.

Только нужно проверять countTreasures на предмет -1, а то может вызвать исключение дальше по коду.

А лучше просто использовать далее по коду конструкцию (countTreasures - 1)

Изменено пользователем Blum
  • Спасибо 1
  • Согласен 1

....- "И не важно куда подует ветер..."

                                                   Freddie Mercury.

Эмм. Извините, что вмешиваюсь. Конечно текущая реализация скрипта вызывает несколько вопросов. Допустим возможность бесконечного цикла. Но это опустим)) Но вот сама постановка вопроса меня несколько удивляет: 

13 часов назад, drMiha сказал:

Под "честным" рандомом имею ввиду разную награду при перезагрузке

Вообще "перезагрузка" - это ненормальный режим. Не - я всё понимаю)) Но ради этого переписывать скрипт. Тогда уж переделывать так, чтобы при выдаче награды была возможность выбора награды. Выпал список - выбрал то, что нужно и пошлепал дальше. :az1000106:

  • Спасибо 1
  • Согласен 1

   УРАГАН.png

                 Краткий гид по моду Тайные Тропы 2

                                      ПАРТИКЛЫ TERRA

 

 

 
8 часов назад, drMiha сказал:

не первый и последний из пулов?

Нет. Для каждого пула не выпадала определённая позиция, не обязательно первая или последняя. Но тут прикол скорее в том, что в текущей очереди не такой порядок как в шаблоне, поэтому скорее всего всё же не выпадает именно последняя (рандом же на 1 меньше глубины пула выходит), но только из самой очереди. Как-то так. А реализовал просто в лоб:

вместо got(self:get_random_item(kk,task_desc.vendor),1) -> got(reward[kk][math.random(#reward[kk])],1)

где reward - это массив массивов наград, т.е. я просто исключил get_random_item из выдачи награды

1 час назад, _Val_ сказал:

Вообще "перезагрузка" - это ненормальный режим.

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

  • Спасибо 2

Уважаемые коллеги, всем спасибо большое!

 

@Blum, Вы правы, но, как я понимаю, внутри цикла и нужно условие на случае, если предмета не будет существовать. Почему сразу "правильно" не сделали и из-за чего такая особенность конкретно тут непонятно, но защита от такой проблемы есть.

 

@_Val_, с одной стороны да, все так. В идеале - это версия, которую сделали разработчики. Это из взгляд, их детище и тот смысл, который разрабы заложили в творение можно понять и почувствовать, только если соприкасаться с ним, без изменений. Но я далек от этих философских сложностей и время от времени что-нибудь подкручиваю. Тем не менее, выбор из сразу всего пула - это уже слишком много, а вот условный честный рандом - это уже ничего. Я имею ввиду, что специально сейвскамом довольно сложно пользоваться, даже если есть SSD. Это слишком запарно. А вот иногда, одну-две пачки патрон выбить, на ту же цепочку, к примеру, требуется (это мой случай, да :D).

 

@Im-not, понял, спасибо большое! Ваша реализация однозначно должна быть быстрее! Я постараюсь разобраться со своей излишней ленью и именно такой вариант сделать. Основная причина, из-за которой оставил практически все старое - это соблюдение инфопоршней (не уверен сколько именно предметов из списков закрыты за ними, но, думаю, такие есть). Подскажите пожалуйста, с помощью каких инструментов Вы тестировали код? Есть ли статьи/гайды по ним на данном сайте?

 

 

1 час назад, drMiha сказал:

с помощью каких инструментов Вы тестировали код?

Никаких, в игре. Менял в cycle_task.ltx пулы и количество наград у ближайшего квестовика. На 1000 штук даже слегка подвисает, а в случае в пулом Новый ствол (78 вариантов) - прилично. Что по поводу прикрывающих поршней, то во всех вариантах цикл завершался value = "" за первый проход, откуда там поршень с таким именем - загадка. В конструкцию if not result then ... вообще никогда не заходило. Такое ощущение, что вся эта функция общего вида, но для данного шаблона пулов она отрабатывает верно и не задействует весь свой спектр.

В дополнении в предыдущему посту вот готовый запарсенный массив reward reward.txt

Изменено пользователем Im-not
  • Спасибо 1

Создайте аккаунт или авторизуйтесь, чтобы оставить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

Создать аккаунт

Зарегистрировать новый аккаунт в нашем сообществе. Это несложно!

Зарегистрировать новый аккаунт

Войти

Есть аккаунт? Войти.

Войти
  • Недавно просматривали   0 пользователей

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