Последний из нереализованных нами классов, и важная область игры - магия. На первый взгляд может показаться, что ее реализация потребует большого объема работы, однако мы уже хорошо продумали и отладили механизмы расширения навыков героя, и введение новых навыков и умений не потребует каких-либо кардинальных переделок и улучшений.
Под магией мы будем понимать способность игрока к выполнению так называемых заклинаний - магических действий, а также к использованию магических предметов. Чтобы выполнить заклинание, персонажу потребуется специальная магическая энергия, в большинстве игр называемая маной.
Добавим персонажу две новые характеристики - по аналогии с уровнем здоровья, Mana и MaxMana:
type THero = record
Chars : array[1..MaxChars] of Integer;
Skills: array[1..MaxSkills] of Integer;
Items : array[1..MaxHeroItems] of TGameItem;
Slots : array[1..MaxSlots] of TGameItem;
x,y,
HP, MaxHP,
Mana, MaxMana,
Exp, MaxExp,
Level, VisLong: Integer;
Class, Race: Integer;
Name: String[20]; end;
Мана должна формироваться и расти вместе с показателями здоровья, хотя для некоторых классов (в нашем случае - для класса воина) способность к магии должна быть запрещена, как того требуют классические ролевые системы. А у стрелка она должна быть развита слабо. В ходе анализа соответствующего кода мы выясним, что у нас пока не реализована разница в здоровье для персонажей разных классов. Для уровня здоровья задействован один массив HPLevel_Table, в котором нет дополнительного деления на классы (впрочем, он
создавался, когда о классах мы еще не задумывались). Давайте такое дополнение введем:
Во всех местах, которые теперь будут компилироваться с ошибками, нам надо будет исправить обращение к массиву уровней здоровья на уточненный вызов с указанием класса, а также добавить код работы с уровнем маны. Часть команд из процедуры InitHero (инициализация HP, MaxHP) перенесем для удобства в конец GenerateHero, так как теперь нам нужно знать выбранный класс героя. Тут же разместим инициализацию уровня маны:
...
with Heroes[CurHero] do begin
MaxHP := HPLevel_Table[Class,Level];
HP := MaxHP;
Mana := ManaLevel_Table[Class,Level];
MaxMana := Mana;
Exp := 0;
MaxExp := ExpLevel_Table[Level];
VisLong := 2; end;
end;
Схожий код исправим и откорректируем в процедуре IncXP (модуль Hero):
{ ----------------- } procedure IncXP( var H: THero; axp: Integer ); begin
inc( H.Exp, axp );
ShowInfo(STR_ADD_EXP + IntToStr(axp)); if H.Exp > H.MaxExp then begin
H.Exp := 0; if H.Level < MaxPlayerLevel then begin
ShowInfo(STR_NEXTLEVEL);
inc(H.Level); end;
H.MaxExp := ExpLevel_Table[H.Level];
H.MaxHP := HPLevel_Table[H.Class,H.Level];
H.MaxMana := ManaLevel_Table[H.Class,H.Level];
H.HP := H.MaxHP; end; end;
Также добавим строку вывода уровня маны в процедуру динамического отображения информации о герое ShowHeroInfo:
Как мана будет расходоваться? Расходоваться она будет на заклинания. А заклинания - товар штучный, их сложно уложить в прокрустово ложе описания структуры. Работа заклинания - процесс оригинальный и будет реализовываться непосредственно в программном коде.
Для демонстрации возможностей магической системы создадим два заклинания. Первое, назовем его "Огненный шторм", будет наносить повреждения от 1 до 4 единиц каждому монстру, находящемуся на любой соседней с героем клеток, а второе - "Самоисцеление", позволит быстро восстановить собственное здоровье. За счет маны, конечно.
По какому принципу будут вызываться заклинания? В крупных ролевых проектах список доступных герою заклинаний формируется постепенно. Например, для этого надо пройти обучение в школе или у какого-нибудь мастера, учителя. Существует также концепция "метания заклинаний", когда у героя имеется некий универсальный навык "метания" - выполнения любого заклинания, и если он срабатывает, персонаж уже выбирает нужное из списка выученных на данный момент.
Далее - создаем заклинание "Огненный шторм".
Исходный код текущей версии для Turbo Pascal (всегда проверен и работоспособен, главный файл - main.pas):