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

Прозекторская


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

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

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

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

Начнем с простенького, но сразу в тему рефакторинга. Скриптик, где банально выдрана работа с нетпакетами из amk, поправлены ошибки древние, и максимальное количество функций развернуто.

 

Делалось для максимальной скорости.

 

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

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

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

 

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

 

В ШМ уже было, ну да пусть еще будет.

 

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

 

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

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


Немножко истории: началось все с оружейного аддона Бака, который в соли тормозил изрядно. Вплоть до того, что приближаясь к группе из десятка сталкеров получали вполне ощутимый эффект "хромоты". При разбирательстве - что же там ТАК тормозит, оказалось, что буквально все, но нетпакеты вносят довольно весомый вклад.

 

При этом код из аддона работал быстрее, чем код от Xstream, и оба - заметно быстрее amk (хотя в амк в принципе тот же экстримовский, но в нем больше кросс-вызовов).

Соответственно, переписан именно чтобы выбросить все лишнее.

 

Скорость, скорость, и еще раз скорость.

Ссылка на комментарий

Гравипушка.

 

На сей раз просто банальный рефакторинг.

Но мало-ли, кто чего обсудить захочет, так что отдельной темой.

 

И как пример к посту про физобъекты в справочнике по ФиК.

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

https://dl.dropboxusercontent.com/u/27871782/sleep_manager.script- сон.

https://dl.dropboxusercontent.com/u/27871782/amk_timers.script- таймеры.

 

А вообще таймеры не нужны.

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

 

Все навороты с 20 взамными вызовами из amk_mod.script - amk.script, из него опять amk_mod и т.д., повторить до полного фалломорфирования (зато там когда-то античит был, да) - тоже не нужны. Сносить к Етицкой Богомыши безжалостно.

 

Разбор того, что внутри: http://www.amk-team.ru/forum/index.php?showtopic=13068&p=912220

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

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

В общем, ковырялку лучше оставить для "ковырнул что попало, ничего не понял, прошу объяснить: что это было, где я, и зачем вообще тут все ? Кусок чегопопала прилагается."
Скриптование - вот там всяких кровососов, типа последнего - вроде, будет нормально искать.

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

 

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

 

Блин, все еще жду, пока это ненормальный движок не успокоится, и не прекратит над постами измываться. 8(

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

xr_logic, pstor, сохранение

 

Итак, от меня небольшой взнос в "Прозекторскую", и будет заказ.

 

Взнос - это про сохранение данных объектов через их pstor, для тех, кому "бездонные" от Артоса-ли, от XStream-ли - не совсем в кассу. Ну, например у меня куча всякого, что именно с pstor'ом, но одного пакета, тем не менее - за глаза. Переписывать все "вдребезги и пополам" - смысла не вижу. Кроме того, api и обертки - это все-таки трата ресуров. Поэтому - простенькие модификации уже имеющегося в xr_logic:

 

pstor_store(), pstor_retrieve() и иже с ними:

[/code]local pstor_number = 0

local pstor_string = 1

local pstor_true = 2

local pstor_false = 3

local pstor_custom = 4

local pstor_table = 5

local pstor_end_t = 6

local pstor_bool = 7

local pstor_types = { ["number"] = 0, ["string"] = 1, ["true"] = 2, ["false"] = 3,

["userdata"] = 4, ["table"] = 5, ["end_table"] = 6, ["boolean"] = 7 }

 

 

function pstor_is_registered_type( tv ) return pstor_types[tv] ~= nil end

 

 

-- Вернет ид актора, если переменной нет в таблице tabl_netpda_varnames

-- быстрее (чтобы не перебирать таблицу) - только указывать запись конкретной переменной на ПДА

function get_pda_id( vn )

return ( tabl_netpda_varnames[vn] and get_pda() ) or 0

end

 

 

function pstor_store( o, vn, v )

-- log( "info", "pstor_store, %s, o: %s", vn, ( o and o:name() ) or "none" )

local st = db.storage[ ( tabl_netpda_varnames[vn] and get_pda() ) or ( o and o:id() ) or 0 ]

if st then

local pstor = st.pstor

if not pstor then

pstor = {}

st.pstor = pstor

end

if pstor_types[ type( v ) ] then pstor[vn] = v

else abort( "pstor_store, invalid type: %s [%s]", type( v ), vn )

end

else abort( "pstor_store, no pstor for variable [%s] !", vn )

end

end

 

 

function pstor_retrieve( o, vn, def )

local pstor = db.storage[ ( tabl_netpda_varnames[vn] and get_pda() ) or

( o and o:id() ) or 0 ].pstor

local r = pstor and pstor[ vn ]

if r ~= nil then return r end

return def

end

 

 

function pstor_get_custom( npc, cls, vn )

local pstor = db.storage[npc:id()].pstor

if pstor then

local v = pstor[vn]

if v then return v.st end

else pstor = {}; db.storage[npc:id()].pstor = pstor end

local v = pstor_custom_impl[cls]()

pstor[vn] = v

return v and v.st

end

 

 

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

n = n + 1

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", p, k, _util.to_str( npc ) )

end end end

pk:w_stringZ( tostring( n ) )

pk:w_u8( pstor_end_t )

end

 

 

function pstor_load_tbl( pk )

local t = {}

local k, v, cls

while true do

k = pk:r_u8()

if k == pstor_number then k = pk:r_float()

elseif k == pstor_string then k = pk:r_stringZ()

elseif k == pstor_end_t then return t

else abort( "pstor_load_tbl, save file corrupted: %s (key type: %s)", _util.to_str( k ) )

end

v = pk:r_u8()

if v == pstor_true then t[k] = true

elseif v == pstor_false then t[k] = false

elseif v == pstor_number then t[k] = pk:r_float()

elseif v == pstor_string then t[k] = pk:r_stringZ()

elseif v == pstor_custom then

cls = pk:r_stringZ()

if cls == "" then v = pstor_custom_impl[k]

else v = pstor_custom_impl[cls]

end

if v then v = v()

else abort( "pstor_load_tbl, invalid custom: [%s], cls: [%s]", k, cls )

end

t[k] = v

v:load( pk )

elseif v == pstor_table then t[k] = pstor_load_tbl( pk )

else abort( "pstor_load_tbl, save file corrupted: %s (type: %s)", _util.to_str( k ), _util.to_str( v ) )

end end

end

 

 

function pstor_load_all( npc, pk )

local id = npc:id()

local pstor = db.storage[id].pstor

if not pstor then

pstor = {}

db.storage[id].pstor = pstor

end

-- local n = pk:r_u32()

-- if ( n >= 11 ) and ( id ~= 0 ) then

-- -- максимум 10 итераций: у неписей пишется 5 переменных, у техники - 7, пусть 10 будет

-- -- если у вас в пстор что-то свое пишется, ориентируйтесь на свои значения

-- -- и обязательно убираем из проверки актора - у него очень толстый пстор, и, к

-- -- тому же, если уж поврежденным будет его пстор, то тут точно уже ничего не поможет

-- if id ~= get_pda() then abort( "pstor_load_all, n: %s (%s)", n, _util.to_str( npc ) )

-- -- return remove_zavis.remove_obj( npc )

-- elseif n >= 1000 then abort( "pstor_load_all, pda, n: %s", n )

-- end end

local k, v, cls

local n = 0

while true do

k = pk:r_stringZ()

v = pk:r_u8()

if v == pstor_true then pstor[k] = true

elseif v == pstor_false then pstor[k] = false

elseif v == pstor_number then pstor[k] = pk:r_float()

elseif v == pstor_string then pstor[k] = pk:r_stringZ()

elseif v == pstor_custom then

cls = pk:r_stringZ()

if cls == "" then v = pstor_custom_impl[k]

else v = pstor_custom_impl[cls]

end

if v then v = v()

else abort( "pstor_load_all, custom: [%s], cls: [%s], n: %s, (%s)", k, cls, n + 1, _util.to_str( npc ) )

end

pstor[k] = v

v:load( pk )

elseif v == pstor_table then pstor[k] = pstor_load_tbl( pk )

elseif v == pstor_end_t and tonumber( k ) == n then return

else abort( "pstor_load_all, save file corrupted: %s, n: %s (%s)", _util.to_str( k ), n + 1, _util.to_str( npc ) )

-- не надо пытаться вылетать - просто не пишем поврежденные данные

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

-- мусора в пстор одно только ее название может повесить загрузку

 

-- dc: таки НАДО вылетать. Если файл битый - он битый, почему-то.

-- pstor[k] = nil

end

n = n + 1

end

end

 

 

function save_obj( npc, pk )

local st = db.storage[npc:id()]

pk:w_stringZ( st.ini_filename or "" )

pk:w_stringZ( st.section_logic or "" )

pk:w_stringZ( st.active_section or "" )

pk:w_stringZ( st.gulag_name or "" )

 

save_logic( npc, pk )

 

if st.active_scheme then issue_event( npc, st[st.active_scheme], "save" ) end

pstor_save_all( npc, pk )

end

 

 

function load_obj( npc, pk )

local id = npc:id()

local st = db.storage[id]

local s = pk:r_stringZ()

if s == "" then st.loaded_ini_filename = nil

else st.loaded_ini_filename = s

end

 

s = pk:r_stringZ()

if s == "" then st.loaded_section_logic = nil

else st.loaded_section_logic = s

end

 

s = pk:r_stringZ()

if s == "" then

-- В activate_by_section нужно передать строку "nil", а не nil, чтобы не

-- активировать ни одной из схем. При этом реальная active_section станет равной nil.

st.loaded_active_section = "nil"

else st.loaded_active_section = s

end

 

s = pk:r_stringZ()

if s == "" then st.loaded_gulag_name = nil

else st.loaded_gulag_name = s

end

 

load_logic( npc, pk )

pstor_load_all( npc, pk )

end[/code]

 

 

pstor_number и т.д. - типы данных, с которыми оно работает. То есть, в отличие от se_stor и иже с ними я здесь не стал пытаться охватить все на любой случай жизни, а выбрал простенько и быстренько.

 

get_pda_id( vn ) -- рудимент амк/соли, где обращение шло традиционно через 500 функций, размазанных по 50 скриптов.

 

pstor_store( o, vn, v ) и pstor_retrieve( o, vn, def ) -- в общем-то то же самое.

 

Объект, имя переменной, значение. Делают они в общем-то то, что извлекают id из game_object o, и пихают/читают переменную vn со значением v (либо подставляют def, если нет такой) в/из db.storage[o:id()].pstor

 

Ну или с "улучшением" - запихивают вообще куда попало, если имя объекта есть в специальном списке.

 

Зачем такое, с дикими тормозами, извращение - я не знаю, когда каждый объект в принципе сам знает и свой id, и где у него pstor. А если не знает - так ему и не надо.

 

pstor_get_custom( npc, cls, vn ) -- некое извращение, присутствующее в Солянке, и там, откуда оно в нее попало. Как бы зачем-то сохраняет в pstor данныe каких-то очень специальных объектов, запиханных в pstor более главному. Оставлено для очередной мифической "совместимости" неизвестно чего с неизвестно чем.

 

pstor_save_tbl( t, pk ) и pstor_load_tbl( pk ) -- а вот это нововведение для работы с таблицами, которые теперь можно держать в pstor'е, и они будут сохраняться/грузиться, без вызовов всяких сташных amk.pack_array_to_string(), amk.unpack_array_from_string и прочих злобнотормозных простыней.

То есть, надо нам таблицу у актора - вот так и кладем ее в db.storage[0].pstor.yet_another_tbl = t; ну или берем там же.

 

pstor_save_all( npc, pk ) и pstor_load_all( npc, pk ) -- в общем-то, как и все, что выше, нормальным людям ;) НЕ НУЖНО. Оно нужно двум функциям, описание которых будет ниже.

