netlib.narod.ru< Назад | Оглавление | Далее >

Сражения и персонажи

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

Хотя вы и ожидаете от боевых последовательностей роскошной графики и крутых эффектов, начинать следует с основ. В основе каждого сражения лежит набор правил (называемых правилами сражения, combat rules), определяющих последствия каждого взмаха оружием, каждого отклоненного удара, и результаты каждого магического заклинания.

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

Использование правил сражения для атаки

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

Набор правил сражения (combat rule set, CRS) вашей игры отталкивается от способностей, атрибутов и умений персонажа, которые вы уже видели в этой главе. Помните, как этим способностям, умениям и атрибутам назначались числовые значения? Догадываетесь зачем? Эти значения используются для генерации нескольких значений, определяющих исход боевых действий.

Например, атрибут меткости игрока используется в вычислении случайного числа, чтобы увидеть, куда попала атака. Затем сравнение с проворностью оппонента атакующего определяет, была ли атака отклонена. Если оппонент оказался не настолько удачлив, в игру вступает значение атаки атакующего, определяющее ущерб. Помните также, что у атакуемого персонажа также есть способность защиты, помогающая уменьшить количество повреждений.

После принятия решения об атаке, результат определяют несколько шагов.

Нанесение удара

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

Значение меткости может находиться в диапазоне от 0 (всегда промахивается) до 999 (всегда попадает). Взяв случайное число и сравнив его со значением меткости вы можете быстро определить, произошло ли попадание. Если случайное число меньше или равно значению атрибута меткости, удар попал в цель. Следующий код показывает, как определить успешность удара:

// ToHit = значение атрибута меткости персонажа
long RandomValue = rand() % 1000;
BOOL HitFlag = (RandomValue <= ToHit) ? TRUE : FALSE;

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

Чтобы применить любой модификатор дополнительного статуса, умножьте на него определенное значение меткости:

if(Ailments & AILMENT_BLIND)
    ToHit = (long)((float)ToHit * 0.75f);

if(Ailments & AILMENT_HAWKEYE)
    ToHit = (long)((float)ToHit * 1.5f);

long RandomValue = rand() % 999;
BOOL HitFlag = (RandomValue <= ToHit) ? TRUE : FALSE;

Отклонение атаки

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

// Agility = значение проворности персонажа
RandomValue = rand() % 999;
BOOL DodgeFlag = (RandomValue <= Agility) ? TRUE : FALSE;

 

ВНИМАНИЕ!
Вы можете определить из вычислений способности уклоняться, что чем выше значение проворности, тем больше шанс уклониться от атаки. Поэтому в общем случае не надо устанавливать слишком большие значения для способности персонажа, поскольку он может стать неприкосновенным.

Для увеличения или уменьшения шансов отклонения атаки вы можете использовать дополнительные статусы неуклюжести и устойчивости. Неуклюжесть уменьшает шансы отклонить атаку на 25 процентов, а устойчивость повышает шансы на 50 процентов (это значит, что персонаж, у которого установлены оба эти дополнительные статусы, увеличивает свои шансы отклонить атаку на 25 процентов):

if(Ailments & AILMENT_CLUMSY)
    Agility = (long)((float)Agility * 0.75f);

if(Ailments & AILMENT_SUREFOOTED)
    Agility = (long)((float)Agility * 1.5f);

long RandomValue = rand() % 999;
BOOL DodgeFlag = (RandomValue <= Agility) ? TRUE : FALSE;''

Обработка ущерба

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

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

Верно. Предметы экипировки добавляют множители к способностям атаковать и защищаться. Ключом является значение модификатора предмета. Это значение представляет собой величину от 0 и больше, которая делится на 100 и увеличивается на единицу, что дает значение множителя, используемого совместно со значением способности. Например, оружие со значением модификатора 150 увеличивает способность атаковать на 50 процентов:

// Attack = значение способности атаковать персонажа
// Item[] = массив главного списка предметов
long Attack = (long)((float)Attack *
      (((float)Item[Weapon].Value / 100.0f) + 1.0f));

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

// Attack = значение способности атаковать атакующего
// Defense = значение способности защищаться обороняющегося
// Item[] = массив главного списка предметов
// Weapon = номер оружия в списке предметов (или -1, если его нет)
// Armor = номер доспехов в списке предметов (или -1, если их нет)
// Shield = номер щита в списке предметов (или -1, если его нет)

