Сповіщення
Очистити все

Обхід обмежень файлу "mp_ranks.ltx"


Ранг:
Майстер
Роль:
Гість
Записи:
752
Приєднався:
7 місяців тому
 

Багато хто з модоробів, які створюють апгрейди для зброї, та й у цілому нову зброю (зокрема поліпшену), стикаються з проблемою переповнення кількості байтів інформації в секції файлу mp_ranks.ltx. Я також не виключення, при створенні скрипта апгрейду зброї все йшло чудово, тест також пройшов на 12, але коли апгрейд став підходити до кінця, то є коли необхідно було прописати всі апгрейди зброї в ранги, відбувся виліт. А прописав усього апгрейд тільки для однієї зброї. Але з усілякої проблеми можна знайти логічний вихід. Пропоную ось цей.

Алгоритм

Для початку необхідно продумати, що і як, коли і за яких умов працюватиме скрипт. Так як ми його розробляли для нашого мода, то приклади і всі складові буде повністю або частково взято з модифікації.

1. Об'єкт викидається.

2. Підбирається НПС.

І якщо зброя не прописана у рангах, то виліт. Щоб НПС підбирав ту зброю, яка прописана в рангах, потрібно видалити непрописану зброю, що викидається, і спанити на її місці точно таку ж, але прописану в рангах, причому візуал і основні характеристики повинні відповідати тій вибраній зброї (щоб не порушити ігровий процес і симуляцію). Такий спосіб можна досягти шляхом зняття ні-пакета з зброї, що викидається, і запису її на таку ж зброю але не апгрейдну. Для початку відстежимо саме викидання. Відкриємо bind_stalker.script і напишемо функцію з умовою, за якої буде видалятися:

 
local sip_b = 1 -– переменная, при определении которой будет
                -- производиться действие, по дефолту 1
function sip_bool(flag) –- функция, которая запускается сторонней функцией
                        -- из другого скрипта, дабы не совершить вылета, аргумент = число
	if flag == 1 then
	sip_b = 1
	else sip_b = 0
	end
end
 

Операція присвоєння здійснюється відповідно, щоб не сплутати. Шукаємо:

 
function actor_binder:on_item_drop (obj)
    level_tasks.proceed(self.object)
end
 

Ця функція відстежує викидання чогось із інвентарю РР. Змінимо так:

 
function actor_binder:on_item_drop (obj)
    level_tasks.proceed(self.object)
	if sip_b == 1 then
	project_sip.delete_weapon(obj)
	end
end
 

Що дозволить обійти той момент запису ні-пакета в неіснуючий об'єкт. Далі створюємо скрипт project_sip.script і пишемо до нього наступне:

 
local sects = {}
local tab_id = {}
local tab_old_id = {}
local now_wpn_id
local sect_old
local sect –- присвоим позже оригинальную секцию оружия,
           -- которая в последующем будет использована для спавна
local orig_sect –- переменной будет присвоена секция оружия 
local count = 0
local num
local new_id
local name –- будет присвоено оригинальное название оружия
function delete_weapon(weapon) -– функция удаления оружия, аргумент сам объект 
--таблица оружия, которое прописано в рангах
local wpn_tab = {"wpn_abakan","wpn_rpg7","wpn_ak74","wpn_fn2000","wpn_g36","wpn_groza","wpn_l85",
"wpn_lr300","wpn_mp5","wpn_rpg7","wpn_sig550","wpn_val","wpn_spas12","wpn_toz34","wpn_wincheaster1300",
"wpn_svd","wpn_svu","wpn_vintorez","wpn_beretta","wpn_colt1911","wpn_desert_eagle",
"wpn_fort","wpn_hpsa","wpn_pb","wpn_pm","wpn_sig220","wpn_walther"}
 
local wpn = weapon:section()
orig_sect = wpn
local pos_act  = db.actor:position()
pos_act.x = pos_act.x + 0.3 –- оружие будет спавниться не в инвентарь к ГГ,
                            -- а в 30см от него, ибо при спавне в инвентарь нет-пакет в оружие не записывается.
-- ниже проверяем, что оружие действительно апгрейдное (в данном случае идет проверка
-- не только на то что оружие апгрейдное, но еще и на то, что оружие имеет секцию смены визуала)
	if string.find(wpn,"list") or string.find(wpn,"prugina") or string.find(wpn,"tormoz")
           or string.find(wpn,"sv1") or string.find(wpn,"sv2") or string.find(wpn,"sv3") or string.find(wpn,"sv4") then
		for k = 1, #wpn_tab do –- запускаем цикл на выявление оригинала оружия (прописанного в рангах)
		name = k
		if string.find(wpn,wpn_tab[name]) then
		sect = wpn_tab[name]
		break –- если условие выполняется, то преждевременно останавливаем выполнение цикла
		end
		end
-- ниже происходит запись в таблицы данных о секциях
	table.insert(sects,orig_sect)
	table.insert(tab_old_id,weapon:id())
-- производим снятие нет-пакета, для этого подготовливаем все условия для этого
	local n_obj = alife():object(weapon:id()) –- определяем объект
	local func_net = net_pack_sip.wpn_d_r(n_obj) –- снимаем нет-пакет объекта
	alife():release(n_obj,true)
        –- присвоим, но не заспавним объект
	local sobj = alife():create(sect,pos_act,db.actor:level_vertex_id(),db.actor:game_vertex_id())
		if sobj then
		table.insert(tab_id,sobj.id) –- запишем id  оружия в таблицу для дальнейшей работы с ним
		net_pack_sip.wpn_d_w(func_net,sobj) –- запишем на это оружие весь нет-пакет удаленного оружия
		end
	end
	return sobj –- заспавним оружие
end
 

Ось, практично, можна сказати що все, проте коли ГГ візьме цю зброю, то вона вже не буде такою, якою вона була до викидання!!! Виправимо цю ситуацію. У біндері знайдемо наступний код:

 
function actor_binder:on_item_take (obj)
    level_tasks.proceed(self.object)
end
 

та змінимо так:

 
function actor_binder:on_item_take (obj)
    level_tasks.proceed(self.object)
	project_sip.spawn_old_wpn(obj)
end
 

 

Ця функція відстежує момент взяття ГГ будь-якого об'єкта, аргументує сам об'єкт. У project_sip.script пропишемо наступний код:

 
function spawn_old_wpn(obj)
	for k = 1, #tab_id do –- запускаем цикл на вычисление идетификатора оружия,
                              -- которое было создано в момент удаления апгрейдного оружия (секция которого была записана ранее)
		if obj:id() == tab_id[k] then 
		num = k
		now_wpn_id = tab_id[num]	-- получаем id объекта	
		sect_old = sects[num] –- получаем секцию удаленного апгрейдного оружия
		spawn_del_weap(sect_old,now_wpn_id) –- запускаем функцию снятия и записи нет-пакета в новое оружие,
                                                    -- дабы не нарушить симуляцию
		break
		end
	end
end
-- прототип данной функции не требует комментария, ибо расписывался ранее
function spawn_del_weap(sect_old,now_wpn_id)
local pos_act  = db.actor:position()
pos_act.x = pos_act.x + 0.3
local n_obj = alife():object(now_wpn_id)
local func_net = net_pack_sip.wpn_d_r(n_obj)
alife():release(n_obj,true)
local sobj = alife():create(sect_old,pos_act,db.actor:level_vertex_id(),db.actor:game_vertex_id())
	if sobj then
	new_id = sobj.id – записываем id оружия для перевода его к ГГ
	net_pack_sip.wpn_d_w(func_net,sobj)
	end
return sobj
end
 
function transfer_new_wpn() –- данная функция предназначена для перевода нового заспавненго оружия (апгрейдного к ГГ)
	if new_id ~= nil then
	local wpn = level.object_by_id(new_id)
		if wpn then
		db.actor:transfer_item(wpn,db.actor)
		new_id = nil
		end
	else return
	end
end
 

Далі в біндері знайдемо:

 
function actor_binder:update(delta)
	object_binder.update(self, delta)
 