А делают они то, что пишут/читают даные pstor объекта в пакет и обратно. Про загрузке/сохранении.

 

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

Прежде всего изменен формат сохранения. Поскольку pstor - это само по себе таблица, с произвольными индексами, смысла считать ее размер (и хранить) - нет. Мы проверяем только момент, когда она закончилась. Далее, хотя ключом может быть что угодно, включая вектор или функцию, на практике такой экзотики нет. Ну и наконец, отдельный признак для bool отдельно значение - не нужны - храним сразу эквивалент для false или true.

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

 

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

 

save_obj( npc, pk ) и load_obj( npc, pk ) -- собственно функции сохранения и загрузки, вызываемые из биндеров. Здесь все элементарно.

 

Итого, мы имеем исправление для xr_logic, позволяющееся обойтись минимальными переделками всего (и только когда руки дойдут), обращающееся с пакетами максимально быстро и экономно.

А что касается ограничения в 8килобайт, то если не хранить в акторе эпические поэмы и видео с порнухой, то на сей раз прав скорее именно Билл Гейтс со своим "640К достаточно доля всего".

 

Разумеется, эти изменения можно и еще доработать, именно в сторону бездонности, и как раз на эту тему у меня будет заказ для тех, кто плотно работает с se_stor.

Точнее, сначала - на class_registrator. Чтоб убить сразу 2-х зайцев.

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

