Случайная подборка модов
Смерти Вопреки. Послушник
3.4
Альтернатива 1.1 Beta
3.0
Ф.О.Т.О.Г.Р.А.Ф
4.2
Another Zone Mod
4.3
Время перемен v2.0
4.1
Блудный сын
2.8
Последние обновленные темы Прямой эфир Самые популярные темы Последние новости
  • Страница 1 из 1
  • 1
Архив - только для чтения
Форум » Архив » Устаревшие темы » Магазинное питание оружия (Попробуем разобраться, как адаптировать под различные моды)
Магазинное питание оружия
Российская Федерация  Mirage
Воскресенье, 03.02.2013, 13:13 | Сообщение # 1
Независимый аниматор
Статус:
Бывалый:
Сообщений: 1130
Награды: 2
Регистрация: 09.06.2012

Только для версии 1.0006, у 1.0004 xr_motivator по другому адаптируется.
Многие игроки знают, что существует такая модификация от товарища Kirag, но не умеют адаптировать под свои любимые моды. В этой статье, попробуем разобраться, что да как.
Итак, самое трудное при адаптации этого мода-это адаптация скриптов. С них и начнем.
Адаптация скриптов.
Сначала попробуем адаптировать _g.script.
Открываем ее через блокнот и после строчек

Код
function dbglog(fmt,...)
       local msg = string.format(fmt, ...)
       local msg_no_ws = string.gsub(msg, "%s", "_")
       get_console():execute("dbg:" .. msg_no_ws)
end


добавляем вот такие строчки:
Код

function qqq(n,o)
       local scr = true
       local con = true
       if o then
        if o == 1 or o == 0 then
         scr = false
        end
        if o == 2 or o == 0 then
         con = false
        end
       end
       local k = "debug data QQQ "..tostring(n)
       if scr then
        if db.actor then
         news_manager.send_tip(db.actor, k, nil, nil, 5000)       
        end
       end
       if con then
        get_console():execute    ("load "..k)       
        get_console():execute    ("flush")       
       end
end

function qqqv(v,n,o)
       local scr = true
       local con = true
       if type(v) == "string" then
        v_name = v
       else
        o = n
        n = v
        v_name = "vector"
       end
       if o then
        if o == 1 or o == 0 then
         scr = false
        end
        if o == 2 or o == 0 then
         con = false
        end
       end
       local v_comp = ": nil"
       if n ~= nil then
        v_comp = ": x = "..n.x..", y = "..n.y..", z = "..n.z
       end
       local k = "debug data QQQ "..v_name..v_comp
       if scr then
        if db.actor then
         news_manager.send_tip(db.actor, k, nil, nil, 5000)       
        end
       end
       if con then
        get_console():execute    ("load "..k)       
        get_console():execute    ("flush")       
       end
end

function parse_data(str)
       local string_parts = {}
       if str == nil then
        string_parts[1] = nil
        return string_parts
       end
       local str_beg,str_end
       str_end = str
       local split_pos = find_split_pos(str_end)
       while split_pos ~= nil do
        str_beg, str_end = split_string(str_end,split_pos)
        table.insert(string_parts,str_beg)
        split_pos = find_split_pos(str_end)
       end
       table.insert(string_parts,str_end)
       return string_parts
end

function find_split_pos(str)
       local split_pos = string.find(str,",")
       if split_pos == nil then
        return nil
       end
       local br1_pos = string.find(str,"(",1,true)
       local br2_pos = string.find(str,")",1,true)
       if br1_pos ~= nil and br2_pos ~= nil and br1_pos < br2_pos and split_pos > br1_pos then
        local str_end1 = string.sub(str,(br2_pos +1),string.len(str))
        if string.find(str_end1,",") ~= nil then
         split_pos = br2_pos + string.find(str_end1,",")
        else
         split_pos = nil
        end
       end
       return split_pos
end

function split_string(str,split_pos)
       local str_beg = (string.sub(str,1,split_pos-1))
       local str_end = string.sub(str,(split_pos+1),string.len(str))
       return str_beg,str_end
end


Внимание, у каждой модификации _g.script отличаются. Если такой строчки нет, то добавляйте это перед строкой
Код
----------------------------------------------------------------------
if nil == time_global then
       time_global = function () return device():time_global() end
end