// Определяем количество атаки

// Начинаем с добавления модификатора имеющегося оружия
if(Weapon != -1)
    long Attack = (long)((float)Attack *
             (((float)Item[Weapon].Value / 100.0f) + 1.0f));

// Подстраиваем в соответствии с дополнительными статусами
if(Ailments & AILMENT_WEAK)
    Attack = (long)((float)Attack * 0.5f);
if(Ailments & AILMENT_STRONG)
    Attack = (long)((float)Attack * 1.5f);

// Определяем количество защиты

// Применяем модификаторы доспехов и щита
if(Armor != -1)
    Defense = (long)((float)Defense *
             (((float)Item[Armor].Value / 100.0f) + 1.0f);
if(Shield != -1)
    Defense = (long)((float)Defense *
             (((float)Item[Shield].Value / 100.0f) + 1.0f);

// Применяем дополнительные статусы
if(Ailments & AILMENT_WEAK)
    Defense = (long)((float)Defense * 0.5f);
if(Ailments & AILMENT_STRONG)
    Defense = (long)((float)Defense * 1.5f);

float DamagePercent = ((float)(rand() % 70) + 50.0f) / 100.0f;
long DamageAmount = (long)((float)Attack * DamagePercent);

// Определяем количество повреждений
// (используя здесь некоторые случайные коэффициенты)
float Range = (float)((rand() % 20) + 90) / 100.0f;
long DmgAmount = (long)((float)Attack * Range);
Range = (float)((rand() % 20) + 80) / 100.0f;
DmgAmount -= (long)((float)Defense * Range);

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

ВНИМАНИЕ!
И снова, способность защищаться у персонажа не должна быть настолько высокой, что защищающийся персонаж будет очень редко получать какие-либо повреждения, когда атака достигает цели.

Заклинания в битве

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

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

// Chance = шанс срабатывания заклинания
// Mental = значение интеллекта заклинателя
Chance = (long)(((float)Mental / 100.0f + 1.0f) * (float)Chance);

Последняя строка показывает, что значение интеллекта может находиться в диапазоне от 0 и выше. Значение 150 означает увеличение шансов на 50 процентов, а значение 200 означает удвоение шанса. Для помощи жертвам заклинаний у персонажей есть связанное с ними значение сопротивляемости, также выступающее как множитель:

// Resistance = сопротивляемость цели
Chance = (long)((1.0f - (float)GetResistance(Target) /
          100.0f) * (float)Chance);

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

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

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

// Chance = шанс срабатывания магического заклинания
// Mental = Интеллект сотворившего заклинание
// Resistance = Сопротивляемость жертвы
// Amount = Базовое количество наносимых заклинанием повреждений

// Применяем дополнительные статусы к интеллекту и сопротивляемости
if(Ailments & AILMENT_DUMBFOUNDED)
    Mental /= 2;
if(Ailments & AILMENT_ENCHANTED)
    Resistance = (long)((float)Resistance * 0.5f);
if(Ailments & AILMENT_BARRIER)
    Resistance = (long)((float)Resistance * 1.5f);

// Проверяем шанс срабатывания и вычисляем ущерб
Chance=(long)(((float)Mental / 100.0f + 1.0f) * (float)Chance);
if((rand() % 100) < Chance) {
    float Resist = 1.0f - ((float)Resistance / 100.0f);
    long DmgAmount = (long)((float)Amount * Resist);

    // Применяем дополнительные повреждения или исцеления,
    // зависящие от класса
}

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

Поскольку вы создадите реальный контроллер персонажей в разделе «Создание класса контроллера персонажей» позже в этой главе, отложим до него завершение работы с заклинаниями.

Интеллект в битвах

Хотя игроки способны полностью управлять их персонажами в игре, на вашу долю остается управление NPC. Чтобы игра была достойной, искусственный интеллект ваших NPC должен быть равным противником для сражений. Их действия должны подражать вашим, выбирают ли они атаку, исцеляют себя или произносят заклинание.

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

Если, с другой стороны, PC попадает в область видимости другого персонажа, враждебный персонаж выбирает, напасть ли физически или провести магическую атаку (если известны какие-нибудь заклинания). Вам необходимо назначить шансы, что персонаж проведет нападение, для каждого типа атаки. Обратите внимание, что атаки базируются на встроенном заряде атакующего существа — чтобы создание атаковало, его заряд должен быть полным.

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

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


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz