Quantcast

Jump to content

» «
Photo

[GTAIV|REL|SRC] C++ Script Hook

1,718 replies to this topic
asd23
  • asd23

    Crackhead

  • Members
  • Joined: 24 Mar 2004

#91

Posted 08 January 2009 - 05:40 PM

QUOTE (sjaak327 @ Jan 8 2009, 16:00)
I just have a question, if I use

DisplayTextWithLiteralString(0.5f, 0.25f, "STRING", "Custom");

the text is displayed ingame, but it's gone in under a second, anyone can give me a pointer as to how I can keep the text for a longer while ?

Call it in the tick event, then it will display every frame. Make some kind of check to see, if you need to display text, or not.


On another note, GetModelHash doesn't always return a valid model hash. It gives me negative value for the Banshee, for example. And for most of the DLC bikes.

Intosia
  • Intosia

    I'm random! ^^

  • Members
  • Joined: 11 Dec 2008

#92

Posted 08 January 2009 - 06:08 PM

EDIT: nevermind turn.gif

sjaak327
  • sjaak327

    Big Homie

  • Members
  • Joined: 01 Dec 2008

#93

Posted 08 January 2009 - 06:49 PM

QUOTE (asd23 @ Jan 8 2009, 17:40)
Call it in the tick event, then it will display every frame. Make some kind of check to see, if you need to display text, or not.



That works,

Of course I now need to find a way to make a check smile.gif


aru
  • aru

    *poof*

  • Members
  • Joined: 20 Jun 2005

#94

Posted 08 January 2009 - 07:04 PM

QUOTE (asd23 @ Jan 8 2009, 12:40)
On another note, GetModelHash doesn't always return a valid model hash. It gives me negative value for the Banshee, for example. And for most of the DLC bikes.

MODEL_BANSHEE = 0xC1E908D2
= 3253274834
= -1041692462

They are all the same... just different representations of the same thing in memory.

ExtraOrdinary
  • ExtraOrdinary

    Player Hater

  • Members
  • Joined: 03 Jan 2009

#95

Posted 08 January 2009 - 08:19 PM Edited by ExtraOrdinary, 08 January 2009 - 08:39 PM.

This looks very nice, I'll try to learn C++ if I have patience biggrin.gif

also, I need a ASI or DLL loader right?

Where can I get that, like are there any good? biggrin.gif

L0uNGeR
  • L0uNGeR

    Ya, that's what I said.

  • Members
  • Joined: 03 Dec 2008

#96

Posted 08 January 2009 - 10:25 PM

Could anyone provide a good example or explanation on how to properly use RunTick() and states please?
What would be a good way to do or check something at all times, without performance penalty? Is it ok to do something like GetClosestCar() in the main RunTick() loop?

aru
  • aru

    *poof*

  • Members
  • Joined: 20 Jun 2005

#97

Posted 09 January 2009 - 12:26 AM Edited by aru, 09 January 2009 - 12:32 AM.

This may sound confusing, but I hope its not...

What essentially is going on here is that there are multiple different script threads running in a single game operating system thread (so really its Single Threaded). The game uses something called co-operative multithreading to allow multiple scripts to run at once... which means one thread gives up control when its waiting on a resource so that other threads/the game can do its work too.

In the game script code... they normally would have...

CODE
if (KeyPressed(a))
{
 RequestModel(x);
 while (!HasModelLoaded(x))
 {
    Wait(0);
    SomeOtherInstruction();
 }
 CreateSomethingFromModel(x);
}


When the game executes this script code... when it comes a Wait(), it saves the state of the script and goes and processes other scripts and other game code (like actually loading the requested model). When it gets back to this script, it'll continue running the instruction after the Wait which is SomeOtherInstruction();

Unfortunately, in the C++ hook code, its too hard to save the state of the code... so we can't use Wait() and the code above won't work! The general rule to use here is that you do not run any infinite loops that wait on resources... instead you set a flag or change the state (so that you know you requested a model, etc) and return back to the game. The next time RunTick() executes we'll use the flag or the state to identify what to do.

So for the code above... we break it apart into something like:

CODE
if (KeyPressed(a))
{
 RequestModel(x);
 modelRequested = true;
}

if (modelRequested)
{
 if (!HasModelLoaded(x))
 {
    SomeOtherInstruction();
 }
 else
 {
    CreateSomethingFromModel(x);
    modelRequested = false;
 }
}


