|  
|  |   
|  
 
 
 Воскресенье, 03.02.2013, 13:13 | Сообщение # 1 Mirage  
  
 | 
 
 
 
 
 
Независимый аниматор  
  
 | Статус: |  |   
 | Бывалый: |  |   
 | Сообщений: | 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 |  |  |  |  |