Давайте сделаем рогалик (Броня и щиты)

armor.png

Следующим нашим шагом будет добавление в игру предметов брони и щитов. Также, чтобы они у нас работали, нам необходимо реализовать команду инвентаря «Взять в руки/Одеть». Тут мы сталкиваемся с небольшой проблемой, так как нам нужно уметь не только одевать предметы, но и снимать их. Так как мы имеем дело с двумя действиями, то имеет смысл реализовать для них две команды: «Взять в руки/Одеть» и «Снять». Этим мы и займемся в этой главе. Добавление новых предметов инвентаря — самая простая часть, так как у нас уже есть все методы работы с инвентарем и нам необходимо только добавить определение новых типов предметов и у нас будут щиты и броня. Тем не менее нам придется обновить объект персонажа для их хранения, а также существующие функции работы с инвентарем — для обработки новых типов предметов. Так что в у нас будет достаточно работы, но когда мы закончим, то добавление в игру новых предметов будет простой задачей. Давайте посмотрим на определение брони и щитов:

inv.bi

'Идентификаторы доспехов
Enum armorids
    armArmorNone
    armCloth        'Плотная ткань. Cloth armor: поглощает 1% повреждений
    armLeather      'Кожаная. Leather armor: поглощает 5%  повреждений
    armCuirboli     'Прошитая кожаная. Cuirboli armor: поглощает 10 %  повреждений
    armRing         'Кожа с металлическими кольцами. Ring armor: поглощает 20%  повреждений
    armBrigantine   'Полная кожаная? Brigantine armor: поглощает 30% повреждений
    armChain        'Кольчуга. Chain armor: поглощает 50 % повреждений
    armScale        'Чешуйчатая броня. Scale armor: поглощает 70% повреждений
    armPlate        'Пластинчатая броня. Plate armor: поглощает 90% повреждений
End Enum

'Идентификаторы щитов
Enum shieldids
    shldShieldNone
    shldLeather    'Значения для щитов такие же как и для доспехов.
    shldCuirboli
    shldRing
    shldBrigantine
    shldChain
    shldScale
    shldPlate
End Enum


Это типы доспехов и щитов, которые будут у нас в игре. Как вы можете видеть из комментариев, броня в подземелье судьбы ведет себя несколько иначе, чем в других ролевых системах. Броня не дает способность персонажу перенести удар полностью без последствий, а просто поглощает часть урона. Так или иначе, повреждения, наносимые персонажу при ударе, зависят от различных факторов защиты. Если персонажа ударили, то броня уменьшает повреждения на определенный процент. Броня из ткани уменьшит его на 1%, а пластинчатые доспехи на 90%. Однако, чем больше повреждений поглощает броня, тем больше у нее требования к параметру силы персонажа для возможности ее использования. Также требование по параметру силы персонажа зависит от генератора случайных чисел, так что удача игрока здесь также немаловажный параметр.

inv.bi

'Слоты инвентаря на персонаже (предметы в руках и т.д.).
Enum wieldpos
    wNone
    wPrimary
    wSecondary
    wArmor
    wNeck
    wRingRt
    wRingLt
End Enum

'Описание типа для брони
Type armortype
    id As armorids       'Тип брони
    evaldr As Integer    'Сложность опознания. Если больше > 0 то магический предмет.
    eval As Integer      'Если предмет опознан.
    effect As Integer    'Магический эффект (заклинание).
    sdesc As String * 30 'Секретное название для магических предметов. Отображается если он опознан.
    noise As Integer     'Производимый шум при использовании или если лежит в инвентаре.
    use As itemuse       'Как предмет используется.
    dampct As Single     'Процент поглощаемых повреждений.
    struse As Integer    'Сколько необходимо значение силы для использования.
    wslot(1 To 2) As wieldpos 'Слоты, занимаемые предметом. Может занимать одновременно до двух слотов.
End Type

'Описание типа для щитов
Type shieldtype
    id As shieldids      'Тип щита
    evaldr As Integer    'Сложность опознания. Ксли больше > 0 то магический.
    eval As Integer      'Если предмет опознан.
    effect As Integer    'Магический эффект.
    sdesc As String * 30 'Секретное название для магических предметов. Отображается если он опознан.
    noise As Integer     'Сколько шума производит при использовании и при нахождении в инвентаре.
    use As itemuse       'Как используется.
    dampct As Single     'Процент поглощаемых повреждений.
    struse As Integer    'Сила, необходимая для использования
    wslot(1 To 2) As wieldpos 'Слоты, занимаемые предметом. Может занимать одновременно до двух слотов.
End Type


Описание типов для брони и щитов содержит довольно много информации. Некоторые поля вы видели раньше, такие как идентификатор (id), опознание (eval), генерируемый предметом шум (noise) и использование (use). Новое поле dampct указывает на количество поглощаемых повреждений, struse — минимальное значение параметры силы персонажа для возможности использования данного предмета и массив, указывающий на занимаемые предметом слоты когда персонаж его использует. Вы у видите как это работает когда мы дойдем до реализации команд «Взять в руки/Одеть» и «Снять».

В Подземелье Судьбы магические броня и оружие содержат заклинания, которые на них могут быть наложены, а не просто являются магическими сами по себе, как это было у нас с едой. Поскольку мы еще не дошли до реализации магии, то пока просто зарезервируем в описании наших предметов место для заклинаний, которые они могу содержать и которое мы сможем заполнить позже, с развитием нашего проекта.

Для генерации новых типов предметов, нам придется обновить каждую из существующих подпрограмм в inv.bi. Процесс очень прост, для брони и щитов мы добавим новый раздел в каждую процедуру. Например, подпрограмма ClearInv обновляется путем добавления нового условия в секцию Select — Case.

inv.bi:ClearInv

Case clArmor
            inv.armor.id = armArmorNone
            inv.armor.evaldr = 0
            inv.armor.eval = FALSE
            inv.armor.effect = 0
            inv.armor.sdesc = ""
            inv.armor.noise = 0
            inv.armor.use = UseNone
            inv.armor.dampct = 0
            inv.armor.struse = 0
            inv.armor.wslot(1) = wNone
            inv.armor.wslot(2) = wNone
          Case clShield
            inv.shield.id = shldShieldNone
            inv.shield.evaldr = 0
            inv.shield.eval = FALSE
            inv.shield.effect = 0
            inv.shield.sdesc = ""
            inv.shield.noise = 0
            inv.shield.use = UseNone
            inv.shield.dampct = 0
            inv.shield.struse = 0
            inv.shield.wslot(1) = wNone
            inv.shield.wslot(2) = wNone


Другие подпрограммы обновляются подобным образом. Для создания доспехов мы вызываем подпрограмму GenerateArmor.

inv.bi