Скрип наполовину готов. Находим в самом конце вот такие строчки:
Код
ammo_section = {}
ammo_section["ammo_9x18_fmj"]  = true
ammo_section["ammo_9x18_pbp"]  = true
ammo_section["ammo_9x18_pmm"]  = true
ammo_section["ammo_9x19_fmj"]  = true
ammo_section["ammo_9x19_pbp"]  = true
ammo_section["ammo_5.45x39_fmj"]    = true
ammo_section["ammo_5.45x39_ap"]  = true
ammo_section["ammo_5.56x45_ss190"]    = true
ammo_section["ammo_5.56x45_ap"]  = true
ammo_section["ammo_5.7x28_fmj"]  = true
ammo_section["ammo_5.7x28_ap"]  = true
ammo_section["ammo_7.62x54_7h1"]    = true
ammo_section["ammo_7.62x54_ap"]  = true
ammo_section["ammo_7.62x54_7h14"]    = true
ammo_section["ammo_9x39_pab9"]  = true
ammo_section["ammo_gauss"]   = true
ammo_section["ammo_9x39_ap"]  = true
ammo_section["ammo_9x39_sp5"]  = true
ammo_section["ammo_11.43x23_fmj"]    = true
ammo_section["ammo_11.43x23_hydro"]    = true
ammo_section["ammo_12x70_buck"]  = true
ammo_section["ammo_12x76_dart"]  = true
ammo_section["ammo_12x76_zhekan"]    = true

Удаляем все эти строки, так как там не все патроны и вставим вот это:
Код
ammo_section = {}
ammo_section["ammo_9x18_fmj"]  = true
ammo_section["ammo_9x18_pbp"]  = true
ammo_section["ammo_9x18_pmm"]  = true
ammo_section["ammo_9x19_fmj"]  = true
ammo_section["ammo_9x19_pbp"]  = true
ammo_section["ammo_5.45x39_fmj"]    = true
ammo_section["ammo_5.45x39_ap"]  = true
ammo_section["ammo_5.56x45_ss190"]    = true
ammo_section["ammo_5.56x45_ap"]  = true
ammo_section["ammo_5.7x28_fmj"]  = true
ammo_section["ammo_5.7x28_ap"]  = true
ammo_section["ammo_7.62x54_7h1"]    = true
ammo_section["ammo_7.62x54_ap"]  = true
ammo_section["ammo_7.62x54_7h14"]    = true
ammo_section["ammo_9x39_pab9"]  = true
ammo_section["ammo_gauss"]   = true
ammo_section["ammo_9x39_ap"]  = true
ammo_section["ammo_9x39_sp5"]  = true
ammo_section["ammo_11.43x23_fmj"]    = true
ammo_section["ammo_11.43x23_hydro"]    = true
ammo_section["ammo_12x70_buck"]  = true
ammo_section["ammo_12x76_dart"]  = true
ammo_section["ammo_12x76_zhekan"]    = true
ammo_section["ammo_357_jfp"]  = true
ammo_section["ammo_357_jhp"]  = true
ammo_section["ammo_7.62x25_p"]  = true
ammo_section["ammo_7.62x25_ps"]  = true
ammo_section["ammo_7.62x39_fmj"]    = true
ammo_section["ammo_7.62x39_ap"]  = true
ammo_section["ammo_7.62x51_fmj"]    = true
ammo_section["ammo_7.62x51_ap"]  = true
ammo_section["ammo_7.92x57_fmj"]    = true
ammo_section["ammo_7.92x57_ap"]  = true
ammo_section["ammo_bolt"]   = true
ammo_section["ammo_gauss_std"]  = true
ammo_section["ammo_gauss_ndl"]  = true
ammo_section["ammo_samopal"]  = true


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

А теперь перейдем к скрипту bind_stalker.script. Тут уже сложнее.
Открываем скрипт.
В функции
----------------------------------------------------------------------------------------------------------------------
function actor_binder:net_spawn(data)
после строк
if(actor_stats.add_to_ranking~=nil)then
actor_stats.add_to_ranking(self.object:id())
end
добавляем вот эти строки:
Код
if xr_logic.pstor_retrieve(db.actor, "first_run", 0)==0 then       
        -- доп. учет веса
        if not db.actor:object("dark_matter_container1") then
         spawn.inv("dark_matter_container1")
        end
        if not db.actor:object("dark_matter_container2") then
         spawn.inv("dark_matter_container2")
        end
              
        xr_logic.pstor_store(db.actor, "first_run", 1)
              end


Так, идем дальше.

В функции
----------------------------------------------------------------------------------------------------------------------
function actor_binder:net_destroy()
После строки
self.object:set_callback(callback.take_item_from_box, nil)
добавляем строку
self.object:set_callback(callback.death, nil)

Дальше в функции
----------------------------------------------------------------------------------------------------------------------
function actor_binder:reinit()
После строки
self.object:set_callback(callback.take_item_from_box, self.take_item_from_box, self)
добавляем строку
self.object:set_callback(callback.death, self.death_callback, self)

Итак, у вас получилось вот так:
Код
function actor_binder:reinit()
       object_binder.reinit(self)
             
       local npc_id = self.object:id()

       db.storage[npc_id] = { }

       self.st = db.storage[npc_id]
       self.st.pstor = nil

       self.next_restrictors_update_time = -10000

       self.object:set_callback(callback.inventory_info, self.info_callback, self)
       self.object:set_callback(callback.article_info, self.article_callback, self)
       self.object:set_callback(callback.on_item_take, self.on_item_take, self)
       self.object:set_callback(callback.on_item_drop, self.on_item_drop, self)
       self.object:set_callback(callback.trade_sell_buy_item, self.on_trade, self) -- for game stats
       --self.object:set_callback(callback.actor_sleep, self.sleep_callback, self)
       self.object:set_callback(callback.task_state, self.task_callback, self)
       --self.object:set_callback(callback.map_location_added, self.map_location_added_callback, self)
       self.object:set_callback(callback.level_border_enter, self.level_border_enter, self)
       self.object:set_callback(callback.level_border_exit, self.level_border_exit, self)
       self.object:set_callback(callback.take_item_from_box, self.take_item_from_box, self)
              self.object:set_callback(callback.death, self.death_callback, self)
end

А сейчас после end создаем новую функцию, то есть пишем все это:
Код
----------------------------------------------------------------------------------------------------------------------
function actor_binder:death_callback(victim, who)
       local slot4 = db.actor:item_in_slot(5)
       if slot4 then
        db.actor:activate_slot(0)
        --db.actor:transfer_item(slot4,db.actor)
        --[[
        db.actor:drop_item(slot4)
        spawn.inv("wpn_binoc")
        --]]
        --alife():release(alife():object(slot4:id()),true)
       end
       --qqq("death callback")
end


Все, идем дальше.

В функции
----------------------------------------------------------------------------------------------------------------------
function actor_binder:info_callback(npc, info_id)
После строки
-- Отметки на карте
level_tasks.process_info_portion(info_id)
добавляем строки
Код
if info_id == "ui_inventory" then
        inv.on_inv_open()
       elseif info_id == "ui_inventory_hide" then
        inv.on_inv_close()
       elseif info_id == "ui_trade" then
        inv.on_trade_open()
       elseif info_id == "ui_trade_hide" then
        inv.on_trade_close()
       elseif info_id == "ui_car_body" then
        inv.on_search_open()
       elseif info_id == "ui_car_body_hide" then
        inv.on_search_close()
       end

В итоге получиться так, к примеру:
Код
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)
              -- Состояние инвентаря
       if info_id == "ui_inventory" then
        inv.on_inv_open()
       elseif info_id == "ui_inventory_hide" then
        inv.on_inv_close()
       elseif info_id == "ui_trade" then
        inv.on_trade_open()
       elseif info_id == "ui_trade_hide" then
        inv.on_trade_close()
       elseif info_id == "ui_car_body" then
        inv.on_search_open()
       elseif info_id == "ui_car_body_hide" then
        inv.on_search_close()
       end
end


Пошли дальше.

В этой функции добавляем строчку, который я показал красным светом:
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_item_take (obj)
level_tasks.proceed(self.object)
kirag_take_drop.on_take(obj)

if rx_ai then rx_ai.actor_item_take(obj) end
if xrs_ai then xrs_ai.actor_item_take(obj) end

--game_stats.update_take_item (obj, self.object)
end
И в следующей функции поступаем также:
----------------------------------------------------------------------------------------------------------------------
function actor_binder:on_item_drop (obj)
level_tasks.proceed(self.object)
kirag_take_drop.on_drop(obj)

--game_stats.update_drop_item (obj, self.object)
end

Готово.

Дальше в функции
----------------------------------------------------------------------------------------------------------------------
function actor_binder:update(delta)
После строки
object_binder.update(self, delta)
Добавляем
if not self.updated then
if inv.init_dark_matter() then
self.updated = true
end
end

В этой же функции после строки
game_stats.update (delta, self.object)
добавляем строки
ammo_manager.update()

kirag_take_drop.on_update()

kirag_take_drop.autopickup_update()

if not inv.inv_mass then
inv.update_mass()
end


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

Осталось адаптировать скрипт xr_motivator.script.
В функции
function motivator_binder:death_callback(victim, who)
после строки
self:clear_callbacks()
добавляем строки
Код
if self.ammo_in_use and (string.sub(self.ammo_in_use,1,4) == "mag_" or string.sub(self.ammo_in_use,1,5) == "clip_" or string.sub(self.ammo_in_use,1,5) == "belt_") then
        local count = math.random(1,4)
        for i = 1,count do
         spawn.inv(self.ammo_in_use,self.object:id()) -- если совсем нет патронов - выдаем
        end
       end


Идем дальше:

В функции
--' Апдейт саундменеджера
после строки
self.object:set_tip_text_default()
end
добавляем вот это
Код
-- апдейт магазинов
       if ammo_manager and self.object:alive() then
        local wpn = self.object:item_in_slot(self.object:active_slot())
        if wpn then
         if not self.wpn or wpn:id() ~= self.wpn:id() then
          self.wpn = wpn
          if self.wpn then
           self.ammo = parse_data(system_ini():r_string(self.wpn:section(),"ammo_class"))
           local curr_ammo = ammo_manager.get_ammo_type(self.wpn:id()) + 1
           self.ammo_in_use = self.ammo[curr_ammo]
           if not self.object:object(self.ammo_in_use) then
            local another_ammo = nil
            for k,v in pairs (self.ammo) do
             if self.object:object(v) then -- вдруг есть другой подходящий БП
              another_ammo = true
              self.ammo_in_use = v -- проходим до конца, выбираем лучшее
             end
            end
            if not another_ammo then
             local count = math.random(1,4)
             for i = 1,count do
              spawn.inv(self.ammo_in_use,self.object:id()) -- если совсем нет патронов - выдаем
             end
            end
           end
           if string.sub(self.ammo_in_use,1,4) == "mag_" or string.sub(self.ammo_in_use,1,5) == "clip_" or string.sub(self.ammo_in_use,1,5) == "belt_" then
            self.mag_cap = system_ini():r_float(self.ammo_in_use,"mag_size") -- емкость магазина
            wpn:set_ammo_elapsed(self.mag_cap) -- оружие заряжено
           else
            self.mag_cap = nil
           end
          end        
          if not self.last_load then       
           self.last_load = wpn:get_ammo_in_magazine()
          end
         end
               
         local load = self.wpn:get_ammo_in_magazine()
         if self.mag_cap and load == 1 and self.last_load == 0 then -- зарядил, магазинное питание
          wpn:set_ammo_elapsed(self.mag_cap)
         end
         self.last_load = load
        end
       end
       if not self.object:alive() then
        if not self.death_mag_recharge then
         self.death_mag_recharge = 3 -- таймер установки заряда магазинов
        end
        if self.death_mag_recharge > 0 then
         if self.death_mag_recharge == 1 then
          local npc = self.object
          set_mag_charge(npc)
         end
         self.death_mag_recharge = self.death_mag_recharge - 1
        end
       end


Готово, идем дальше:

В функции
--' Проверка потери жизни
После строки(внимание, строки if xrs_grenade then xrs_grenade.npc_update(self) end, может у вас не быть)
if v:enabled(o) then
v:register(o)
end

