Jump to content
    1. Welcome to GTAForums!

    1. GTANet.com

    1. GTA Online

      1. Los Santos Drug Wars
      2. Updates
      3. Find Lobbies & Players
      4. Guides & Strategies
      5. Vehicles
      6. Content Creator
      7. Help & Support
    2. Red Dead Online

      1. Blood Money
      2. Frontier Pursuits
      3. Find Lobbies & Outlaws
      4. Help & Support
    3. Crews

    1. Grand Theft Auto Series

      1. Bugs*
      2. St. Andrews Cathedral
    2. GTA VI

    3. GTA V

      1. Guides & Strategies
      2. Help & Support
    4. GTA IV

      1. The Lost and Damned
      2. The Ballad of Gay Tony
      3. Guides & Strategies
      4. Help & Support
    5. GTA San Andreas

      1. Classic GTA SA
      2. Guides & Strategies
      3. Help & Support
    6. GTA Vice City

      1. Classic GTA VC
      2. Guides & Strategies
      3. Help & Support
    7. GTA III

      1. Classic GTA III
      2. Guides & Strategies
      3. Help & Support
    8. Portable Games

      1. GTA Chinatown Wars
      2. GTA Vice City Stories
      3. GTA Liberty City Stories
    9. Top-Down Games

      1. GTA Advance
      2. GTA 2
      3. GTA
    1. Red Dead Redemption 2

      1. PC
      2. Help & Support
    2. Red Dead Redemption

    1. GTA Mods

      1. GTA V
      2. GTA IV
      3. GTA III, VC & SA
      4. Tutorials
    2. Red Dead Mods

      1. Documentation
    3. Mod Showroom

      1. Scripts & Plugins
      2. Maps
      3. Total Conversions
      4. Vehicles
      5. Textures
      6. Characters
      7. Tools
      8. Other
      9. Workshop
    4. Featured Mods

      1. Design Your Own Mission
      2. OpenIV
      3. GTA: Underground
      4. GTA: Liberty City
      5. GTA: State of Liberty
    1. Rockstar Games

    2. Rockstar Collectors

    1. Off-Topic

      1. General Chat
      2. Gaming
      3. Technology
      4. Movies & TV
      5. Music
      6. Sports
      7. Vehicles
    2. Expression

      1. Graphics / Visual Arts
      2. GFX Requests & Tutorials
      3. Writers' Discussion
      4. Debates & Discussion
    1. Announcements

    2. Forum Support

    3. Suggestions

[BETA] GTAIV .Net ScriptHook


HazardX
 Share

Recommended Posts

 

as long as i know in winForms you can override OnPaint or subscribe to Paint event, so i think it still make sense. anyway it's okay. maybe provide both??lol.giftounge.gif

Well okay, we could agree upon the OnTick method here. wink.gif However, while overriding the OnXYZ methods is possible in the .Net standard, it is a pretty bad habit to do so if you just want to catch the event, because you will prevent the XYZ event from firing (unless you call base.OnXYZ or fire XYZ manually). The overridable OnXYZ methods are basically only meant for situations where you want to execute stuff before/after the event fires, or if you want to block the event. Not for handling it.

See it like this: In the old version you were forced to do event handling wrong, now you are forced to do it right. lol.gif

yeah, one should know exactly what they're doing when overriding OnXYZ.

 

oh, is it possible to provide a chance for us to clean up when user ReloadScripts? sometimes i got a Blip attached to a car or something, later i reloadscripts and there's no way to delete it. maybe IDisposable or ScriptReload event?

 

[EDIT] ScriptTerminate event may be proper

Edited by diryboy
Link to comment
Share on other sites

Ah cheers for that hazard. I'm still having trouble with keyDown and multiple keyPress. I'm looking at the test scripts but not quite understanding it.

Link to comment
Share on other sites

 

yeah, one should know exactly what they're doing when overriding OnXYZ.

 