'Создает предмет брони.
Sub GenerateArmor(inv As invtype, currlevel As Integer, arid As armorids = armArmorNone)
    Dim item As armorids
    Dim As Integer isMagic = ItemIsMagic(currlevel)

    'Общее для всех предметов.
    If arid = armArmorNone Then
        item = RandomRange(armCloth, armPlate)
        inv.armor.id = item
    Else
        item = arid
        inv.armor.id = item
    End If
    inv.icon = Chr(234)
    inv.iconclr = fbEmeraldGreen
    inv.armor.use = useWieldWear
    inv.armor.eval = FALSE
    inv.armor.wslot(1) = wArmor
    'Магический предмет.
    If IsMagic = TRUE Then
        inv.armor.evaldr = RandomRange(currlevel, currlevel * 2)
        inv.armor.effect = 0
    Endif
    'Зададим тип брони и параметры.
    Select Case item
        Case armCloth
            inv.desc = "Cloth Armor" 'Cloth armor: 1% damage reduction.
            inv.armor.noise = 1
            inv.armor.dampct = .01
            inv.armor.struse = 10
        Case armLeather 'Leather armor: 5% damage reduction
            inv.desc = "Leather Armor"
            inv.armor.noise = 5
            inv.armor.dampct = .05
            inv.armor.struse = 50
        Case armCuirboli 'Cuirboli armor: 10 % damage reduction
            inv.desc = "Cuirboli Armor"
            inv.armor.noise = 10
            inv.armor.dampct = .10
            inv.armor.struse = 100
        Case armRing  'Ring armor: 20% damage reduction
            inv.desc = "Ring Armor"
            inv.armor.noise = 15
            inv.armor.dampct = .20
            inv.armor.struse = 150
        Case armBrigantine 'Brigantine armor: 30% dam reduction
            inv.desc = "Brigantine Armor"
            inv.armor.noise = 20
            inv.armor.dampct = .30
            inv.armor.struse = 200
        Case armChain 'Chain armor: 50 % dam reduction
            inv.desc = "Chain Armor"
            inv.armor.noise = 25
            inv.armor.dampct = .50
            inv.armor.struse = 250
        Case armScale 'Scale armor: 70% dam reduction
            inv.desc = "Scale Armor"
            inv.armor.noise = 30
            inv.armor.dampct = .70
            inv.armor.struse = 300
        Case armPlate 'Plate armor: 90% dam reduction
            inv.desc = "Plate Armor"
            inv.armor.noise = 35
            inv.armor.dampct = .90
            inv.armor.struse = 350
    End Select
    'Зададим секретное описание.
    If IsMagic = TRUE Then
        inv.armor.sdesc = inv.desc
    Else
        inv.armor.sdesc = inv.desc
    Endif
End Sub


Данная процедура почти идентична процедуре генерации предметов еды, но генерирует параметры для доспехов. В нее же мы могли добавить и генерацию щитов. Так как щиты у нас это просто еще один вид брони, но для наглядности я создал для брони и щитов две разных функции чтобы лучше показать ход выполнения программы. Посмотрев на код в inv.bi вы обнаружите, что точно такой же алгоритм используется во всех подпрограммах работы с инвентарем. По аналогии с тем, как мы добавили броню, мы будем добавлять в игру все новые предметы. Которые бы нам ни потребовались.

После того, как броня и щиты созданы и размещены на карте, мы должны дать игроку возможность их использовать, что подводит нас к реализации команд инвентаря «Одеть» и «Снять».

В подпрограмме ManageInventory файла dod.bas для данных команд мы добавили новую возможность выбора.

dod.bas

'«Одеть/Взыть в руки» предмет.
         If kch = "U" Then
            ret = ProcessUnequip()
            'Screen changed.
            If ret = TRUE Then
               DrawInventoryScreen
            Endif
         Endif
         '«Снять».
         If kch = "Q" Then
            ret = ProcessEquip()
            'Screen changed.
            If ret = TRUE Then
               DrawInventoryScreen
            Endif
         Endif


Содержание этих двух новых подпрограмм аналогично уже существующим подпрограммам инвентаря, поэтому их код должен быть вам знаком.

dod.bas

