Гость
Статистика Форума
Последнии темы Популярные темы Лучшии пользователи Новые пользователи
» [16.12.2018] Шаблон AniMan v2 для uCoz (0)
» [13.12.2018] Полный список кодов ответов FTP сервера (0)
» [13.12.2018] Список кодов состояния HTTP (0)
» [13.12.2018] Прозрачность элементов при помощи CSS (0)
» [13.12.2018] Полная таблица alt-кодов (0)
» [13.12.2018] Таблица Web - оттенков (0)
» [02.12.2018] Hardcore pack for SGM 2.2 (0)
» [02.12.2018] Geonezis Addon for SGM 2.0 (0)
» [02.12.2018] F.A.Q по прохождению модификации Ф.О.Т.О.Г.Р.А.... (5)
» [02.12.2018] Лечение вылетов "Ф.О.Т.О.Г.Р.А.Ф" (0)
» Тайники и подсказки (82)
» FAQ прохождения по локациям DOPPELGANGER 7.63 Time Gap (50)
» Русскоязычное руководство по моду Frackin' Universe... (38)
» Фоны для сталкерского сайта (32)
» [DMX] Народное творчество (24)
» Capital-Rp Wikia Code (22)
» ГИД Прохождение остальных квестов ОП - 2 (21)
» CoC Вылеты и их решение (21)
» Личные сообщения (18)
» Редактирование мода «Народная солянка Объединенный пак ... (18)
» Xemordio (3024)
» NL-Vincenz (12)
» Duzeppa26 (5)
» Ghosteron (4)
» Glomar (1)
» ZION (1)
» gromgold (1)
» Бармен (1)
» Даниил_Хороший (1)
» goooooooooogle380 (0)
» [16.12.2018] styder2012
» [15.12.2018] Dead_Land
» [12.12.2018] revere98
» [12.12.2018] olegrayviner
» [07.12.2018] Ne_NuJeN
» [07.12.2018] gorelov
» [06.12.2018] prist12332
» [06.12.2018] jorik501
» [04.12.2018] колючий
» [03.12.2018] iozef32

  • Страница 1 из 1
  • 1
Форум » Игры // games » S.T.A.L.K.E.R. » Модостроение сталкер » Патроны в поясе+перепаковщик патронов
Патроны в поясе+перепаковщик патронов
Xemordio Offline Дата: Пятница, 21.09.2018, 12:24 | Сообщение # 1
Администратор
Звание: Маршал [?]
Сообщений: 3024
Патроны в поясе и перепаковщик патронов. Решил создать тему, так как нигде не нашел туториал, как добавить в игру патроны в поясе(или адаптировать). Возможно, кому-то они еще понадобятся.

Патроны в поясе
Действие 1(скрипты).

Создаем скрипт с названием mod_man.script и пишем туда:

Код
--dbg.log("MOD_MAN: start")

local actor_update_func = {}
local actor_item_take_func = {}
local actor_item_drop_func = {}
local actor_car_body_func = {}
local actor_car_body_hide_func = {}
local actor_inventory_func = {}
local actor_inventory_hide_func = {}

function register_actor_update(func)
      table.insert(actor_update_func, func)
end

function register_actor_item_take(func)
      table.insert(actor_item_take_func, func)
end

function register_actor_item_drop(func)
      table.insert(actor_item_drop_func, func)
end

function register_on_actor_car_body(func)
      table.insert(actor_car_body_func, func)
end

function register_on_actor_car_body_hide(func)
      table.insert(actor_car_body_hide_func, func)
end

function register_actor_inventory(func)
      table.insert(actor_inventory_func, func)
end

function register_actor_inventory_hide(func)
      table.insert(actor_inventory_hide_func, func)
end

function on_actor_update()
      call_from_table(actor_update_func)
end

function on_actor_item_take(item)
--    dbg.log("MOD_MAN: on_actor_item_take(item=%s)", item:name())
      call_from_table(actor_item_take_func, item)
end

