[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 2 из 4
  • «
  • 1
  • 2
  • 3
  • 4
  • »
Форум » Игры серии GTA » GTA IV » Вопросы по скриптингу GTA IV (Общие вопросы по ScriptHookDotNet)
Вопросы по скриптингу GTA IV
wmysterio
Администраторы
Скриптер
21.02.14 12:25
Offline
В этой теме обсуждаются общие вопросы по скриптингу GTA 4. Пока этот род моддинга не очень развит в этой части игры, но на некоторые вопросы всё же можно ответить.

wmysterio
Администраторы
Скриптер
14.11.18 09:18
Offline
Vital, есть старый дедовский метод:
Код
if (trg != null) {
          /* ... */
}
У меня заработала такая проверка.

Vital
Друзья
Скриптер
14.11.18 09:18
Offline
wmysterio, всё равно выходит else... Полный код:

Код
using System;
using System.Windows.Forms;
using GTA;

namespace Model
{
     public class Model : Script
     {
         GTA.Model mdl;

         public Model()
         {
             this.KeyDown += new GTA.KeyEventHandler(this.MK);
         }

         private void MK(object sender, GTA.KeyEventArgs e)
         {
             if (e.Key == Keys.C && Game.isGameKeyPressed(GTA.GameKey.Aim) && !Player.Character.isInVehicle())
             {  
                 Ped trg = Player.GetTargetedPed();                
                 if (trg != null)
                 {                     
                     mdl = trg.Model;
                     Player.Model = mdl;
                 }
                 else Game.DisplayText("You have no targeted ped");
             }
         }

     }
}
2109: create_special_actor $VITAL in_front_of_computer

wmysterio
Администраторы
Скриптер
14.11.18 09:18
Offline
Vital, хм, у меня всё работает. Скин меняется:
Вот мой код:
Код
using System;
using System.Windows.Forms;
using GTA;

namespace Model {
       public class Model : Script {
           GTA.Model mdl;
             
           public Model() {
               Player.Character.Weapons.MP5.Ammo = 120;
               this.KeyDown += new GTA.KeyEventHandler(this.MK);
           }

           private void MK(object sender, GTA.KeyEventArgs e) {
               if (e.Key == Keys.C && Game.isGameKeyPressed(GTA.GameKey.Aim) && !Player.Character.isInVehicle()) {
                   Ped trg = Player.GetTargetedPed();
                   if (trg != null) {
                       mdl = trg.Model;
                       Player.Model = mdl;
                       Game.DisplayText("Ok");
                   } else
                       Game.DisplayText("You have no targeted ped");
               }
           }

       }
}
Добавил только сообшение, когда скин меняется и дал оружие в начале игры. Он начал меняться только тогда, когда я целился в педа с оружия
Прикрепления: 9228738.png(517.1 Kb)

Vital
Друзья
Скриптер
14.11.18 09:18
Offline
wmysterio, вот это я и забыл smile Оказывается, прицел без оружия не работает, что странно.
P.S. Уже не по этой теме: как "закрыть" событие. Вот есть событие нажатия клавиши, которое выполняется постоянно, в отличие от простого public, а как его завершить? Что-то типа break?
2109: create_special_actor $VITAL in_front_of_computer

wmysterio
Администраторы
Скриптер
14.11.18 09:18
Offline
Vital, я не знаю как прям отключить событие от отработки, но можно просто не выполнять код события используя оператор return, поставив  условие. Вот простой пример:
Код
using System;
using System.Windows.Forms;
using GTA;

namespace Model {
         public class Model : Script {
             GTA.Model mdl;

             bool EventDisable = false;
                 
             public Model() {
                 Player.Character.Weapons.MP5.Ammo = 120;
                 this.KeyDown += new GTA.KeyEventHandler(this.MK);
             }

             private void MK(object sender, GTA.KeyEventArgs e) {
                 if (EventDisable) {
                     return;
                 }

                 if (e.Key == Keys.C && Game.isGameKeyPressed(GTA.GameKey.Aim) && !Player.Character.isInVehicle()) {
                     Ped trg = Player.GetTargetedPed();
                     if (trg != null) {
                         mdl = trg.Model;
                         Player.Model = mdl;
                         Game.DisplayText("Ok");
                         EventDisable = true;
                     } else
                         Game.DisplayText("You have no targeted ped");
                 }
             }

         }
}
Менять скин можно будет только 1 раз

Vital
Друзья
Скриптер
14.11.18 09:18
Offline
wmysterio, то есть скрипт сначала выполнит всё в public Model, потом перейдёт к событию, а после return вернётся в public? И тогда он снова выполнит всё, что там было, или просто завершится работа скрипта?
2109: create_special_actor $VITAL in_front_of_computer

wmysterio
Администраторы
Скриптер
14.11.18 09:19
Offline
Vital, нет, ruturn действует как в консоли - завершить приложение. То есть в нашем случаи он завершает обработку события, как и всех функций, но не удалит само событие. Так же как переменные, которые мы создаём, C# не удаляет их. Это делает уборщик .NET после завершения приложения.

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

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

Vital
Друзья
Скриптер
14.11.18 09:19
Offline
wmysterio, понятно, спасибо. Действительно, зачем делать событие, если можно сделать цикл repeat, к примеру, в главном потоке и он сам завершится. Я видел у тебя while (true), в нём, я так понимаю, тоже нужен Wait(0)?
2109: create_special_actor $VITAL in_front_of_computer

wmysterio
Администраторы
Скриптер
14.11.18 09:19
Offline
Vital, Да, как и в SannyBuilder нужна задержка в циклах. Без неё идёт зависание

andre500
Пользователи
14.11.18 09:19
Offline
Вопрос по GTA 5. Надеюсь, кто-нибудь шарит по этой игре smile

Не получается активировать функции ENABLE_CLOWN_BLOOD_VFX и ENABLE_ALIEN_BLOOD_VFX, эффекты крови не отображаются. Что я делаю не так?

Код
using GTA;
using GTA.Native;
using GTA.Math;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;

public class myFirstScript : Script
{
    public myFirstScript()
    {
  KeyDown += onkeydown;
    }

    public void PrintText(string text, int time)
    {
  GTA.Native.Function.Call(GTA.Native.Hash._0xB87A37EEB7FAA67D, "STRING");
  GTA.Native.Function.Call(GTA.Native.Hash._ADD_TEXT_COMPONENT_STRING, text);
  GTA.Native.Function.Call(GTA.Native.Hash._0x9D77056A530643F6, time, 1);
    }

    void onkeydown(object sender, KeyEventArgs e)
    {
  if (e.KeyCode == Keys.K)
  {
   GTA.Native.Function.Call(GTA.Native.Hash._0xD821490579791273, true);
   PrintText("Activated!", 2000);
  }
  else if (e.KeyCode == Keys.J)
  {
   GTA.Native.Function.Call(GTA.Native.Hash._0xD821490579791273, false);
   PrintText("Deactivated!", 2000);
  }
    }
}


Функции:

void ENABLE_CLOWN_BLOOD_VFX(BOOL toggle) // D821490579791273 C61C75E9
void ENABLE_ALIEN_BLOOD_VFX(BOOL Toggle) // 9DCE1F0F78260875 CE8B8748

Обе функции используются в миссиях "Агитатор Майкл" и "Агитатор Тревор". Если конкретнее, то хочу активировать мультяшные эффекты крови из миссии с Тревором (демонстрация) без общей "наркоманской" картинки, хотя её я без проблем смог активировать, но она мне пока не нужна.

Пробовал по-всякому вызывать эти команды, но либо скрипт падал с ошибкой, либо всё тоже самое - никаких эффектов, даже стандартная кровь пропадает.

Очень надеюсь на вашу помощь, а то всё желание пропадает продолжать учиться скриптить, когда не получается реализовать свою задумку sad

wmysterio
Администраторы
Скриптер
14.11.18 09:19
Offline
А останки:
Код
C61C75E9 и CE8B8748
это от адреса отделилось или имеет другое предназначение?

andre500
Пользователи
14.11.18 09:19
Offline
Цитата wmysterio ()
это от адреса отделилось или имеет другое предназначение?

Это второй хэш. Не совсем понимаю зачем он там. Исходя из информации, короткий хэш от XBOX360 версии игры, а длинный от PC. Скрипт падал от попытки заюзать короткий smile

Добавлено (27.09.17, 19:55)
---------------------------------------------
В общем, один чел с гтафорумса предположил, что данные функции не создают эффекты крови, а лишь загружают их в игру, убирая стандартные. Все эффекты мол придется создавать вручную.

На это предположение и указывает тот факт, что в миссии "Агитатор Майкл" нет никакой крови, ни новой, ни стандартной. Из эффектов там только луч света, который время от времени выпускает пришелец, чтобы захватить разум главного героя. При этом в функции присутствует слово "BLOOD". Тут стоит понимать, что все имена функций не являются оригинальными, на деле мы имеем только список хешей и в данный момент мы знаем работу далеко не всех игровых функций.

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



Учитывая мои нынешние познания в скриптинге GTA 5 да и в C# в целом, вряд ли хватит сил сейчас так же сделать эффекты на каждое оружие отдельно. Но это уже совсем другая история, которая мало кому интересна smile

Очевидно, в справке по функциям серьезная недоработка. Мало того, что функцию прозвали несколько неправильно (ENABLE, вместо REQUEST), так ещё и описания по её работе толком нет.

Код
void ENABLE_CLOWN_BLOOD_VFX(BOOL toggle) // 0xD821490579791273 0xC61C75E9
Creates cartoon effect when Michel smokes the weed


Ощущение, что создатели справки даже не тестировали толком работу этой функции. Потому что такие эффекты создаются в миссии с Тревором, а не Майклом.
Отредактировал andre500 - Вторник, 26.09.17, 21:35

wmysterio
Администраторы
Скриптер
14.11.18 09:20
Offline
andre500, не знаю. Возможно, нужно делать также, как и в методе "PrintText" - задавать какие-то дополнительные параметры.

ed9mkm
Пользователи
14.02.19 06:52
Offline
Все не понимаю, почему когда здоровье актера становится меньше 120, то начинает выполняться только тот один цикл? Почему в это время у Нико здоровье не регенерируется и он не говорит ничего при драках? Хотя до этого все работает, как надо. Здоровье и речь у Нико появляется лишь на те 3 секунды, которые в конце цикла стоят. А потом снова как бы конфликт циклов. Не пойму этого уже несколько дней.

Код
while (true)
                    {
                        Wait(0);
                        AnimationSet anims = new AnimationSet("amb@smoking_spliff");
                        AnimationFlags animflags = AnimationFlags.Unknown12 | AnimationFlags.Unknown11 | AnimationFlags.Unknown09;

                        if (MyPed.isInMeleeCombat && MyPed.Health > 120)
                        {
                            Wait(500);
                            MyPed.SayAmbientSpeech("DODGE");
                            Wait(3000);
                            MyPed.SayAmbientSpeech("FIGHT");
                        }

                        if (Player.Character.isInMeleeCombat || Player.Character.isInCombat)
                        {
                            Wait(500);
                            Player.Character.Voice = "NIKO_EXTRAS";
                            Player.Character.SayAmbientSpeech("INHALE");
                            Wait(1500);
                            Player.Character.SayAmbientSpeech("FUCK_FALL");
                        }

                        if (Player.Character.Health < 100)
                        {
                            Player.Character.Health += 1;
                            Wait(20);
                        }

                        if (MyPed.Health < 120)
                        {
                            MyPed.Health = 119;
                            MyPed.Voice = "PAIN_MALE_EXTRAS";
                            MyPed.SayAmbientSpeech("HIGH_FALL");
                            MyPed.AlwaysDiesOnLowHealth = false;
                            MyPed.ChangeRelationship(RelationshipGroup.Player, Relationship.Companion);
                            MyPed.Enemy = false;
                            Wait(4000);
                            MyPed.SayAmbientSpeech("CLEAR_THROAT");
                            spliff = World.CreateObject(0xD130ADEF, MyPed.Position);
                            MyPed.Animation.Play(anims, "create_spliff", 8.0F, animflags);
                            spliff.AttachToPed(MyPed, Bone.RightHand, new Vector3(0.14F, 0.03F, 0.04F), new Vector3(2.21F, -0.12F, 0.0F));
                            MyPed.Task.PlayAnimation(anims, "partial_smoke", 8.0F, animflags);
                            MyPed.Task.GoTo(Player.Character);
                            Wait(6000);
                            MyPed.SayAmbientSpeech("LAUGH");
                            Wait(6000);
                            MyPed.SayAmbientSpeech("HIGH_FALL");
                            MyPed.Euphoria.LeanToPosition.Start(4000);
                            Wait(4000);
                            MyPed.SayAmbientSpeech("CLEAR_THROAT");
                            MyPed.Euphoria.LeanToPosition.Stop();
                            Wait(5000);
                            MyPed.SayAmbientSpeech("HIGH_FALL");
                            MyPed.Euphoria.Grab.Start(3000);
                            Wait(5000);
                            MyPed.SayAmbientSpeech("COUGH");
                            MyPed.Euphoria.Grab.Stop();
                            Wait(5000);
                            MyPed.SayAmbientSpeech("LAUGH");
                            MyPed.Task.WanderAround();
                            Wait(3000);
                            MyPed.SayAmbientSpeech("HIGH_FALL");
                            Wait(3000);
                            MyPed.SayAmbientSpeech("COUGH");
                            Wait(4000);
                            MyPed.SayAmbientSpeech("LAUGH");
                            Wait(3000);
                        }

                    }

wmysterio
Администраторы
Скриптер
24.02.19 12:17
Offline
Цитата ed9mkm ()
А потом снова как бы конфликт циклов.
Там только 1 цикл и если бы там был конфликт, то скрипт перестал бы работать. И кто там "MyPed"? Цель или какой-то другой чел?

ed9mkm
Пользователи
03.03.19 05:18
Offline
Цитата wmysterio ()
Там только 1 цикл и если бы там был конфликт, то скрипт перестал бы работать. И кто там "MyPed"? Цель или какой-то другой чел?

Я разобрался - это сам язык C# такой, что он выполняет одновременно только по одному циклу. Чтобы выполнялось одновременно два или более цикла, приходится создавать разные классы. Но тогда есть проблема с переменными - в другом классе переменные пешеходов, например, уже не узнаются, и так и не понял, как к ним обращаться - как звонить в другой класс (на форуме программистов обсуждал, но так и не решилась проблема). Это для главного героя тут проблем нет - у него есть своя переменная, которой не нужно значение присваивать.

Я довольно долго тестирую скрипт. Все не могу решить проблему - чтобы актер не умирал, восстанавливал здоровье. Я даже нашел один способ для его оживления - MyPed.Task.ClearAll или MyPed.Task.ClearAllImmediately, но тогда, после его оживления, появляется другая проблема - с ним никто не дерется, все начинают его бояться.


Вот это один из тестов скрипта. MyPed - это человек на этом видео, который с сигаретой.
Отредактировал ed9mkm - Воскресенье, 03.03.19, 05:19

wmysterio
Администраторы
Скриптер
03.03.19 17:35
Offline
Цитата ed9mkm ()
Но тогда есть проблема с переменными - в другом классе переменные пешеходов, например, уже не узнаются, и так и не понял, как к ним обращаться - как звонить в другой класс (на форуме программистов обсуждал, но так и не решилась проблема)
Если брать скриптинг GTA IV, то никак не получится, так как они выполняются отдельно и самостоятельно. Сами объекты(объекты классов) создаются автоматически и получить доступ к ним не представляется возможным. Можно использовать статику, тогда доступ можно получить к переменной независимо от того, выполняется ли скрипт или нет:
public class Script1 : Script {

public static int Variable; /* ~ общая переменная для всех Script1 */

}

public class Script2 : Script {

public Script2() {
/* так как Variable является public, то она доступна и другим классам */
Script1.Variable = 2;
}

}
Цитата ed9mkm ()
другая проблема - с ним никто не дерется, все начинают его бояться
Скрипт написан не правильно, точнее учтены не все условия. Получается, что какой-то код заставляет его так реагировать. Нужно делать дополнительные проверки, чтобы после оживления, скрипт ждал пока он опять умрёт.

ed9mkm
Пользователи
03.03.19 21:36
Offline
Цитата wmysterio ()
Можно использовать статику, тогда доступ можно получить к переменной независимо от того, выполняется ли скрипт или нет:

И для пешеходов так переменные можно создавать? Попробую.

Цитата wmysterio ()
Скрипт написан не правильно, точнее учтены не все условия. Получается, что какой-то код заставляет его так реагировать. Нужно делать дополнительные проверки, чтобы после оживления, скрипт ждал пока он опять умрёт.

Я совсем недавно стал писать скрипты. Я недавно еще думал, что это запредельно сложно. Я с тех пор переписал скрипт не раз.

Мне трудно понять, какой код еще ему нужен. Загадки тут часто возникают для меня. Например, я добавил команду "Game.AllowEmergencyServices" и после этого у него перестало получаться ударить копов. Сейчас не пойму, почему в него копы не стреляют, когда он их бьет. Не вижу кода пока, который бы заставлял копов его игнорировать.

Добавлено (03.03.19, 22:51)
---------------------------------------------
Я сделал так:

Код
namespace Dude
{

    public class DudeUkurok : Script
    {

       
        public static Ped MyPed;

Код
DudeUkurok.MyPed = World.CreatePed("M_Y_GAfr_Lo_01", MyVec, Ukurok);


Но это почему-то не работает:
Код
    public class DudeUkurok4 : Script
    {
        public DudeUkurok4()
        {
            while (true)
            {
                Wait(0);
                if (!Exists(DudeUkurok.MyPed)) return;
                    if (DudeUkurok.MyPed.Health < 250 || !DudeUkurok.MyPed.isAlive || DudeUkurok.MyPed.isInjured)
                    {
                        Game.DisplayText("Dude health is restored!", 3000);
                        DudeUkurok.MyPed.Health = 250;
                        DudeUkurok.MyPed.Armor = 100;

                        Wait(3000);
                    }
            }
        }
    }

Хотя и ошибок вроде бы нет.

wmysterio
Администраторы
Скриптер
04.03.19 12:56
Offline
Цитата ed9mkm ()
И для пешеходов так переменные можно создавать?
Можно хранить практически любые типы.
Цитата ed9mkm ()
я добавил команду
Названия здесь не всегда правильны. Как и в случае с Sanny Builder, на начальном этапе команды тоже имели описание, которое не соответствовали реальному названию.
Цитата ed9mkm ()
Хотя и ошибок вроде бы нет
Попробуйте так:
public class DudeUkurok : Script {

public static Ped MyPed;

public DudeUkurok() {
MyPed = World.CreatePed( "M_Y_GAfr_Lo_01", MyVec, Ukurok);
}

}

/* --- --- --- */

public class DudeUkurok4 : Script {

public DudeUkurok4() {

while( true ) {
Wait( 0 );

if( !Exists( DudeUkurok.MyPed ) ) continue; /* НЕ return; */

if( !DudeUkurok.MyPed.isAlive || DudeUkurok.MyPed.isInjured ) {
/* делаем что-то, когда пед мёртв или isInjured */
continue;
}

if( DudeUkurok.MyPed.Health < 250 ) {
Game.DisplayText( "Dude health is restored!", 3000 );
DudeUkurok.MyPed.Health = 250;
DudeUkurok.MyPed.Armor = 100;
Wait( 3000 );
}

}

}

}

ed9mkm
Пользователи
04.03.19 21:44
Offline
Цитата wmysterio ()
Названия здесь не всегда правильны. Как и в случае с Sanny Builder, на начальном этапе команды тоже имели описание, которое не соответствовали реальному названию.

Но команда "Game.AllowEmergencyServices" все же действительно вызывает приезд скорой помощи. Но в то же время создает какой-то глюк - копы становятся как стенами какими-то - их не может ударить этот актер, хотя пытается.

Цитата wmysterio ()
Попробуйте так:

Спасибо, наконец-то получилось! Пришлось просто то же сделать и с MyVec и Ukurok:

Код
namespace Dude
{
    public class DudeUkurok : Script
    {
        public static Ped MyPed;
        public static Vector3 MyVec;
        public static RelationshipGroup Ukurok;

Код
MyVec = Player.Character.Position;
                    MyVec.Y += 4.0F;
                    MyVec.Z += 0.7F;
                    MyVec.X += 0.0F;
                    Ukurok = new RelationshipGroup();
            MyPed = World.CreatePed("M_Y_GAfr_Lo_01", MyVec, Ukurok);


Код
    public class DudeUkurok4 : Script
    {
        public DudeUkurok4()
        {
            while (true)
            {
                Wait(0);
                if (!Exists(DudeUkurok.MyPed)) continue;
                if (DudeUkurok.MyPed.Health < 200 || !DudeUkurok.MyPed.isAlive || DudeUkurok.MyPed.isInjured)
                {
                    Game.DisplayText("Dude health is restored!", 3000);
                    DudeUkurok.MyPed.Health = 250;
                    DudeUkurok.MyPed.Armor = 100;

                    Wait(3000);
                }
            }
        }
    }

Добавлено (06.03.19, 09:21)
---------------------------------------------

Код
MyPed = World.CreatePed("M_Y_GAfr_Lo_01", MyVec, Ukurok);

Это можно все же не писать. А то бывает, что после загрузки игры копия этого актера уже стоит на улице. Все дело было в том, что здесь должно быть continue:

Код
while (true)
            {
                Wait(0);
                if (!Exists(DudeUkurok.MyPed)) continue;


Все интересно, можно ли реализовать поднимание и бросание кирпичей для других персонажей? Т.е. как главный герой чтобы могли это делать. Я пока немного "научил" этого персонажа бросать кирпич. Но это не то - он чуть бросает, ни в кого не целится и урона нет никакого от такого кидания.

Форум » Игры серии GTA » GTA IV » Вопросы по скриптингу GTA IV (Общие вопросы по ScriptHookDotNet)
  • Страница 2 из 4
  • «
  • 1
  • 2
  • 3
  • 4
  • »
Поиск: