Давайте сделаем рогалик (Оружие)

weapon.png

Прежде чем перейти к реализации оружия, давайте взглянем на некоторые изменения в коде. Вместе с последним обновление появилась странная ошибка, в результате которой на карте появлялись фантомные предметы. На карту добавлялся идентификатор предмета и ничего больше. Глядя на код генерации предметов питания я обнаружил, что перечисление, используемое в генераторе случайных чисел, было изменено. Вместо того, чтобы верхняя граница задавалась supBottleOil (бутылка с маслом), почему то была указана броня armPlate. Я не знаю как это произошло, но это и являлось причиной создания фантомных предметов. Я исправил эту проблему и добавил в нескольких местах кода проверки, чтобы сразу знать что происходит нечто странное, если такая же ситуация повторится. (Примечание: бутылка масла была удалена из кода последующих глав, так как у нас не будет темных подземелий. Смотри раздел примечаний, где описаны идеи того, как можно добавить темные подземелья в игру).

inv.bi

Case Else
         inv.desc = "Uknown Supply"
         inv.supply.noise = 0
         inv.icon = Chr(63)
         inv.iconclr = fbYellow
         inv.supply.eval = FALSE
         inv.supply.use = useNone


В подпрограмму генерации предметов я добавил Case Else конструкцию, которая будет сигнализировать нам о том, что тип сгенерированного предмета не определился. Т. е. мы создадим предмет с описанием «Uknown Supply» что поможет нам в более быстром обнаружении места ошибки и, что главное, этот код нисколько не повлияет на производительность нашей программы.

Еще одно изменение я внес в функцию GetFullDesc, которая используется подпрограммой ProcessInspect. Раньше тут был ряд вложенных конструкций Select Case, но вложенный Select необходим только для предметов еды, поэтому можно упростить код.

inv.bi

'Возвращает подробное описание предмета.
Sub GetFullDesc(lines() As String, inv As invtype)
    Dim As Integer idx = 0

    'Очистим массив.
    Redim lines(0 To idx) As String
    'Убедимся что задан идентификатор типа предмета.
    If inv.classid <> clNone Then
        'Выберем предмет.
        Select Case inv.classid
            Case clSupplies
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = GetInvItemDesc(inv)
                Select Case inv.supply.id
                    Case supHealingHerb
                        idx += 1
                        Redim Preserve lines(0 To idx) As String
                        lines(idx) = "* Adds 50% max HP to current HP"
                        idx += 1
                        Redim Preserve lines(0 To idx) As String
                        lines(idx) = "* Magic: Max healing"
                    Case supHunkMeat
                        idx += 1
                        Redim Preserve lines(0 To idx) As String
                        lines(idx) = "* Adds 25% max HP to current HP"
                        idx += 1
                        Redim Preserve lines(0 To idx) As String
                        lines(idx) = "* Magic: Bonus to STR stat"
                    Case supBread
                        idx += 1
                        Redim Preserve lines(0 To idx) As String
                        lines(idx) = "* Adds 10% max HP to current HP"
                        idx += 1
                        Redim Preserve lines(0 To idx) As String
                        lines(idx) = "* Magic: Cure poison"
                    Case supBottleOil
                        idx += 1
                        Redim Preserve lines(0 To idx) As String
                        lines(idx) = "* Fuel for lantern"
                        idx += 1
                        Redim Preserve lines(0 To idx) As String
                        lines(idx) = "* Magic: See all tiles on map"
                End Select
                idx += 1
                Redim Preserve lines(0 To idx) As String
                If IsEval(inv) = TRUE Then
                    lines(idx) = "* Item is evaluated"
                Else
                    lines(idx) = "* Item is not evaluated"
                End If
            Case clArmor
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = GetInvItemDesc(inv)
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = "* " & (inv.armor.dampct * 100) & "% damage reduction"
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = "* Strength Required: " & inv.armor.struse
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = "* Magic: Defense and Healing"
                idx += 1
                Redim Preserve lines(0 To idx) As String
                If IsEval(inv) = TRUE Then
                    lines(idx) = "* Item is evaluated"
                Else
                    lines(idx) = "* Item is not evaluated"
                End If
            Case clShield
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = GetInvItemDesc(inv)
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = "* " & (inv.shield.dampct * 100) & "% damage reduction"
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = "* Strength Required: " & inv.shield.struse
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = "* Magic: Defense and Healing"
                idx += 1
                Redim Preserve lines(0 To idx) As String
                If IsEval(inv) = TRUE Then
                    lines(idx) = "* Item is evaluated"
                Else
                    lines(idx) = "* Item is not evaluated"
                End If
            Case clWeapon
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = GetInvItemDesc(inv)
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = "* " & inv.weapon.dam & " weapon damage"
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = "* Hands Required: " & inv.weapon.hands
                idx += 1
                Redim Preserve lines(0 To idx) As String
                lines(idx) = "* Magic: Offense and Defense"
                idx += 1
                Redim Preserve lines(0 To idx) As String
                If IsEval(inv) = TRUE Then
                    lines(idx) = "* Item is evaluated"
                Else
                    lines(idx) = "* Item is not evaluated"
                End If
        End Select
    Endif

