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

Погода и освещение


The ReapeR

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

(изменено)

Мониторы, конечно же, у всех студийные и калиброванные, освещение - строго по ГОСТу, ну и, главное, глаза клонированные.

 

Ролик у меня выглядит препоганейше.

 

Да тут совсем не в этом дело. В том же Atmosfear Cromm Cruac корректировал параметры освещения в user.ltx для получения более сочной картинки, контрастных теней и годной имитации привыкания глаз к свету и темноте, единоразово изменяв их через скрипт. The.

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

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


Ссылка на сообщение
(изменено)

Кстати, соляночный скриптик переписанный надо кому - упрощенный-ускоренный, + с управлением вероятности погоды не только переписыванием конфигов, но и "одним движением" ?


 

 

https://dl.dropboxusercontent.com/u/27871782/level_weathers.script

 

К вопросу о рефакторинге. Скриптик когда-то был соляночным. Сейчас, впрочем, он тоже соляночный, но с изменениями.

Старый смысла разбирать не вижу, поскольку трэш, угар, и содомия, да еще и с багами типа "вечной ночи" (на самом деле была банальная опечатка, но от того не легче).

 

Что сделано и как оно работает: во-первых, развернуто в плоские функции, ибо ООП там не нужно ни зачем вообще, во-вторых - динамический апдейт. это значит, что снесен весь мусор типа

class "WeatherManager"function WeatherManager:__init()	init()endfunction WeatherManager:reset() endfunction WeatherManager:save( pk ) endfunction WeatherManager:load( pk )	if db.storage[0].pstor.weather then return end	pk:r_stringZ()	pk:r_u32()endfunction WeatherManager:update()	-- called from bind_stalker.script	update()endlocal weather_managerfunction get_weather_manager()	if weather_manager then return weather_manager end	weather_manager = WeatherManager()	return weather_managerend

 

и соответствующая ему содомия в биндере актора. Хотите использовать без переделок - надо ее вернуть.

 

Раз уж здесь требуют расписать построчно, распишу.

 

local string_sub, string_find, string_gmatch = string.sub, string.find, string.gmatchlocal math_floor = math.floorlocal math_random = math.randomlocal table_insert, table_sort = table.insert, table.sortfunction log( ... ) _util.log( "level_weathers", ... ) endfunction abort( ... ) _util.abort( "level_weathers", ... ) endlocal ini = ini_file( "weathers\\environment.ltx" )local lname = level.name()-- check if level name corresponds to one of the levels that should use special indoor level-- as configured in game_maps_single.ltxlocal indoors = {}for i, v in ipairs( { "l03u_agr_underground", "l04u_labx18", "peshera", "av_peshera",	"warlab", "marsh", "l08u_brainlab", "l10u_bunker", "l12u_sarcofag",	"l12u_control_monolith" } ) do	indoors[v] = trueend

 

Библиотечные функции локализуются, дабы меньше томозило.

С той же целью ini файл открывается один раз при подцеплении скрипта.

 

Табличка уровней - такая же, как в оригинале - это уровни, где погода статическая. На ее основе считается переменная l_indoor и если она определена, то погода берется из game.ltx, а не вычисляется динамически.

 

local t_prob = {	-- вероятности типов погоды	["beta"] = 20,	["dry"] = 10,	["foggy"] = 10,	["rainy"] = 20,	["grey"] = 20,	["stormy"] = 10,	["thunder"] = 10 }local trans_types = {}	-- выходы из transitionlocal l_indoor = falseif indoors[lname] then l_indoor = true endlocal trans_t, trans_n, trans_id = {}, 0, 10000	-- таблица переходовlocal next_tm = 0local next_wlocal lv_weather = "default"local lv_suffix

 

табличка t_prob - собственно, позволяет поменять вероятность выбора той или иной погоды глобально, а не перелопачивать каждый раз все конфиги.

Ну а дальше просто объявляется куча всяких разных нужных переменных.

 


 

 

Eдем дальше, теперь - с конца:

function init()

	lv_suffix = ( ini:section_exist( "level_suffix_table" )		and ini:line_exist( "level_suffix_table", lname )		and ini:r_string( "level_suffix_table", lname ) )	local r, k, v, kk, vv, t	if ini:section_exist( "weather_transition_times" ) then		for i = 0, ini:line_count( "weather_transition_times" ) - 1 do			r, k, v = ini:r_line( "weather_transition_times", i, "", "" )			t = {}			trans_n = trans_n + 1; trans_t[trans_n] = { k + 0, v, t }			if ini:section_exist( v ) then				for ii = 0, ini:line_count( v ) - 1 do					r, kk, vv = ini:r_line( v, ii, "", "" )					t[kk] = vv					if t_prob[vv] then trans_types[kk] = vv end				end			else abort( "invalid section: [%s]", v )		end	end	else abort( "invalid section: [weather_transition_times]" )	end	table_sort( trans_t, function( a, b ) return a[1] < b[1] end )	-- из конфигов читается как попало, поэтому сортируем по времени	trans_n = trans_n + 1; trans_t[trans_n] = { 1440, trans_t[1][2], trans_t[1][3] }	-- синтетическая секция для 24-х часов.	-- Надо, чтобы был корректный переход со "стандартным" конфигом.	-- _util.list_tbl( trans_t, "transitions" )

 

