Давайте сделаем рогалик (Магия ювелирных изделий)

jewelmagic.png

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


Inv.bi

'Список id эффектов.
  Enum spellid
    ...
    splUCF         'Украшение: +% к UCF.
    splACF         'Украшение: +% к ACF.
    splPCF         'Украшение: +% к PCF.
    splMCF         'Украшение: +% к MCF.
    splCDF         'Украшение: +% к CDF.
    splMDF         'Украшение: +% к MDF.
    splRegenHP     'Украшение: +% к восстановлению здоровья за ход.
    splRegenMana   'Украшение: +% к восстановлению маны за ход.
  End Enum

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

inv.bi
'Эффекты драгоценностей.
  Enum jeffects
    jwNone 
    jwUCF 
    jwACF 
    jwPCF 
    jwMCF 
    jwCDF 
    jwMDF 
    jwRegenHP
    jwRegenMana 
  End Enum

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

Изменения, внесенные в процедуру генерации ювелирных изделий очень просты:

inv.bi:GenerateJewlery
...
    'Магический предмет.
    If IsMagic = TRUE Then
      inv.jewelry.evaldr = GetScaledFactor(charint, currlevel)
      inv.jewelry.spell.id = RandomRange(splUCF, splRegenMana) 'id заклинания.
      GenerateSpell inv.jewelry.spell, currlevel
      inv.jewelry.spelleffect = GetJewelrySpellEffect(inv.jewelry.spell.id)
    Endif
  ...

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

inv.bi
'Возвращает магический эффект для ювелирного изделия.
  Function GetJewelrySpellEffect(id As spellid) As jeffects
    Dim ret As jeffects
      
    Select Case id
      Case splUCF
         ret = jwUCF
      Case splACF
         ret = jwACF
      Case splPCF
         ret = jwPCF
      Case splMCF
         ret = jwMCF
      Case splCDF
         ret = jwCDF
      Case splMDF
         ret = jwMDF
      Case splRegenHP
         ret = jwRegenHP
      Case splRegenMana
         ret = jwRegenMana
      Case Else
         ret = jwNone
    End Select
 
    Return ret
  End Function

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

character.bi
'Возвращает магический эффект любого украшения.
  Function character.GetJewleryEffect(effect As jeffects, baseamt As Integer) As Integer
    Dim As Integer ret = 0
    
    'Проверим, это амулет или кольцо.
    If _cinfo.cwield(wNeck).classid = clNecklace Then
      'Убедимся что продмет опознан.
      If _cinfo.cwield(wNeck).jewelry.eval = TRUE Then
         'Проверим на наличие заклинаний.
         If _cinfo.cwield(wNeck).jewelry.spell.id <> splNone Then
            'Проверим, совпадает ли эффект.
            If _cinfo.cwield(wNeck).jewelry.spelleffect = effect Then
               'Увелимим значение силы эффекта.
               ret += Int((_cinfo.cwield(wNeck).jewelry.spell.lvl / 100) * baseamt) + 1
            Endif
         End If
      Endif
    Endif
    If _cinfo.cwield(wRingRt).classid = clRing Then
      'Убедимся что предмет опознан.
      If _cinfo.cwield(wRingRt).jewelry.eval = TRUE Then
         'Проверим на наличие заклинаний.
         If _cinfo.cwield(wRingRt).jewelry.spell.id <> splNone Then
            'Проверим эффект.
            If _cinfo.cwield(wRingRt).jewelry.spelleffect = effect Then
               'Увелисим силу эффекта.
               ret += Int((_cinfo.cwield(wRingRt).jewelry.spell.lvl / 100) * baseamt) + 1
            Endif
         End If
      Endif
    Endif
    If _cinfo.cwield(wRingLt).classid = clRing Then
      'Убедимся что продмет опознан.
      If _cinfo.cwield(wRingLt).jewelry.eval = TRUE Then
         'Проверим на наличие заклинаний.
         If _cinfo.cwield(wRingLt).jewelry.spell.id <> splNone Then
            Проверим, совпадает ли эффект.
            If _cinfo.cwield(wRingLt).jewelry.spelleffect = effect Then
               'Увелисим силу эффекта.
               ret += Int((_cinfo.cwield(wRingLt).jewelry.spell.lvl / 100) * baseamt) + 1
            Endif
         End If
      Endif
    Endif
    
    Return ret
  End Function

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

character.bi
'Возвращает текущий боевой фактор, зависяций от того, какими предметами владее персонаж.
  Function character.GetMeleeCombatFactor() As Integer
    Dim As Integer ret
     
    'Рукопашный бой.
    If (_cinfo.cwield(wPrimary).classid <> clWeapon) And (_cinfo.cwield(wSecondary).classid <> clWeapon) Then
      ret = CurrUcf + BonUcf
      ret += GetJewleryEffect(jwUCF, ret)
   Else
      'Проверим главный слот.
      If _cinfo.cwield(wPrimary).classid = clWeapon Then
         'Экипировано оружие ближнего боя.
         If _cinfo.cwield(wPrimary).weapon.weapontype <> wtProjectile Then
            ret = CurrAcf + BonAcf
            ret += GetJewleryEffect(jwACF, ret)
         Else
          'Вернуть UCF, дистанционное оружие — не оружие для ближнего боя.
           ret = CurrUcf + BonUcf
           ret += GetJewleryEffect(jwACF, ret)
         Endif
      Else
         If _cinfo.cwield(wSecondary).classid = clWeapon Then
            'Экипировано оружие ближнего боя.
            If _cinfo.cwield(wSecondary).weapon.weapontype <> wtProjectile Then
               ret = CurrAcf + BonAcf
               ret += GetJewleryEffect(jwACF, ret)
            Else
               'Вернуть UCF, дистанционное оружие — не оружие для ближнего боя.
               ret = CurrUcf + BonUcf
               ret += GetJewleryEffect(jwACF, ret)
            End If
         Endif
      End If
    Endif
 
    Return ret
  End Function

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

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

character.bi:DoTimedEvents
...
   'Check for necklaces and rings.
   statamt = MaxHP
   amt = GetJewleryEffect(jwRegenHP, statamt)
   CurrHP = CurrHP + amt
   statamt = MaxMana
   amt = GetJewleryEffect(jwRegenMana, statamt)
   CurrMana = CurrMana + amt
  ...

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

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

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

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