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

Скриптование


Svoboда

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

"Вспомни т.н. "рельсы", когда модели убитых монстров растягивались на пол локации."

 

Кстати, а что это вообще было ?

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


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

Странное и загадочное:

-- v_lin, v_ang = vector(), vector()

ps:get_linear_vel( v_lin )

ps:get_angular_vel( v_ang )

 

Если строку с присвоением нулевого вектора раскомментировать, все работает как надо. Вот так - не понятно как, но как-то совсем не так.

Переменные типа vector() объявлены глобально.

 

Что это, Бэрримор ?

 

P.S. вообще, с нотацией у операций с векторами какой-то мрак и ужас. Что-то - возвращает, что-то - заполняет переданное, что-то возвращает результат операции, что-то - модифицирует полученное, и его же возвращает...

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


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

Да, оттуда. Впрочем, понял: моя ошибка. Здесь как раз все нормально, хоть с закомментированной строкой, хоть с раскомментированной. Я не отследил, что старые значения сохраняются не v:set() (заполнением), а копированием ссылки. Везде исправил, а сохранение - нет. И в приведенном коде - затираются новыми.

 

Исправил монстрометод на вот такое:

function track_item()
	local item = thrown_id and lobj_by_id( thrown_id )
	local pos, ps
	if item then
		pos = item:position()
		-- if check_on_level( pos ) then
		if level.get_bounding_volume().min.y < pos.y then ps = item:get_physics_shell()
		else
			local obj = sim:object( thrown_id )	-- улетел за пределы уровня, удаляем
			if obj then sim:release( obj, true ) end
	end	end

	if ps and ( thrown_upd >= global_time_ms ) then
		-- v_lin, v_ang = vector(), vector()	-- странное и загадочное, но иначе не работает
		ps:get_linear_vel( v_lin )
		ps:get_angular_vel( v_ang )
		if not lv_lin then	-- летим
			lv_lin, lv_ang = vector():set( t_impulse ), vector():set( v_ang )
			return
		end

		local cos_l = vector():set( v_lin ):normalize():dotproduct(
			vector():set( lv_lin ):normalize() )

		-- ловим удар брошенного предмета обо что-либо
		if ( cos_l < 0.86 or ( cos_l < 0.99 and pos:distance_to_sqr( dev.cam_pos ) >= 9 ) )
			-- основной показатель удара - изменение направления вектора линейной скорости
		  and v_ang:magnitude() ~= 0 and ( lv_ang:magnitude() == 0
		    or vector():set( v_ang ):normalize():dotproduct(
			vector():set( lv_ang ):normalize() ) < 0.99 ) then
			local sect = item:section()
			if string_find( sect, "explosive" ) then item:explode()
			elseif string_sub( sect, 1, 3 ) == "af_" then
				af_activate( sect, pos, thrown_id )
			end
			-- все, упали
		else lv_lin:set( v_lin ); lv_ang:set( v_ang ); return	-- продолжаем лететь
	end	end
	thrown_id, thrown_upd = false, 0
	lv_lin = false
end

 

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

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


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

+1 к выше про кости.

Тем более как раз недавно правил нечто подобное как раз в соли.

Еще можно посмотреть там же bind_monster на предмет кода с попаданием кровососу в голову. Код точно рабочий, и точно работает.

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


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

[error]Description : Particle effect or group doesn't exist

 

Вопрос: а наличие оного эффекта можно как-то проверить до вызова particles_object(), и, соответственно, повисания чего попало с такой вот ошибкой в логе ?

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


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

Возник внезапно очередной странный вопрос: а коллбэки в :net_destroy() вообще надо в nil устанавливать, или еще как-либо трогать ? Клиентский объект же вроде как в принципе уничтожается, так какие у него после этого могут быть коллбэки ?

 

Очередной рудимент, или оно все-таки зачем-то надо ?

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


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

[q]Условия возникновения: имея кучу всяких данных в таблице, которые хотелось бы сохранить, перевожу таблицу в строку.[/q]

 

Кстати, а зачем ?

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


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

По большому счету, даже выделенное хранилище совсем не нужно как таковое, со своим собственным API.

Имеет смысл воткнуть его непосредственно в save_all/load_all. Все равно они вызываются исключительно при сохранениях/загрузках, но зато - всегда. А тем более не нужны постоянные бессмысленные конвертации таблиц в строки и обратно при передаче между функциями - в любом случае передается ссылка.

Это просто-напросто трата памяти и времени.

 

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

Итого, всего лишь добавить к оригинальным float, bool, строка и объект еще один тип - таблица.

 

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

 