- чтение конфигов.

Таблица суффиксов (уровней с динамической погодой) из environments.ltx (мы его открыли при подцеплении скрипта), таблица переходов и их вероятностей. Впрочем, вероятности теперь можно в конфигах не писать, по тому как есть табличка в скрипте, универсальная. Так что нам нужно только время, и на что переключаться можно.

 

	local ini = ini_file( "game.ltx" )	local pp	if ini:section_exist( lname ) then		if ini:line_exist( lname, "postprocess" ) then			pp = ini:r_string( lname, "postprocess" )		end		if ini:line_exist( lname, "weathers" ) then			lv_weather =  ini:r_string( lname, "weathers" )	end	end	if pp then level.add_pp_effector( pp, 999, true )	else level.remove_pp_effector( 999 )	end	-- log( "info", "init, default: %s, suffix: %s", lv_weather or "nil", lv_suffix or "nil" )	bind_stalker.task_add( "level_weathers.update", 5000, update )	return true

 

 

end - из game.ltx читаем постпроцессы типа желтизны на янтаре, и запускаем, а также статическую погоду для подземных уровней. И, наконец, вешаем на динамический апдейт код самого апдейта.


 

 

Не знаю, что там кто будет формировать - по мне так кроме самого скрипта вообще больше ничего не надо.

Собственно, самая интересная часть здесь - апдейт.

 

В логике того, что было, способен разобраться, наверное, только Создатель. Плюс там останки кучи каких-то древних модов, которые вообще ни за чем не нужны. Так что, все переделано в одну единственную функцию.

function update()

	local tm = level.get_time_hours() * 60 + level.get_time_minutes()	if tm < next_tm then return end	-- выбираем таблицу погод на следующий раз	if ( trans_id >= trans_n ) or ( trans_t[trans_id][1] >= tm ) then	-- нет данных или почему-то забежали вперед		for i, v in ipairs( trans_t ) do	-- вычисляем "с нуля"			if tm < v[1] then trans_id = i break end		end	else trans_id = trans_id + 1	end	-- log( "info", "update, id: %s (%s)", trans_id, trans_n )	local t = trans_t[trans_id]	next_tm = t[1]	-- _util.list_tbl( t[3], t[2] )

 

- если время что-то делать не подошло, не делаем ничего. А вот если подошло, то выбираем таблицу погод для СЛЕДУЮЩЕГО раза. Даже если находимся под землей, или прямо сейчас происходит выброс. Зачем это надо - кроме упрощения кода можно прицепить, например, к новостям прогноз погоды. Не "фэйковый", а реальный. Ну и кроме того, плохая идея, когда при каждой загрузке сэйва погода - разная получается.

	local pstor = db.storage[0].pstor	if next_w then	-- погоду знаем		-- log( "info", "update, to: %s, next id: %s, at: %s", next_w, trans_id, next_tm / 60 )		pstor.weather = next_w	else	-- сначала выберем текущую		next_w = pstor.weather		if next_w then			-- log( "info", "update, current: %s, next id: %s, at: %s", next_w, trans_id, next_tm / 60 )		else			local tt, nn = {}, 0			for k, v in pairs( t[3] ) do				nn = nn + 1; tt[nn] = k			end			next_w = tt[math_random( nn )]			-- log( "info", "update, new: %s, next id: %s, at: %s", next_w, trans_id, next_tm / 60 )			pstor.weather = next_w		end	end

 

- а вот если "предсказанной" погоды нет - только тогда считаем на основе загруженной таблицы. И если не под землей, и не выброс - устанавливаем. А если под землей - ставим нужную, но для поверхности дальше все равно идет рассчет нового "прогноза":

	local s = t[3][next_w]	-- log( "info", "update, select: %s", string_sub( s or "nil", 1, 180 ) )	local tt, nn = {}, 0	if s then	-- для следующего раза		for k, v in string_gmatch( s, "([%w]+):?([%d]*),?" ) do			-- log( "info", "update, allowed: [%s:%s]", k, v )			if t_prob[k] then v = t_prob[k]; tt[k] = v; nn = nn + v			else				v = trans_types[k]				if v then v = t_prob[v]; tt[k] = v; nn = nn + v				-- else log( "error", "invalid section: [%s], line: [%s]", t[2], k )	end	end	end	end	if t_prob[next_w] and not tt[next_w] then	-- текущая тоже участвует в конкурсе		s = t_prob[next_w]; tt[next_w] = s; nn = nn + s		-- log( "info", "update, add current: [%s]", next_w )	end	if nn ~= 0 then		s = math_random( nn )		-- log( "info", "update, total: %s, rnd: %s", nn, s )		-- for k, v in pairs( tt ) do log( "info", "update, [%s:%s]", k, v ) end		for k, v in pairs( tt ) do			if v < s then s = s - v			else next_w = k; break		end	end		-- log( "info", "update, next: [%s]", next_w )	-- else log( "error", "invalid section: [%s], entry [%s] absent", t[2], next_w )	end

 

- собственно, это и был прогноз погоды. Все.

end

 


 

 

В init() после строки table_sort( trans_t, function( a, b ) return a[1] < b[1] end ) -- из конфигов читается как попало, поэтому сортируем по времени

 

Добавил:

trans_n = trans_n + 1; trans_t[trans_n] = { 1440, trans_t[1][2], trans_t[1][3] } -- синтетическая секция для 24-х часов.

-- Надо, чтобы был корректный переход со "стандартным" конфигом.

 

Спасибо Карлан за то, что обратил внимание, и за тестирование с этим самым "стандартным" конфигом из Dynamic Weather v0.9.4

Изменено пользователем Murarius
  • Нравится 1

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


Ссылка на сообщение
(изменено)

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

Вот вариант с учетом известных проблем с конфигами (в комментариях все подробности)
https://dl.dropboxusercontent.com/u/27871782/level_weathers_bad_cofigs.script

В идеале, конечно, лучше бы конфиги починить, а сон делать через исправленную set_curent_time() в _g.script:

 


local set_current_time_t, set_current_time_f

function set_current_time_wait()
	if game.get_game_time() < set_current_time_t then return false end
	level.set_time_factor( set_current_time_f )
	set_current_time_f = false
	return true
end


function set_current_time( hour, min, sec )	-- починено, работает.
	game_time_time = game.get_game_time()	-- полное игровое время

	local new_time = game.CTime()	-- нужно выставить
	new_time:setHMS( hour, min, sec )

	local hh, mm, ss
	_, _, _, hh, mm, ss = game_time_time:get()	-- текущее время
	local c_time = game.CTime()
	c_time:setHMS( hh, mm, ss )

	if new_time == c_time then return	-- ничего не делаем
	elseif new_time < c_time then		-- следующие сутки
		new_time:setHMS( hour + 24, min, sec )
	end

	new_time:setHMS( 0, 0, new_time:diffSec( c_time ) )
	set_current_time_t = game_time_time + new_time

	if not set_current_time_f then set_current_time_f = level.get_time_factor() end

	level.set_time_factor( 10000 )
	level.add_call( set_current_time_wait, dummy_action )
end

 



Этот - именно для тех, кто любит чинить кривые, но зато Священные и Неприкосновенные конфиги скриптами.

 

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

Изменено пользователем Dennis_Chikin
  • Нравится 1
  • Полезно 2

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


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

Забавно, но, во-первых, "явных ошибок синтаксиса" не видит компилятор LUA, а во-вторых он с этими "ошибками" как-то проработал у меня целых 7 лет уже, и еще у 2-х человек минимум.

 

Другое дело, там в посте вроде было расписано, в чем отличие от всем привычного, и WeatherManager в этом файле, действительно, больше нет.

 

То есть, от bind_stalker требуется наличие функции task_add(), а в скрипте имеется функция init(), которую кто-то должен дернуть для запуска. Не важно, кто, по большому счету. Как удобнее будет использующему скрипт.

 

То есть, описание требуется прочитать внимательно.

 

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

 

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

  • Полезно 1

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


Ссылка на сообщение
(изменено)

Фар плэйн - это расстояние, на котором рисуются элементы пейзажа. Фог дистанс - это расстояние заливки цветом тумана.

 

https://www.dropbox.com/s/datlapi5x4b6xn6/rainy.png?dl=0

 

А вот денсити - это заляпывание картинки непосредственно перед носом.

 

Собственно, на картинке денсити на нуле, дабы не тормозило, дистенс фога - то-ли 80, то-ли 100. Плейн - 280, поскольку мапперов у нас дофига, но вот локи на треугольники вменяемого размера разбить - "а зачем, если можно этот плэйн выставить в 100500, и лет через 20 непременно появятся видюхи, которые при этом не тормозят, и воют вентилятором может быть даже чуть тише стратегического бомбера на взлете ?"

Изменено пользователем Dennis_Chikin
  • Смешно 1

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


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

Таких как ДМХ - на этом форуме действительно нет. Все вопросы  -  на сайт к авторам.

А в принципе, просто узнаем текущую секцию через level.get_weather(), и меняем в этой и В СОСЕДНИХ по тому же конфигу.

 

Если вопрос: "куда вписать level.get_weather() и как искать в конфигах" - курсов информатики на этом форуме, опять же, нет. Парадокс: пара-тройка учителей информатики техникумов были, но вот курсов - нет.

  • Нравится 1

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


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

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

AMK-Team.ru

×
×
  • Создать...