oh, is it possible to provide a chance for us to clean up when user ReloadScripts? sometimes i got a Blip attached to a car or something, later i reloadscripts and there's no way to delete it. maybe IDisposable or ScriptReload event?

 

[EDIT] ScriptTerminate event may be proper

Yes, i'll store all Blips created by .Net scripts and remove them automatically on abort/reload in the next version. But a proper Teminate event would be very useful nevertheless. The problem is just that the scripts have to get processing time while aborting... i'll try to find a way.

 

@Gangsta Killa: What kind of problems do you have exactly? The new KeyDown event has a KeyEventArgs object (e) as a parameter. e.Key contains the pressed Key without Shift/Control/Alt info and e.KeyWithModifiers is with it. Doing "if (myKeyCombination == e.KeyWithModifiers) { do stuff here }" should work.

Link to comment
Share on other sites

Actually nevermind, I had more of a play around and found that the scriptsettings has a method for returning a keyvalue.

Link to comment
Share on other sites

yeah, one should know exactly what they're doing when overriding OnXYZ.

 

oh, is it possible to provide a chance for us to clean up when user ReloadScripts? sometimes i got a Blip attached to a car or something, later i reloadscripts and there's no way to delete it. maybe IDisposable or ScriptReload event?

 

[EDIT] ScriptTerminate event may be proper

Yes, i'll store all Blips created by .Net scripts and remove them automatically on abort/reload in the next version. But a proper Teminate event would be very useful nevertheless. The problem is just that the scripts have to get processing time while aborting... i'll try to find a way.

 

@Gangsta Killa: What kind of problems do you have exactly? The new KeyDown event has a KeyEventArgs object (e) as a parameter. e.Key contains the pressed Key without Shift/Control/Alt info and e.KeyWithModifiers is with it. Doing "if (myKeyCombination == e.KeyWithModifiers) { do stuff here }" should work.

Ice cold! man! (i steal this from Brucie tounge.gif )

 

@Gangsta Killa: Hazard's correct. i remember i also posted my idea earlier, i use it myself and it works fine.

Link to comment
Share on other sites

Nah still having problems. I'm loading the keys from an ini file using the getKeyValue method.

 

 

INIHAZARDTOGGLE = Control, H

 

 

 

Keys hazardToggle;this.KeyDown += new GTA.KeyEventHandler(KeyDownHandler);//get the keys from filehazardToggle = fSettings.GetValueKey("HAZARDTOGGLE", "KEYS", Keys.H);//check ifpublic void KeyDownHandler(object sender, GTA.KeyEventArgs e)       {if (hazardToggle == e.KeyWithModifiers)

 

}

 

It doesn't seem to register the key press.

Link to comment
Share on other sites

INI File:

 

[KEYS]HAZARDTOGGLE = Control, H

 

 

Script:

 

