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

wmysterio
Администраторы
Скриптер
06.03.19 13:39
Offline
Цитата ed9mkm ()
А то бывает, что после загрузки игры копия этого актера уже стоит на улице
Оно так и будет, так как после загрузки скрипты начитают выполнятся сначала. Без создания педа при первой загрузке "MyPed" всегда будет null и это "if (!Exists(DudeUkurok.MyPed)) continue;" не позволит скрипту выполнятся дальше. Можно отредактировать код так, чтобы актёр создавался когда нужно:
public class DudeUkurok4 : Script {

public static Ped MyPed = null;

public DudeUkurok4() {

while( true ) {
Wait( 0 );

if( !Exists( MyPed ) ) {
if( УСЛОВИЯ_КОГДА_НУЖНО_СОЗДАТЬ_ПЕДА ) {

MyPed = World.CreatePed( "M_Y_GAfr_Lo_01",
( Player.Character.Position + new Vector3( 4f, 0.7f, 0f ) ),
new RelationshipGroup() );

} else { continue; }
}

/* ... */

}

}

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

ed9mkm
Пользователи
07.03.19 04:01
Offline
Цитата wmysterio ()
Оно так и будет, так как после загрузки скрипты начитают выполнятся сначала. Без создания педа при первой загрузке "MyPed" всегда будет null и это "if (!Exists(DudeUkurok.MyPed)) continue;" не позволит скрипту выполнятся дальше. Можно отредактировать код так, чтобы актёр создавался когда нужно:

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

Цитата wmysterio ()
С этим пока неясно. Всё, что доступно игроку не означает, что и любому другому педу это можно делать.

Жаль. Но что-то похожее точно можно сделать. Есть команды типа ApplyForce. Я написал код, который заставляет персонажа бросать кирпич:

Код

AnimationSet throwbrick = new AnimationSet("misseddie1");
AnimationFlags throwbrickflags = AnimationFlags.Unknown12 | AnimationFlags.Unknown11 | AnimationFlags.Unknown09;