End Sub


Обратите внимание, что для доспехов, щитов и оружия нет вложенных Select-ов, так как они, на самом деле, не нужны. В результате код становится проще и его легче модифицировать. Теперь настала очередь оружия.

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

inv.bi

'Идентификаторы оружия.
Enum weaponids
    wpNone
    wpClub            '1 ручное, dam 4 chr:33
    wpWarclub         '1 ручное, dam 4
    wpCudgel          '1 ручное, dam 5
    wpDagger          '1 ручное, dam 4 chr: 173
    wpLongknife       '1 ручное, dam 6
    wpSmallsword      '1 ручное, dam 4
    wpShortsword      '1 ручное, dam 6
    wpRapier          '1 ручное, dam 9
    wpBroadsword      '1 ручное, dam 12
    wpScimitar        '1 ручное, dam 10
    wpKatana          '2 ручное, dam 12
    wpLongsword       '2 ручное, dam 14
    wpClaymore        '2 ручное, dam 16
    wpGreatsword      '2 ручное, dam 18
    wpOdinsword       '2 ручное, dam 20
    wpHellguard       '2 ручное, dam 30
    wpQuarterstaff    '2 ручное, dam 4
    wpLongstaff       '2 ручное, dam 6
    wpPolearm         '2 ручное, dam 8
    wpLightspear      '2 ручное, dam 7 chr: 179
    wpHeavyspear      '2 ручное, dam 9
    wpTrident         '2 ручное, dam 10
    wpGlaive          '2 ручное, dam 12
    wpHandaxe         '1 ручное, dam 6 chr: 244
    wpBattleaxe       '1 ручное, dam 9
    wpGothicbattleaxe '2 ручное, dam 12
    wpWaraxe          '2 ручное, dam 14
    wpHalberd         '2 ручное, dam 16
    wpPoleaxe         '2 ручное, dam 18
    wpGreataxe        '2 ручное, dam 20
    wpSmallmace       '1 ручное, dam 6 chr: 226
    wpBattlemace      '1 ручное, dam 8
    wpSpikedmace      '1 ручное, dam 10
    wpDoubleballmace  '1 ручное, dam 12
    wpWarhammer       '1 ручное, dam 14
    wpMaul            '2 ручное, dam 16
    wpGreatMaul       '2 ручное, dam 20
    wpHellMaul        '2 ручное, dam 30
    wpBullwhip        '1 ручное, dam 4 chr: 231
    wpBallflail       '1 ручное, dam 6
    wpSpikedflail     '1 ручное, dam 8
    wpMorningstar     '1 ручное, dam 10
    wpBattleflail     '2 ручное, dam 12
    wpBishopsflail    '2 ручное, dam 14
    wpSling           '1 ручное, dam 2 chr: 125
    wpShortbow        '2 ручное, dam 8
    wpLongbow         '2 ручное, dam 10
    wpBonebow         '2 ручное, dam 14
    wpAdaminebow      '2 ручное, dam 20
    wpLightcrossbow   '2 ручное, dam 10 chr: 209
    wpHeavycrossbow   '2 ручное, dam 14
    wpBarrelcrossbow  '2 ручное, dam 18
    wpAdaminecrossbow '2 ручное, dam 25
End Enum

'Описание типа для оружия.
Type weapontype
    id As weaponids      'Идентификатор
    evaldr As Integer    'Сложность опознания. Если > 0 то есть магия.
    eval As Integer      'Если предмет опознан.
    effect As Integer    'Наложенное заклинание.
    sdesc As String * 30 'Секретное описание для магических предметов. Доступно если опознан.
    noise As Integer     'Кол-во генерируемого шума.
    use As itemuse       'Как используется.
    dam As Integer       'Наносимые повреждения.
    hands As Integer     'Сколько рук необходимо для использования.
    wslot(1 To 2) As wieldpos 'Слоты для размещения когда используется.
