CollisionRadius, CollisionHeight и DrawScale уже заявлены в классе Actor и наследуются через него мутатором. Вторичное объявление одних и тех же переменных ведет к глюкам.
2) Что значит "изменение DrawScale в defaultproperties у меня не работает" что именно не работает? У вас не объявлена config переменная, которую нужно конфигурировать в файле InstaSniper.ini (Зачем вам вообще этот файл, чем вам user.ini не нравится?)
3) DrawScale/Default.DrawScale должно давать единицу.
4) в выражении: PlayerPawn(Other).SetCollisionSize(CollisionRadius*DrawScale/Default.DrawScale, CollisionHeight*DrawScale/Default.DrawScale) вы применяете переменные ( CollisionRadius, CollisionHeight, DrawScale ) не Pawn-а, а мутатора. То есть вы применяете к Pawn-у переметры мутатора. Логики я не вижу.
5) в выражении PlayerPawn(Other).SetCollisionSize кастинг из Other-а в Pawn не нужен, в заголовке функции объявлено, что Other является Pawn-ом
Более правильный код: //=====================================================
// Объявляем что настройки мутатора будут храниться в файле User.ini class InstaSniperMutator extends Mutator config(User);
// Объявляем config переменную, значение которой будет храниться в User.ini var() config float NewDrawScale;
function ModifyPlayer(Pawn Other) // вызывается из функции GameInfo.RestartPlayer() { if ( Other.IsA('PlayerPawn' ) { // увиличиваем исходную коллизию игрока в NewDrawScale раз. Other.SetCollisionSize( Other.Default.CollisionRadius*NewDrawScale, Other.Default. CollisionHeight*NewDrawScale); } DeathMatchPlus(Level.Game).GiveWeapon(Other,"InstaSniper.TSniperRifle");
if ( NextMutator != None ) NextMutator.ModifyPlayer(Other); }
Как раз таки роботает. А потому, что то что указано в DefaultProperties мутатора относитса к мутатору а не к Pawn-у. Как и любой другой актор у мутатора есть и колизия, и DrawScale, мало того у него есть даже Location, и все акторы в том числе и мутаторы, и hud даже находятса в центре карты все время просто отрисовывать у них нечего, но сделать можно. А код роботает просто потому что Pawn-у устанавливаетса колизия такая же как у мутатора , а DrawScale ему не устанавливаетса.
Сообщение отредактировал GP - Четверг, 15 Декабрь 16, 00:40
Вопрос к знтокам - при каких условиях бот стреляет не в игрока, а в предмет? (например, в ассаульте при атаке разрушаемых обьектов).
Я бы предложил сделать следующее:
1) Как только Игрок берет в руки снайперскую винтовку, к его голове аттачится невидимая золотая медалька. (во время тестирования медальку можно сделать видимой, чтобы понять, спаунится она или нет). 2) При появлении медальки, её хозяином объявляется сам игрок. 3) В медальке запускается функция Таймер, с промежутком, допустим в несколько секунд. Эта функция перебирает всех ботов, и если Bot.Enemy == Owner || (Bot.Enemy == None && Bot.LineOfSightTo(медалька) ) Bot.Target = Медалька (Здесь нужно потестировать - сделать так, чтобы бот стрелял в медальку - иными словами, в голову игрока). 4) Если игрок убирает винтовку или погибает - медалька удаляется.
К сожалению, я не настоько хорошо знаю UT, чтобы ответить на вопрос при каких условиях бот стреляет не в игрока, а в предмет?
Сообщение отредактировал Reborn - Четверг, 15 Декабрь 16, 01:36
Добавлено: Вот очень грубая схема того, как это должно работать (запустите карту с одним ботом, и попытайтесь спрятаться от него за преградой на другой стороне пропасти)
Добавлено 2: Вот менее глючный, но несколько более сложный для понимания вариант. (запустите карту с одним ботом, и попытайтесь спрятаться от него за преградой на другой стороне пропасти).
Что значит "изменение DrawScale в defaultproperties у меня не работает" что именно не работает?У вас не объявлена config переменная, которую нужно конфигурировать в файле InstaSniper.ini (Зачем вам вообще этот файл, чем вам user.ini не нравится?)
Я хотел именно, чтобы drawscale работал в defaultproperties, эта не та переменная, которую игроки захотят менять часто и которую нужно менять вообще. Все что меняется часто, как, например, количество патронов в снайперке, у меня вынесено в отдельный конфиг под названием InstaSniper.ini. Не вижу смысла выносить все в user.ini, так как там приличное кол-во опций и человек малоопытный может не найти сразу те настройки, которые относятся к моему мутатору. И если человек захочет ПОЛНОСТЬЮ удалить мой мутатор, то его настройки скорее всего остануться в user.ini, вряд ли кто будет ручками все удалять. Я просто интересуюсь психологией и стараюсь смотреть на игру глазами другого игрока, отсюда такие мысли.
Далее... Ваша новая переменная NewDrawScale заработала в свойствах по умолчанию, но как-то страновато. Вместо того чтобы просто увеличить с помощью нее размер игрока, была также еще увеличена коллизия в сторону высоты. То есть игрок стал не просто больше, он стал бегать по воздуху и перестал заходить в узкие проемы. Это можно было сделать, увеличив в несколько раз от дефолта переменную CollisionHeight. И я это делал. И надеялся с помощью NewDrawScale или DrawScale только увеличить игрока, опустить его на землю, при этом сохранив значения коллизии... не вышло.
ЦитатаReborn ()
Добавлено: Вот очень грубая схема того, как это должно работать(запустите карту с одним ботом, и попытайтесь спрятаться от него за преградой на другой стороне пропасти) Прикрепления: DM-Test05.unr(78Kb)
Протестировал эту карту с классическим мутатором sniper arena. Заходил за заграждение, но бот похоже видел мой центр коллизии в области груди и стрелял. Ну, разумеется, убивал двумя выстрелами, так как пули не шли в голову. Кстати, если плейерстарты были бы поближе к заграждениям, то это облегчило бы тест.. Просто не добегаешь.
Сообщение отредактировал Gadavre - Четверг, 15 Декабрь 16, 17:56
1) Так вы же в своём коде не меняли DrawScale, и я подумал, что вам это не нужно. Чтобы изменить размер самой модели, достаточно было добавить одну строку.
class InstaSniperMutator extends Mutator config(User); var() config float NewDrawScale; function ModifyPlayer(Pawn Other) // вызывается из функции GameInfo.RestartPlayer() { if ( Other.IsA('PlayerPawn' ) { Other.SetCollisionSize( Other.Default.CollisionRadius*NewDrawScale, Other.Default.CollisionHeight*NewDrawScale ); Other.DrawScale = Other.Default.DrawScale*NewDrawScale; } DeathMatchPlus(Level.Game).GiveWeapon(Other,"InstaSniper.TSniperRifle");
if ( NextMutator != None ) NextMutator.ModifyPlayer(Other); }
2) Вы невнимательно смотрели. Впрочем, суть карты не в этом, а в том, что бот может поражать человека, который прячется за препятствием. Технически проблему я решил. А куда он будет стрелять - в торс или в голову это уже дело техники, там в скриптах всё элементарно настраивается.
Сообщение отредактировал Reborn - Четверг, 15 Декабрь 16, 18:09
Впрочем, суть карты не в этом, а в том, что бот может поражать человека, который прячется за препятствием.
Я уже ничего не понимаю в логике бота , так значит бот видит торс игрока через припятствие, раз он стреляет? Если бы видел одну голову, то не стрелял бы, верно? А почему тогда в моем видео на deck16][ он не видит через припятствие?
Сообщение отредактировал Gadavre - Четверг, 15 Декабрь 16, 18:35
Это вы не заметили флажок, который висит над головой игрока, и показывает боту, куда нужно стрелять. Как я и угрожал, я подвесил над головой игрока золотую медальку, и приказал боту стрелять в неё. Теперь, если опустить медальку на уровень головы игрока, то бот, стреляя в неё, будет попадать точно игроку в голову.
Данный способ позволяет достаточно гибко настроить интеллект бота, однако не отвечает на вопрос "как сделать так, чтобы было реалистично". Вопрос в требуемом проценте попаданий, и в требуемом проценте хэдшотов. А так же в том, насколько часто бот будет стрелять в частично видимую мишень. Я мог бы сделать так, чтобы бот шарашил 100 хэшотов из ста, но это не то, что нужно.
Исправленный код (адаптированный для вашего мутатора) выложу чуть позже, есть вопросы которые я ещё хочу потестировать. По дальнейшим действиям так же отпишусь позже. Можете пока потестировать вариант с попаданиями в голову.
function PostBeginPlay() { Super.PostBeginPlay(); Spawn(class'ShootTarget'); }
2) Создайте нового актера ShootTarget.uc со следующим кодом.
Код
//============================================================================= // ShootTarget. //============================================================================= class ShootTarget expands Decoration;
function PostBeginPlay() { Super.PostBeginPlay(); SetTimer (1.0, true); }
function Timer() { Local PlayerPawn P; Local Bot B; Local int TeamID;
ForEach AllActors(class'PlayerPawn', P) { if (P.Health <= 0 || P.weapon == None) continue; // Не обрабатывать мертвых и безоружных игроков if (owner == none) SetOwner(P); // Если хозяина нет - первый же игрок будет хозяином;
// далее обрабатываем случай если живых игроков несколько if (owner != none && P != Owner) Spawn(class'ShootTarget',P,,(P.Location+vect(0,0,64))); // В этом случае для другого игрока спаунится другая мишень.
// перемещаем мишень вместе с хозяином if (P == Owner) { if(P.bIsCrouching) SetLocation (P.Location + Vect(0,0,24)); // Ниже, если на корточках. else SetLocation (P.Location + Vect(0,0,50)); //На высоте головы } }
P=PlayerPawn(Owner); // P = Хозяин. if (P == None || P.PlayerReplicationInfo == None || P.Health <= 0) return; // обрабатываем случай если нет живых игроков TeamID = P.PlayerReplicationInfo.TeamID; // Запоминаем, в какой команде играет Хозяин.
ForEach AllActors(class'Bot', B) { if (B.Health <= 0 || B.weapon == None) continue; // Не обрабатывать мертвых и безоружных ботов If (B.LineOfSightTo(P)) continue; // Если бот видит игрока целиком - ничего не делать If (!B.LineOfSightTo(Self)) continue; // Если бот не видит мишень - ничего не делать If (B.Enemy != None && B.Enemy != Owner) continue; // Если у бота другой враг - пусть с ним и воюет. If (B.Enemy == None) B.Enemy = P; // Если у бота нет врага - назначить врагом игрока B.FaceTarget = Self; // Смотреть в лицо игроку B.target = Self; // Цель = мишень = лицо игрока. B.bShootSpecial = true; // Эта опция разрешает стрелять не в игрока а в мишень. if (P.LineOfSightTo(B) && !NeedToTurn(B)) B.FireWeapon(); // Если бот повёрнут лицом к игроку - стрелять else B.gotostate('RangedAttack','FaceTarget'); // В противном случае повернуться лицом к игроку } }
// Эта функция устанавливает максимальный угол, с которого боту разрешено стрелять. function bool NeedToTurn(Bot B) { Local Rotator NeedRot; Local int Real, Need, Result;
NeedRot = Rotator(B.location - Owner.location); Need = NeedRot.Yaw & 65535; Real = B.Rotation.Yaw & 65535; Result = ABS(Need-Real);
Логика такова: 1) В начале игры мутатор создает "медальку", которая аттачится к голове ближайшего игрока. 2) Если живых игроков несколько - для каждого создается своя медалька. 3) Если бот не видит игрока, но видит медальку, он получает приказ стрелять в медальку, но попадает, естественно, в голову игрока. 4) В своих бот стрелять не должен (но я не тестировал в командной игре). 5) Точно так же бот не должен стрелять в мёртвых игроков и спектаторов.
Я отладил насколько возможно, дальше отлаживать мне лениво. Обрабатывать все возможные ошибки и игровые события мне неинтересно. P.S. Приложенная карта предназначена для наблюдения за работой "медальки" без мутатора. С мутатором её запускать не нужно.
3) Если бот не видит игрока, но видит медальку, он получает приказ стрелять в медальку, но попадает, естественно, в голову игрока.
1.То есть , если игрок, стоит за высоким укрытием, преградой и не видит бота, но бот видит медальку, то игрок будет убит??? 2. Как я могу временно сделать медальку видимой, чтобы хотя понять где она находиться и если будут проблемы то попробывать сместить ее координаты?
Протестировать я могу все сам. В ближайшие 1-2 отпишусь.
Сообщение отредактировал Gadavre - Четверг, 15 Декабрь 16, 22:33
В последних версиях (начиная с DM-Test09.unr) с медалька находится "на лбу" у игрока. Таким образом если бот видит медальку, значит он видит и голову игрока.
Кроме того, впоследних версиях (начиная с DM-Test09.unr) попадание в медальку боту ничего не дает: медалька простреливается насквозь, не причиняя игроку никакого ущерба. Бот попадает именно в голову игрока, расположенную точно там же, где и медалька.
Медальку можно сравнить с надетым на голову игрока прозрачным пакетом: если попал в пакет, значит попал и в голову.
Таким образом если бот видит медальку, значит он видит и голову игрока.
Значит и игрок имеет возможность видеть своего килера...
Добавлено (15 Декабря 16, 22:40) --------------------------------------------- else SetLocation (P.Location + Vect(0,0,50)); //На высоте головы В этой строке координаты медальки? Изменив эти 3 цифры можно при необходимости подправить ее позицию, верно?
Сообщение отредактировал Gadavre - Четверг, 15 Декабрь 16, 22:41
P.S. Приложенная карта предназначена для наблюдения за работой "медальки" без мутатора.С мутатором её запускать не нужно. Прикрепления: DM-Test10.unr(89Kb)
Когда игрок стоит за преградой, то умирает мгновенно. Но если на открытом пространстве, то для гибели игрока нужно 2 выстрела бота. А, почему так происходит?
Буду вносить ваши строки в свой мутатор и тестить уже завтра. Дай Бог чтоб работало без глюков....
Сообщение отредактировал Gadavre - Пятница, 16 Декабрь 16, 00:08
Когда игрок стоит за преградой, то умирает мгновенно. Но если на открытом пространстве, то для гибели игрока нужно 2 выстрела бота. А, почему так происходит?
А "На открытом пространстве" бот стреляет игроку в голову или в тело? Смотрите, сколько HP снимается после каждого выстрела. Насколько я помню, в Ut1 попадание бота в голову игроку является редкостью.
Иными словами, если бот попадает в середину коллизии игрока, снимается 45 пунктов здоровья, Если бот попадает в нижние 62% коллизии, снимается 45 пунктов здоровья, Если бот попадает в верхние 38% цилиндра коллизии - снимается 100 пунктов здоровья и убийце засчитывается Headshot (поскольку MyDamageType=shot, а AltDamageType=Decapitated ) Обратите внимание, что Headshot умеют делать только высокоуровневые боты. Если Bot(Instigator).bNovice хэдшота не будет, и с игрока снимут 45% здоровья.
Ёж полагает, что если игрок прячется за преградой, нижние 62% цилиндра коллизии скрыты преградой, и попасть в них бот никак не может. Поэтому всегда попадает в верхние 38%
//======================================
P.S. На открытом пространстве медалька не работает. Вообще. Она включается только когда игрок за преградой.
If (B.LineOfSightTo(P)) continue; // Если бот видит игрока целиком - ничего не делать
Извините за назойливость, но мне просто уж до чертиков интересно, как вы сделали в едиторе вот то простое помещение из DM-Test10.unr? Я хотел бы повторить то же с нуля. видеуроков в ютубе по этому движку не видел , да и статей по строительству элементарной архитектуры нет.
Я начинал вот с этого туториала: (правда, он для Unreal1, но в Ut1 мало что изменилось) http://unrealscript.narod.ru/tutorials/editing/basics/basics.html (он же без рекламы на этом сайте: http://rusut.ru/articles/unreal_tournament_99/ue1/osnovy_unreal_editor_1_2/27-1-0-199
Следующий за ним вот этот: http://unrealscript.narod.ru/tutorials/editing/detailing/detailing.html
И вообще, эти туториалы стоит почитать (большинство из их для UT1): http://unrealscript.narod.ru/tutorials/tutorials.html
Сообщение отредактировал Reborn - Пятница, 16 Декабрь 16, 00:08
//======================================= Добавлено: Режим "Хардкор" на 10% быстрее и на 30% смертельнее. Режим "Турбо" на 30% быстрее и на 30% смертельнее. Очевидно, у вас в тренировке включен режим "Хардкор" или "Турбо", раз после выстрела в тело остается 33 пойнта здоровья. Для тестов это не совсем хорошо, поскольку данные о повреждениях в скриптах приведены для режима "Классик".
//======================================= Добавлено 2: Сборник туториалов ещё с тех далёких времен. По ним в основном и учился. http://rgho.st/892tZY7Mw
Сообщение отредактировал Reborn - Пятница, 16 Декабрь 16, 00:29
Код в моем мутаторе работает, но отлавил вот этот неприятный баг. Бот выстреливает свои бесценные патроны, даже тогда..., когда игрок его не видит вообще. А иногда игрок получает пулю, что весьма печально и читерно... Нужно последнюю третью цифру в каждой строке уменьшать пока не будет достигнут результат? if(P.bIsCrouching) SetLocation (P.Location + Vect(0,0,24)); else SetLocation (P.Location + Vect(0,0,50));
ЦитатаReborn ()
bHidden=False
Сделал так, но не увидел никакой медальки, колпака на голове игрока, когда он стоит за преградой. Смотрел со стороны спины игрока(behindview 1) Видимо она появляется очень быстро и быстро исчезает со смертью игрока. Ну это не так важно теперь , главное отладить правильно ее положение.
Сообщение отредактировал Gadavre - Пятница, 16 Декабрь 16, 12:21
Да, можете поиграться с высотой мишени, а так же её коллизией. (там по умолчанию 22 высота 22 радиус) Можно изменить высоту и радиус в defaultproperties, как это сделано в других скриптах.
Кроме этого, можете добавить строку If (B.LineOfSightTo(P)) continue; // Если бот видит игрока целиком - ничего не делать If (!B.LineOfSightTo(Self)) continue; // Если бот не видит мишень - ничего не делать If (!P.LineOfSightTo(B)) continue; // Если ИГРОК НЕ МОЖЕТ ВИДЕТЬ БОТА - ничего не делать If (B.Enemy != None && B.Enemy != Owner) continue; // Если у бота другой враг - пусть с ним и воюет. If (B.Enemy == None) B.Enemy = P; // Если у бота нет врага - назначить врагом игрока
Эта строка запрещает боту стрелять, если игрок не может его (бота) видеть.
Здесь вопрос в том, как сделать так, чтобы было максимально реалистично.
Добавлено (16 Декабря 16, 12:27) ---------------------------------------------
ЦитатаGadavre ()
Reborn () bHidden=FalseСделал так, но не увидел никакой медальки, колпака на голове игрока, когда он стоит за преградой. Смотрел со стороны спины игрока(behindview 1) Видимо она появляется очень быстро и быстро исчезает со смертью игрока. Ну это не так важно теперь , главное отладить правильно ее положение.
Если медалька находится "в голове" игрока, он не видит её, потому что она находится прямо у него в мозгу. Отступите на несколько шагов спиной вперед - медалька должна появится у вас перед носом, и снова исчезнуть.
Добавлено (16 Декабрь 16, 12:31) --------------------------------------------- Если очень хочется именно посмотреть на медальку - Поднимите её повыше