                    DudeUkurok.MyPed.Task.PlayAnimation(throwbrick, "throw_object", 8.0F, throwbrickflags);
                    Wait(1000);
                    brick2.Detach();
                    brick2.ApplyForce(Vector3.RelativeFront);


Т.е. анимация бросания - анимация как раз бросания объекта, которым в игре являются кирпичи, сигареты, бутылки и прочее. И далее сам объект отсоединяется от руки и кидается - примерно через секунду после анимации бросания. Но какой Vector3 я ни делал, он кидает как-то так себе. Даже когда я делал команду кидания в главного героя игры, то он все равно кидал даже в другую сторону. Но думаю, что как-то можно это сделать. Ведь даже в ГТА 5 в некоторых модах реализовали кидание снежков другими актерами. В ГТА 5 ведь кидать что-нибудь может только управляемый игроком персонаж. Если не считать иногда летящих от копов газовых шашек. Но реализовали кидание снежков. И скрипты для ГТА 4 и 5 в целом похожи.

Добавлено (07.03.19, 04:05)
---------------------------------------------
А эта функция делает любой объект поднимаемым и бросаемым:

Код
GTA.Native.Function.Call("SET_OBJECT_AS_STEALABLE", brick22, 1);

Где brick22 - объект. В данном случае это кирпич. Но многие объекты при этом будут после поднятия некорректно отображаться руке. Поэтому поднимаемыми стоит делать лишь небольшие объекты.

Добавлено (07.03.19, 10:44)
---------------------------------------------
И все же проблема с оживлением актера остается. Несмотря на то, что теперь у него действует мгновенный регенератор здоровья, он все равно часто оказывается серьезно раненым (т.е. лежит) педами, которые используют ножи, например. Я нашел новые способы его восстановления в таких случаях - это и анимация типа "перекат", это и команда "DudeUkurok.MyPed.Exists();". Но после этого он всегда теряет нужные параметры - его начинают все бояться, никто с ним не дерется больше. И иногда он вообще начинает идти, как обычные педы - даже ни на кого не нападает. Один раз под дождем даже зонт взял - это просто удивило. Вернее, он теряет, думаю, параметры уже после ранения - ведь после ранения он лежит и не думает уже драться. Как же вернуть ему не только здоровье, но и все параметры?


wmysterio
Администраторы
Скриптер
10.03.19 00:46
Offline
Цитата ed9mkm ()
Куда более сложных примеров кода много, а такого примитива никак не найти.
Ну, сложные примеры состоят из кучи лёгких. Неверное, Вы не знаете часть простых примеров, вот и возникают сложности.

Цитата ed9mkm ()
Но какой Vector3 я ни делал, он кидает как-то так себе
Здесь вектором мы можем только указать направление. Остальное делает за нас физический движок.
Цитата ed9mkm ()
brick2.ApplyForce(Vector3.RelativeFront);
Это, по-идеи, заставит бросить объект с силой 1 не учитывая сторону, в которую смотрит сам объект. Можно попробовать умножить его на каке-то значение, чтобы понять как он будет себя вести.
brick2.ApplyForce( Vector3.RelativeFront * 4f );
/* или */
var tmp = Vector3.RelativeFront;
tmp.x += 4f;
brick2.ApplyForce( tmp );
Нужно тестировать, а GTA IV сейчас под рукой нет. Ещё и работает только в VS 2010 или меньше.
Цитата ed9mkm ()
Как же вернуть ему не только здоровье, но и все параметры?
Метод в лоб: пересоздать педа.

ed9mkm
Пользователи
10.03.19 07:47
Offline
Цитата wmysterio ()
Неверное, Вы не знаете часть простых примеров, вот и возникают сложности.

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

Цитата wmysterio ()
Здесь вектором мы можем только указать направление. Остальное делает за нас физический движок.

В том и дело, что кирпич летит обычно даже не туда, куда нужно. Я прописываю, чтобы летел в сторону главного героя - чтобы было видно, нанесет ли он какой урон ему. Но летит часто в совсем другую сторону.

Цитата wmysterio ()
Нужно тестировать, а GTA IV сейчас под рукой нет. Ещё и работает только в VS 2010 или меньше.

Спасибо, протестирую. А пока я нашел еще один способ метания объектов в GTA IV:

Код
GTA.Native.Function.Call("SET_OBJECT_INITIAL_VELOCITY", brick, 10.0F, 15.0F, 5.0F);

Brick - это имя объекта, остальное - сила или скорость в X, Y, Z.
Проверил - да, работает, кирпич подпрыгивает и перелетает. Пока просто проверил на кирпиче, без прикрепления к руке того или иного актера.

Добавлено (10.03.19, 07:54)
---------------------------------------------

Цитата wmysterio ()
Метод в лоб: пересоздать педа.

Я тоже об этом подумывал. А то когда пед становится тяжело раненым - т.е. уже лежит и не может драться, то удаляются многие его параметры - даже если его восстановить, то его начинают все бояться. Как ожившего мертвеца. Восстановить возможно несколькими способами, но результат один. Я бы ему назначил сразу побольше здоровья, чтобы он никогда не погибал, но проблема в том, что в игре когда больше 500 пунктов здоровья, то актер не может... драться. Не знаю, чем это объясняется. В ГТА 5 можно поставить хоть много тысяч здоровья, и актер будет драться все равно. А в ГТА 4 если здоровье превышает этот предел, то актер стоит и только собирается драться, но ударить не может. И это относится как к другим актерам, так и к Нико.

Добавлено (10.03.19, 07:57)
---------------------------------------------
И еще я сегодня интересную особенность обнаружил. Когда ставлю 250 пунктов здоровья в скрипте, то в игре показывается 350 - если трейнером включить опцию, показывающую здоровье. Я то думал, что в скрипте 250 - это проценты. Поэтому и ставил 250 - чтобы было 500 пунктов здоровья. Теперь, как понимаю, всем педам можно по 400 поставить - чтобы в итоге было по 500. Когда не выше 500, то они могут драться.

Добавлено (10.03.19, 08:11)
---------------------------------------------

Код
var tmp = Player.Character.Position;
                    tmp.X += 4f;
                    tmp.Y += 15f;
                    tmp.Z += 5f;
                    GTA.Native.Function.Call("SET_OBJECT_INITIAL_VELOCITY", brick, tmp.X, tmp.Y, tmp.Z);

Это работает. Но все равно кирпич летит куда-то в неопределенную сторону.
Отредактировал ed9mkm - Воскресенье, 10.03.19, 07:49

wmysterio
Администраторы
Скриптер
15.03.19 21:59
Offline
Цитата ed9mkm ()
Но все равно кирпич летит куда-то в неопределенную сторону
Скорее всего там используется относительная скорость. Можно попробовать через разницу векторов определить направление:
var playerPos = Player.Character.Position;
var myPedPosition = MyPed.Position;

myPedPosition.X -= playerPos.X;
myPedPosition.Y -= playerPos.Y;
myPedPosition.Z -= playerPos.Z;

/* или вместо MyPed.Position использовать brick.Position */

GTA.Native.Function.Call( "SET_OBJECT_INITIAL_VELOCITY", brick, myPedPosition.X, myPedPosition.Y, myPedPosition.Z );

ed9mkm
Пользователи
16.03.19 06:02
Offline
Цитата wmysterio ()
Скорее всего там используется относительная скорость. Можно попробовать через разницу векторов определить направление:

Мне удалось написать код, которые направляет полет объектов в сторону направления камеры игры. Это в случае с главным героем. Код позволяет главному герою метать любые объекты, а не только те, которые он подбирает после нажатия на клавишу E:

Код
GTA.Object sfire = World.CreateObject("amb_chocbar", pp);
sfire.AttachToPed(Player.Character, Bone.RightHand, new Vector3(0.14F, 0.03F, 0.04F), new Vector3(2.21F, -0.12F, 0.0F));
Player.Character.Task.PlayAnimation(lightfire, "light_molotov", 12.0F, lightfireflags);
Wait(1500);
Int32 ll = GTA.Native.Function.Call<Int32>("START_PTFX_ON_OBJ", "break_sparks", sfire, 0.2, 0.02, 0.03, 0.0, 0.0, 0.0, 0.3);
Player.Character.Task.PlayAnimation(throwsfire, "throw_object", 12.0F, throwsfireflags);
Player.Character.Voice = "NIKO_EXTRAS";
Player.Character.SayAmbientSpeech("INHALE");
Wait(1000);
sfire.Detach();
sfire.Collision = true;
sfire.ApplyForce(Game.CurrentCamera.Direction * 40F);

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

Добавлено (16.03.19, 06:09)
---------------------------------------------
Другим педам я тоже выдал тот же объект для метания. У них код тот же, за исключением направления:

Код
sfire24.ApplyForce(BG.MyPed24.Direction * 40F, BG.MyPed24.Position);

Т.е. педы бросают объект в том направлении, в котором находятся на момент бросания. Это еще далеко от идеального решения - я хочу, чтобы они бросали в цель - в своих врагов, а не просто в сторону, куда смотрят. Часто и получается, что бросаемые объекты летят в сторону врагов. Но не всегда. И попадают в них редко. Думаю, как бы написать код, который определяет целью врагов и заставляет лететь объекты ровно в эту цель. Казалось бы, это должно быть просто. Но нет - в коде если указать только позицию какого-либо персонажа, то это работать не будет. Или я еще каких-то тонкостей не понял.

Далее, хотелось бы узнать, можно ли задавать объектам вес? В GTA San Andreas это возможно - и от веса объекта зависит урон при попадании. А вот с GTA 4 пока не знаю.

wmysterio
Администраторы
Скриптер
17.03.19 15:11
Offline
Цитата ed9mkm ()
я хочу, чтобы они бросали в цель - в своих врагов
Я написал как такое сделать выше. Нужно найти направление. Определяется через разницу векторов. Формула такая:
Vdirection = (Vcurrent - Vtarget)
Где Vcurrent - позиция кирпича или педа, который его держит. Vtarget - позиция, в которую нужно бросать.

Обычно разницу нормализуют, но я не помню есть ли такой метод. Нормализация преобразует значения в диапазон он -1 до 1, чтобы можно к ней добавить множитель (40F). Без нормализации множитель не используется. Разве что для координаты Z, чтобы летел по дуге.
Цитата ed9mkm ()
Далее, хотелось бы узнать, можно ли задавать объектам вес?
Класс "GTA.Object" я ещё не рассматривал.

ed9mkm
Пользователи
17.03.19 20:27
Offline
Цитата wmysterio ()
Формула такая:

Да, на GTA X Scripting вроде бы эта формула приводится. И еще я разобрался, как корректно указывать координаты для загрузки педов, объектов, транспорта:

Код
Vector3 plpos = Player.Character.GetOffsetPosition(new Vector3(0.0F, 2.0F, -0.8F));

Т.е. не при помощи Player.Character.Position. Когда с помощью Player.Character.Position, то оси X, Y - мировые, они закреплены самой картой. А если нужно, чтобы всегда перед главным героем что-нибудь спавнилось, независимо от того, куда он повернут, где находится, то нужно писать тот код, который я сейчас привел.

wmysterio
Администраторы
Скриптер
18.03.19 13:50
Offline
Цитата ed9mkm ()
А если нужно, чтобы всегда перед главным героем что-нибудь спавнилось, независимо от того, куда он повернут, где находится, то нужно писать тот код, который я сейчас привел.
Я в курсе. В уроке я этот метод указывал. Если нужны относительные координаты, то лучше через "GetOffsetPosition" искать.
Цитата ed9mkm ()
как корректно указывать координаты
В обеих случаях они будут "корректны". Разница только в способе smile

ed9mkm
Пользователи
18.03.19 16:08
Offline
Цитата wmysterio ()
В обеих случаях они будут "корректны". Разница только в способе

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

Цитата wmysterio ()
Я в курсе. В уроке я этот метод указывал.

Кстати, в этом уроке неправильно описывается один код. Вот этот:
Код
Player.Character.CantBeDamagedByRelationshipGroup( RelationshipGroup.Cop, true);

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

Добавлено (18.03.19, 23:39)
---------------------------------------------


Сделал такую ракету. Но еще хотелось бы прикрепить к ней камеру. Я знаю, что это в принципе возможно. Т.е. прикрепить как-то нужно камеру к объекту, чтобы камера все время была закреплена независимо от того, куда перемещается объект. Известный в наших кругах скриптер JulioNIB как-то прикреплял камеру к ракете в одном из своих модов. Там можно нажимать на одну клавишу и видеть все с камеры, закрепленной на ракете.


wmysterio
Администраторы
Скриптер
20.03.19 14:29
Offline
Цитата ed9mkm ()
Но еще хотелось бы прикрепить к ней камеру.
Это действительно интересный вопрос. Я тестировал класс с камерой, чтобы сделать урок о видео-роликах. К несчастью камера работает не так, как хотелось. Мне удалось поместить её в определённой точке, но вернуть управление обратно - нет. Возможно я не понял все аспекты её работы.
Цитата ed9mkm ()
Я проверил этот код много раз уже, он запрещает повреждать не отношения с группой, а исключает урон между участниками групп
Описание не точное (поправлю). Перечисление "RelationshipGroup" не работает с группами, как таковыми. Оно предназначено для работы с актёрами. Т.е это перечисление является описанием типов пешеходов. Возможно название метода "CantBeDamagedByRelationshipGroup" не корректно.

ed9mkm
Пользователи
22.03.19 03:33
Offline
Цитата wmysterio ()
Перечисление "RelationshipGroup" не работает с группами, как таковыми. Оно предназначено для работы с актёрами. Т.е это перечисление является описанием типов пешеходов. Возможно название метода "CantBeDamagedByRelationshipGroup" не корректно.

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

Еще в тестовом скрипте, который есть в папке scripts для разработчиков, так прописаны коды для телохранителей:
Код
p.RelationshipGroup = RelationshipGroup.Player;
p.ChangeRelationship(RelationshipGroup.Player, Relationship.Companion);
p.CantBeDamagedByRelationshipGroup(RelationshipGroup.Player, true);


Цитата wmysterio ()
Это действительно интересный вопрос. Я тестировал класс с камерой, чтобы сделать урок о видео-роликах. К несчастью камера работает не так, как хотелось. Мне удалось поместить её в определённой точке, но вернуть управление обратно - нет. Возможно я не понял все аспекты её работы.

А если разобраться хорошо, то наверно возможно будет сделать нечто похожее на то, что получается делать во встроенном игровом видеоредакторе? Т.е. возможно устанавливать камеры так, чтобы делать фильмы? В целом у скриптинга ГТА 4 вижу очень много возможностей. Странно, что скриптов для игры намного меньше, чем для GTA SA и 5.

wmysterio
Администраторы
Скриптер
22.03.19 19:31
Offline
Цитата ed9mkm ()
Т.е. возможно устанавливать камеры так, чтобы делать фильмы?
Да. Я делал ролик. Установить камеру в нужное место можно без проблем. Я говорил о том, что не смог поместить её в обычный режим (прикрепить к Нико).
Цитата ed9mkm ()
А если разобраться хорошо, то наверно возможно будет сделать нечто похожее на то, что получается делать во встроенном игровом видеоредакторе?
Я не пользовался ним, так что ответить не смогу.

ed9mkm
Пользователи
31.03.19 09:41
Offline
Пишу скрипт фейерверка. И мне нужно так сделать, чтобы фейерверк взрывался в двух случаях - при столкновении с чем-нибудь и просто через секунды 3 при свободном полете. Условие столкновения то я сделал без проблем. А вот второе чего-то не получается.

Код
    public class Firework2 : Script
    {
        
