Перейти к контенту

Скриптование


Svoboда

Рекомендуемые сообщения

Всем доброго времени ссуток.

После прохождения SoC(1.0006) мне захотелось сделать некоторые не архисложные модификации игры :

Начну с того что проходя вышеупомянутую часть сталкера мне не удалось заполучить одну редкую винтовку..

Уже после прохождения игры я наткнулся на тутор как прописать игроку в рюкзак предметы скриптом.

Теперь внимание вопрос:

Как игра подключает скрипты ? т.е. как заинклюдить свой пользовательский файл со скриптом чтобы он был виден из других скриптов ?

Чтобы вызвать его к примеру из  S.T.A.L.K.E.R - Shadow of Chernobyl\gamedata\scripts\ui_main_menu.script

 

--        if dik == DIK_keys.DIK_S then
--            self:OnButton_load_spawn()
            
--        else

        if dik == DIK_keys.DIK_Q then
            self:OnMessageQuitWin()--после этого
            
        elseif db.actor~=nil and dik==DIK_keys.DIK_F4 then
            add_all_Wpn()--Моя функция которую я хочу иметь в своем скрипте а не дописывать их в конец уже имеющегося игрового скрипта, так как такой способ я считаю неправильным или просто нехорошим :(

P.S.Я тут новенький так что если что не так то прошу тапками не кидать.Туторы читал и там не нашел такой инфы.

Поделиться этим сообщением


Ссылка на сообщение
Немогу понять почему не работает скрипт.По задумки при сбросе рюкзака он должен заполнятся инвентарем актора, делаю для теста что-бы понять как это все потом сделать в другом моде.
файл bind_stalker.script
function actor_binder:update(delta)
object_binder.update(self, delta)
 
-- DEBUG slowdown
-- slowdown.update()
 
local time = time_global()
 
game_stats.update (delta, self.object)
--***************************************************
-->>Treasure rucksack 1/2--- вот рабочий код сбрасываемого рюкзака, брал из википедии сталкера, этот код работает поэтому полностью его не привожу
if self.rr_id~=nil then--то что мы записали при дропе
-- пытаемся получить объект по id
local se_obj=alife():object(self.rr_id)
-- проверяем, что объекта нет
if se_obj==nil or se_obj:section_name()~="inv_ruck" then
local ruck=alife():create("active_ruck", db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id())
level.map_add_object_spot_ser(ruck.id, "red_location", "%c[255,238,155,23]Моя нычка для хабара")
news_manager.send_tip(db.actor, "Тайник заложен.", nil, nil, 5000)
--obj_ruck = ruck--это типа  переменной для теста с таймером
--Start_Timer_5_minutes()--подумал что может не успевает отработать, но с таймером та-же байда
my_mod.push_all(ruck) --вот та функция которая ЗДЕСЬ не работает, но работает в другом месте, не пойму что не так
end
-- сбросим переменную
self.rr_id=nil
end
--Timer_N_minutes()--пробовал типа по таймеру вызывать, все так-же не работает
--<<
--***************************************************
 
-- апдейт погоды
дальше все стандартно
...
Если сделать так, то рюкзак сбрасывается но походу после my_mod.push_all(ruck) ничего не работает :-( игра не вылетает но повторно скрипт уже не срабатывает как нужно, с таймером пробовал но все так-же.Код таймера не привожу так как там по сути все то-же самое только вызывается с задержкой.
 
Из my_mod.script
Функция заимствована из скрипта арены там где телепортирует актера на арену а все вещи складываются в ящик.
 
local function transfer_object_item(item)
    db.actor:transfer_item(item, in_object)
end
 
function push_all(obj)
    in_object  = obj
db.actor:inventory_for_each(transfer_object_item) 
end
 

Эту функцию я тестировал с модовым рюкзаком вызывая ее из калбека когда перс забирает предмет(ы) из ящика и там она работает

function actor_binder:take_item_from_box(box, item)--

--my_mod.push_all(obj)--вот так она работает, при перемещении чего либо из ящика срабатывает калбак, инвентарь актора перемещается в ящик, то что мы оттуда забрали перемещается в инвентарь так как и должно по коду игры.
--my_mod.Message("take_item_from_box")--типа сообщение для информирования 
Изменено пользователем antihumanist

Поделиться этим сообщением


Ссылка на сообщение

 

 

antihumanist, у тебя ruck это серверный объект, а в transfer_item нужно передавать клиентский.

Хм а получить его как ? в справочнике из очевидного не нашел

Поделиться этим сообщением


Ссылка на сообщение

Точнее - проверять, пока не появился

 

Ура работает ! спасибо !

 

--***********************************************************************
--Код тестовый и по хорошему его нужно переделать, но для теста пойдет и так

local iTimer --переменная времени для таймера(никто не мешает использовать ее как простой флаг)
local obj_ruck-- серверный обдж рюкзака, тут думаю лучше передавать сразу ид, но для теста сойдет

function Start_Timer_5_minutes() 
    iTimer = --[[time_global() +]] 300  --тут закоментирован код таймера, просто устанавлевается флаг
end


function Timer_N_minutes() -- таймер переделанный в функцию проверки на существование, в апдейте
    if iTimer ~= nil --[[and iTimer < time_global()]] then
local c_ruck = level.object_by_id(obj_ruck.id)--поидее если объект не нашелся то его нет(работает)
if  c_ruck then
        my_mod.push_all(c_ruck)
iTimer = nil--убираем флаг или обнуляем таймер
end
    end
end
----------------------------------------------------------------------------------------------------------------------
function actor_binder:update(delta)
object_binder.update(self, delta)


-- DEBUG slowdown
-- slowdown.update()


local time = time_global()


game_stats.update (delta, self.object)
--***************************************************
-->>Treasure rucksack 1/2
if self.rr_id~=nil then--то что мы записали при дропе
-- пытаемся получить объект по id
local se_obj=alife():object(self.rr_id)
-- проверяем, что объекта нет
if se_obj==nil or se_obj:section_name()~="inv_ruck" then
local ruck=alife():create("active_ruck", db.actor:position(), db.actor:level_vertex_id(), db.actor:game_vertex_id())
level.map_add_object_spot_ser(ruck.id, "red_location", "%c[255,238,155,23]Моя нычка для хабара")
news_manager.send_tip(db.actor, "Тайник заложен.", nil, nil, 5000)
obj_ruck = ruck--передаем в переменную
  Start_Timer_5_minutes()--ставим флаг или таймер
--my_mod.push_all(level.object_by_id(ruck.id))--тут работать не будет
end
-- сбросим переменную
self.rr_id=nil
end
Timer_N_minutes()--выполняем таймер/функцию апдейта состояния рюкзака
--<<
--***************************************************


-- апдейт погоды

 

Тогда еще пара вопросов уж простите.Делаю  фан мод и сборку из  чужих скриптов для этого мода и поэтому вопросы совершенно разные.

Сделал ремонтные наборы, но столкнулся со странным багом, не совсем понимаю его природу.

суть его в том что когда я вызываю подряд две функции на съедание одного и того-же предмета то последняя функция не выполняется и дает глюки, точно так-же с вызовом удаления предмета.

Все обернуто в функцию которая вызывается из колбека self.object:set_callback(callback.use_object, self.repair_start, self)

 

function actor_binder:repair_start(obj, who)
my_mod.Message("use_object")
    if obj then 
main_sleep.sleep(obj)
        if obj:section() == "repair_kit_outfit" then --здесь указываем предмет, при использовании которого будет срабатывать функция ниже
         exp_mod.action_repair() --тут функции которые не учавствуют в тесте и уже тестироваись
elseif obj:section() == "repair_kit" then
exp_mod.repair_all()
elseif obj:section() == "repair_kit_wpn" then
exp_mod.repair_wpn()
--второй вариант ремонта
elseif obj:section() == "repair_kit_device" then--вот отсюда вызываю
exp_mod.repair_device()
elseif obj:section() == "repair_kit_wpn2" then
exp_mod.repair_wpn2()
elseif obj:section() == "repair_kit_outfit2" then
exp_mod.repair_outfit2()
        end
    end
end
--Короче говоря в моде есть три "съедобных" итема ящик с инструментами и ремкомплекты один для брони и другой для оружия, когда игрок пытается съесть ящик с инструментами то выполняется эта функция, которая по задумке должна ремонтировать все во всех слотах при этом съедая/удаляя из инвентаря расходники ремкомплектов. но оставляя инструменты.Не работает когда я пытаюсь вызвать подряд две функции съедания/удаления одного вида предмета.Ремкомплекты так-же обрабатываются при употреблении в пищу, с расчетом одна еденица ремкомплекта на одну еденицу брони/оружия в слоте.С оружием работают последовательно что сделанно для удобства ремонта чего-то одного а не всего сразу.
--repair_item_in_slot(num) -- это моя функция ремонта, переделанная, с википедии сталкера, к ней нет нареканий
--Она проверяет  слот num и возвращает true если предмет был отремонтирован, если в слоте пусто или предмет не того состояния которого требуется для ремонта или еще что не так то возвращает false, так-же информирует игрока.


function repair_device()--ящик с инструментами repair_kit_device, функция в которой должно ремонтироваться все что в слотах(сразу)


 local actor = db.actor
 local kit_outfit2 = actor:object("repair_kit_outfit2")--ремкомплект для костюма




   alife():create("repair_kit_device", vector(),0,0,0)--cпавним сразу как съели, хотя работало и если поместить в конец.
   
if kit_outfit2 then--проверяем наличие расходника для ремонта в инвентаре актора
--db.actor:eat(db.actor:object("repair_kit_outfit2"))         --можно его сразу тупо съесть
   if repair_item_in_slot(6) then                            --тогда этот код здесь не нужен, он запустися в биндере при "поедании" "repair_kit_outfit2"
       alife():release(alife():object(kit_outfit2:id()), true)--и этот код будет то-же не нужен
end--
end--конец ремонта костюма   


local kit_wpn2 = actor:object("repair_kit_wpn2")--ремкомплект для оружия, поидее тут я хочу отремонтировать сразу все стволы, т.е. два слота 1 и 2 поэтому делаю два раза одно и то-же.


if kit_wpn2 then
--db.actor:eat(db.actor:object("repair_kit_wpn2"))можно место удаления съедать, но у меня так не работало для двух одинаковых предметов сразу и я решил переделать
   if repair_item_in_slot(2) then
    alife():release(alife():object(kit_wpn2:id()), true)
end
end 
--Если раскомментировать код ниже, то он работать не будет ! но почему ?
--kit_wpn2 = actor:object("repair_kit_wpn2")--Здесь еще раз инициализируется на случай если объект съеден/удален кодом выше


--if kit_wpn2 then
----db.actor:eat(db.actor:object("repair_kit_wpn2"))--либо код жрачки либо код удаления
 --if repair_item_in_slot(1) then--при юзе кода жрачки не требуется
  --alife():release(alife():object(kit_wpn2:id()), true)
 --end 
--end 
  
end

 

Изменено пользователем Kirgudu

Поделиться этим сообщением


Ссылка на сообщение

Ужасно. Неизвестно что делается неизвестно когда с неизвестно чем.

Вот переделал все для демонстрации бага на стандартных вещах и без "лишних" функций.

Вызов бага показан в функции test_bug.Остальное привел для полноты данных.

--Добавление нового колбека в bind_stalker.script
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.use_object, self.repair_start, self)--Установка коллбэка
--*****************************************************************************************
end
--******************************РЕМОНТ*****************************************************
function actor_binder:repair_start(obj, who)--Функция коллбека callback.use_object
  if obj then 
if obj:section() == "bread" then
exp_mod.test_debug()
    end
  end
end
 
 
 
 
--*****************************************************************************************
function actor_binder:net_destroy()
if(actor_stats.remove_from_ranking~=nil)then
actor_stats.remove_from_ranking(self.object:id())
end
-- game_stats.shutdown ()
db.del_actor(self.object)
 
 
    sr_light.clean_up ()
 
 
self.object:set_callback(callback.inventory_info, nil)
self.object:set_callback(callback.article_info, nil)
self.object:set_callback(callback.on_item_take, nil)
self.object:set_callback(callback.on_item_drop, nil)
--self.object:set_callback(callback.actor_sleep, nil)
self.object:set_callback(callback.task_state, nil)
self.object:set_callback(callback.level_border_enter, nil)
self.object:set_callback(callback.level_border_exit, nil)
self.object:set_callback(callback.take_item_from_box, nil)
 
 
--****************************РЕМОНТ**********************************
self.object:set_callback(callback.use_object, nil)--
--********************************************************************
 
 
if sr_psy_antenna.psy_antenna then
sr_psy_antenna.psy_antenna:destroy()
sr_psy_antenna.psy_antenna = false
end
 
 
xr_sound.stop_all_sound_object()
 
 
object_binder.net_destroy(self)
end
 
 
--exp_mod.script--Мой скрипт
--Тестовая функция
function test_debug()--При использовании "bread"
 
 
alife():create("bread", vector(),0,0,0)
 
 
 local actor = db.actor
 local test_obj = actor:object("conserva")
 
 
 --При использовании "bread" нужно удалить два test_obj (если их имеется столько в инвентаре).
 
 
 if test_obj then
alife():release(alife():object(test_obj:id()), true)
 end   
 
 
 test_obj = actor:object("conserva")
 
 
 if test_obj then 
alife():release(alife():object(test_obj:id()), true)--этот код не срабатывает но из игры не выкидывает
 end 
 
 
end
 
 
--При вызове этой функции срабатывает только удаление первого test_obj, кроме того повторно эта функция уже не работает.

 

Поделиться этим сообщением


Ссылка на сообщение
  • Недавно просматривали   0 пользователей

    • Ни один зарегистрированный пользователь не просматривает эту страницу.
×
×
  • Создать...