function on_info(info_id)
      if info_id == "ui_car_body" then
       call_from_table(actor_car_body_func)
      elseif info_id == "ui_car_body_hide" then
       call_from_table(actor_car_body_hide_func)
      elseif info_id == "ui_inventory" then
       call_from_table(actor_inventory_func)
      elseif info_id == "ui_inventory_hide" then
       call_from_table(actor_inventory_hide_func)       
      end
end

function init()
      --dbg.log("MOD_MAN: init")
      local ini = ini_file("mods.ltx")
      local s = ini:r_string("mods", "register")
      local t = str_explode(",", s, true)
      for i, v in ipairs(t) do
       --dbg.log("MOD_MAN: find mod %s", v)
       loadstring(v..".register()")()
      end
end

function call_from_table(t,...)
      for i, f in ipairs(t) do
       f(...)
      end
end

function trim (s)
      return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end

function str_explode(div,str,clear)
      local t={}
      local cpt = string.find (str, div, 1, true)
      if cpt then
       repeat
        if clear then
         table.insert( t, trim(string.sub(str, 1, cpt-1)) )
        else
         table.insert( t, string.sub(str, 1, cpt-1) )
        end
        str = string.sub( str, cpt+string.len(div) )
        cpt = string.find (str, div, 1, true)
       until cpt==nil
      end
      if clear then
       table.insert(t, trim(str))
      else
       table.insert(t, str)
      end
      return t
end


Все, скрипт готов.

Теперь создаем скрипт с названием inventory.script и пишем туда:

Код
belt = {}
belt_id = {}
belt_status = false

local need_update = true
local inventory_open = false
local separator_spawned = false
local separator = "separator"

local debug = false
local flag

function update()

     if (need_update == false) then return end

     if debug == true and belt_status == true then get_console():execute("belt_status=false") end
     belt_status = false

     -- Спавним разделяющий елемент
     if (separator_spawned == false) then
      alife():create(separator,
       db.actor:position(),
       db.actor:level_vertex_id(),
       db.actor:game_vertex_id(),
       db.actor:id())
      separator_spawned = true
      if debug == true then get_console():execute("separator_spawned") end
      return
     end

     belt = {}
     belt_id = {}
     flag = 0

     -- Сканируем инвентарь
     db.actor:inventory_for_each(scan_inv)
     need_update = false

     -- Удаляем разделяющий елемент
     db.actor:inventory_for_each(del_separator)
     separator_spawned = false

     if debug == true and belt_status == false then get_console():execute("belt_status=true") end
     belt_status = true

     if debug == true then
      for i,k in pairs(belt) do
       get_console():execute(i.."="..k)
      end
     end
end

-- Перебор предметов инвентаря
function scan_inv(item)
     local section = item:section()

     if section == separator then
      flag = 1
      return
     end

     if flag == 1 then
      if slot_item(item) ~= nil then
       flag = 2
      else
       insert_to_table(belt, section)
       belt_id[item:id()] = true
      end
     end
end

-- Добавление в таблицу
function insert_to_table(tbl, section)
     if tbl[section] == nil then
      tbl[section] = 1
     else
      tbl[section] = tbl[section] + 1
     end
end

-- Удаление разделяющего предмета
function del_separator(item)
     if item:section() == separator then
      alife():release(alife():object(item:id()), true)
      if debug == true then get_console():execute("separator_removed") end
     end
end

-- Определение налечия предмета в одном из слотов
function slot_item(item)
     for i=0,12 do
      local obj = db.actor:item_in_slot(i)
      if obj and item:id() == obj:id() then
       return i
      end
     end

     return nil
end

-- Поднятие предмета
function on_item_take(item)
     if item:section() == separator then return end

     if (inventory_open == false) then
      if (separator_spawned == true) then
       db.actor:inventory_for_each(del_separator)
       separator_spawned = false
      end

      need_update = true
      if debug == true then get_console():execute("item_take") end
     end
end

-- Выброс предмета
function on_item_drop(item)
     if item:section() == separator then return end

     if (inventory_open == false) then
      if (separator_spawned == true) then
       db.actor:inventory_for_each(del_separator)
       separator_spawned = false
      end

      need_update = true
      if debug == true then get_console():execute("item_drop") end
     end
end