End Type


(В оригинальной книге в описании типа weapontype для параметра id был задан тип shieldids, но это, разумеется, ошибка, поэтому здесь я это исправил (примечание переводчика)).

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

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

Я говорил в прошлой главе, что очень просто добавлять новые типы предметов в игру, и это на самом деле так. Все что нужно для добавления оружия, это добавить новые варианты выбора в команды Select — case или If в подпрограммах работы с предметами. Так как вы уже несколько раз видели подобный код, то я оставляю эту задачу для вас. Вам теперь должно быть очевидно, что каждый новый подраздел кода, это продолжение уже написанного ранее, и так все и останется, если мы не изменим основной код работы с инвентарем.

Новый код у нас находится только в подпрограмме генерации оружия.

inv.bi

'Создаем оружие.
Sub GenerateWeapon(inv As invtype, currlevel As Integer, wpid As weaponids = wpNone)
    Dim item As weaponids = wpid
    Dim As Integer isMagic = ItemIsMagic(currlevel)

    'Создадим тип предмета, если не указан.
    If item = wpNone Then
        item = RandomRange(wpClub, wpAdaminecrossbow)
    Endif
    'Общее для всех типов оружия.
    inv.weapon.id = item
    inv.iconclr = fbCadmiumYellow
    inv.weapon.use = useWieldWear
    inv.weapon.eval = FALSE
    inv.weapon.wslot(1) = wPrimary
    inv.weapon.wslot(2) = wSecondary
    'Предмет содержит магию.
    If IsMagic = TRUE Then
        inv.weapon.evaldr = RandomRange(currlevel, currlevel * 2)
        inv.weapon.effect = 0
    Endif
    'Заполним характеристики оружия.
    Select Case item
        Case wpClub            '1 ручное, dam 4 chr:33
            inv.desc = "Club"
            inv.icon = Chr(33)
            inv.weapon.noise = 1
            inv.weapon.dam = 4
            inv.weapon.hands = 1
        Case wpCudgel          '1 ручное, dam 5
            inv.desc = "Cudgel"
            inv.icon = Chr(33)
            inv.weapon.noise = 2
            inv.weapon.dam = 5
            inv.weapon.hands = 1
        Case wpWarclub         '1 ручное, dam 6
            inv.desc = "War Club"
            inv.icon = Chr(33)
            inv.weapon.noise = 3
            inv.weapon.dam = 6
            inv.weapon.hands = 1
        Case wpDagger          '1 ручное, dam 4 chr: 173
            inv.desc = "Dagger"
            inv.icon = Chr(173)
            inv.weapon.noise = 1
            inv.weapon.dam = 4
            inv.weapon.hands = 1
        Case wpLongknife       '1 ручное, dam 5
            inv.desc = "Dagger"
            inv.icon = Chr(173)
            inv.weapon.noise = 2
            inv.weapon.dam = 5
            inv.weapon.hands = 1
        Case wpSmallsword      '1 ручное, dam 6
            inv.desc = "Small Sword"
            inv.icon = Chr(173)
            inv.weapon.noise = 3
            inv.weapon.dam = 6
            inv.weapon.hands = 1
        Case wpShortsword      '1 ручное, dam 8
            inv.desc = "Short Sword"
            inv.icon = Chr(173)
            inv.weapon.noise = 4
            inv.weapon.dam = 8
            inv.weapon.hands = 1
        Case wpRapier          '1 ручное, dam 10
            inv.desc = "Rapier"
            inv.icon = Chr(173)
            inv.weapon.noise = 5
            inv.weapon.dam = 10
            inv.weapon.hands = 1
        Case wpBroadsword      '1 ручное, dam 12
            inv.desc = "Broadsword"
            inv.icon = Chr(173)
            inv.weapon.noise = 6
            inv.weapon.dam = 12
            inv.weapon.hands = 1
        Case wpScimitar        '1 ручное, dam 12
            inv.desc = "Scimitar"
            inv.icon = Chr(173)
            inv.weapon.noise = 7
            inv.weapon.dam = 12
            inv.weapon.hands = 1
        Case wpLongsword       '2 ручное, dam 14
            inv.desc = "Longsword"
            inv.icon = Chr(173)
            inv.weapon.noise = 8
            inv.weapon.dam = 16
            inv.weapon.hands = 2
        Case wpKatana          '2 ручное, dam 16
            inv.desc = "Katana"
            inv.icon = Chr(173)
            inv.weapon.noise = 9
            inv.weapon.dam = 16
            inv.weapon.hands = 2
        Case wpClaymore        '2 ручное, dam 18
            inv.desc = "Claynore"
            inv.icon = Chr(173)
            inv.weapon.noise = 12
            inv.weapon.dam = 18
            inv.weapon.hands = 2
        Case wpGreatsword      '2 ручное, dam 20
            inv.desc = "Greatsword"
            inv.icon = Chr(173)
            inv.weapon.noise = 16
            inv.weapon.dam = 20
            inv.weapon.hands = 2
        Case wpOdinsword       '2 ручное, dam 30
            inv.desc = "Odinsword"
            inv.icon = Chr(173)
            inv.weapon.noise = 20
            inv.weapon.dam = 30
            inv.weapon.hands = 2
        Case wpHellguard       '2 ручное, dam 40
            inv.desc = "Hellguard"
            inv.icon = Chr(173)
            inv.weapon.noise = 30
            inv.weapon.dam = 40
            inv.weapon.hands = 2
        Case wpQuarterstaff    '2 ручное, dam 4 chr: 179
            inv.desc = "Quarterstaff"
            inv.icon = Chr(179)
            inv.weapon.noise = 1
            inv.weapon.dam = 4
            inv.weapon.hands = 2
        Case wpLongstaff       '2 ручное, dam 6
            inv.desc = "Longstaff"
            inv.icon = Chr(179)
            inv.weapon.noise = 2
            inv.weapon.dam = 6
            inv.weapon.hands = 2
        Case wpLightspear      '2 ручное, dam 7
            inv.desc = "Light Spear"
            inv.icon = Chr(179)
            inv.weapon.noise = 3
            inv.weapon.dam = 7
            inv.weapon.hands = 2
        Case wpPolearm         '2 ручное, dam 8
            inv.desc = "Polearm"
            inv.icon = Chr(179)
            inv.weapon.noise = 4
            inv.weapon.dam = 8
            inv.weapon.hands = 2
        Case wpHeavyspear      '2 ручное, dam 9
            inv.desc = "Heavy Spear"
            inv.icon = Chr(179)
            inv.weapon.noise = 5
            inv.weapon.dam = 9
            inv.weapon.hands = 2
        Case wpTrident         '2 ручное, dam 10
            inv.desc = "Trident"
            inv.icon = Chr(179)
            inv.weapon.noise = 6
            inv.weapon.dam = 10
            inv.weapon.hands = 2
        Case wpGlaive          '2 ручное, dam 12
            inv.desc = "Glaive"
            inv.icon = Chr(179)
            inv.weapon.noise = 7
            inv.weapon.dam = 12
            inv.weapon.hands = 2
        Case wpHandaxe         '1 ручное, dam 6 chr: 244
            inv.desc = "Hand Axe"
            inv.icon = Chr(244)
            inv.weapon.noise = 2
            inv.weapon.dam = 6
            inv.weapon.hands = 1
        Case wpBattleaxe       '1 ручное, dam 9
            inv.desc = "Battle Axe"
            inv.icon = Chr(244)
            inv.weapon.noise = 3
            inv.weapon.dam = 9
            inv.weapon.hands = 1
        Case wpGothicbattleaxe '2 ручное, dam 12
            inv.desc = "Gothic Battle Axe"
            inv.icon = Chr(244)
            inv.weapon.noise = 4
            inv.weapon.dam = 12
            inv.weapon.hands = 2
        Case wpWaraxe          '2 ручное, dam 14
            inv.desc = "War Axe"
            inv.icon = Chr(244)
            inv.weapon.noise = 5
            inv.weapon.dam = 14
            inv.weapon.hands = 2
        Case wpHalberd         '2 ручное, dam 16
            inv.desc = "Halberd"
            inv.icon = Chr(244)
            inv.weapon.noise = 6
            inv.weapon.dam = 16
            inv.weapon.hands = 2
        Case wpPoleaxe         '2 ручное, dam 18
            inv.desc = "Pole Axe"
            inv.icon = Chr(244)
            inv.weapon.noise = 8
            inv.weapon.dam = 18
            inv.weapon.hands = 2
        Case wpGreataxe        '2 ручное, dam 20
            inv.desc = "Great Axe"
            inv.icon = Chr(244)
            inv.weapon.noise = 10
            inv.weapon.dam = 20
            inv.weapon.hands = 2
        Case wpSmallmace       '1 ручное, dam 6 chr: 226
            inv.desc = "Small Mace"
            inv.icon = Chr(226)
            inv.weapon.noise = 1
            inv.weapon.dam = 6
            inv.weapon.hands = 1
        Case wpBattlemace      '1 ручное, dam 8
            inv.desc = "Battle Mace"
            inv.icon = Chr(226)
            inv.weapon.noise = 4
            inv.weapon.dam = 8
            inv.weapon.hands = 1
        Case wpSpikedmace      '1 ручное, dam 10
            inv.desc = "Spiked Mace"
            inv.icon = Chr(226)
            inv.weapon.noise = 6
            inv.weapon.dam = 10
            inv.weapon.hands = 1
        Case wpDoubleballmace  '1 ручное, dam 12
            inv.desc = "Double-Ball Mace"
            inv.icon = Chr(226)
            inv.weapon.noise = 8
            inv.weapon.dam = 12
            inv.weapon.hands = 1
        Case wpWarhammer       '1 ручное, dam 14
            inv.desc = "War Hammer"
            inv.icon = Chr(226)
            inv.weapon.noise = 10
            inv.weapon.dam = 14
            inv.weapon.hands = 1
        Case wpMaul            '2 ручное, dam 16
            inv.desc = "Maul"
            inv.icon = Chr(226)
            inv.weapon.noise = 12
            inv.weapon.dam = 16
            inv.weapon.hands = 2
        Case wpBullwhip        '1 ручное, dam 4 chr: 231
            inv.desc = "Bull Whip"
            inv.icon = Chr(231)
            inv.weapon.noise = 2
            inv.weapon.dam = 4
            inv.weapon.hands = 1
        Case wpBallflail       '1 ручное, dam 6
            inv.desc = "Ball Flail"
            inv.icon = Chr(231)
            inv.weapon.noise = 4
            inv.weapon.dam = 6
            inv.weapon.hands = 1
        Case wpSpikedflail     '1 ручное, dam 8
            inv.desc = "Spiked Flail"
            inv.icon = Chr(231)
            inv.weapon.noise = 6
            inv.weapon.dam = 8
            inv.weapon.hands = 1
        Case wpMorningstar     '1 ручное, dam 10
            inv.desc = "Morning Star"
            inv.icon = Chr(231)
            inv.weapon.noise = 8
            inv.weapon.dam = 10
            inv.weapon.hands = 1
        Case wpBattleflail     '2 ручное, dam 12
            inv.desc = "Battle Flail"
            inv.icon = Chr(231)
            inv.weapon.noise = 10
            inv.weapon.dam = 12
            inv.weapon.hands = 2
        Case wpBishopsflail    '2 ручное, dam 14
            inv.desc = "Bishop's Flail"
            inv.icon = Chr(231)
            inv.weapon.noise = 12
            inv.weapon.dam = 14
            inv.weapon.hands = 2
        Case wpSling           '1 ручное, dam 2 chr: 125
            inv.desc = "Sling"
            inv.icon = Chr(125)
            inv.weapon.noise = 1
            inv.weapon.dam = 2
            inv.weapon.hands = 1
        Case wpShortbow        '2 ручное, dam 8
            inv.desc = "Short Bow"
            inv.icon = Chr(125)
            inv.weapon.noise = 4
            inv.weapon.dam = 8
            inv.weapon.hands = 2
        Case wpLongbow         '2 ручное, dam 10
            inv.desc = "Long Bow"
            inv.icon = Chr(125)
            inv.weapon.noise = 6
            inv.weapon.dam = 10
            inv.weapon.hands = 2
        Case wpBonebow         '2 ручное, dam 14
            inv.desc = "Dragon Bone Bow"
            inv.icon = Chr(125)
            inv.weapon.noise = 10
            inv.weapon.dam = 14
            inv.weapon.hands = 2
        Case wpAdaminebow      '2 ручное, dam 20
            inv.desc = "Adamine Bow"
            inv.icon = Chr(125)
            inv.weapon.noise = 12
            inv.weapon.dam = 20
            inv.weapon.hands = 2
        Case wpLightcrossbow   '2 ручное, dam 10 chr: 209
            inv.desc = "Light Crossbow"
            inv.icon = Chr(209)
            inv.weapon.noise = 4
            inv.weapon.dam = 10
            inv.weapon.hands = 2
        Case wpHeavycrossbow   '2 ручное, dam 14
            inv.desc = "Heavy Crossbow"
            inv.icon = Chr(209)
            inv.weapon.noise = 8
            inv.weapon.dam = 14
            inv.weapon.hands = 2
        Case wpBarrelcrossbow  '2 ручное, dam 18
            inv.desc = "Barrel Crossbow"
            inv.icon = Chr(209)
            inv.weapon.noise = 12
            inv.weapon.dam = 18
            inv.weapon.hands = 2
        Case wpAdaminecrossbow '2 ручное, dam 25
            inv.desc = "Adamine Crossbow"
            inv.icon = Chr(209)
            inv.weapon.noise = 16
            inv.weapon.dam = 25
            inv.weapon.hands = 2
        Case Else
            inv.desc = "Unknown Weapon"
            inv.icon = Chr(63)
            inv.weapon.noise = 0
            inv.weapon.dam = 0
            inv.weapon.hands = 0
    End Select
    'Установим полное описание.
    If IsMagic = TRUE Then
        inv.weapon.sdesc = inv.desc
    Else
        inv.weapon.sdesc = inv.desc
    Endif
End Sub


Как вы можете убедится, процесс такой же как для брони и щитов. Для того, чтобы мы могли создавать этой подпрограммой определенные предметы оружия у нее есть дополнительный параметр weaponids, так же как и в процедуре генерации доспехов. Мы этим воспользуемся, например, чтобы создать нож с которым персонаж начинает игру по умолчанию. Если этот параметр не задан, то используется значение по умолчанию wpNone и генерируется случайное оружие. Если вы сравните процедуры генерации различных типов предметов, то заметите, что их код идентичен. Все предметы имеют схожие свойства, которые задаются данными подпрограммами, в результате вы можете просто скопировать уже написанную процедуру генерации предметов и вставить ее в код для генерации предметов другого типа, внеся в нее лишь небольшие изменения. Однако, здесь нужно быть очень осторожным и не стоит этого вообще делать, если вы досконально не понимаете как данная процедура работает.

Нам осталось только внести изменения в команду инвентаря «Одеть/Взять в руки».

dod.bas

'Команда «Одеть/Взять в руки».
Function ProcessEquip() As Integer
    Dim As String res, mask, desc, msg
    Dim As Integer i, iret, iitem, idx, ret = FALSE, freecnt
    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) 'Получим индекс в инвентаре.
                'Получим предмет.
                pchar.GetInventoryItem iitem, inv
                'Получим описание предмета.
                desc = GetInvItemDesc(inv)
                iret = FALSE
                idx = 0
                'Проверим слот 1.
                slot = GetInvWSlot(inv, 1)
                If slot <> wNone Then
                    'Проверим, свободен ли слот у персонажа.
                    If pchar.HasInvItem(slot) = FALSE Then
                        idx = slot
                        iret = TRUE
                    Endif
                End If
                'Если первый занят.
                If iret = FALSE Then
                    'Проверим слот 2.
                    slot = GetInvWSlot(inv, 2)
                    If slot <> wNone Then
                        'Проверим, свободен ли слот у персонажа.
                        If pchar.HasInvItem(slot) = FALSE Then
                            idx = slot
                            iret = TRUE
                        Endif
                    End If
                Endif
                'Нет свободных слотов.
                If iret = FALSE Then
                    msg = "No empty slots to equip " & desc & "."
                Else
                    'Если это оружие и необходимо более одной свободной руки.
                    If inv.classid = clWeapon Then
                        freecnt = 0
                        'Проверим свободные слоты.
                        If pchar.HasInvItem(wPrimary) = FALSE Then
                            freecnt += 1
                        Endif
                        If pchar.HasInvItem(wSecondary) = FALSE Then
                            freecnt += 1
                        Endif
                        If inv.weapon.hands > freecnt Then
                            iret = FALSE
                            msg = "Not enough free hands to equip " & desc & "."
                        Endif
                    End If
                    'Может ли персонаж воспользоваться щитом или оружием?
                    If inv.classid = clArmor Or inv.classid = clShield Then
                        If pchar.CanWear(inv) = false Then
                            iret = FALSE
                            msg = "Not enough strength to equip " & desc & "."
                        End If
                    Endif
                End If
                'Пустой слот найден?
                If iret = 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", msg, tWidgets.MsgBoxType.gmbOK
                End If
            Next
        Endif
    Endif

    Return ret
End Function


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

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

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

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

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

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