Перепаковщик патронов SoC — S.T.A.L.K.E.R. Inside Wiki

Перепаковщик патронов SoC

Материал из S.T.A.L.K.E.R. Inside Wiki

Версия от 23:42, 29 сентября 2012; 95.134.120.194 (обсуждение)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Вступление


Привет всем. Сегодня наш урок будет о том, как сделать перепаковщик пачек патронов для Теней Чернобыля. Ведь когда играешь и собираешь кучу патронов, не получается сделать элементарную нычку какую-либо, потому что патроны, собранные с убитых вами сталкеров, состоят из 3, 7, 10, 14 и.т.д патронов в каждой пачке, а охота, чтобы все эти патроны перепаковывались в одну или несколько нормальных пачек, вот поэтому я сегодня объясню, как сделать такой же перепаковщик пачек патронов как и во многих других глобальных модах.

Действие 1

Заходим в (gamedata/scripts) и создаём там новый скрипт с таким названием: dunin_ammo.script и вписываем в него вот это:
local ammo = {}
local inited = false
local repack = false
 
--------
-- инициализация переменных, выполняется единожды
--------
function init()
local i, result, section, value
-- отсюда возьмём размеры полных пачек
local sys = system_ini()
-- список патронов возьмём из "death_generic.ltx"
local ini = ini_file("misc\\death_generic.ltx")
local n = ini:line_count("ammo_sections")
for i=0,n-1 do
result, section, value = ini:r_line("ammo_sections",i,"","")
ammo[section] = {}
ammo[section].repack = false
ammo[section].box = sys:r_u32(section, "box_size")
end
repack = false
inited = true
end
 
--------
-- вызывается при добавлении в инвентарь ГГ любых патрон
-- obj - game_object добавляемой пачки
-- здесь будем только ставить флажки о необходимости проверки,
-- саму проверку и перепаковку сделаем в апдейте актёра,
-- если перепаковку делать прям здесь, то будет глюк при загрузки и
-- при взятии из нычки кучи патрон (взять всё)
--------
function on_take(obj)
if not inited then
init()
end
 
local section = obj:section()
--dbglog("on_take('%s')", section)
--local msg = string.format("on_take('%s')", obj: name())
--get_console():execute("dbg:" .. msg)
 
if ammo[section] ~= nil and section ~= nil and ammo[section].repack == false then
if get_ammo_size(obj) < ammo[section].box then
ammo[section].repack = true
repack = true
end
end
end
 
 
--------
-- вызывается из апдейта актёра
-- проверяет наличие флажков и вызывает процедуру переупаковки
--------
function on_update()
if repack then
local section, data
for section, data in pairs(ammo) do
if data.repack then
repack_ammo(section, data.box)
data.repack = false
end
end
repack = false
end
end
 
--------
-- переупаковка патронов заданного типа
-- section - строка, имя секции (тип патрон)
-- box_size - колличество патрон в полной пачке
-- сначало составляем список неполных пачек, затем
-- удаляем их и создаём нужное колличество полных
--------
function repack_ammo(section, box_size)
--dbglog("repack_ammo('%s')", section)
local s, t = enum_ammo(section, box_size)
if (s > 0) and (table.getn(t) > 1) then
--dbglog("repacking(magazins=%d, bullets=%d)", table.getn(t), s)
local i, id
local sim = alife()
local pos = db.actor:position()
local lvid = db.actor:level_vertex_id()
local gvid = db.actor:game_vertex_id()
local pid = db.actor:id()
 
for i, id in pairs(t) do
sim:release(sim:object(id), true)
end
 
while s >= box_size do
sim:create_ammo(section, pos, lvid, gvid, pid, box_size)
s = s - box_size
end
 
if s > 0 then
sim:create_ammo(section, pos, lvid, gvid, pid, s)
end
end
end
 
--------
-- пробегаемся по инветарю ГГ и собираем инфу о неполных пачках
-- section - строка, имя секции (тип патрон)
-- box_size - колличество патрон в полной пачке
-- возвращает сумарное колличество патрон в неполных пачках и массив id-шников этих пачек
--------
function enum_ammo(section, box_size)
local i, obj, size
local s = 0
local t = {}
for i=0, db.actor:object_count()-1 do
obj = db.actor:object(i)
if obj:section() == section then
size = get_ammo_size(obj)
if size < box_size then
table.insert(t, obj:id())
s = s + size
end
end
end
return s, t
end
 
--------
-- возвращает колличество патрон в пачке
-- вроде подходящих функций нет, пришлось делать через net_packet
--------
function get_ammo_size(obj)
local se_obj = alife():object(obj:id())
local packet = net_packet()
cse_alife_item_ammo.STATE_Write(se_obj, packet)
--packet:r_advance(18)
--packet:r_stringZ()
--packet:r_advance(8)
--packet:r_stringZ()
--packet:r_advance(5)
packet:r_seek(packet:w_tell() - 2)
return packet:r_u16()
end

Действие 2:

Теперь нам нужно вписать наш перепаковщик патронов в bind_stalker.script, открываем его и ищем там такую функцию:

function actor_binder:on_item_take (obj)

и ставим внизу перед "end" вот такую функцию:

dunin_ammo.on_take(obj)

Вот как должно у нас получится:

function actor_binder:on_item_take (obj)
level_tasks.proceed(self.object)
--game_stats.update_take_item (obj, self.object)
dunin_ammo.on_take(obj)
end

Далее в этом же bind_stalker.script ищем функцию:

-- апдейт звуковой схемы актера
xr_sound.update_actor()

И ставим после неё функцию нашего перепаковщика:

-- перепаковщик патронов
dunin_ammo.on_update()

Вот как должно получится:

-- апдейт звуковой схемы актера
xr_sound.update_actor()
 
-- перепаковщик патронов
dunin_ammo.on_update()

Всё, готово, сохраняем bind_stalker.script и тестируем.

Участник:VIPeRs

Другие места
LANGUAGE