drMiha 0 Опубликовано 22 Февраля Уважаемые коллеги, товарищи, все здравствуйте! Отдельная большая благодарность за одобрение моей регистрации с немного странным, мягко-говоря 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 Поделиться этим сообщением Ссылка на сообщение
drMiha 0 Опубликовано 22 Февраля @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 Поделиться этим сообщением Ссылка на сообщение
drMiha 0 Опубликовано 22 Февраля А вот это интересно! @Im-not, спасибо большое! Я проверил, чисто в игре: получал награды за два квеста и пистолетные патроны выпали новые, которые никогда еще не выпадали, но в пуле были, но, похоже из-за малой выборки, проблемы не увидел. Странно, конечно, что состояние очереди частично блокирует работу math.random(), но это вполне возможно. Переделаю на Ваш вариант, заодно уберу все лишнее, кроме пересоздание очереди, если она не создана (вдруг это тоже на что-то влияет в дальнейшем на другие скрипты и т.д.). Если вдруг записали, те предметы, что никогда не выпадают, не первый и последний из пулов?.. И пока я писал этот вопрос, я понял, где "собака зарыта", проблема. Проблема вот тут: countTreasures = self.task_ini:line_count("random_"..random_level)-1 Я взял именно в минус один из-за того, что в цикле, если предмет не получилось выбрать, идет условие с созданием новой очереди и там, в свою очередь, новое кол-во получается с минус один. Из-за этого один предмет, предполагаю последний, никогда не выпадает... Огромное спасибо за тесты! Переделаю. Поделиться этим сообщением Ссылка на сообщение
drMiha 0 Опубликовано 22 Февраля 3 минуты назад, h0N0r сказал: Советуют предварительно запускать: math.randomseed(os.time()) В _g.script есть пример: random_number Спасибо большое! Добавлю! Точно, можно будет добавить в функцию инициализации цикличек. Поделиться этим сообщением Ссылка на сообщение
drMiha 0 Опубликовано 23 Февраля Уважаемые коллеги, всем спасибо большое! @Blum, Вы правы, но, как я понимаю, внутри цикла и нужно условие на случае, если предмета не будет существовать. Почему сразу "правильно" не сделали и из-за чего такая особенность конкретно тут непонятно, но защита от такой проблемы есть. @_Val_, с одной стороны да, все так. В идеале - это версия, которую сделали разработчики. Это из взгляд, их детище и тот смысл, который разрабы заложили в творение можно понять и почувствовать, только если соприкасаться с ним, без изменений. Но я далек от этих философских сложностей и время от времени что-нибудь подкручиваю. Тем не менее, выбор из сразу всего пула - это уже слишком много, а вот условный честный рандом - это уже ничего. Я имею ввиду, что специально сейвскамом довольно сложно пользоваться, даже если есть SSD. Это слишком запарно. А вот иногда, одну-две пачки патрон выбить, на ту же цепочку, к примеру, требуется (это мой случай, да :D). @Im-not, понял, спасибо большое! Ваша реализация однозначно должна быть быстрее! Я постараюсь разобраться со своей излишней ленью и именно такой вариант сделать. Основная причина, из-за которой оставил практически все старое - это соблюдение инфопоршней (не уверен сколько именно предметов из списков закрыты за ними, но, думаю, такие есть). Подскажите пожалуйста, с помощью каких инструментов Вы тестировали код? Есть ли статьи/гайды по ним на данном сайте? Поделиться этим сообщением Ссылка на сообщение
drMiha 0 Опубликовано 23 Февраля @Im-not, понял, спасибо большое за информацию и за файлик! Странно это все, конечно, сегодня немного модифицировал код и ставил аддон "Воля Отступника". Начал ловить странные вылеты, если Не использую очередь. При использовании очереди, все нормально (под использованием имею ввиду взять значение/создать новую очередь (хотя если в это условие никогда не заходят, то остается только действие "взять значение")). Странно это все. Похоже, что функция или от старой версии осталась или делалась с запасом на все возможные использования (что я одобряю полностью, но разобраться в этом сложно, конечно ). Поделиться этим сообщением Ссылка на сообщение