And the infinite wait loop is gone... and the game can process the actual loading of the model, and other threads are not blocked while you are waiting.

A state machine is just a fancy implementation of this... we just change the state to let the program know where the next execution should start instead of setting a flag.

You only need to do this when you have to wait for something to load/process/complete... this is usually the case for functions like RequestModel, RequestAnims, etc. Some other examples where you should be using states/flags to process the next section of code:

CODE
while(!IsScreenFadingOut())
{
 Wait(0);
}
MoreCode();


CODE
while(TimerA() < 500)
{
 Wait(0);
}
MoreCode();


99% of the functions would not require you to do this. To use GetClosestCar() you do NOT need to break it apart into a new state and can just call it normally in a linear fashion. You can check anything, anywhere... just as long as you make sure you don't put a non-deterministic loop around it smile.gif

sjaak327
  • sjaak327

    Big Homie

  • Members
  • Joined: 01 Dec 2008

#98

Posted 09 January 2009 - 01:12 AM

I'm having fun with this, and have quite a few natives that I'm using in a single asi.

Now I do have a question about something I cannot seem to be getting right.

Simple example in LUA,

I would declare

GOD_MODE = 0

then in the main function:

if (IsKeyPressed(97) == 1) then
GodMode()
end

function GodMode()

if (GOD_MODE == 0) then
PushInt(PLAYER_INDEX)
PushInt(1)
CallNative("SET_PLAYER_INVINCIBLE")
GOD_MODE = 1
else
PushInt(PLAYER_INDEX)
PushInt(0)
CallNative("SET_PLAYER_INVINCIBLE")
GOD_MODE = 0
end
end

Now, I am not able to get this simple thing working in C++, press one key, and depending on the value of GOD_MODE, act accordingly.

Any help is appriciated.




Indi
  • Indi

    "Party's over, kid!"

  • Andolini Mafia Family
  • Joined: 22 Nov 2008

#99

Posted 09 January 2009 - 01:21 AM

Love this tool, I must learn C++ sometime tounge.gif

aru
  • aru

    *poof*

  • Members
  • Joined: 20 Jun 2005

#100

Posted 09 January 2009 - 02:04 AM Edited by aru, 09 January 2009 - 02:08 AM.

QUOTE (sjaak327 @ Jan 8 2009, 20:12)
I'm having fun with this, and have quite a few natives that I'm using in a single asi.

Now I do have a question about something I cannot seem to be getting right.

Simple example in LUA,

I would declare

GOD_MODE = 0

then in the main function:

if (IsKeyPressed(97) == 1) then
     GodMode()
     end

function GodMode()
 
if (GOD_MODE == 0) then
  PushInt(PLAYER_INDEX)
  PushInt(1)
  CallNative("SET_PLAYER_INVINCIBLE")
  GOD_MODE = 1
else
  PushInt(PLAYER_INDEX)
  PushInt(0)
  CallNative("SET_PLAYER_INVINCIBLE")
  GOD_MODE = 0
  end
end

Now, I am not able to get this simple thing working in C++, press one key, and depending on the value of GOD_MODE, act accordingly.

Any help is appriciated.

So you would declare...

CODE
bool GOD_MODE = false;


Then in the main function you would have:

CODE
if ((GetAsyncKeyState('A') & 1) != 0)
{
  GodMode();
}


Then outside the main function you would declare:

CODE
void GodMode()
{
    if (GOD_MODE == false)
    {
        SetPlayerInvincible(PLAYER_INDEX, true);
        GOD_MODE = true;
    }
    else
    {
        SetPlayerInvincible(PLAYER_INDEX, false);
        GOD_MODE = false;
    }
}


Then in scripting.h you would add (since SetPlayerInvincible is not defined in your copy of scripting.h):

CODE
static void SetPlayerInvincible(u32 playerIndex, b8 invincible) { NativeInvoke::Invoke< ScriptVoid >("SET_PLAYER_INVINCIBLE", playerIndex, invincible); }


And viola, you're done!

Ofcourse.. if you want to be an awesome programmer, you would do this instead:

CODE
void GodMode()
{
    SetPlayerInvincible(PLAYER_INDEX, !GOD_MODE);
    GOD_MODE = !GOD_MODE;
}

Sacky
  • Sacky

    IV's Limit Adjuster

  • Members
  • Joined: 10 Nov 2006

#101

Posted 09 January 2009 - 04:31 AM

