на главную
об игре
Serious Sam The Second Encounter 08.02.2002

Работа с SDK. Введение новых параметров для врага

Информация о статье

Статья предусматривает то, что Вы умеете создавать директории для модов, а также, что у Вас имеется Visual C++ 6.0 и он полностью настроен на работу с SDK.

Статья посвящена следующим вопросам:

  • Добавление в редактор возможности задания здоровья врага;
  • Добавление в редактор возможности выставить бессмертие врагам;
  • Добавление в редактор возможности выставить невидимость врагам;
  • Добавление в редактор возможности возможности выставить скорость передвижения врага;
  • Добавление в редактор возможности выставить кол-во очков за смерть врага;
  • Добавление в редактор возможности чтобы при каждом убийстве враги разлетались на куски;
  • Добавление в редактор возможности выставить кол-во куском мяса с врага;
  • Добавление в редактор возможности выставить снаряды врага(лазер, ракеты, гранаты...).
  • Добавление в редактор возможности включить полосу жизни врага.

Модернизация врага

Рассмотрим модернизацию врага на примере Зорга, или же на английской версии - Grunt.

1) Для добавления здоровья в редактор, необходимо указать соответствующую переменную после кода:

properties:

1 enum GruntType m_gtType "Type" 'Y' = GT_SOLDIER,

2 INDEX fHealth "Health" = 40,
 

Здесь мы объявили целочисленную переменную с именем fHealth, задали как она будет называться в редакторе в двойных кавычках: "Health" и задали некое начальное значение равное 40. Переменная есть - теперь нужно ее связать с здоровьем. Опуститесь ниже и найдите главную функцию:

Main(EVoid)

Найдите строки:

SetHealth(40.0f);
m_fMaxHealth = 40.0f;

И замените их на:

SetHealth(fHealth);
m_fMaxHealth = fHealth;
 

Далее найдите строки:

SetHealth(60.0f);
m_fMaxHealth = 60.0f;

Замените на:

SetHealth(fHealth);
m_fMaxHealth = fHealth;
 

Мы установили здоровье равное значению переменной как и у зорга-солдата так и у зорга-командира. Теперь можно запросто выставлять здоровье через редактор:

image hosting blogs journals
image hosting blogs journals

2) Добавим остальные интересующие нас переменные как показано на рисунке:

image hosting blogs journals
image hosting blogs journals

(на номера строк во втором окне не смотреть, у Вас они будут совсем другие)

Вот эти строки:

3 BOOL invisible "Invisible" = FALSE,
4 FLOAT speed "Speed" = 6.5,
5 BOOL alwaysBlobUp "Always BlowUp" = FALSE,
6 INDEX scorePerKill "Score" = 500,
7 enum SoldierWeapon m_weapon "Soldier Weapon" = Laser,
8 BOOL invulnerability "Invulnerability" = FALSE,
9 INDEX bodyParts "Body Parts" = 4,
 

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

3 BOOL invisible "Invisible" = FALSE,

Означает, что параметр может иметь два значения - "Истина"(TRUE) или "Ложь"(FALSE). Этот параметр отвечает за невидимость врага. Поэтому поставим по умолчанию чтобы враги были видимы. Не нарушаем игровой баланс. Вы можете поставить и TRUE чтобы усложнить игру. Следующий параметр:

4 FLOAT speed "Speed" = 6.5,

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

5 BOOL alwaysBlobUp "Always BlowUp" = FALSE,

Имеет тип как и невидимость, поэтому на нем останавливаться не будем. За кол-во очков, заработанных за убийство монстра будет отвечать эта переменная:

6 INDEX scorePerKill "Score" = 500,

Через строку идет еще две переменных:

8 BOOL invulnerability "Invulnerability" = FALSE,
9 INDEX bodyParts "Body Parts" = 4,

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

7 enum SoldierWeapon m_weapon "Soldier Weapon" = Laser,

Тип enum происходит от английского слова - enumeration(перечисление). Да, действительно этот тип представляет собою перечисление.

Вот как выглядит пример перечисления в редакторе:

image hosting blogs journals
image hosting blogs journals

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

Вставьте следующий код в указанном месте, как на рисунке:

image hosting blogs journals
image hosting blogs journals

Вот этот код:

enum SoldierWeapon {
0 Laser "LASER",
1 Rocket "ROCKET",
};
 

Laser, Rocket - идентификаторы(Значения, которые может принимать переменная, в нашем случае -m_weapon). "LASER", "ROCKET" - текст, который будет отображаться в редакторе в меню выбора элемента перечисления.

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

3) Реализуем необходимый функционал для наших переменных. Для обеспечения неуязвимости вставим код как показано на картинке:

image hosting blogs journals
image hosting blogs journals

if (invulnerability==false){ CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection);}

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

image hosting blogs journals
image hosting blogs journals

Код:

m_fAttackRunSpeed = FRnd() + speed;

Отвечает за скорость врага. Код:

m_fAttackDistance = 1000.0f;

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

if (alwaysBlobUp==FALSE)
{
m_fBlowUpAmount = 80.0f;
}
else
{
m_fBlowUpAmount = 0.1f;
 }

Если переменная враги всегда разлетаюсь = ложь, то враг будет разлетаться только в случае, если ему нанесено 80 или более единиц урона, в ином случае - если менее 1 единицы урона.  На следующем коде подробно останавливаться не будем, он представляет привязку здоровья и очков за врага к переменным:

m_iScore = scorePerKill;
SetHealth(fHealth);
m_fMaxHealth = fHealth;
 

При установке флага невидимости данный код обеспечивает прозрачность врага:

if (invisible==TRUE)
{
GetModelObject()->mo_colBlendColor = C_WHITE|0x25;
}

Подобным образом Вы можете описать параметры и для командира, можете улучшить их, так как это командир. Я написал такие же параметры:

image hosting blogs journals
image hosting blogs journals

4) Теперь разберемся с оружием врага. Будет стрелять он лазером или ракетами. Для этого отредактируйте как на картинке указанный участок кода:

image hosting blogs journals
image hosting blogs journals

StartModelAnim(GRUNT_ANIM_FIRE, 0);

if (m_weapon==Rocket){
ShootProjectile(PRT_WALKER_ROCKET, FIREPOS_SOLDIER, ANGLE3D(0, 0, 0));
}
else
{
ShootProjectile(PRT_GRUNT_PROJECTILE_SOL, FIREPOS_SOLDIER, ANGLE3D(0, 0, 0));
}
PlaySound(m_soFire1, SOUND_FIRE, SOF_3D);

autowait(0.15f + FRnd()*0.1f);
StartModelAnim(GRUNT_ANIM_FIRE, 0);
if (m_weapon==Rocket){
ShootProjectile(PRT_WALKER_ROCKET, FIREPOS_SOLDIER, ANGLE3D(0, 0, 0));
}
else
{
ShootProjectile(PRT_GRUNT_PROJECTILE_SOL, FIREPOS_SOLDIER, ANGLE3D(0, 0, 0));
}
 

Рассмотрим как стреляет зорг-солдат, он останавливается и с определенным интервалом выстреливает два раза. Вот этот промежуток времени между выстрелами:

autowait(0.15f + FRnd()*0.1f);

Далее снова идет анимация выстрела:

StartModelAnim(GRUNT_ANIM_FIRE, 0);

И сам выстрел -ShootProjectile. И в зависимости от того m_weapon=Rocket(равно ли?). Выполяется либо выстрел лазером, либо выстрел ракетой:

PRT_GRUNT_PROJECTILE_SOL

PRT_WALKER_ROCKET

Результат виден на снимке экрана:

image hosting blogs journals
image hosting blogs journals

5) Рассмотрим добавление полосы жизни врагам. Итак, начнем с того, что большинство врагов являются наследниками от класса EnemyBase, в котором есть поле:

144 BOOL m_bBoss = FALSE,// set for bosses (for health display)

Именно это поле и отвечает за отображение полосы здоровья. Но, к сожалению, не у каждого монстра есть возможность скорректировать данное свойство, а как следует из кода, то по умолчанию стоит значение FALSE, следовательно полоса здоровья отображаться не будет. Данную проблему легко решить следующим образом: добавляем в класс нашего монстра новую переменную логического типа(BOOL), которую потом будем использовать для установки значения m_bBoss. Пример добавления приведен на следующем снимке:

image hosting blogs journals
image hosting blogs journals

Сам код, который нужно добавить:

12 BOOL m_bGruntBoss "Boss" 'B' = FALSE

Мы ввели новую переменную. Теперь необходимо связать эти две переменные - переменную родительского класса и переменную дочернего класса. Для этого в методе Main(EVoid) добавляем следующий код:

m_bBoss=m_bGruntBoss;
 

Например, добавим полосу зоргу-солдату, но не зоргу-коммандиру:

image hosting blogs journals
image hosting blogs journals

Если требуется добавить всем типам данного монстра то следует добавлять вне оператора switch(m_gtType) {}

Результат виден на следующем снимке:

image hosting blogs journals
image hosting blogs journals

 

Заключение

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

Данная статья помогла:

* Расширить параметры врага. Это видно со следующего снимка:

image hosting blogs journals
image hosting blogs journals

А именно реализовать задачи, поставленные вначале.

* Улучшить навыки в поиске необходимого кода(разбираться в коде)

* Узнать больше о синтаксических конструкциях языка С++, а также о конструкциях, которые используются в SDK.

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

Удачи в создании модификаций!  
 

Комментарии: 0
Ваш комментарий