        public Firework2()
        {
            
            while (true)
            {
                Wait(0);
                if (!Exists(Firework.FWS)) continue;

                Тут нужен старт счетчика.

                if (GTA.Native.Function.Call<bool>("HAS_OBJECT_COLLIDED_WITH_ANYTHING", Firework.FWS) || Тут нужно условие - если прошло 3 секунды)
                {
                    


Т.е. в этом коде нужно сделать два условия - или если объект во что-то врезался или прошло 3 секунды. Нужно как-то счетчик сделать. Ну или любой альтернативный вариант. Я видел подобное у JulioNIB, но он программирует на VB.

wmysterio
Администраторы
Скриптер
31.03.19 16:33
Offline
Цитата ed9mkm ()
Нужно как-то счетчик сделать. Ну или любой альтернативный вариант
Вариантов счётчика достаточно много. Можно даже использовать стандартный таймер:
using System;
using System.Windows.Forms;

public class Example : Script {

Timer timer = new Timer();
int counter = 0;
bool enableTimer = false;

private void clearCounter() {
counter = 0;
enableTimer = false;
}

public Example() {
timer.Tick += delegate { if( enableTimer ) counter += 1; };

while( true ) {
Wait( 0 );

if( !Exists( Firework.FWS ) ) continue;

enableTimer = true;

if( GTA.Native.Function.Call( "HAS_OBJECT_COLLIDED_WITH_ANYTHING", Firework.FWS ) || counter == 3 ) {
clearCounter();
/* действие... */
}
}
}

}

ed9mkm
Пользователи
01.04.19 12:49
Offline
Цитата wmysterio ()
Вариантов счётчика достаточно много. Можно даже использовать стандартный таймер:

К сожалению не работает почему-то. Сперва я увидел сообщение о том, что "неоднозначная ссылка между System.Windows.Form.Timer и GTA.Timer. Это я решил при помощи добавления "using Timer = System.Windows.Forms.Timer;", но код не работает.

У меня так это все сделано:

Код
    public class Firework2 : Script
    {

        Timer timer = new Timer();
        int counter = 0;
        bool enableTimer = false;

        private void clearCounter()
        {
            counter = 0;
            enableTimer = false;
        }

        public Firework2()
        {
            timer.Tick += delegate { if( enableTimer ) counter += 1; };
            while (true)
            {
                Wait(0);
                if (!Exists(Firework.FWS)) continue;
                enableTimer = true;

                if (GTA.Native.Function.Call<bool>("HAS_OBJECT_COLLIDED_WITH_ANYTHING", Firework.FWS) || counter == 2)
                {
                    clearCounter();

wmysterio
Администраторы
Скриптер
01.04.19 14:52
Offline
Цитата ed9mkm ()
К сожалению не работает почему-то. Сперва я увидел сообщение о том, что "неоднозначная ссылка между System.Windows.Form.Timer и GTA.Timer.
Ну здесь понятно. Timer есть в обеих пространствах имён. Лечится это путём указания полного типа:
class A {

System.Windows.Form.Timer timer = new System.Windows.Form.Timer();

/* или */

GTA.Timer timer = new GTA.Timer();

}
Я просто не помню какой именно таймер использовать, чтобы было событие "Tick". Нету GTA IV, чтобы адекватно тестировать код. Пишу всё по-памяти. Вместо событий можно отслуживать текущую дату с сравнивать сколько секунд прошло от начала:
public class A : Script {

DateTime dt1 = DateTime.Now;
DateTime dt2 = DateTime.Now;

public A() {

while( true ) {
Wait( 0 );

if (!Exists(Firework.FWS)) { ResetDates(); continue; }

dt2 = DateTime.Now;
var seconds = ( dt2 - dt1 ).TotalSeconds;

if (GTA.Native.Function.Call("HAS_OBJECT_COLLIDED_WITH_ANYTHING", Firework.FWS) || seconds > 2f ) {
ResetDates();
/* действие */
}

}

}

void ResetDates() {
dt1 = DateTime.Now;
dt2 = DateTime.Now;
}

}

ed9mkm
Пользователи
01.04.19 23:44
Offline
Цитата wmysterio ()
Вместо событий можно отслуживать текущую дату с сравнивать сколько секунд прошло от начала:

Тоже почему-то не работает. Я сделал потом иначе:

Код
        public Firework2()
        {
            
            while (true)
            {
                Wait(0);
                if (!Exists(Firework.FWS)) continue;
                Task task1 = Task.Factory.StartNew( () => {
                Wait(2000);
            });

            task1.Wait();
            

                if (GTA.Native.Function.Call<bool>("HAS_OBJECT_COLLIDED_WITH_ANYTHING", Firework.FWS) || task1.IsCompleted)
                {
                    task1.Dispose();

Т.е. я разместил задачу - подождать 2 секунды. Это получилось. Но перестало работать первое условие - условие столкновения объекта. Видимо, ждет, пока задача полностью не выполнится. Что-то нужно изменить, чтобы выполнение задачи могло бы быть прервано.

wmysterio
Администраторы
Скриптер
02.04.19 00:37
Offline
Цитата ed9mkm ()
я разместил задачу - подождать 2 секунды. Это получилось.
Вы уверены, что скрипты ScriptHook-а поддерживают многопоточность, раз перешли сразу к Task? Очень костыльный способ... Я не могу разобраться с этой задачей из за лени скачивать 4-ку, думаю всё намного проще. По памяти и на интуицию я не напишу правильный код.

ed9mkm
Пользователи
02.04.19 00:58
Offline
Цитата wmysterio ()
Вы уверены, что скрипты ScriptHook-а поддерживают многопоточность, раз перешли сразу к Task?

Я ни в чем не уверен. Вроде бы работает, но не так, как нужно. Возможно, мешает "task1.Dispose();", но когда я его размещал ниже кода эффектов, то потом известную ошибку выдавало - об отсутствующем объекте.

Очень трудно найти пример простого таймера. Везде, где я нахожу, таймер потом вызывается в "private void", а мне это не нужно. Я не знаю, как эти "void" вставлять в обычные public.

Добавлено (02.04.19, 01:02)
---------------------------------------------
В папке, где лежат файлы для разработчиков, в примерах скриптов есть такой:

Код
   // ### This script will give you all advanced weapons and lots of ammo every 5 seconds ###
   public class BasicTickExample : Script {

      public BasicTickExample() {
         Interval = 5000; // Interval is the time between two Ticks (in milliseconds)
         this.Tick += new EventHandler(this.BasicTickExample_Tick);
      }

      private void BasicTickExample_Tick(object sender, EventArgs e) {
         Game.DisableMaxAmmoLimit = true;
         Ped p = Player.Character;
         p.Weapons.BaseballBat.Ammo = 1;
         p.Weapons.Grenades.Ammo = 30000;
         p.Weapons.DesertEagle.Ammo = 30000;
         p.Weapons.BarettaShotgun.Ammo = 30000;
         p.Weapons.MP5.Ammo = 30000;
         p.Weapons.AssaultRifle_M4.Ammo = 30000;
         p.Weapons.SniperRifle_M40A1.Ammo = 30000;
         p.Weapons.RocketLauncher.Ammo = 30000;
      }

   }

Как бы его переделать, чтобы вызывать один раз через 2 - 3 секунды нужный мне код. Без этого void чтобы можно было. Тут написано "private void BasicTickExample_Tick", но мне нужно вызывать этот код без void.

Добавлено (02.04.19, 07:52)
---------------------------------------------
В общем сейчас загадка для меня одна. Такой код работает:

Код
    public class Firework3 : Script
    {
        
        private void FS_Tick(object sender, EventArgs e)
        {

            Player.Character.Voice = "NIKO_EXTRAS";
            Player.Character.SayAmbientSpeech("HIGH_FALL");
        }

        public Firework3()
        {

                    Interval = 3000;
                    this.Tick += new EventHandler(this.FS_Tick);

        }

    }

А такой уже нет:

Код
  public class Firework3 : Script
    {
        
        private void FS_Tick(object sender, EventArgs e)
        {

            Player.Character.Voice = "NIKO_EXTRAS";
            Player.Character.SayAmbientSpeech("HIGH_FALL");
        }

        public Firework3()
        {
            while (true)
            {
                Wait(0);
                if (Player.Character.isAlive)
                {
                    Interval = 3000;
                    this.Tick += new EventHandler(this.FS_Tick);
                }

            }

        }

    }

Т.е. стоит добавить while (true), как код уже не работает. А ведь мне нужен именно такой код - я бы в private void FS_Tick поместил бы "count += 1;" и потом бы в условие поместил проверку "count == 1".

Добавлено (03.04.19, 12:13)
---------------------------------------------
Придумал сделать счетчик очень простым способом. Просто создал новый класс:

Код
    public class Firework3 : Script
    {
        public static int count = 0;
        public Firework3()
        {

            while (true)
            {
                Wait(0);
                if (!Exists(Firework.FWS)) continue;
                Wait(2000);
                Firework3.count = 1;
                Wait(1000);
                Firework3.count = 0;
            }
        }
    }


И в предыдущем разместил условие:

Код
    public class Firework2 : Script
    {

        public Firework2()
        {

            while (true)
            {
                Wait(0);
                if (!Exists(Firework.FWS)) continue;

                if (GTA.Native.Function.Call<bool>("HAS_OBJECT_COLLIDED_WITH_ANYTHING", Firework.FWS) || Firework3.count == 1)

Получился тот же счетчик! Все работает - фейерверк взрывается либо через 2 секунды при беспрепятственном полете, либо врезаясь во что-нибудь. Думаю, что поставлю 3 секунды. Просто 2 ставил, чтобы было лучше понятно, работает ли.

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