-- Открытие/закрытие инвентаря
function on_inventory_info(info_id)
     if info_id == "ui_inventory" then
      inventory_open = true
      if debug == true then get_console():execute("inventory_open") end

     elseif info_id == "ui_inventory_hide" then
      inventory_open = false
      need_update = true
      if debug == true then get_console():execute("inventory_close") end
     end
end

function check_blood()
--   if belt_status == true then
          if belt["af_blood"]~=nil and belt["af_blood"]>0 then -- то есть когда параметр пояса[af_blood] равен 1, 2, 3.. Сколько навесишь Камней.
                 amk.send_tip("Кровь Камня на поясе")
              end
--   end
end



Все, скрипт готов.

Теперь создаем еще один скрипт ammo_ctrl.script и пишем туда следующее:
Код
local ammo_types = {
--    ["grenade_f1"] = true,
--    ["grenade_rgd5"] = true,
       ["ammo_9x18_fmj"] = true,
       ["ammo_9x18_pbp"] = true,
       ["ammo_9x18_pmm"] = true,
       ["ammo_9x19_pbp"] = true,
       ["ammo_9x19_fmj"] = true,
       ["ammo_5.45x39_ap"] = true,
       ["ammo_5.45x39_fmj"] = true,
       ["ammo_5.56x45_ap"] = true,
       ["ammo_5.56x45_ss190"] = true,
       ["ammo_5.7x28_fmj"] = true,
       ["ammo_5.7x28_ap"] = true,
       ["ammo_7.62x54_ap"] = true,
       ["ammo_7.62x54_7h14"] = true,
       ["ammo_7.62x54_7h1"] = true,
       ["ammo_9x39_sp5"] = true,
       ["ammo_9x39_ap"] = true,
       ["ammo_9x39_pab9"] = true,
       ["ammo_gauss"] = true,
       ["ammo_11.43x23_fmj"] = true,
       ["ammo_11.43x23_hydro"] = true,
       ["ammo_12x76_dart"] = true,
       ["ammo_12x76_zhekan"] = true,
       ["ammo_12x70_buck"] = true,
       ["ammo_og-7b"] = true,
       ["ammo_vog-25p"] = true,
       ["ammo_vog-25"] = true,
--    ["ammo_m209"] = true,
}
local ammo_fake_types = {}

local need_convert = false
local need_init = true
local need_update = false
local before_update = true

function on_update()
       if before_update then
        before_update = false
        need_convert = true
        --dbg.log("AMMO_CTRL: first update, may convert")        
       end
             
       if not need_update then return end
       --dbg.log("AMMO_CTRL: update")
       if not inventory.belt_status then return end
       --dbg.log("AMMO_CTRL: update 1")
             
       local t = {}
       db.actor:iterate_inventory(
        function(npc, item)
         if ammo_types[item:section()] and inventory.belt_id[item:id()] == nil then
          --dbg.log("AMMO_CTRL: find item %s", item:name())         
          table.insert(t, item:id())
         end
        end
        , db.actor)
              
       for i, id in ipairs(t) do
        local sim = alife()
        local obj = level.object_by_id(id)
        local cnt = get_ammo_size(obj)
        if cnt ~= 0 then
         sim:release(sim:object(id), true)
         local npc = db.actor
         local section = obj:section()
         local newsect = section.."_fake"
         spawn_ammo_in_inv(newsect, cnt, db.actor)
        end
       end       
             
       need_update = false
end

function on_inventory_open()
       --dbg.log("AMMO_CTRL: on_inventory_open")
       need_convert = false
       local t = {}
       db.actor:iterate_inventory(
        function(npc, item)
         if ammo_fake_types[item:section()] then
          --dbg.log("AMMO_CTRL: find item %s", item:name())
          table.insert(t, item:id())
         end
        end
        , db.actor)
              
       for i, id in ipairs(t) do
        local sim = alife()
        local obj = level.object_by_id(id)
        local cnt = get_ammo_size(obj)
        if cnt ~= 0 then
         sim:release(sim:object(id), true)
         local npc = db.actor
         local section = obj:section()
         local newsect = string.sub(section, 1, string.len(section) - 5)
         spawn_ammo_in_inv(newsect, cnt, db.actor)
        end
       end
end

function on_inventory_close()
       --dbg.log("AMMO_CTRL: on_inventory_close")
       need_convert = true
       need_update = true
end

function on_item_drop(item)
       --dbg.log("AMMO_CTRL: on_item_drop")
end

function on_item_take(item)
       if need_init then init() end

       --dbg.log("AMMO_CTRL: on_item_take")       
       local section = item:section()
       if ammo_types[section] and need_convert then       
        local cnt = get_ammo_size(item)
        if cnt == 0 then return end
        local sim = alife()
        sim:release(sim:object(item:id()), true)
        local newsect = section.."_fake"
        spawn_ammo_in_inv(newsect, cnt, db.actor)
       end
end

function init()
       --dbg.log("AMMO_CTRL: init")
       for k, v in pairs(ammo_types) do
        ammo_fake_types[k.."_fake"] = v
       end
       need_init = false
end

function register()
       --dbg.log("AMMO_CTRL: register")
       mod_man.register_actor_update(on_update)
       mod_man.register_actor_item_take(on_item_take)
       mod_man.register_actor_item_drop(on_item_drop)
       mod_man.register_actor_inventory(on_inventory_open)
       mod_man.register_actor_inventory_hide(on_inventory_close)
end

--------
-- возвращает колличество патрон в пачке
-- вроде подходящих функций нет, пришлось делать через net_packet
--------
function get_ammo_size(obj)
       local se_obj = alife():object(obj:id())
       if se_obj == nil then return 0 end       
       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

function spawn_ammo_in_inv(spawn_item,number,npc)
       if npc==nil then       
        npc=db.actor       
       end
       if number > 0 then
        return se_respawn.create_ammo(spawn_item,       
         npc:position(),
         npc:level_vertex_id(),        
         npc:game_vertex_id(),
         npc:id(),
         number)
       end
end


Скрипты готовы. Кидаем все скрипты в папку gamedata/scripts

Теперь пропишем эти оба скрипта в bind_stalker.script
Путь:gamedata\scripts\bind_stalker.script

в функции(строки)
function actor_binder:info_callback(npc, info_id)
в конец добавляется
mod_man.on_info(info_id)
inventory.on_inventory_info(info_id)


в функции
function actor_binder:on_item_take (obj)
в конец добавляется
mod_man.on_actor_item_take(obj)
inventory.on_item_take(obj)

в функции
function actor_binder:update(delta)
в конец добавляется
mod_man.on_actor_update()
inventory.update()


в функции
function actor_binder:on_item_drop (obj)
в конец добавляется
inventory.on_item_drop(obj)

Пример:
function actor_binder:info_callback(npc, info_id)
printf("*INFO*: npc='%s' id='%s'", npc:name(), info_id)
--' Сюжет
level_tasks.proceed(self.object)
-- Отметки на карте
level_tasks.process_info_portion(info_id)
inventory.on_inventory_info(info_id)
mod_man.on_info(info_id)
end


Вот так должно выглядеть.

Все, в bind_stalker.script все готово, а теперь пропишем в скрипте _g.script скрипт mod_man.script:

в функцию
start_game_callback()
в конец добавляется
mod_man.init()

Все, готово.

Действие 2(конфиги).
Создаем конфиг с названием mods.ltx и пишем туда следующее:
Code
[mods]
        register = ammo_ctrl

Кидаем конфиг mod.ltx в папку gamedata/config

В папке gamedata/configs/weapons создаем конфиг ammo_fake.ltx и в нее пропишем следуещее:

Code
[ammo_9x18_fmj_fake]:ammo_9x18_fmj
[ammo_9x18_pbp_fake]:ammo_9x18_pbp
[ammo_9x18_pmm_fake]:ammo_9x18_pmm
[ammo_9x19_pbp_fake]:ammo_9x19_pbp
[ammo_9x19_fmj_fake]:ammo_9x19_fmj
[ammo_5.45x39_ap_fake]:ammo_5.45x39_ap
[ammo_5.45x39_fmj_fake]:ammo_5.45x39_fmj
[ammo_5.56x45_ap_fake]:ammo_5.56x45_ap
[ammo_5.56x45_ss190_fake]:ammo_5.56x45_ss190
[ammo_5.7x28_fmj_fake]:ammo_5.7x28_fmj
[ammo_5.7x28_ap_fake]:ammo_5.7x28_ap
[ammo_7.62x54_ap_fake]:ammo_7.62x54_ap
[ammo_7.62x54_7h14_fake]:ammo_7.62x54_7h14
[ammo_7.62x54_7h1_fake]:ammo_7.62x54_7h1
[ammo_9x39_sp5_fake]:ammo_9x39_sp5
[ammo_9x39_ap_fake]:ammo_9x39_ap
[ammo_9x39_pab9_fake]:ammo_9x39_pab9
[ammo_gauss_fake]:ammo_gauss
[ammo_11.43x23_fmj_fake]:ammo_11.43x23_fmj
[ammo_11.43x23_hydro_fake]:ammo_11.43x23_hydro
[ammo_12x76_dart_fake]:ammo_12x76_dart
[ammo_12x76_zhekan_fake]:ammo_12x76_zhekan
[ammo_12x70_buck_fake]:ammo_12x70_buck
[ammo_og-7b_fake]:ammo_og-7b
[ammo_vog-25p_fake]:ammo_vog-25p
[ammo_vog-25_fake]:ammo_vog-25


Все, конфиг готов. Этот конфиг ammo_fake.ltx пропишем в файле weapons.ltx
Для этого открываем weapons.ltx и в конце пропишем следующее:

;Патроны на поясе
#include "ammo_fake.ltx"


Пока weapons.ltx не закрывем, в секции AMMUNITION , отредактируем строку ;belt=false; .
false меняем на true и перед строкой ;belt = true; убираем точку запятой, должно выглядеть так: belt = true;

А тепер в gamedata/configs/misc открываем файл items.ltx и в конце пропишем следующее:

Code
[separator]:bread
inv_grid_width   = 0
inv_grid_height   = 0
inv_weight   = 0


Вроде все с патронами в поясе.

Слоты в поясе.

Слоты в инвентаре добавляйте сами. Сделайте в фотошопе если умеете. Чтоб самому нарисовать, заходим
в папку gamedata/texstures/ui/ и находите там файл inventory_belt.dds. Открываете ее и редактируете.
Если сделали 16 слотов в поясе, то не забудьте прописать слоты и координаты в файле gamedata/configs/ui/inventory_new.xml и inventory_new_16.xml
Например:
Code
<belt_slots x="10" y="-1" width="1014" height="128">
              <texture>ui\inventory_belt</texture>              
                     <text x="15" y="142" font="graffiti22" r="231" g="153" b="22">ui_inv_belt</text>
             </belt_slots>             
Где строка <texture>ui\inventory_belt</texture> это путь вашему отредактированному слоту инвентаря.

<dragdrop_belt x="40" y="174" width="1005" height="60"
                        cell_width = "53" cell_height="53" rows_num="1" cols_num="16" custom_placement="1"/>
Где: rows_num="1"-это означает все слоты в одном ряду, если там значение 2, то слоты расположены в двух рядах, на первом ряду 8, во втром 8.
                 cols_num="16"-это количество слотов.


Перепаковщик патронов.
Действие 1(скрипты).
Заходим в (gamedata/scripts) и создаём там новый скрипт с таким названием: dunin_ammo.script и вписываем в него вот это:

Code
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


Готово.

Теперь нам нужно вписать наш перепаковщик патронов в 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 и тестируем.

Туториал о перепаковщике патронов взял из inside, автор VIPeRs.

Возможно, кому-то покажется, что я не все правильно написал, если так, прошу поправить. Надеюсь ничего не забыл.
Патроны в поясе для чистой ТЧ http://www.sendspace.com/file/zdqjzs
Дата регистрации: 22.07.2017
Форум » Игры // games » S.T.A.L.K.E.R. » Модостроение сталкер » Патроны в поясе+перепаковщик патронов
  • Страница 1 из 1
  • 1
Поиск:

02:21