Выложил "затравочный" пост.

 

Суть же заказа с class_registrator: Артос его дорабатывал для нетпакетов и хранилища, но в результате "потерялась" никогда не существовавшая совместимость с другим кодом/конфигами. А читаемость скрипта в оригинале была ужасна, в модах - еще хуже.

 

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

Ну и откомментить как-то.

 

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

 

Карлан,

 

С измененными "менеджерами" (которые надо оторвать совсем, как минимум от актора) у меня пакет сейчас в районе 1800-2000байт. Это в солянке-то.

 

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

 

Второй момент, кстати, это медленные и печальные is_monster() / is_stalker() в _g.script.

и многочисленные их аналоги повсюду, например - в se_smart_terrain.script (в последнем оно еще каждый апдейт проверяется - надо ли заполнять !!!). Ну а от самих функций - кроме мордобития (возврата true) - ни каких чудес.

Я для себя аж 8 новых констант/константотаблиц завел, к которым можно обрашаться как if c_mob[obj.clsid], например, и при этом они там не true хранят, а что-то полезное. НО это, во-первых, инитить надо довольно криво, во-вторых - таблицы руками забиваются. Вместо того, чтобы вот в регистраторе сразу все и сделать.

 

Ну вот например, маленький кусочек:

 

["mob"] = { [clsid.bloodsucker_s] = "bloodsucker_s", [clsid.boar_s] = "boar_s", [clsid.burer_s] = "burer_s", [clsid.cat_s] = "cat_s", [clsid.chimera_s] = "chimera_s", [clsid.controller_s] = "controller_s", [clsid.dog_s] = "dog_s", [clsid.flesh_s] = "flesh_s", [clsid.fracture_s] = "fracture_s", [clsid.gigant_s] = "gigant_s", [clsid.poltergeist_s] = "poltergeist_s", [clsid.pseudodog_s] = "pseudodog_s", [clsid.psy_dog_s] = "psy_dog_s", [clsid.snork_s] = "snork_s", [clsid.tushkano_s] = "tushkano_s", [clsid.zombie_s] = "zombie_s" },

-- по синтаксису видно, кстати, что это только часть чего-то большого. Примерно понятно, зачем оно надо ? А есть синтетическая табличка c_ai - для там есть сталкеры, но нет актора. И т.д.

 

По поводу давно и у всех - ну вот примерно то и видим в показанном недавно скрипте того же кровососа. ;)

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

 

-- возвращает:-- а) если сталкер: группировку сталкера и true-- б) если монстр: вид монстра и falsefunction se_smart_terrain:get_obj_community( obj ) local cls = obj:clsid() if cls == clsid.script_stalker then return obj:community(), true else return monster_classes[cls], false endend -- заполняет таблицу monster_classesfunction se_smart_terrain:fill_monster_classes() if not monster_classes then monster_classes = { [clsid.bloodsucker_s ] = "bloodsucker", [clsid.boar_s ] = "boar", [clsid.burer_s ] = "burer", [clsid.cat_s ] = "cat", [clsid.chimera_s ] = "chimera", [clsid.controller_s ] = "controller", [clsid.pseudodog_s ] = "pseudodog", [clsid.psy_dog_s ] = "psy_dog", [clsid.dog_s ] = "dog", [clsid.flesh_s ] = "flesh", [clsid.fracture_s ] = "fracture", [clsid.poltergeist_s ] = "poltergeist", [clsid.gigant_s ] = "pseudo_gigant", [clsid.snork_s ] = "snork", [clsid.tushkano_s ] = "tushkano", [clsid.zombie_s ] = "zombie" } endend function se_smart_terrain:register_if_needed() --' Если уже зарегистрены то ничего не делать. if self.registred == true then return end self.registred = true printf( "%s register called", self:name() ) -- DEBUG if self.disabled then return end self:fill_monster_classes()...

 

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

@Dennis_Chikin, в целом занятно, с актором через такое будет работать быстрее, нежели чем гонять таблица-строка-таблица. Я например se_stor никогда не пользовался, как-то без надобности порнуху хранить (но система проста и гениальна, круто))) Стандартный акторский пакет + система сохранения через побитовые операции в принципе за глаза (а если еще все сохранения переписать, то можно еще высвободить несколько сотен байт).

 

А что с class_registrator не так?

 

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

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

@_Val_, я увидел вопрос от тебя, был ли он серьезен, не мои проблемы :) Я ответил. Для конфигов отдельной темы не надо, есть ковырялка и горы статей на эту самую логику.

Если ктото "желает" почитать мои сыроватые скрипты (@Dennis_Chikin вроде заказывал пакеты, глянь tm_storage и tm_modify_method, может что поймешь), прошу, писать вики пока не намерен, но все возможно, комменты к коду будут.


 

 

а разве ее мало?

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

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

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий

 

 

on_info3 = {=now_weather(groza:rain)} walker@agro_stalk_post_71

Жесткий у тебя подход :) 

 

@Desertir, а разве ее мало?


Очередной вброс от меня, немного переписал сохранение тайников:

 

 

--// сохранение
function CTreasure:save(p)
	local size, n = {}, 0
	for k,v in pairs(self.treasure_info) do
		local flag = 0
		if v.active then flag = bit_or(flag,1) end --// 1
		if v.done   then flag = bit_or(flag,2) end --// 2 or 3
		if flag ~= 0 then
			size[v.target] = flag
			n = n+1
		end
	end
	p:w_u16(n)
	for target,flag in pairs(size) do
		p:w_u16(target)
		p:w_u8(flag)
	end
end
--// загрузка
function CTreasure:load(p)
	local n = p:r_u16()
	for i=1,n do
		local target = p:r_u16() 
		local flag   = p:r_u8() 
		local k = self.treasure_by_target[target] 
		if self.treasure_info[k] then
			self.treasure_info[k].active = bit_and(flag,1) ~= 0 
			self.treasure_info[k].done   = bit_and(flag,2) ~= 0 
		end
	end
end

 

 

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

Ссылка на комментарий

@Dennis_Chikin, ну вариантов много, можно взяться и рефакторить оригинал, т.е. отрубить отовсюду все портянки и написать один скрипт с большим массивом, где будут координаты, модели и т.д. и т.п., но это статика от которой мы стараемся убежать, так как в сталкер все же хочется поиграть за одну НИ подольше, чем пара-тройка игровых дней. Я же предлагаю писать какой-то объединенный (с ЗПшной идеей) "менеджер", где не будет никаких конфигов и олспавнов, а будет несколько небольших массивов и все. Задача на сегодняшний день тривиальная, стоит действительно лишь определится насколько глубоко стоит в это лезть, и с какой стороны заходить, так же стоит определится добавлять что-то свое, или писать такой более менее динамичный аналог оригинала (рандомное наполнение, рандомные координаты, рандомные визуалы) с последующим навешиванием (уже своего) чего угодно (маячки/замки/растяжки...). В целом немного муторно (с формулами корректировки позиции спавна), но совсем не сложно (на первый взгляд опять же). Это будет действительно функциональней, там хочешь сделаешь тот же оригинал, выставишь лимит тайников на 200 штук, на каждый зарегаешь стори айди и работай в последующим с ними абсолютно так же как в оригинальном менеджере, потом хлоп - все вычистил, и по новой... Ну а воровство тайников (и из тайников) прикрутить-то дело не хитрое :)

Ссылка на комментарий

Я например se_stor никогда не пользовался, как-то без надобности порнуху хранить (но система проста и гениальна, круто)))

В давние времена (Дезертир помнит) у меня была в моде архаически-динозавровая система хранения всего-на-свете в пакетах/псторах физ.объектов. Этот реликтовый монстр утрамбовывал все до битов (ага, даже не до байтов) и засовывал все в какую-нибудь лампочку. Которая ему на локации приглянулась. 8 сохраненных переменных в одном байте нетпакета - это конечно прикольно. Но в итоге этот динозавр вымер (даже архивов не сохранилось), уступив место se_stor. Потому что правда удобнее, для любых технических нужд там сохранять все что вздумается. Так надо ли плодить таких динозавров?

 

Суть же заказа с class_registrator: Артос его дорабатывал для нетпакетов и хранилища, но в результате "потерялась" никогда не существовавшая совместимость с другим кодом/конфигами. А читаемость скрипта в оригинале была ужасна, в модах - еще хуже. Что надо: отпрепарировать/провести необходимые гибридизации для повышения читабельности, сразу разобрав на блоки - что осталось от оригинала, что от амк, что добавлено для хранилища, что - для пакетов. Ну и откомментить как-то.

Что-то я вообще не понял о чем речь идет. класс_регистратор - это же в основном просто набор строчек наподобие такой

cs_register    (object_factory, "CWeaponAK74",        "se_item.se_weapon_magazined_w_gl",        "WP_AK74",    "wpn_ak74_s")

иногда упакованных в блоки if что-то там then ... end. Или я отстал от жизни и там все иначе?

Как простейший вариант - упаковать вообще все в блоки if then присобачив к каждому комментарий, а для чего нужен этот блок. Больше я не знаю что там еще городить и зачем.

 

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

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

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

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

Мод, где не бывает одинаковых путей - Судьба Зоны. (Лучшее, что у меня получилось на X-Ray) На базе модифицированного движка OGSR Engine.

Бывший мододел на X-Ray / Начинающий игродел на Unreal Engine. Программист.

AMD Ryzen 9 7950X (16 ядер, 32 потока, 5.75 ГГц); RTX 3080; 128 ГБ DDR5; Arctic Liquid Freezer II-420; 3 ТБ SSD PCIe 4.0; 4ТБ HDD.

Ссылка на комментарий

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

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

На чистой игре версии 1.0004 по моим расчетам в физ. объекты можно записать 7567352 байт ~= 7.2 мегабайт. Неверно посчитал, делите на два, это чуть больше 3 МБ. И это только физ. объекты, если взять все (или почти все) объекты, получим хранилище в 39 МБ. Ну это так, забавы ради.

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

Я не придумал ничего проще, чем add_data("key1", "my_awesome_data") или get_data("key1"). Т.е. это глобальные функции. При нормальном сохранении (без вылетов и прочего) данные сохраняются вместе с пакетами объектов.

У @Zander_driver на сколько я помню, были то ли захардкожены эти лампочки, то ли еще чтото такое. У меня просто мой метод динамически подсасывается к оригинальным методам сохранения и загрузки. Ну собственно вся магия на этом заканчивается. Заботится об каком то сильном сжатии не вижу смысла, как и производительности, т.к. это происходит только в момент сохранения. По сравнению с записью на диск, весь код в скриптах - пшик. Если надо и будет время, откомментирую код.

PS: выложил потому, что появилась возможность оправдать те часы коддинга, которые я потратил на мод.

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

ТЧ 1.0004. SAP и Trans mod

github

Ссылка на комментарий

торговля, trade_manager

 

Я, конечно, понимаю, что И ЭТО ТОЖЕ давно у всех исправлено, и вообще написано свое. У ВСЕХ, а так же и у многих других. Но я вот лично вчера наконец вчитался, и {замаскированный мат здесь запрещен, так что даже и на латыни свое состояние описывать не буду}.

 

Итак, сегодня у нас на столе вот такая забавная зверушка - этот вот самый trade_manager:

 

function update(npc)

...

if tt.update_time ~= nil and tt.update_time < time_global() then return end

tt.update_time = time_global() + 3600000

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

Особенно, если

if tt.current_buy_supplies ~= str then

if tt.resuply_time ~= nil and tt.resuply_time < time_global() then return end

...

tt.resuply_time = time_global() + 24*3600000

- ведь ассортимент у торговцев явственно меняется по мере диалога с тем же Сидоровичем в самом начале, да и цены у позеленевших неписей явно взлетают, а покупать что-то они согласны только совсем задешево, по сравнению с желтыми ?

(Последнее, кстати, само по себе забавная шуточка, но если о ней сказать все, что я думаю, то уже сам себе по 2.1 один раз выписал, а теперь точно придется на месяц в r/o уйти. Но да, есть такой анекдот, про "но ты же - друг !")

 

В общем, я отвлекся, а на самом деле все очень просто: СНАЧАЛА делается load() из xr_motivator/bind_monster, а потом из xr_logic.set_schemes() дергается

function init()

...

trade_manager[npc:id()] = {}

 

Вот так вот. И при апдейте все эти

tt.что_попало естественно оказываются ~= str, зато очень даже ~= nil

И апдейт благополучно все обновляет.

 

А завершающим номером нашего цирка будет - Маэстро, урежте марш - разумеется:

function load(obj, packet)

...

tt.config = ini_file(tt.cfg_ltx)

 

после чего - неожиданно овощи:

function trade_init(npc, cfg)

...

trade_manager[npc:id()].config = ini_file(cfg)

 

- да, да. Для КАЖДОГО непися, входящего в онлайн. Со всеми 1700 костюмами и прочими 30000 квестовыми итемами.

 

Ура, товарищи ! ТакЪ победимЪ !

 

P.S. Да, разумеется, переписал, щас тестить буду под ОПу.

P.P.S. Да, разумеется, вывод все тот же - НЕ НУЖЕН. Совсем. По тому как обновление всего этого ахтунга имеет смысл только в начале диалога с конкретным трейдером или неписем, и ТОЛЬКО для этого непися.

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

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

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

Ссылка на комментарий

init() очевидно не нужен вообще, "апдейт" - нужен исключительно по вызову из xr_meet.

Ну и про открытие 10000 файлов, которые не system_ltx() все написано и в подполье, и вытащено оттуда в солянкотему.

 

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

 

 

upd: в общем, поправленного на скорую руку уродца, так, чтобы больше ни где ничего не трогать, выложил в теме солянкоразработки. Просто такой вот фикс для старья всякого, против тормозов.

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