Nice work. But am I correct in thinking it doesn't work outside the thread it's contained in? (For example only able to be used in ::RunScript)

Deanimator
  • Deanimator

    Player Hater

  • Members
  • Joined: 07 Jan 2009

#102

Posted 09 January 2009 - 05:30 AM

in order to have a godmode where explosions affect niko i tried to set health to 1000 each tick. Niko would still die in explosions, but the screen stayed in full color(no black and white death scene). Anybody know why or have any suggestions?

sjaak327
  • sjaak327

    Big Homie

  • Members
  • Joined: 01 Dec 2008

#103

Posted 09 January 2009 - 07:06 AM Edited by sjaak327, 09 January 2009 - 07:19 AM.

QUOTE (aru @ Jan 9 2009, 02:04)
CODE
if ((GetAsyncKeyState('A') & 1) != 0)
{
  GodMode();
}



That was the only thing that was missing, I don't know how to declare a new function, I did declare the native in scripting.h
and was using:

else if ((GetAsyncKeyState(VK_MENU)&&(GetAsyncKeyState(VK_NUMPAD1) & 0x8000) != 0))
{

u32 playerIndex = ConvertIntToPlayerIndex(GetPlayerId());
SetPlayerInvincible(playerIndex, 1);
}

else if ((GetAsyncKeyState(VK_RCONTROL)&&(GetAsyncKeyState(VK_NUMPAD1) & 0x8000) != 0))
{

u32 playerIndex = ConvertIntToPlayerIndex(GetPlayerId());
SetPlayerInvincible(playerIndex, 0);

I feel stupid now smile.gif

(alltough it did work, but not with a simple one key keypress. )

Thank you very much smile.gif

dingbat2000
  • dingbat2000

    Player Hater

  • Members
  • Joined: 30 Dec 2008

#104

Posted 09 January 2009 - 07:55 AM

Scripts don't seem to re-hook when there is a new player creation beyond the first instance.

e.g. if you are in game, then join an mp game, then return to single player a script no longer functions.

How do I correct this?

kellis
  • kellis

    Player Hater

  • Members
  • Joined: 29 Dec 2008

#105

Posted 09 January 2009 - 08:12 AM

thank you aru for this nice toy icon14.gif , i think it will be alot of fun biggrin.gif

aru
  • aru

    *poof*

  • Members
  • Joined: 20 Jun 2005

#106

Posted 09 January 2009 - 08:38 AM

@Sacky... If you mean operating system thread, then yes... this is actually a good thing because the game uses TLS for data allocations. Just try running CreateCar from a seperate OS thread... it won't be pretty. If you mean game script thread, then no... you can always set the active script to another script and run a command that will attach the created resource to that thread.

@dingbat2000... I have no intentions of getting it to work under MP. Although I can appreciate the usefulness of it for some non-interfering mods, I really rather not be the root cause for a cheating epidemic. However, that being said... if a new game is loaded, it should rehook.... so that's a bug that I will look at smile.gif.

aceship
  • aceship

    Just An Indonesian Scripter

  • Members
  • Joined: 20 Dec 2008

#107

Posted 09 January 2009 - 10:36 AM Edited by aceship, 09 January 2009 - 10:53 AM.

Asking,
how to build "equal" or =?
in this?
QUOTE

(&p4 = x + p1 );
(&p5 = y + p2 );
(&p6 = z );

i made something with this but deadlier/ sucide

Got This:
QUOTE
1>CustomThread.cpp
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(114) : error C2440: '=' : cannot convert from 'f32' to 'Scripting::ScriptAny *'
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(115) : error C2440: '=' : cannot convert from 'f32' to 'Scripting::ScriptAny *'
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(116) : error C2440: '=' : cannot convert from 'f32' to 'Scripting::ScriptAny *'
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(118) : warning C4244: 'argument' : conversion from 'Scripting::ScriptAny' to 'f32', possible loss of data
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(118) : warning C4244: 'argument' : conversion from 'Scripting::ScriptAny' to 'f32', possible loss of data
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(118) : warning C4244: 'argument' : conversion from 'Scripting::ScriptAny' to 'f32', possible loss of data

PatrickW
  • PatrickW

    GTA Juggernaut

  • Moderator
  • Joined: 07 Jan 2004
  • Netherlands

#108

Posted 09 January 2009 - 10:55 AM

In C++ the equality comparison operator is "==".

e.g.
CODE

(&p4 == 3)

aceship
  • aceship

    Just An Indonesian Scripter

  • Members
  • Joined: 20 Dec 2008

#109

Posted 09 January 2009 - 11:12 AM Edited by aceship, 09 January 2009 - 11:26 AM.

Still error
QUOTE
1>CustomThread.cpp
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(112) : error C2440: '=' : cannot convert from 'f32' to 'f32 *'
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(113) : error C2440: '=' : cannot convert from 'f32' to 'f32 *'
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(114) : error C2440: '=' : cannot convert from 'f32' to 'f32 *'


My Build
QUOTE
Char c;
  f32 x,y,z, x1, y1, z1;
  f32 p1,p2,p3;
 

  u32 playerIndex = ConvertIntToPlayerIndex(GetPlayerId());
  GetPlayerChar(playerIndex, &c);

  GetCharCoordinates(c, &x, &y, &z);
  GetCharVelocity(c, &x1, &y1, &z1);

  (&p1 = x + x1 );
  (&p2 = y + y1 );
  (&p3 = z );


Edit all: New One

Sacky
  • Sacky

    IV's Limit Adjuster

  • Members
  • Joined: 10 Nov 2006

#110

Posted 09 January 2009 - 11:19 AM

QUOTE
@Sacky... If you mean operating system thread, then yes... this is actually a good thing because the game uses TLS for data allocations. Just try running CreateCar from a seperate OS thread... it won't be pretty. If you mean game script thread, then no... you can always set the active script to another script and run a command that will attach the created resource to that thread.


Funnily enough I've tried running CreateCar from the main OS Thread, and sure enough it crashes. Although the game uses TLS for data allocations, isn't there a way to execute a chunk of code in that thread 'context' (that would allow the code to see the TLS allocations without actually being in the thread itself)? The reason I ask is I find it a bit restrictive that it's only possible to execute natives within the thread tick, for example let's say I hook the keyboard with SetWindowsHookEx in another DLL, and I want to inject natives off that callback? I've tried different variations of Suspend/Resume thread, but nothing's really working for me, any ideas?

Intosia
  • Intosia

    I'm random! ^^

  • Members
  • Joined: 11 Dec 2008

#111

Posted 09 January 2009 - 12:18 PM

I had some fun with ApplyForceToCar, idea from Lounger's LUA script biggrin.gif



_O_ Ill code when i get home (its very simple)

asd23
  • asd23

    Crackhead

  • Members
  • Joined: 24 Mar 2004

#112

Posted 09 January 2009 - 12:30 PM

Is there some way to check if a vehicle exists(not model)? I'm asking this, because of my Car Spawner. I added the DLC bikes to the spawn list, but if someone without the DLC mod spawns any of them, it crashes.

I *think* checking for the models won't help, because HasModelLoaded returns true, since the model files are there, but not in the default.ide.

dingbat2000
  • dingbat2000

    Player Hater

  • Members
  • Joined: 30 Dec 2008

#113

Posted 09 January 2009 - 12:45 PM

QUOTE (aru @ Jan 9 2009, 08:38)
@dingbat2000... I have no intentions of getting it to work under MP. Although I can appreciate the usefulness of it for some non-interfering mods, I really rather not be the root cause for a cheating epidemic. However, that being said... if a new game is loaded, it should rehook.... so that's a bug that I will look at smile.gif.

haha. its more to do with it not functioning after loading a savegame, or entering then exiting the video editor etc... but I can see your point about MP

PatrickW
  • PatrickW

    GTA Juggernaut

  • Moderator
  • Joined: 07 Jan 2004
  • Netherlands

#114

Posted 09 January 2009 - 01:04 PM

QUOTE (aceship @ Jan 9 2009, 12:12)
Still error
QUOTE
1>CustomThread.cpp
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(112) : error C2440: '=' : cannot convert from 'f32' to 'f32 *'
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(113) : error C2440: '=' : cannot convert from 'f32' to 'f32 *'
1>e:\program files\rockstar games\grand theft auto iv\customthread.cpp(114) : error C2440: '=' : cannot convert from 'f32' to 'f32 *'


My Build
QUOTE
Char c;
  f32 x,y,z, x1, y1, z1;
  f32 p1,p2,p3;
 

  u32 playerIndex = ConvertIntToPlayerIndex(GetPlayerId());
  GetPlayerChar(playerIndex, &c);

  GetCharCoordinates(c, &x, &y, &z);
  GetCharVelocity(c, &x1, &y1, &z1);

  (&p1 = x + x1 );
  (&p2 = y + y1 );
  (&p3 = z );


Edit all: New One

try:
CODE
Char c;
 f32 x,y,z, x1, y1, z1;
 f32 p1,p2,p3;
 

 u32 playerIndex = ConvertIntToPlayerIndex(GetPlayerId());
 GetPlayerChar(playerIndex, &c);

 GetCharCoordinates(c, &x, &y, &z);
 GetCharVelocity(c, &x1, &y1, &z1);

 (p1 = x + x1 );
 (p2 = y + y1 );
 (p3 = z );


You don't need the address of a variable to use it as a left hand argument in an assignment.

(Sorry, for misunderstanding your previous post tounge.gif)

Intosia
  • Intosia

    I'm random! ^^

  • Members
  • Joined: 11 Dec 2008

#115

Posted 09 January 2009 - 01:04 PM

Im still wondering, how to teleport a player to a coord? Is it possible with a function or does it need memory editing?

aceship
  • aceship

    Just An Indonesian Scripter

  • Members
  • Joined: 20 Dec 2008

#116

Posted 09 January 2009 - 01:22 PM

thanks for the help but it cant be used when i used it like this

(p1 = x + x1*1.2);
(p2 = y + y1*1.2);
(p3 = z );


im not using this for super running

sjaak327
  • sjaak327

    Big Homie

  • Members
  • Joined: 01 Dec 2008

#117

Posted 09 January 2009 - 01:42 PM

QUOTE (Intosia @ Jan 9 2009, 13:04)
Im still wondering, how to teleport a player to a coord? Is it possible with a function or does it need memory editing?

You can easily do that with this hook.

Look at the LUA main thread (page 36 or so) where I have posted how to do it in LUA, but it's basically the same in C++ of course you need to include the native set_char_coordinates into scripting.h


aceship
  • aceship

    Just An Indonesian Scripter

  • Members
  • Joined: 20 Dec 2008

#118

Posted 09 January 2009 - 01:46 PM Edited by aceship, 12 January 2009 - 09:36 AM.

I Made SOMETHING with help from here of course.
QUOTE

Deleted, Need Some Approvement


Running Explosion!
Faster You Run , Farther Your Explosion Skill
(Reccomended to use Hand,not pistol or other weapon,Can Be A sucide one If you Don Run)

HazardX
  • HazardX

    pedestrian mangler

  • Members
  • Joined: 13 Dec 2008

#119

Posted 09 January 2009 - 01:56 PM

Hey aru, it really works! colgate.gif I've got a plugin ready now, which is able to load scripts written in any .Net language! In enumerates through all DLLs in the plugins folder, checks if the DLL is a managed assembly, loads it, enumerates through all classes, checks if the class in a subclass of the GTA.GtaScript class, loads it, and runs all those collected scripts from within the CustomThread class.

You can really use the whole power of the .Net Framework within those scripts. And since the scripts are written and compiled in Visual Studio you'll have full code highlighting, error checks and stuff. It's amazing! Now i have to clean it up and get it ready for a release (still a lot of work).

Simple Script like this one work already:
CODE
Public Class TestScript
  Inherits GTA.GtaScript

  Public Overrides Sub Startup()
  End Sub

  Public Overrides Sub Tick()
     If isKeyPressed(Windows.Forms.Keys.M) Then
        Dim PlayerIndex As Integer = ConvertIntToPlayerIndex(GetPlayerID)
        AddScore(PlayerIndex, 5000)
     End If
  End Sub

End Class


I'll make a new thread when it's ready, since i don't want to clutter your one. smile.gif Thanks ALOT aru! icon14.gif

Intosia
  • Intosia

    I'm random! ^^

  • Members
  • Joined: 11 Dec 2008

#120

Posted 09 January 2009 - 02:37 PM

QUOTE (sjaak327 @ Jan 9 2009, 13:42)
QUOTE (Intosia @ Jan 9 2009, 13:04)
Im still wondering, how to teleport a player to a coord? Is it possible with a function or does it need memory editing?

You can easily do that with this hook.

Look at the LUA main thread (page 36 or so) where I have posted how to do it in LUA, but it's basically the same in C++ of course you need to include the native set_char_coordinates into scripting.h

Thanks, found it. Must have overlooked that function lol.gif




1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users