'Реализация команды «Одеть/Взять в руки».
Function ProcessEquip() As Integer
    Dim As String res, mask, desc
    Dim As Integer i, iret, iitem, idx, ret = FALSE
    Dim As invtype inv
    Dim As tWidgets.btnID btn
    Dim As tWidgets.tInputbox ib
    Dim As vec mvec
    Dim slot As Integer

    'Убедимя что в инвентаре есть что одеть.
    For i = pchar.LowInv To pchar.HighInv
        iitem = pchar.HasInvItem(i)
        If iitem = TRUE Then
            'Получим предмет инвентаря.
            pchar.GetInventoryItem i, inv
            'Если предмет можно одеть взять.
            iret = MatchUse(inv, useWieldWear)
            'Добавим его в возможность выбора.
            If iret = TRUE Then
                'Построим маску.
                mask &= Chr(i)
            End If
        Endif
    Next
    If Len(mask) = 0 Then
        ShowMsg "Equip Items", "Nothing to equip.", tWidgets.MsgBoxType.gmbOK
    Else
        'Нарисовать поле ввода.
        ib.Title = "Equip Items"
        ib.Prompt = "Select item(s) to equip (" & mask & ")"
        ib.Row = 39
        ib.EditMask = mask
        ib.MaxLen = Len(mask)
        ib.InputLen = Len(mask)
        btn = ib.Inputbox(res)
        'Если игрок что то выбрал.
        If (btn <> tWidgets.btnID.gbnCancel) And (Len(res) > 0) Then
            'Переберем все предметы.
            For i = 1 To Len(res)
                iitem = Asc(res, i) 'Get index into wield inventory.
                'Получим предмет инвентаря.
                pchar.GetInventoryItem iitem, inv
                'Получим описание предмета.
                desc = GetInvItemDesc(inv)
                iret = FALSE
                idx = 0
                'Проверим первый слот.
                slot = GetInvWSlot(inv, 1)
                If slot <> wNone Then
                    'Проверим, что данный слот персонажа не занят.
                    If pchar.HasInvItem(slot) = FALSE Then
                        idx = slot
                        iret = TRUE
                    Endif
                Else
                    'Проверим второй слот.
                    slot = GetInvWSlot(inv, 2)
                    If slot <> wNone Then
                        'Проверим, что данный слот персонажа не занят.
                        If pchar.HasInvItem(slot) = FALSE Then
                            idx = slot
                            iret = TRUE
                        Endif
                    End If
                Endif
                'Есть свободное место?
                If iret = TRUE Then
                    'Убедимся что персонаж может использовать предмет.
                    If pchar.CanWear(inv) = TRUE Then
                        'Поместим предмет на «одеваемую» позизию.
                        pchar.AddInvItem idx, inv
                        'Уберем его из инвентаря.
                        ClearInv inv
                        'Обновим состояние слотов.
                        pchar.AddInvItem iitem, inv
                        ret = TRUE
                        desc &= " was equipped."
                        ShowMsg "Equip Items", desc, tWidgets.MsgBoxType.gmbOK
                    Else
                        ShowMsg "Equip Items", "Not enough strength to equip " & desc & ".",tWidgets.MsgBoxType.gmbOK
                    End If
                Else
                    'Нет свободного места.
                    desc = "No empty slots to equip item."
                    ShowMsg "Equip Items", desc, tWidgets.MsgBoxType.gmbOK
                    Exit For
                Endif
            Next
        Endif
    Endif

    Return ret
End Function


Так же, как мы делали в подпрограмме опознания предметов, мы проверяем предметы из инвентаря — какие из них могут быть одеты или взяты в руки персонажем. Как только список таких предметов сформирован, мы предоставляем го пользователю, чтобы он смог сделать выбор. После того, как игрок выбрал предмет, мы должны проверить в какой слот этот предмет может быть размещен и не занят ли он уже. Каждый из «одеваемых» предметов может занимать определенное место в слотах персонажа, которое описано перечислением, определенным в inv.bi. Мы получаем этот слот вызывая функцию GetInvWSlot.

inv.bi

'Возвращает слоты инвентаря для одеваемых предметов.
Function GetInvWSlot(inv As invtype, slotnum As Integer) As Integer
    Dim As Integer ret = wNone

    If inv.classid = clArmor Then
        If slotnum >= Lbound(inv.armor.wslot) And slotnum <= Ubound(inv.armor.wslot) Then
            ret = inv.armor.wslot(slotnum)
        End If
    Elseif inv.classid = clShield Then
        If slotnum >= Lbound(inv.shield.wslot) And slotnum <= Ubound(inv.shield.wslot) Then
            ret = inv.shield.wslot(slotnum)
        End If
    Endif

    Return ret
End Function


Параметр slotnum является индексом массива wslot в описании типов для доспехов и щитов. У нас каждый предмет может находится максимум в каких либо 2-х разных слотах, например оружие — может находится в правой и в левой руке (первичный и вторичный слот). Для того, чтобы получить слот в котором должен быть размещен предмет мы передаем индекс в эту функцию. Доспехи у нас могут располагаться только в слоте для доспехов, поэтому у них в массиве wslot по индексу 1 будет содержаться wArmor, по индексу 2 — wNone или 0. Функция возвращает wNone — если слот не задан в массиве wslot.

Что означают цифры указывающие на слот? Это индекс в массиве слотов содержащемся в объекте персонажа.

character.bi

cwield(wPrimary To wRingLt) As invtype 'Активный предмет: 1 = главное оружие, 2 = второе оружие/щит, 3 = броня, 4 = ожерелье, 5 = кольцо пр., 6 = кольцо лр.


Также они используются для меню выбора одеваемого/снимаемого предмета инвентаря, как это показано на изображении в начале главы. Связав меню выбора предмета с реальным размером массива мы упрощаем выбор слота одеваемого или снимаемого предмета. Мы можем наблюдать это в коде функции ProcessEquip который «одевает» предмет.

dod.bas

'проверим слот 1.
slot = GetInvWSlot(inv, 1)
If slot <> wNone Then
    'Проверим персонажа чтобы убедится что слот свободен.
    If pchar.HasInvItem(slot) = FALSE Then
        idx = slot
        iret = TRUE
    Endif
Else
    'Проверим слот 2.
    slot = GetInvWSlot(inv, 2)
    If slot <> wNone Then
        'Проверим персонажа чтобы убедится что слот свободен .
        If pchar.HasInvItem(slot) = FALSE Then
            idx = slot
            iret = TRUE
        Endif
    End If
Endif


Обратите внимание, что мы используем индекс, получаемый из GetInvWSlot чтобы использовать его в функции персонажа HasInvItem, которую мы обновили для проверки: занят или свободен конкретный слот для «одеваемых» предметов.

character.bi

'Возвращает True если предмет находится в инвентаре.
Function character.HasInvItem(idx As Integer) As Integer
    'Проверим одетые предметы.
    If idx >= Lbound(_cinfo.cwield) And idx <= Ubound(_cinfo.cwield) Then
        'Проверим идентификатор класса предмета.
        If _cinfo.cwield(idx).classid = clNone Then
            Return FALSE
        Else
            Return TRUE
        Endif
    Else
        'Проверка индекса.
        If idx >= Lbound(_cinfo.cinv) And idx <= Ubound(_cinfo.cinv) Then
            'Проверка идентификатора класса.
            If _cinfo.cinv(idx).classid = clNone Then
                Return FALSE
            Else
                Return TRUE
            Endif
        Else
            Return FALSE
        End If
    Endif

End Function


Первый оператор If проверяет, попадает ли индекс в диапазон массива одеваемых на персонажа предметов. Поскольку id занимаемого места у нас соответствует индексу массива слотов, то далее мы просто проверяем массив по этому индексу чтобы узнать — занят слот или свободен. Это соответствие индексов расположения и индексов массива слотов позволяет упростить код и сделать его более понятным и простым в отладке и обслуживании.

Если слот пуст, то мы просто помещаем в него предмет и удаляем его из массива инвентаря персонажа.

dod.bas:ProcessEquip

'Пустой слот найден?
If iret = TRUE Then
    'Убедимся, может ли персонаж пользоваться предметом.
    If pchar.CanWear(inv) = TRUE Then
        'Поместим в «одеваемый» слот.
        pchar.AddInvItem idx, inv
        'Удалим из инвентаря.
        ClearInv inv
        'Обновим «одеваемые» слоты.
        pchar.AddInvItem iitem, inv
        ret = TRUE
        desc &= " was equipped."
        ShowMsg "Equip Items", desc, tWidgets.MsgBoxType.gmbOK
    Else
        ShowMsg "Equip Items", "Not enough strength to equip " & desc & ".",tWidgets.MsgBoxType.gmbOK
    End If
Else
    'Нет свободного слота.
    desc = "No empty slots to equip item."
    ShowMsg "Equip Items", desc, tWidgets.MsgBoxType.gmbOK
    Exit For
Endif


Перед тем как одеть предмет, необходимо проверить — достаточно ли у персонажа показатель силы для использования данного щита или доспехов. Для данной проверки мы добавили новую функцию в объект персонажа: CanWear.

character.bi

'Возвращает True если персонаж может использовать предмет
Function character.CanWear(inv As invtype) As Integer
    Dim As Integer ret = TRUE

    If inv.classid = clArmor Then
        If inv.armor.struse > _cinfo.stratt(0) Then
            ret = FALSE
        Endif
    Endif

    If inv.classid = clShield Then
        If inv.shield.struse > _cinfo.stratt(0) Then
            ret = FALSE
        Endif
    Endif

    Return ret
End Function


Здесь у брони и щитов проверяется поле struse, для того чтобы определить — достаточно ли сил у персонажа. Обратите внимание, что возвращаемое по умолчанию значение — True. Только предметы определенного типа могут изменить значение на False (в нашем случае броня и щиты), а для всех остальных мы будем возвращать True.

Для команды «снять» мы делаем противоположные действия.

dod.bas

'Обработаем команду «снять».
Function ProcessUnEquip() As Integer
    Dim As String res, mask, desc
    Dim As Integer i, iret, iitem, ret = FALSE
    Dim As invtype inv
    Dim As tWidgets.btnID btn
    Dim As tWidgets.tInputbox ib
    Dim As vec mvec

    'Проверим предметы которые можно снять.
    For i = wPrimary To wRingLt
        iitem = pchar.HasInvItem(i)
        If iitem = TRUE Then
            'Построим маску.
            mask &= Str(i)
        Endif
    Next
    If Len(mask) = 0 Then
        ShowMsg "Unequip Items", "Nothing to unequip.", tWidgets.MsgBoxType.gmbOK
    Else
        'Нарисуем поле для ввода.
        ib.Title = "Unequip Items"
        ib.Prompt = "Select item(s) to unequip (" & mask & ")"
        ib.Row = 39
        ib.EditMask = mask
        ib.MaxLen = Len(mask)
        ib.InputLen = Len(mask)
        btn = ib.Inputbox(res)
        'Проверим каждый предмет из списка.
        If (btn <> tWidgets.btnID.gbnCancel) And (Len(res) > 0) Then
            'Переберем список предметов.
            For i = 1 To Len(res)
                iitem = Val(Mid(res, i, 1)) 'Получим индекс слота.
                'Получим предмет инвентаря.
                pchar.GetInventoryItem iitem, inv
                'Получим описание.
                desc = GetInvItemDesc(inv)
                'Ищем пустой слот инвентаря.
                iret = pchar.GetFreeInventoryIndex
                'Нашелся пустой слот?
                If iret > -1 Then
                    'Поместим предмет в инвентарь.
                    pchar.AddInvItem iret, inv
                    'Очистим предмет.
                    ClearInv inv
                    'Обновим одеваемые слоты.
                    pchar.AddInvItem iitem, inv
                    ret = TRUE
                    desc &= " was unequipped."
                    ShowMsg "Unequip Items", desc, tWidgets.MsgBoxType.gmbOK
                Else
                    'Нет места в инвентаре.
                    desc = "No empty inventory slots to unequip item."
                    ShowMsg "Unequip Items", desc, tWidgets.MsgBoxType.gmbOK
                    Exit For
                Endif
            Next
        Endif
    Endif

    Return ret
End Function


Вместо того, чтобы перебирать предметы из инвентаря персонажыа, мы перебираем массив «одеваемых» слотов: For i = wPrimary To wRingLt. Вызывая HasInvItem, мы проверяем — занят ли слот, и если занят, то добавляем предмет в список. Другое отличие здесь в том, что вместо использования ASCII колов мы используем в маске фактические номера слотов: mask &= Str(i).

После того как сок список создан и игрок сделал свой выбор, мы обрабатываем его почти также, как и список выбрасываемых предметов. Опять же, разница в том, что мы должны обрабатывать номер индекса массива а не ASCII код: iitem = Val(Mid(res, i, 1)). За исключением этих отличий, алгоритм почти такой же, как и в команде «выбросить», мы перемещаем предмет из слота одетых предметов в слот инвентаря персонажа. Используя функцию GetFreeInventoryIndex мы получаем индекс свободного слота в инвентаре персонажа, так же, как мы это делали в команде «Поднять». Свободный слот нам нужен для того. Чтобы положить туда снятый с персонажа предмет.

Теперь нам необходимо отобразить на экране одетые на персонажа предметы. Мы обновили код в DrawMainScreen чтобы любые одетые предметы отображались на информационной панели.

dod.bas

'Проверим одетые предметы.
If pchar.HasInvItem(wPrimary) = TRUE Then
    pchar.GetInventoryItem wPrimary, inv
    idesc = GetInvItemDesc(inv)
Else
    idesc = ""
Endif
PutText "Primary: " & idesc, row, col
row += 1
If pchar.HasInvItem(wSecondary) = TRUE Then
    pchar.GetInventoryItem wSecondary, inv
    idesc = GetInvItemDesc(inv)
Else
    idesc = ""
Endif
PutText "Secondary: " & idesc, row, col
row += 1
If pchar.HasInvItem(wArmor) = TRUE Then
    pchar.GetInventoryItem wArmor, inv
    idesc = GetInvItemDesc(inv)
Else
    idesc = ""
Endif
PutText "Armor: " & idesc, row, col
row += 1
If pchar.HasInvItem(wNeck) = TRUE Then
    pchar.GetInventoryItem wNeck, inv
    idesc = GetInvItemDesc(inv)
Else
    idesc = ""
Endif
PutText "Neck: " & idesc, row, col
row += 1
If pchar.HasInvItem(wRingRt) = TRUE Then
    pchar.GetInventoryItem wRingRt, inv
    idesc = GetInvItemDesc(inv)
Else
    idesc = ""
Endif
PutText "Ring RT: " & idesc, row, col
row += 1
If pchar.HasInvItem(wRingLt) = TRUE Then
    pchar.GetInventoryItem wRingLt, inv
    idesc = GetInvItemDesc(inv)
Else
    idesc = ""
Endif
PutText "Ring LT: " & idesc, row, col


Здесь мы просто проверяем все слоты для одетых предметов и если какой либо слот не пуст, то получаем название предмета который в нем находится и выводим его на экран.

Последнее что нам осталось сделать, это чтобы персонаж начинал игру с какой нибудь броней. Для этого необходимо добавить код в подпрограмму GenerateCharacter.

character.bi

'Добавим персонаджу броню из обычной ткани.
inv.classid = clArmor
GenerateArmor inv, 1, armCloth
SetInvEval inv, TRUE
AddInvItem wArmor, inv
'Добавим персонажу нож


Как только персонаж создан, мы создаем для него доспехи из ткани и помещаем в слот для доспехов. Обратите внимание, что мы отметили место вставки кода для добавление персонажу ножа. Наш персонаж будет начинать с ним игру, чтобы не быть совсем уж беззащитным.

Теперь у нас есть доспехи, но еще нам необходимо и оружие, которое мы добавим в следующей главе.

Перевод на русский: Fantik

содержание | назад | вперед