Новости/News | | Туториалы/Tutorials | | Форум/Forum | | ЧаВо/FAQ | | Файлы/Downloads | | Ссылки/Links | | Авторы/About |

Оружие, простреливающее стены и игроков

Содержание

Вступление

Большинство из Вас наверняка играли в популярный мод к Half-Life под незамысловатым названием Counter Strike. Одной из приятнейших вещей этого мода является наличие оружия, достаточно сильных, чтобы пробивать стены. В случае с Half-Life дела обстоят довольно просто, т.к. в нем уже был ряд оружия, способного простреливать стены. Поэтому, все, что оставалось сделать рядовому модеру это незначительная настройка уже существующего оружия. Unreal Tournament, к сожалению, таким арсеналом похвастаться не может. Остается только своими силами добиться реализации подобного эффекта.

Без сомнения, существует много различных вариантов для "создания" такого вида оружия. Нижеописанный метод всего лишь один из многих пришедших в голову. У него есть свои недостатки (см. главу Недостатки), но в силу своей простоты и легкости реализации был выбран именно такой путь.

Теория

В Unreal Tournament оружия "мгновенного" типа (пистолет, пулемет, винтовка) используют понятие траектории (trace) для обнаружения конечной цели выстрела. Траектория начинается непосредственно с игрока, который выстрелил, затем происходит анализ вдоль траектории (прямой) до тех пор, пока линия не пересечется с объектом (стена, игрок и пр.). Если все это перенести графически на плоскость, то нормальное оружие стреляет таким образом:

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

Когда же стена толще, чем Х, исходная точка второй траектории будет находиться внутри стены и, достигнув внутренней части стены, остановится:

В реальном мире все намного сложнее. Проблема состоит в том, что игрок достаточно "толстый" и, соответственно, фактор проникновения должен быть достаточно высок, чтобы прострелить его. Если Вы установите для Х большое значение, то Ваше оружие будет простреливать стены намного толще, чем Вы бы сами того желали. Решением этой проблемы является назначение двух различных факторов проникновения: один для pawns (в число которых и входит игрок) и другой для всего остального. В конце первой траектории будет опрашиваться, с кем она пересеклась (pawn или же просто препятствие) и, в зависимости от ситуации, будет использован соответствующий фактор проникновения.

Практика

Звучит, как Вы видите, просто. Но как все это реализовать? И в этом также нет ничего сложного. Все, что для этого понадобиться, это перегрузить метод TraceFire() и в него заскриптить вызов второй траектории. Но, не думайте, что Вы можете скопировать и вставить этот код в любое оружие, и все будет ОК. Часть проблемы лежит в том, что перегруженный метод вызывает функцию ProcessTraceHit() дважды, что в свою очередь вызовет появления двух гильз и пр.

// Weapon fire that goes through wall
// By Mr.Self-Destruct

// Проникновение через стены
var() float Thick;
// Проникновение через pawns
var() float PawnThick;

function TraceFire( float Accuracy ) {

    local vector HitLocation, HitNormal, StartTrace, EndTrace, X,Y,Z;
    local actor Other;
    local Pawn PawnOwner;
    local float Penetration;

    PawnOwner = Pawn(Owner);

    Owner.MakeNoise(PawnOwner.SoundDampening);
    GetAxes(PawnOwner.ViewRotation,X,Y,Z);
    // Первая траектория, такая же, как и у обычного оружия
    StartTrace = Owner.Location + CalcDrawOffset() + FireOffset.X * X
      + FireOffset.Y * Y + FireOffset.Z * Z; 
    AdjustedAim = PawnOwner.AdjustAim(1000000, StartTrace, 2*AimError, False, False);  
    EndTrace = StartTrace + Accuracy * (FRand() - 0.5 )* Y * 1000
      + Accuracy * (FRand() - 0.5 ) * Z * 1000;
    X = vector(AdjustedAim);
    EndTrace += (10000 * X); 
    Other = PawnOwner.TraceShot(HitLocation,HitNormal,EndTrace,StartTrace);
    // Обработка контакта с первой целью
    ProcessTraceHit(Other, HitLocation, HitNormal, X,Y,Z);

    // Вторая траектория, ее исходная точка берется с учетом
    // конечной точки первой траектории
    if (Other.IsA('Pawn'))
      Penetration = PawnThick;
    else
      Penetration = Thick;
    StartTrace = HitLocation + HitNormal + (Penetration * X);
    EndTrace = StartTrace + Accuracy * (FRand() - 0.5 )* Y * 1000
      + Accuracy * (FRand() - 0.5 ) * Z * 1000;
    EndTrace += (10000 * X);
    Other = PawnOwner.TraceShot(HitLocation,HitNormal,EndTrace,StartTrace);
    // Обработка контакта со второй целью
    ProcessTraceHit(Other, HitLocation, HitNormal, X,Y,Z);
}

defaultproperties {

    // Стены твердые, проникновение меньше
    Thick=20.0
    // Pawns довольно мягкие и им нужно большее значение
    // проникновения чем стенам
    // Collision radius = 17 является значением по умолчанию в UT, поэтому
    // дадим фактору проникновения значение, превышающее толщину игрока
    PawnThick=36.0
}

"И все!?" - удивитесь Вы, - "всего лишь 9 новых строчек!?" Но, как и было сказано в начале, все довольно просто.

Недостатки

Этот метод создания подобного оружия имеет свои недочеты, в основном видные уже на этапе теории:

  1. Сперва, нужно отметить тот факт, что Вы можете прострелить только одну стену или одного pawn (в частности, игрока). Конечно, можно заскриптить порождение еще нескольких траекторий, но этого делать не желательно. Плюс ко всему, это довольно "дорогостоящая" операция для движка, и сильное злоупотребление может вызвать падение производительности;
  2. При указании слишком большого фактора проникновения, результат может оказаться нежелательным. Например, игрок, стоящий за стеной, не будет поврежден:

  3. Следы пуль (decal). Это не является насущной проблемой создание следов от пуль, но для ультра-реализма, очень хотелось бы создать следы в местах выхода пуль из стены с другой стороны. Этого довольно сложно добиться. Можно, например, породить еще одну траекторию в направлении, противоположном выстрелу;

Заключение

Как и было сказано в начале, это не лучший способ решения проблемы для создания подобного оружия, но, тем не менее, этот метод достаточно прост и легок в реализации. Если кто-то хочет предложить другой способ (не очень сложный), то свяжитесь с автором и Ваша идея не останется в стороне.

Если Вы хотите посмотреть пример реальной реализации данного метода (кстати, в примере решена проблема появления двух гильз), загрузите мод Super Sniper Rifle, использующий вышеописанную технику с некоторыми доработками.

Автор

Mr.Self-Destruct
Источник: CHiMERiC
Перевод сделан 32_Pistoleta

Хостинг от uCoz