P.S. А в соли мы вообще занимались полной ерундой, сохраняя мнимую "совместимость" сэйвов, когда все равно по куче других причин каждое дополнение == новая игра. И, кстати, меня слегка уже поддостало даже в той же соли выковыривать отовсюду кучу заведомо бессмысленных переменных, и еще более бессмысленных "конвертаций". В нетпакете у актора там хранить реально почти нечего.

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


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

простейшая модификация оригинала:

function pstor_save_tbl( t, pk )
	pk:w_u8( pstor_table )
	local p
	for k, v in pairs( t ) do
		if type( k ) == "number" then pk:w_u8( pstor_number ); pk:w_float( k )
		else pk:w_u8( pstor_string ); pk:w_stringZ( k )
		end
		if v == true then pk:w_u8( pstor_true )
		elseif v == false then pk:w_u8( pstor_false )
		else
			p = type( v )
			if p == "number" then pk:w_u8( pstor_number ); pk:w_float( v )
			elseif p == "string" then pk:w_u8( pstor_string ); pk:w_stringZ( v )
			elseif p == "userdata" then
				pk:w_u8( pstor_custom )
				if v.classname == k then pk:w_stringZ( "" )
				else pk:w_stringZ( v.classname )
				end
				v:save( pk )
			elseif p == "table" then pstor_save_tbl( v, pk )
			else abort( "pstor_save_all, not registered type: %s, k: %s", p, k )
	end	end	end
	pk:w_u8( pstor_end_t )	
end


function pstor_save_all( npc, pk )
	local pstor = db.storage[npc:id()].pstor
	if not pstor then
		pstor = {}
		db.storage[npc:id()].pstor = pstor
	end
	local n = 0
	for k, v in pairs( pstor ) do n = n + 1 end
	pk:w_u32( n )
	local p
	for k, v in pairs( pstor ) do
		pk:w_stringZ( k )
		if v == true then pk:w_u8( pstor_true )
		elseif v == false then pk:w_u8( pstor_false )
		else
			p = type( v )
			if p == "number" then pk:w_u8( pstor_number ); pk:w_float( v )
			elseif p == "string" then pk:w_u8( pstor_string ); pk:w_stringZ( v )
			elseif p == "userdata" then
				pk:w_u8( pstor_custom )
				if v.classname == k then pk:w_stringZ( "" )
				else pk:w_stringZ( v.classname )
				end
				v:save( pk )
			elseif p == "table" then pstor_save_tbl( v, pk )
			else abort( "pstor_save_all, not registered type: %s, k: %s", t, k, _util.to_str( npc ) )
	end	end	end
end

 

 

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

  • Нравится 1

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


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

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

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

Теперь возвращаемся к преобразованию таблиц в строки:
С учетом того, что в луа для этого нет адекватных средств - оверхэд получается просто чудовищный. Сами данные при этом также разбухают (ага, тэги, да и просто num в strZ).
Далее, получив строку, не лезущую в остаток пакета, я так понимаю, предлагается применить к ней string.sub(), в обрамлении некоторой логики ? Опять же, оверхэд. В то время, как при поэлементной записи делить ничего не надо - просто продолжать писать в другой. И так же и читать.

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

Zander_driver, а добавить контроль размера пакета после записи каждой строки, и писать его в лог - не ? Естественно, что при записи в него 8 кил - переполнится.

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

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


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

Опять регэкспы, и опять я чего-то не понимаю:

на входе: 50|{=best_pistol}psy_armed,psy_pain@wounded_psy\

|20|=best_pistol}psy_shoot,psy_pain@{=best_pistol}wounded_psy_shoot,wounded_psy

Разбираем:

for name in string.gfind( s, "(%|*%d+%|[^%|]+)%p*" ) do
t_pos = string.find( name, "|", 1, true )
s_pos = string.find( name, "@", 1, true )
dist = string.sub( name, 1, t_pos - 1 )
if s_pos then
	state = string.sub( name, t_pos + 1, s_pos - 1 )
	sound = string.sub( name, s_pos + 1)
else state, sound = string.sub( name, t_pos + 1 ), nil
end
Получается как раз 2 подстроки, так, как я разделил "новой строкой".

Из первой и вправду получается позиция, два состояния и звук.

А из второй ?

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

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


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

Я не понял, куда делась ведущая вертикальная черта во второй подстроке. С которой позиция будет не 3, а 1.

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


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

"Вертикальная черта относится к классу %p"

 

О, спасибо.

 

Нет, оптимизировать так, по-моему, нельзя. Звук может быть не прописан.

Как минимум, %@?([^%|]*), и проверка на ~= "".

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

 

upd: И, кстати, сначала выделять только значение и строку, а строку потом уже еще раз разбирать. С учетом последующего (xr_meet.script) - что-то типа вот такого:

 

local t, n = {}, 0
local pos, state, snd
for d, v in string.gfind( s, "[%|%s]*(%d+)[%|%s]*([^%|]+)" ) do
	n = n + 1
	pos = string.find( v, "%@" )
	if pos then
		state, snd = string.sub( v, 1, pos - 1 ), string.sub( v, pos + 1 )
		t[n] = {
			["dist"] = tonumber( dist ),
			["state"] = xr_logic.parse_condlist( npc, dist, state, state ),
			["sound"] = xr_logic.parse_condlist( npc, dist, snd, snd )
		}
	else
		t[n] = {
			["dist"] = tonumber( dist ),
			["state"] = xr_logic.parse_condlist( npc, dist, v, v )
		}
end	end

 

 

...мда, и моя любимая привычка с копипастом строк, не проверив имена переменных...

Либо dist в цикле, либо d в tonumber(), разумеется.

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

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


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

Ну а теперь profile_timer() в руки, и мерить варианты. ;)

И кстати, проверить случай с 50|{=best_pistol}psy_armed,psy_pain|20|=best_pistol}psy_shoot,psy_pain

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


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

А вот я тут опять не понимаю, и опять с регэкспами.
На этот раз соседний с parse_data xr_meet.parse_syn_data. Ну, то есть, st1@snd1|st2@snd2 он, положим, разгребет. Но там в поиске шаблон какой-вообще чудовищный, и мне интересно, что будет, если он по ошибке таки получит что-нибудь, реально начинающееся на | ?

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

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


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

"Или могут быть варианты через | ? (запамятовал)"

Разделитель. Там в итоге получается тоже таблица, как и в parse_data(). Вот что и где с ней дальше делают - не смотрел еще.

 

Но шаблон все равно странен.

И, естественно, сразу возникает мысль: либо такое действительно зачем-то нужно, либо это запчасть от чего-то еще, но недоделанное/обрезанное. И тогда если переписывать - нельзя ли упростить, либо чревато ахтунгом, если ЭТО в исходном виде переваривает нечто, что я еще не нашел, но где-то есть, а новый вариант на такое рассчитан не будет.

То есть, если трогать, то надо разбираться, как же оно все-таки работает, и зачем ?

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


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

Artos, по вариантам:

 

state == {} - это нормально ?

Захват первого | в подстроку - он зачем оставлен ?

 

P.S. В абсолютном большинстве случаев abort из xr_logic.script не срабатывает. Так что передавать что-то неотловленное раньше, и непися/секцию/имя строки в parse_condlist и иже с ним - малополезно.

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


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

Artos, все равно не понял:

[codе]if sState then

if sState ~= '' then

tDat.state = xr_logic.parse_condlist(oNPC, sDist, sState, sState)

else tDat.state = {}

end

end[/code]

в xr_wounded что-то типа:

[codе]local t

if self.npc:see( actor ) then t = self.a.hp_state_see

else t = self.a.hp_state

end

if t then ... ищем подходящий key

else return "nil", "nil"

end

if t[key].state then парсинг и возврат результата, либо тот же "nil"

[/code]

То есть, нет стейта - то и все entry в таблице той же hp_state н нужно.

 

Опять же в parse_data() у тебя захват:

for sField in sStr:gmatch("(%|*%d+%|[^%|]+)%p*")
то есть, |10|st1@snd1 - она так и хватается, а дальше из нее выдирается ^| и далее по тексту.

А почему не поиск/захват "%|*(%d+%|[^%|]+)%p*" ?

 

P.S. С abort(), чтобы изнутри неписевых схем отрабатывал - разве что более другой движок. Иначе в лучшем случае будет сообщение в логе, а дальше - все равно висяк, с которым и сохраниться можно.

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

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


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

Гм, а разве поиск и захват подстроки - не полностью взаимоперпендикулярны ? При условии, что вообще нашлось то, что подходит под шаблон ?

 

%|* - внутри шаблона захвата - должен захватить и | тоже, если дальнейшее совпадет с остатком шаблона.

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

 

%d+%|[^%|]+ - тут все понятно. Захватываем то, что на надо. %p* за пределами шаблона захвата - как раз поиск разделителя, без его захвата. Это для parse_data().

Для parse_zone_data() вместо %d+ будет [^|]+ (и, кстати, за такие секции зон надо давать 10 лет строгого расстрела, так же как за секции всех прочих объектов и за имена файлов).

Ну а для syndata - вообще без ключа, просто пары state@sound|state@sound должны быть... То есть, просто "([^|]+)%p*", по-хорошему.

 

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

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


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

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

AMK-Team.ru

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