та нижче напишемо:

 
project_sip.transfer_new_wpn() – для перевода оружия к ГГ
 

скрипт net_pack_sip.script, у якому напишемо наступний код:

 
function wpn_d_r(sobj)
local sv_sip = net_packet()
sobj:STATE_Write(sv_sip)
local size = sv_sip:w_tell()
sv_sip:r_seek(0)
local tab_config = {object_pack = {},visual_pack = {},item_pack = {},item_wpn_packet = {}}
 
local function up_vis_pack(visual_pack,sv_sip,size)
visual_pack.visual_name = sv_sip:r_stringZ()
visual_pack.vsu8u1 = sv_sip:r_u8()
	return visual_pack
end
 
	tab_config.object_pack.gvid = sv_sip:r_u16()
	tab_config.object_pack.obf32u1 = sv_sip:r_float()
	tab_config.object_pack.obs32u2 = sv_sip:r_s32()
	tab_config.object_pack.lvid = sv_sip:r_s32()
	tab_config.object_pack.oflags = sv_sip:r_s32()
	tab_config.object_pack.custom = sv_sip:r_stringZ()
	tab_config.object_pack.sid = sv_sip:r_s32()
	tab_config.object_pack.obs32u3 = sv_sip:r_s32()
 
	up_vis_pack(tab_config.visual_pack,sv_sip,size)
 
	tab_config.item_pack.condition = sv_sip:r_float()
 
	tab_config.item_wpn_packet.ammo_current = sv_sip:r_u16()
	tab_config.item_wpn_packet.ammo_elapsed = sv_sip:r_u16()
	tab_config.item_wpn_packet.weapon_state = sv_sip:r_u8()
	tab_config.item_wpn_packet.addon_flags = sv_sip:r_u8()
	tab_config.item_wpn_packet.ammo_type = sv_sip:r_u8()
 
		return tab_config
end
 
function wpn_d_w(tab_config,sobj)
local sv_sip = net_packet()
local function vis_pack_rd(visual_pack,sv_sip)
sv_sip:w_stringZ(visual_pack.visual_name)
sv_sip:w_u8(visual_pack.vsu8u1)
	return visual_pack
end
 
	sv_sip:w_u16(tab_config.object_pack.gvid)
	sv_sip:w_float(tab_config.object_pack.obf32u1)
	sv_sip:w_s32(tab_config.object_pack.obs32u2)
	sv_sip:w_s32(tab_config.object_pack.lvid)
	sv_sip:w_s32(tab_config.object_pack.oflags)
	sv_sip:w_stringZ(tab_config.object_pack.custom)
	sv_sip:w_s32(tab_config.object_pack.sid)
	sv_sip:w_s32(tab_config.object_pack.obs32u3)
 
	vis_pack_rd(tab_config.visual_pack,sv_sip)
 
	sv_sip:w_float(tab_config.item_pack.condition)
 
	sv_sip:w_u16(tab_config.item_wpn_packet.ammo_current)
	sv_sip:w_u16(tab_config.item_wpn_packet.ammo_elapsed)
	sv_sip:w_u8(tab_config.item_wpn_packet.weapon_state)
	sv_sip:w_u8(tab_config.item_wpn_packet.addon_flags)
	sv_sip:w_u8(tab_config.item_wpn_packet.ammo_type)
 
	sv_sip:w_u16(tab_config.object_pack.gvid)
	sv_sip:w_float(tab_config.object_pack.obf32u1)
	sv_sip:w_s32(tab_config.object_pack.obs32u2)
	sv_sip:w_s32(tab_config.object_pack.lvid)
	sv_sip:w_s32(tab_config.object_pack.oflags)
	sv_sip:w_stringZ(tab_config.object_pack.custom)
	sv_sip:w_s32(tab_config.object_pack.sid)
	sv_sip:w_s32(tab_config.object_pack.obs32u3)
 
local size = sv_sip:w_tell()
sv_sip:r_seek(0)
sobj:STATE_Read(sv_sip,size)
end
 

 


   
Цитата