public class MyScript : Script { Keys hazardToggle; public MyScript() {   this.KeyDown += new GTA.KeyEventHandler(KeyDownHandler);   //get the keys from file   hazardToggle = Settings.GetValueKey("HAZARDTOGGLE", "KEYS", Keys.H); } //check if private void KeyDownHandler(object sender, GTA.KeyEventArgs e) {   if (hazardToggle == e.KeyWithModifiers) {     Game.DisplayText("It works!!!");   } }}

 

 

This should work. If the INI file is NOT loaded the message will be triggered any time you press H without Control (because Keys.H is the default value there). If the INI file is loaded correctly it will be triggered when you press H with Control.

Edited by HazardX
Link to comment
Share on other sites

Doh!, I'd upgraded the hook version I was using to develop with, but I hadn't upgraded the version used to load the script in the game!! blush.gif All fixed now.

Link to comment
Share on other sites

Doh!, I'd upgraded the hook version I was using to develop with, but I hadn't upgraded the version used to load the script in the game!! blush.gif All fixed now.

Okay, this explains alot. wink.gif Good to know that it works now.

Link to comment
Share on other sites

Hmm, errors and errors galore. I'm not quite sure whats causing these.

 

 

removed again

 

 

As far as I'm aware everything is referenced and set up.

 

Edit, sorted it, forgot to initalise something.

 

edit2: maybe not. sad.gif

 

edit: fixed it, was adding to something before i initalised it. blush.gif

 

edit4: still having trouble with the key presses, it doesn't appear to be loading them in from the settings file.

Edited by Gangsta Killa
Link to comment
Share on other sites

Great work on the update! icon14.gif Now the CurrentRoom properties work for vehicles and objects too. biggrin.gif

 

 

I was also wondering if there was a way to easily create multiple threads to use within the scripts.

 

The reason I ask is because I have multiple For loops to check the various ped lists; distance, health, blips, tasks, etc. As you already know, Wait blocks everything which can make the script appear to be lagging. Threading.Thread.Sleep will cause the game itself to appear to be lagging if a value other than 0 is specified, as it makes the game thread sleep for the specified time, but 0 seems to work allowing everything to be processed without any pause in the script or lag.

 

If I remove all Wait and Sleep methods, the game will begin to lag if too many peds are spawned. I have the tick interval set to 1000 so I'm not sure what else I can do. I tried creating a new thread, to test it out, but couldn't figure out how to invoke the methods. There were access violation crashes which led me to keep it the way I currently have it. I guess it works good enough, I just think multithreading would be a great alternative to the Tick event; for those of us who have fairly large scripts or lots of loops. What do you think, is it even possible?

 

 

One more thing, the Finalize method.. is it used to dispose any globals that might've been in use during the script runtime? I was looking for the Dispose event and that was the closest thing I found. I just want to be sure that's what it's used for. lol.gif

Link to comment
Share on other sites

 

edit4: still having trouble with the key presses, it doesn't appear to be loading them in from the settings file.

Id the filename of the INI correct? If the script is named MyScript.net the ini filename has to be MyScript.ini . If it is MyScript.net.dll the ini has to be MyScript.net.ini , i guess.

 

@CoMPMStR: New Threads won't work for two reasons: 1) they have no right to access the game memory. 2) a new thread will not wait when other scripts run and thus will do stuff at the same time as other scripts which results in EVIL thread conflicts.

At the moment the closest thing to threads would be to use multiple scripts that interact through ScriptCommands (see ScriptCommunicationExample). You can also get a second script from the first script using Game.GetScript if your second script has a GUID. After that you can access members of the second script directly.

There is not Cleanup event yet. It is planned for the next version. Finalize might not work because it will run in another thread that is not eligible to access all script functions.

Edited by HazardX
Link to comment
Share on other sites

 

edit4: still having trouble with the key presses, it doesn't appear to be loading them in from the settings file.

Id the filename of the INI correct? If the script is named MyScript.net the ini filename has to be MyScript.ini . If it is MyScript.net.dll the ini has to be MyScript.net.ini , i guess.

Oh, I thought it could be named anything. I'll give that a shot.

I've got a fSettings varible that is a from ScriptSettings and I've given it the path to my ini file.

 

 

ScriptSettings fSettings;fSettings = new ScriptSettings("gkfuelsettings.ini");

 

 

edit: that sorted it, cheers.

Edited by Gangsta Killa
Link to comment
Share on other sites

 

Oh, I thought it could be named anything. I'll give that a shot.

I've got a fSettings varible that is a from ScriptSettings and I've given it the path to my ini file.

Sorry, we misunderstood us here. You are creating a new ScriptSettings object. This should work with any filename, but you have to give a full path, not just the filename. BUT, every script comes with a default "Settings" object and THIS settings object is bound to a specific filename. Just remove the "fSettings" object and access "Settings" instead.

Link to comment
Share on other sites

Ah, I got it working with the default settings. so the path for the fSettings object would be "scripts/inifile.ini"?

Link to comment
Share on other sites

Ah, I got it working with the default settings. so the path for the fSettings object would be "scripts/inifile.ini"?

Yes, this should be okay. But i prefer to make the path absolute by using Game.InstallFolder infront of it, just to make sure.

Link to comment
Share on other sites

How would i fix this error.. I tried Byval graphic as gta.graphics but that gave me even more. This is to show a menu..

 

 

Private Sub carspawner_PerFrameDrawing1(ByVal sender As Object, ByVal e As GTA.GraphicsEventArgs) Handles Me.PerFrameDrawing       If menuShown Then ShowMainMenu(graphics,all other settings here...)

 

 

 

Error	3	'graphics' is ambiguous, imported from the namespaces or types 'System.Drawing, GTA'.	D:\Documents and Settings\\Desktop\gtavb\86\scripts\for Developers\TestScriptVB\Scripts\script.vb	863	40	TestScriptVB

 

 

Also (graphics) is where the error is

Link to comment
Share on other sites

 

Also is this ...

The correct code for a startup sub

Startup was removed use this now:

 

Public Sub New()  Interval = 10End Sub

 

 

and graphics is a member of the GraphicsEventArgs (e) now. Thus use "e.Graphics" instead of "graphics".

Link to comment
Share on other sites

I'm just starting with C# (Have done a bit C++ with Aru's hook), and it seems a bit complicated to me.

For example, how would I do this:

 

//C++ Example 1.Player playerIndex = ConvertIntToPlayerIndex(GetPlayerId());Char c;GetPlayerChar(playerIndex, &c);Vehicle v;GetCarCharIsUsing(c, &v);f32 Speed;GetCarSpeed(v,&Speed);

 

 

In C#? When I try to type something, a drop-down menu appears. I've looked at the example scripts for a bit, and it seems it works a bit like this:

 

//C#Player.Character.isInVehicle();

 

Would be

 

//C++Player playerIndex = ConvertIntToPlayerIndex(GetPlayerId());Char c;GetPlayerChar(playerIndex, &c);IsCharInAnyCar©;

 

 

How would I type Example 1. in C#?

 

Sorry for asking such noob questions wink.gif

 

 

Link to comment
Share on other sites

Also is this ...

The correct code for a startup sub

Startup was removed use this now:

 

Public Sub New()  Interval = 10End Sub

 

 

and graphics is a member of the GraphicsEventArgs (e) now. Thus use "e.Graphics" instead of "graphics".

Ty i just fixed my scripts. No errors

Link to comment
Share on other sites

I'm just starting with C# (Have done a bit C++ with Aru's hook), and it seems a bit complicated to me.

For example, how would I do this:

 

//C++ Example 1.Player playerIndex = ConvertIntToPlayerIndex(GetPlayerId());Char c;GetPlayerChar(playerIndex, &c);Vehicle v;GetCarCharIsUsing(c, &v);f32 Speed;GetCarSpeed(v,&Speed);

 

 

In C#? When I try to type something, a drop-down menu appears. I've looked at the example scripts for a bit, and it seems it works a bit like this:

 

//C#Player.Character.isInVehicle();

 

Would be

 

//C++Player playerIndex = ConvertIntToPlayerIndex(GetPlayerId());Char c;GetPlayerChar(playerIndex, &c);IsCharInAnyCar©;

 

 

How would I type Example 1. in C#?

 

Sorry for asking such noob questions wink.gif

 

//C++ Example 1.Player playerIndex = ConvertIntToPlayerIndex(GetPlayerId());Char c;GetPlayerChar(playerIndex, &c);Vehicle v;GetCarCharIsUsing(c, &v);f32 Speed;GetCarSpeed(v,&Speed);

 

 

Like this

 

 

ped player;player = Player.Character;Vehicle veh;veh = Player.Character.CurrentVehicle;float speed;speed = veh.Speed;

 

 

Link to comment
Share on other sites

 

I'm just starting with C# (Have done a bit C++ with Aru's hook), and it seems a bit complicated to me.

For example, how would I do this:

 

