Давайте сделаем рогалик (Волшебные жезлы)
Волшебные жезлы являются одним из основных типов оружия в большинстве рогаликов, и «Подземелье Судьбы» казалось бы не завершенным, если бы мы их не реализовали. Есть два пути реализации применения жезлов в игре, в качестве магического оружия — когда жезл используется для создания волшебниками заклинаний, и в качестве наступательного оружия. Лично я склоняюсь к использованию жезлов способом, который я подсмотрел во Властелине Колец, т. е. в качестве наступательного оружия. Поскольку у нас уже реализованы дистанционные атаки, то, вполне естественно, что жезлы будут добавлены в игру как еще один тип дистанционного оружия. Как вы увидите, добавить их будет достаточно легко.
Во первых давайте определим некоторые правила для жезлов. У нас будут различные типы жезлов, основанные на материале из которого они изготовлены, такие как железо или, например, золото. Редкость металла, из которого изготовлен жезл, будет отвечать за его силу. Железные жезлы будут самыми слабыми, а золотые — самыми сильными. Жезлы будет иметь определенное количество зарядов и чтобы их сбалансировать, мы дадим более слабым жезлам больше зарядов, а более сильным — меньше. Когда заряды жезла закончатся, то его нельзя будет «перезарядить» как оружие. Когда мы доберемся до реализации магии, то мы добавим заклинания для подзарядки жезлов, но сейчас они у нас будут одноразовыми. Хотя механизм использования жезлов такой же как и для дистанционного орудия, мы будем классифицировать их как магические предметы и при их применении будем использовать факторы магической атаки и магической зашиты, а не факторы для обычных и дистанционных атак.
Первое что нужно сделать, это добавить несколько жезлов в наш список оружия.
inv.bi
'идентификаторы оружия. Enum weaponids ... wpAdaminecrossbow '2 ручное, повр. 25 wpIronWand '1 ручное, повр. 10 wpBrassWand '1 ручное, повр. 20 wpCopperWand '1 ручное, повр. 40 wpSilverWand '1 ручное, повр. 80 wpGoldWand '1 ручное, повр. 100 End Enum
Этим мы добавили в игру несколько магических жезлов. Как вы можете видеть
по комментариями, они достаточно мощные, поэтому нам нужно ограничить их
использование в игре.
Следующее что необходимо сделать, это добавить жезлы в подпрограмму генерации оружия — GenerateWeapon.
inv.bi
Case wpIronWand '1 ручное, повр. 10 inv.desc = "Iron Wand" inv.icon = Chr(139) inv.weapon.noise = 1 inv.weapon.dam = 10 inv.weapon.hands = 1 inv.weapon.weapontype = wtProjectile inv.weapon.capacity = RandomRange(1, 100) inv.weapon.ammotype = amNone inv.weapon.ammocnt = inv.weapon.capacity inv.weapon.iswand = TRUE Case wpBrassWand '1 hand, dam 20 inv.desc = "Brass Wand" inv.icon = Chr(139) inv.weapon.noise = 1 inv.weapon.dam = 20 inv.weapon.hands = 1 inv.weapon.weapontype = wtProjectile inv.weapon.capacity = RandomRange(1, 80) inv.weapon.ammotype = amNone inv.weapon.ammocnt = inv.weapon.capacity inv.weapon.iswand = TRUE Case wpCopperWand '1 ручное, повр. 40 inv.desc = "Copper Wand" inv.icon = Chr(139) inv.weapon.noise = 1 inv.weapon.dam = 40 inv.weapon.hands = 1 inv.weapon.weapontype = wtProjectile inv.weapon.capacity = RandomRange(1, 40) inv.weapon.ammotype = amNone inv.weapon.ammocnt = inv.weapon.capacity inv.weapon.iswand = TRUE Case wpSilverWand '1 ручное, повр. 80 inv.desc = "Silver Wand" inv.icon = Chr(139) inv.weapon.noise = 1 inv.weapon.dam = 80 inv.weapon.hands = 1 inv.weapon.weapontype = wtProjectile inv.weapon.capacity = RandomRange(1, 20) inv.weapon.ammotype = amNone inv.weapon.ammocnt = inv.weapon.capacity inv.weapon.iswand = TRUE Case wpGoldWand '1 ручное, повр. 100 inv.desc = "Gold Wand" inv.icon = Chr(139) inv.weapon.noise = 1 inv.weapon.dam = 100 inv.weapon.hands = 1 inv.weapon.weapontype = wtProjectile inv.weapon.capacity = RandomRange(1, 10) inv.weapon.ammotype = amNone inv.weapon.ammocnt = inv.weapon.capacity inv.weapon.iswand = TRUE
Обратите внимание, что в определение типа оружия мы добавили новое поле:
iswand. Мы будем использовать его для расчета факторов атаки и зашиты. Для
большинства видов оружия оно будет равно false. Мы устанавливаем его в true для
жезлов во время их создания.
Ключевым полем для жезлов является емкость (capacity). Для железных жезлов оно принимает значение от 1 до 100, для золотых — от 1 до 10. Как только мы получили емкость жезла, мы используем это значение чтобы зарядить жезл необходимым количеством зарядов, заполняя значение поля ammocnt. Жезлы не могут быть перезаряжены, поэтому тип боеприпасов для них мы устанавливаем в amNone.
Этого достаточно, чтобы получить жезлы как новый тип предмета инвентаря, но для их использования необходимо добавить некоторые изменения в процедуру пользования дистанционного оружия.
dod.bas:DoProjectileCombat
... 'Получим фактор зашиты монстра. If pchar.ProjectileIsWand(wslot) = TRUE Then df = level.GetMonsterMagicDefense(mx, my) Else df = level.GetMonsterDefense(mx, my) Endif ... 'Возвращает фактор атаки зависящий от используемого оружия. If pchar.ProjectileIsWand(wslot) = TRUE Then cf = pchar.GetMagicCombatFactor() Else cf = pchar.GetProjectileCombatFactor() Endif ...
Функция ProjectileIsWand просто возвращает значение из поля iswand
объекта оружия. Если это так, то мы получаем значения магической защиты монстра
и магической атаки персонажа используя функции GetMonsterMagicDefense и
GetMagicCombatFactor. Верьте или нет, но это единственные изменения, которые
необходимо в нести для модификации удаленных атак.
Давайте взглянем на две новые функции:
level.bi
'Возвращает магическую защиту монстра. Function levelobj.GetMonsterMagicDefense(mx As Integer, my As Integer) As Integer Dim As Integer ret = 0, midx = 0 'Убедимся что монстр здесь. If _level.lmap(mx, my).monidx > 0 Then midx = _level.lmap(mx, my).monidx ret = _level.moninfo(midx).md Endif Return ret End Function
Мы просто проверяем, находится ли монстр по указанным координатам и
возвращаем значение поля md описания монстра, которое содержит его фактор
магической защиты.
Получить фактор магической атаки персонажа также просто:
character.bi
'Возвращает фактор магической атаки. Function character.GetMagicCombatFactor() As Integer Return CurrMCF + BonMcf End Function
Просто возвращаем значение фактора магической атаки вместе с бонусом.
Все что нам осталось сделать, это обновить часть подпрограммы описания объектов, добавив в нее обработку новых полей.
inv.bi
... 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 If inv.weapon.weapontype = wtProjectile Then idx += 1 Redim Preserve lines(0 To idx) As String lines(idx) = "* Capacity: " & inv.weapon.capacity idx += 1 Redim Preserve lines(0 To idx) As String lines(idx) = "* Ammo Cnt: " & inv.weapon.ammocnt Endif 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" idx += 1 Redim Preserve lines(0 To idx) As String lines(idx) = "* Spell: " & GetSpellDescriptions(inv.weapon.spell) Else lines(idx) = "* Item is not evaluated" End If ...
Мы добавили секцию IF, чтобы отображать количество зарядов в оружии, если
необходимо. Это будет работать не только с жезлами, но и с любым другим
дистанционным оружием.
Это все что необходимо для добавления магических жезлов в игру. Как вы можете видеть, мы использовали код реализации дистанционного оружия для добавления оружия нового типа, хотя оно и является достаточно экзотическим. Ключевым моментом является использование поля емкости обоймы (capacity) метательного оружия. Без него мы не могли бы добавить жезлы так же легко. Но наличие этого поля и кода, связанного с ним, позволило нам очень малыми силами добавить даже такое экзотическое оружие как магические жезлы.
Перевод на русский: Fantik
содержание | назад | вперед