Пользователей: 0
Гостей: 362
Всего: 362

» Подробно
» Сегодня


Привет, Гость!

Ник


Пароль


Запомнить?




» Добавить в избранное

» Сделать стартовой

Главная
Форум
Обзор игры
Мир Зоны
Файлы
Галерея
Разное







Распечатать     
Вопрос: Как определить нахождение предмета на поясе?
Ответ: Достаточно долго бытовало мнение, что определить предмет на поясе невозможно. Теоретически так оно и есть, так как слот belt нигде не отслеживается. Но благодаря ПЫСам, которые наконец соизволили объяснить, пусть не прямой, а косвеный, но всётаки способ определения нахождения предмета на поясе. Давайте сначала разберём как мы это будем делать, чтобы в дальнейшем не было глупых вопросов.
Итак, мы имеем инвентарь актора. Чтобы определить список всего инвентаря, который имеется у актора в наличии, нужно использовать метод db.actor:inventory_for_each(ScanInventory)
Где ScanInventory --имя функции которая вызывается для каждого объекта инвентаря.
Спросите, и как же мы определим какие предметы из них на поясе, а какие нет?! Вот это я щас и попытаюсь описать. Массив инвентаря актора состоит из нескольких субмассивов, которые запрашиваются в фиксированном порядке. А порядок здесь такой:
1. Массив рюкзака.
2. Массив пояса.
3. Первый слот.
4. Второй слот.
и т. д.

Чтобы при итерации всего списка инвентаря выудить именно массив пояса, нужно определить последний элемент в массиве рюкзака и ближайший элемент в одном из слотов. Предметы находящиеся между ними и будут являться предметами навешанными на пояс belt.
Если с предметами находяшимися в слотах проблем нет, их определение свободно производится через проверку нахождения онных в слотах по их нумерации. То с последним предметом в рюкзаке немного сложнее, тут нету никаких особенных данных различающих их от предметов на поясе. Но...
В связи с тем, что подбираемые или заспавненные предметы в инвентарь, добавляются именно в конец массива рюкзака, можно определять путём спавна/удаления предмета разделителя, по которому мы и будем узнавать конец массива рюкзака.
Тоесть порядок действий такой:
1. Спавним предмет-разделитель в инвентарь актора.
2. Производим итерацию предметов инвентаря.
3. Как только итератор дойдёт до предмета-разделителя включаем ключ добавления инвентаря во внешнюю таблицу.
4. После включения ключа, следующие предметы после разделителя будут добавляться в таблицу.
5. По мере добавления, производим проверку на нахождение онных в одном из слотов. И как только один из них окажется предметом находящемся в слоте, завершаем пополнение таблицы.
После всех этих действий, внешняя таблица будет содержать только список предметов находящихся на поясе.

Вот собственно и весь принцип.

Итак создаём в скриптах новый файл с именем bind_belt.script, и вставляем в него код:

Код:
belt = {} --//внешняя таблица пояса

local fix_time = 0           --//фиксатор интервала времени апдейта
local separator = nil        --//переменная для сохранения userdata разделителя
local del_separator = false  --//ключь удаления разделителя
local start_add_belt = false --//ключь начала заполнения таблицы belt
local open_inventory = false --//ключь открытия/закрытия инвентаря

--основная функция итерации инвентаря
--(привязана к функции update() в файле bind_stalker.script)
function IterateInventory()
    if not db.actor or not db.actor:alive() or time_global() < fix_time or open_inventory then return end

    if del_separator and separator then
        this.DeleteSeparator()
    end

    if separator then
        belt = {}
        db.actor:inventory_for_each(ScanInventory)
        del_separator = true
        start_add_belt = false
    else
        separator = alife():create("separator", db.actor:position(), db.actor:level_vertex_id(),
        db.actor:game_vertex_id(), db.actor:id())
    end
end

--функция удаления разделителя
function DeleteSeparator()
    alife():release(separator, true)
    separator = nil
    del_separator = false
    fix_time = time_global() + 1000 --//текущее время + интервал между циклами апдейта
    test_time = test_time + 1
end

--функция сканирования инвентаря
function ScanInventory(item)
    local section = item:section()

    if start_add_belt and not DetermineSlot(item:id()) then
        if not belt[section] then
            belt[section] = 1
        else
            belt[section] = belt[section] + 1
        end
    end

    if item:section() == "separator" then
        start_add_belt = true
    end
end

--функция определения привязки объекта к одному из слотов
function DetermineSlot(item_id)
    for i=0, 12 do
        local obj = db.actor:item_in_slot( i )
        if obj and obj:id() == item_id then return true end
    end

    return false
end

--функция отключения итерации при открытии инвентаря
--(привязана к колбэку info_callback() в файле bind_stalker.script)
function InventoryInfo(info)
    if info == "ui_inventory" then
        open_inventory = true
        this.DeleteSeparator()
    elseif info == "ui_inventory_hide" then
        open_inventory = false
    end
end

--функция сброса итерации, при взятии/выбрасывании предметов инвентаря
--(привязана к колбэкам on_item_take() и on_item_drop () в файле bind_stalker.script)
function TakeAndDrop(item)
    if item:section() == "separator" or not separator then return end

    if not open_inventory then
        this.DeleteSeparator()
    end
end


Создаём объект в конфигах (файл config/misc/items.ltx) с именем секции [separator]:

Код:
[separator]:identity_immunities
GroupControlSection = spawn_group
discovery_dependency =
$spawn = ""
$prefetch = 32
class = II_BANDG
cform = skeleton
visual = equipments\item_bandage.ogf
description = 
inv_name        = 
inv_name_short      = 
inv_weight        = 0
inv_grid_width = 0
inv_grid_height = 0
inv_grid_x = 0
inv_grid_y = 0
eat_health = 0
eat_satiety = 0
eat_power = 0
eat_radiation = 0
wounds_heal_perc = 0
eat_portions_num = 1
cost    = 0
animation_slot  = 4


Затем в файле bind_stalker.script производим пропись всех нужных привязок функций:

1. Функция actor_binder:info_callback(npc, info_id):
вписываем в конец тела функции: bind_belt.InventoryInfo(info_id)

2. Функция actor_binder:on_item_take (obj):
вписываем в конец тела функции: bind_belt.TakeAndDrop(obj)

3. Функция actor_binder:on_item_drop (obj)
вписываем в конец тела функции: bind_belt.TakeAndDrop(obj)

4. Функция actor_binder:update(delta)
вписываем в конец тела функции: bind_belt.IterateInventory()

Вот собственно и всё.
(просмотров: 2108)

  


???????@Mail.ru Rambler's Top100
Продолжая пользоваться сайтом, вы соглашаетесь с использованием файлов cookie. Страницы сайта могут содержать информацию, запрещенную для
просмотра посетителям младше 18 лет. Авторское право на серию игр «S.T.A.L.K.E.R» и используемые в ней материалы принадлежит GSC Game World.

Использование материалов сайта возможно с разрешения администрации. Все права защищены. © 2004–2024 «Stalker-Portal.ru»