Обход ограничений mp ranks.ltx (метод рекрита) - Работа со скриптами - Тени Чернобыля - Каталог статей - S.T.A.L.K.E.R - комната модов
Главная | Регистрация | Вход | Приветствую Вас | Гость| RSS















Меню
Категории раздела
Работа со скриптами [32]
Самые разные полезные статьи по скриптам игры S.T.A.L.K.E.R
Работа с конфигами [13]
Всякие полезные материалы по работе со Сталкером ТЧ.
Базовые знания [6]
Основы для тех кто хочет заниматься модами.
Для тех кто чуть больше чем новичок :) [7]
Работа с ACDC, all.spawn , скрипты...
SDK [3]
Все о работе в официальном SDK.
Прохождения модов ТЧ. [20]
Здесь выкладываем различные прохождения кучи различных модов для ТЧ.
Свежий хабар






Главная » Статьи » Тени Чернобыля » Работа со скриптами

Обход ограничений mp ranks.ltx (метод рекрита)

Для начала необходимо продумать, что и как, когда 

и при каких условиях будет работать скрипт. Так как мы его разрабатывали

 для нашего мода, то примеры и все составляющие будут полностью либо 

частично взяты из модификации.

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 

Работа с нет-пакетами будет описана в отдельной статье, объясню лишь общий смысл предназначения нет-пакета. Он предназначен для хранения состояния объекта и его характеристик, и по сути своей является буфером обмена, в котором и хранится вся эта информация, в последующем действии идет запись по определенным таблицам каждого вида характеристик. Во второй функции происходит запись того снятого состояния объекта к новосозданному. Эта операция напоминает алгоритм спавна all.spawn и неспроста! Ибо при статистичном спавне через скрипт объекту также присваивается состояние, которое записано как дефолтовое, а спавн через нет-пакет предусматривает широкий спектр выбора характеристик спавненного оружия что в положительную сторону влияет на симуляцию.Ну вот в общем-то и все, теперь объясню, почему этот метод рекрита работает на 99%. Потому что на выполнение этих всех процессов требуется время, сам биндер запускается с периодом примерно 0,5 сек. (точно не помню), значит, чтобы отследить либо выбрасывание оружия, либо наоборот, его взятие нужен один период биндера, далее также необходим второй период для перевода нового заспавненного оружия к ГГ, итого не для выполнения всех этих действий требуется как минимум 0,8 сек. Почему не переводится при первом периоде биндера, мне так и не удалось выяснить, но факт есть факт, соответственно, если подойти вплотную к НПС и выбросить оружие, то произойдет вылет, если же произвести выбрасывание на некотором расстоянии, к примеру на 10 см, то вылета не будет. Нагрузка на оперативную память незначительна, так что можно смело использовать.В планах совершенствование метода рекрита и доведение его работоспособности до 99,9%.


Byurrer, spark95


P.S. - Если что то не работает (при переносе с сайта stalkerin.gameru.net/wiki могли потеряться пробелы) идем на эту страницу
Категория: Работа со скриптами | Добавил: drweb66 (11.10.2011)
Просмотров: 906 | Рейтинг: 0.0/0
Всего комментариев: 0
avatar
PDA
Поиск
Как вы думаете,
Верите ли вы что СТАЛКЕР 2 выйдет?
Всего ответов: 2098
Сообщения
Разное
AP production - видео обзоры модов для игры S.T.A.L.K.E.R.

На территории Зоны: 1
Отмычек: 1
Опытных ходоков: 0


Design by:
Guenplenтм, with the participation of Orlenok Design Studio ®
Правообладателям
2016