//C++ Example 1.Player playerIndex = ConvertIntToPlayerIndex(GetPlayerId());Char c;GetPlayerChar(playerIndex, &c);Vehicle v;GetCarCharIsUsing(c, &v);f32 Speed;GetCarSpeed(v,&Speed);

 

The .Net ScriptHook uses a completely different approach. In the C++ hook you are calling all script functions directly, while in the .Net Scripthook everything is packed up in an easy to use object-oriented class structure. This requires less code in scripts and is WAAAAY less error prone. Your whole example requires just one line of code:

 

float speed = Player.Character.CurrentVehicle.Speed;

 

 

This may only create an error if the player is not in a vehicle currently. Thus you may want to check for Player.Character.isInVehicle() before.

Link to comment
Share on other sites

 

@CoMPMStR: New Threads won't work for two reasons: 1) they have no right to access the game memory. 2) a new thread will not wait when other scripts run and thus will do stuff at the same time as other scripts which results in EVIL thread conflicts.

At the moment the closest thing to threads would be to use multiple scripts that interact through ScriptCommands (see ScriptCommunicationExample). You can also get a second script from the first script using Game.GetScript if your second script has a GUID. After that you can access members of the second script directly.

There is not Cleanup event yet. It is planned for the next version. Finalize might not work because it will run in another thread that is not eligible to access all script functions.

I didn't think the thread waiting would be a problem. I read that .NET has a SyncLock statement to allow thread synchronization, the memory access rights I understand. Is there any way to give a created thread proper access rights to the game memory?

 

I'll give the script communications a shot and see how it performs. icon14.gif

 

 

@thaCURSEDpie: This is how you can display the vehicle speed:

 

 

          if (Exists(Player.Character.CurrentVehicle))         {             Game.DisplayText(Player.Character.CurrentVehicle.Speed.ToString);         }

 

Link to comment
Share on other sites

 

I didn't think the thread waiting would be a problem. I read that .NET has a SyncLock statement to allow thread synchronization, the memory access rights I understand. Is there any way to give a created thread proper access rights to the game memory?

SyncLock doesn't help here because of the fiber thread architecture. I could make a thread class, yes, but in the end it would basically be the same as the script class.

 

@thaCURSEDpie: Information overload. lol.gif I hope we didn't confuse you. colgate.gif

Edited by HazardX
Link to comment
Share on other sites

@HazardX

No, I think I'm beginning to understand it smile.gif. This actually is an easier method than Aru's hook.

 

Warning: long post wow.gif

 

But now I have a question. I want to make some sort of a "Cruise control" script. This will work as follows:

 

1. The player presses a button. The current vehicle speed is saved to a variable.

2. Some way or another the game is forced to keep the vehicle going forward.

3. If the vehicle's speed excedes the the saved speed, the vehicle speed is set to the saved speed.

4. The cruise control turns off when the player presses the button again, or:

- leaves the vehicle

- brakes

- accelerates manually.

 

I'm having a hard time with step no.2. Ofcourse, I could just force the car speed to be the initial speed at all times, but this has some nasty side-effects. (Car goes flying, keeps ramming into walls, etc. I know this out of experience tounge.gif)

So, I want to "force" the car to keep going forward. This can (theoretically) be done in two ways:

 

1. Use some sort of an internal command in the game. This can be done in Source games: just type in the console "+jump" and the player jumps, or "bind J +forward" and the player moves forward when J is pressed.

But I have been unable to find such a technique in GTA:IV sad.gif.

 

2. There is also a second method, which is a bit more... rude so to speak. You let the script "press" the forward key, so the game thinks the key is actually being pressed.

I've tried this method, and it's hard. I've tried it in C++ and when I simulated the "W" keypress (and release) the camera began to turn... nice.

After this I tried GlovePie, a nice programme that let's you make macros and use the WiiMote on your PC. I bound "End" as a switch, so that "W" would be kept pressed. I started up GTA, but the game just ignored it. (other games, like HL2 actually do respond to this.)

 

So, I wanted to try it in another scripting language, to see if I might get better results. I was happy when I found "SendKeys.Send({string})". But this didn't work either. I got an error message. (and thanks to the awesome dev-console it was a very helpful error message). It said something like: "This game does not use Windows input. Try SendKeys.SendWait()." So, that's what I did. I loaded up the game again, pressed the desired button and the game froze =/

 

Now, I'm pretty much out of options. Does anybody have any suggestions?

 

In short:

1. Is there a way to force things ingame, like: Car.AccelerateForward(true) or Player.FireGun()? (Like the +attack and +forward commands in the Source engine)

2. If not, is there a way to simulate keypresses to do "force" this kind of thing?

 

 

 

Link to comment
Share on other sites

 

@HazardX

No, I think I'm beginning to understand it smile.gif. This actually is an easier method than Aru's hook.

 

Warning: long post wow.gif

 

But now I have a question. I want to make some sort of a "Cruise control" script. This will work as follows:

 

1. The player presses a button. The current vehicle speed is saved to a variable.

2. Some way or another the game is forced to keep the vehicle going forward.

3. If the vehicle's speed excedes the the saved speed, the vehicle speed is set to the saved speed.

4. The cruise control turns off when the player presses the button again, or:

- leaves the vehicle

- brakes

- accelerates manually.

 

I'm having a hard time with step no.2. Ofcourse, I could just force the car speed to be the initial speed at all times, but this has some nasty side-effects. (Car goes flying, keeps ramming into walls, etc. I know this out of experience tounge.gif)

So, I want to "force" the car to keep going forward. This can (theoretically) be done in two ways:

 

1. Use some sort of an internal command in the game. This can be done in Source games: just type in the console "+jump" and the player jumps, or "bind J +forward" and the player moves forward when J is pressed.

But I have been unable to find such a technique in GTA:IV sad.gif.

 

2. There is also a second method, which is a bit more... rude so to speak. You let the script "press" the forward key, so the game thinks the key is actually being pressed.

I've tried this method, and it's hard. I've tried it in C++ and when I simulated the "W" keypress (and release) the camera began to turn... nice.

After this I tried GlovePie, a nice programme that let's you make macros and use the WiiMote on your PC. I bound "End" as a switch, so that "W" would be kept pressed. I started up GTA, but the game just ignored it. (other games, like HL2 actually do respond to this.)

 

So, I wanted to try it in another scripting language, to see if I might get better results. I was happy when I found "SendKeys.Send({string})". But this didn't work either. I got an error message. (and thanks to the awesome dev-console it was a very helpful error message). It said something like: "This game does not use Windows input. Try SendKeys.SendWait()." So, that's what I did. I loaded up the game again, pressed the desired button and the game froze =/

 

Now, I'm pretty much out of options. Does anybody have any suggestions?

 

In short:

1. Is there a way to force things ingame, like: Car.AccelerateForward(true) or Player.FireGun()? (Like the +attack and +forward commands in the Source engine)

2. If not, is there a way to simulate keypresses to do "force" this kind of thing?

Hmm i had this idea. I think you could use. player.character.currentvehicle.speed = storedspeed.

 

if e.key = keys.e then

stored speed = player.character.currentvehicle.speed

something = true

then in a timer

if something = true then

player.character.currentvehicle.speed = storedspeed

 

 

But tweak it ( tahts just the basic concept , That i think will work( im not sure )

* just say if u want more code( because thast not whole thing )

Edited by boomer678
Link to comment
Share on other sites

A question about spawning enemies and groups:

 

So I have a basic script that spawns an enemy. However, I don't want the enemies to fight each other, how can this be done? Does it involve adding the spawn to a group?

 

Genral question about the scripthook:

 

Is there an API or something for this? Its quite amazing all the things you can do, and for the most part every mothod is selfexplanity, but I'm curious if such a thing exists.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • 4 Users Currently Viewing
    0 members, 0 Anonymous, 4 Guests

×
×
  • Create New...

Important Information

By using GTAForums.com, you agree to our Terms of Use and Privacy Policy.