treasure_manager, тайники, сохранение


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

Соответственно, не надо это дело дергать/инитить ни из _g.script, ни даже грузить/сохранять в акторе.

Хотя, тогда уж наверное и se_что-там_у_них (кстати, что ?) поправить.

Вопрос все тот же: ну и зачем он такой красивый вообще нужен, в виде менеджера, с целым отдельным классом, когда все прекрасно умещается в целых 3 банальных плоских функции ?

P.S. 1824 -> 660 байтиков. Пакет для "Солянки" стал. 28ms инициализация все-про-все. Сохранение, кстати, тоже очевидно быстрее. Ибо зачем писать сиды, если они в конфиге все руками вбиты ? И вообще не нужны, кстати.

P.P.S. Там же, кстати, проверяем соответствие конфига и спавна сразу.

То есть, сохраняя, зачем-то, формат ООП-шного уежища, получаем со всеми наворотами нечто вроде: https://dl.dropboxusercontent.com/u/27871782/treasure_manager.script

 

Upd 06.01.2015: упс, ой ! Для ООП и иже с ним оно больше не подходит. Исправлял ошибку - закинул свой, уже от "обезжиренной" соли. Ну да оно и к лучшему. Будем сразу приучаться к нормальным скриптам, без заведомого мусора.

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

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

В принципе, только одну табличку надо руками поправить - вписать clsid'ы оружия. Но можно и пустую оставить.
Что и зачем:

-- Сталкеры не пялятся на ГГ по пол-часа, и, соответственно, не застревают в проходах,
-- если не пялиться на них. Если смотреть в сторону - через 5 секунд продолжат заниматься своими делами.
-- Если увеличить радиус взятия предметов - актора не заклинивает при попытке начать разговор
-- с расстояния более 2-х метров - разговор просто не начинается. Кроме Сидоровича, которому надо еще
-- биндер править.
-- Тормоза злостные исправлены.

-- todo: решить что-то с жертвами аборта^w^w заказов на убийства, ибо бред и тормоза.

-- ВНИМАНИЕ !!! Для адаптации под древнескрипты:

-- log() и abort() поправить на свои
-- cannot_talk_by_weapon() см. на предмет отключенной проверки use.

local c_wpn = _G.c_wpn or {} -- здесь должна быть табличка clsid стволов.

Внимание, в файле опечатка: local c_wnp вместо local c_wpn. Не влияет, если определено _G.c_wpn, но будет вылетать/виснуть, если определяете здесь. Поправьте.

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

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

Не знаю куда лучше написать, напишу сюда. Распутайте мне пожалуйста цепочку скрипта xr_wounded, а конкретно значения ключей hp_victim hp_fight и не используемый в скрипте (но используемый движком) hp_cover. А то после сравнения дистанции с количеством здоровья я понял что ниасилю понимание этого чудо-скрипта.

Добавлено Dennis_Chikin,

Сюда обратиться.

Ссылка на комментарий

Фи, поручик ! ©

Вот специально создана тема под крупную форму.

 

Для начала имею предложить вот: https://dl.dropboxusercontent.com/u/27871782/xr_wounded.script

 

Он не столько распутан, сколько переписан, и под модифицированный _g.script + модифицированную обвеску, но зато все плоско и отформачено.

 

Надеюсь, actor в _G и global_time_ms вместо time_global() не сильно мешать будут.

 

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

 

 

local parse_data1, parse_syn_data1 = xr_logic.parse_data, xr_logic.parse_syn_data

local parse_condlist1 = xr_logic.parse_condlist1

 

- это аналоги стандартных, но принимающие один аргумент, по тому как остальные не нужны, и в стандартных тоже не работают.

 

Upd 12.07.2015: тоже обновил, с учетом того, что pstor для неписей не сохраняется нормально, и вообще много лишних переменных где попало - зло.

Изменено пользователем Dennis_Chikin
Ссылка на комментарий

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

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

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

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

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

Войти

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

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

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