break
end
end]]
if xrs_grenade then xrs_grenade.npc_update(self) end
end
добавляем
Код
[function set_mag_charge(npc)
       npc:iterate_inventory(
        function(dummy, item)
         local section = item:section()
          -- питание оружия из магазинов
         if string.sub(section,1,4) == "mag_" or string.sub(section,1,5) == "clip_" or string.sub(section,1,5) == "belt_" then
          local load = 1
          if math.random() < 0.2 then -- примерно каждый пятый магазин отстрелян на 10-90%
           load = math.random() * 0.8 + 0.1
          end
          item:set_condition(0.995*load)
         elseif section == "power_supply" then
          item:set_condition(math.random() * 0.75 + 0.25)
         end
        end
       ,npc)
end


Все, скрипт xr_motivator готов.
А остальные скрипты ammo_manager.script, inv.script, item_effects.script, kirag_take_drop.script и spawn.script кидаем в папку gamedata/script. А скрипт escape_dialog.script можете не копировать, лучше пусть остается скрипт вашей модификации.

Все, скриптами покончено, теперь перейдем конфигам.
Конфиги text и ui можете кидать с заменой файлов.
А вот над папкой weapons придется поработать.
Так, сначала открываем weapons.ltx.
Там, где прописаны конфиги оружия в конце добавляем строку
#include "dark_matter.ltx"

В функции
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; AMUNITION
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
после строк
[ammo_base]:identity_immunities
;belt = true;
добавляем вот эти строки
Код
#include "ammo\magazines.ltx"
#include "ammo\9x18.ltx"
#include "ammo\9x19.ltx"
#include "ammo\9x39.ltx"
#include "ammo\12cal.ltx"
#include "ammo\57x28.ltx"
#include "ammo\357.ltx"
#include "ammo\545x39.ltx"
#include "ammo\556x45.ltx"
#include "ammo\762x25.ltx"
#include "ammo\762x39.ltx"
#include "ammo\762x51.ltx"
#include "ammo\762x54.ltx"
#include "ammo\792x57.ltx"
#include "ammo\1143x23.ltx"
#include "ammo\1270x99.ltx"
#include "ammo\1270x108.ltx"
#include "ammo\gauss_ammo.ltx"


Дальше удаляем все конфиги патронов в weapons.ltx до этих строчек:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Код
[ammo_og-7b]:ammo_base
GroupControlSection    = spawn_group
discovery_dependency =       
$spawn   = "weapons\ammo\ammo_og-7b" ; option for Level Editor
class   = A_OG7B
cform                   = skeleton
visual                  = weapons\ammo\ammo_og-7b.ogf
description    = enc_weapons1_ammo_ammo-og-7b
$prefetch   = 64

cost      = 1000

box_size  = 1

inv_name  = ammo-og-7b
inv_name_short    = ammo-og-7b
inv_weight  = 1.0

inv_grid_width  = 3
inv_grid_height  = 1
inv_grid_x   = 15
inv_grid_y   = 19

k_dist   = 1
k_disp   = 1
k_hit   = 1
k_impulse  = 1
k_pierce  = 1.25
impair   = 1.15
buck_shot  = 0
tracer   = off
wm_size         = 0.1

;могут ли боеприпасы быть неограниченными : 1 - могут, 0 - не могут
can_be_unlimited = true ;false

Как вы поняли, не трогаем только конфиги гранат подствольников, рпг, так же не трогаем конфиги аддонов для оружия(оптики, подсвольники, глушаки)

На этом работа с weapon.ltx закончена.

Перейдем к конфигам оружия. Если вы используете оружейный аддон(правозатворное оружие и тд.), то придется поработать.
И так, в каждом конфиге оружия придется написать следующее(не трогаем конфиги дробовиков и обрезов):
Например, берем конфиг ак-74, открываем его и находим строчки
ammo_mag_size = 30
и
ammo_class = ammo_5.45x39_fmj, ammo_5.45x39_ap ;
Вот эти строки нам надо и редактировать.
Приступим:

Значит так, перед строкой
ammo_mag_size = 30
вставим строку
ammo_mag_size = 1 ;(это значит, что к магазину можно одновременно цеплять только 1 магазин)
А на строке
ammo_class = ammo_5.45x39_fmj, ammo_5.45x39_ap ; вместо ammo пишем mag и количество патронов обоймы и в конце убираем точку запятой и ставим просто запятую.
Получиться так:
ammo_class = mag_30_5.45x39_fmj, mag_30_5.45x39_ap, mag_45_5.45x39_fmj, mag_45_5.45x39_ap,
После этой строки добавляем
; ammo_class = ammo_5.45x39_fmj, ammo_5.45x39_ap ;
И в итоге получиться вот так:
Код
ammo_mag_size    = 1 ; ammo_mag_size   = 30    ; clip (magazine) size
fire_modes    = 1, -1

ammo_class    = mag_30_5.45x39_fmj, mag_30_5.45x39_ap, mag_45_5.45x39_fmj, mag_45_5.45x39_ap, mag_75_5.45x39_fmj, mag_75_5.45x39_ap
;    ammo_class    = ammo_5.45x39_fmj, ammo_5.45x39_ap   ;

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

Идем дальше.
Остается только закинуть в папку weapons папку ammo и конфиг dark_matter.ltx.

Все, конфиги готовы.

А теперь кидаем папки meshes и sounds в gamedata.

А папку textures кидаем без папки ui, так как ui.icons.equpments у вас другой.
А теперь дело техники, открываем ui.icons.equpments фотошопом и переносим иконки обоймы на свой ui.icons.equpments, потом прописываем координаты. Все.

А ссылка на файл магазинное питание оружия(gamedata_magazines_v1.1_fixed) у нас на сайте есть. Удачи.
Если что я не правильно сделал, поправьте.
Сообщение отредактировал Mirage - Вторник, 21.05.2013, 10:13
  Злобная реклама
Воскресенье, 03.02.2013, 13:13
Статус:
Сообщений: 666
Регистрация: 09.06.2012
Форум » Архив » Устаревшие темы » Магазинное питание оружия (Попробуем разобраться, как адаптировать под различные моды)
  • Страница 1 из 1
  • 1
Поиск: