Jump to content
    1. Welcome to GTAForums!

    1. GTANet.com

    1. GTA Online

      1. The Criminal Enterprises
      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. Support

    3. Suggestions

*DO NOT* SHARE MEDIA OR LINKS TO LEAKED COPYRIGHTED MATERIAL. Discussion is allowed.

{Q}C++ hook and DrawText


ceedj
 Share

Recommended Posts

Didn't want to spam aru's topic with this.

 

I'm using a custom fiber thread for my code. I'd LIKE to use the DRAW_TEXT native (the "old" text_draw from the III era games) to display some status messages. I did some searching and found that the text displays for one frame. Here's my code:

 

 

void IVTextDraw(f32 x, f32 y, char CustomString[]){	SetTextScale(0.40f,0.30f);DisplayTextWithLiteralString(x, y, "STRING", CustomString);Wait(0);}///I call with this (example)               switch (Switch){ 	case 1: 	Wait(50); 	IVTextDraw(0.925f, 0.960f, gxtList38); 	goto FreezeClock; 	case 2: 	Wait(50); 	IVTextDraw(0.925f, 0.960f, gxtList39); 	Switch = 0;

 

 

I've tried a couple of methods to get it to "stay" on screen; a while loop works great, except it chokes the rest of the thread. I also did a simple variable (if Blah == this) {display text), but that's more of a timed thing. I COULD shove it all into its own thread, but that seems like a lot of unnecessary code. Anyone have any ideas on how I can best use this to display text so that it stays on until I want it to go away?

 

Thanks! smile.gif

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

I dont see the problem? Just call it on the bottom of your script every 'tick' (loop). And remove the wait...

Link to comment
Share on other sites

The problem is there is a BUNCH of text codes I need to display depending on what happens; this was just a simple example. I'd like to display different text after creation (Ped 1 Created!, Ped 2 Created, Car 1 Created, Weather set to Sunny!, Done!, etc). I think I have around 50 or so different custom text messages. Your solution would provide a "blinking" text, which will work, but not what I'm looking for. I have a LOT of keys to listen for.

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

I'm not sure if this is the right way to do it with the c++ hook...

But what you need is basically a Method that gets called every single frame and does your drawing. I think Aru's c++ hook is able to hook D3D, so you will probably need to use that, in order to draw every frame. I'd define a handler that will notify all subscribed drawing functions of other objects every single frame. Those functions will then do their drawing. Within those concrete drawing functions you could then use some bools and a timer to control the exact duration that each function draws their stuff. But make sure you set the bool that decides whether to draw or not inside a Tick method and not inside the function that does the drawing. This function should only check whether it should draw or not and then based on the result of that do it's drawing or return. I think that's basically the way it's done in .NET hook, however thanks to delegates and events it's much easier to develop for it. ;)

You might want to take a look at the Observer pattern if you choose this approach ( http://www.go4expert.com/forums/showthread...t=5127#observer ).

 

Sorry that I can't be more precise about this. I don't (directly ;) use the C++ Hook very much.

Edited by ech3lon
Link to comment
Share on other sites

Yes, Ech3lon is right. I know understand now what you mean. Basicly you need to make a function whats get called eery frame that does the rendering (and takes the string), then check every call with a timer if 3sec's have past. If not passed > draw, else reset timer, and dont draw anything.

 

The .NET Hooks 'PerFrameDrawing' does basicly the same thing. Except its a event.

 

Sry if i told the say as ech3lon but thoughed id would explane to. (felt like typing biggrin.gif

Edited by Intosia
Link to comment
Share on other sites

No, it's cool guys, I appreciate the ideas. I managed to do something similar; basically created its own thread for the text, and used a switch statement to run through the possible text entries; this is all contained in a FOR loop, so it runs all the time. Then I use GXTShow = gxt entry in my main code. I did a blank entry as " ", so it looks like:

 

GXTShow = 0;

GXTShow = 8;

 

which clears the old text for me (like the old text_draw_toggle from San An) so I can put the new one up. The FOR loop is controlled by it's own variable (TextOn) so I can shut the whole thing down if I want; I do something very similar with my clock freeze routine.

 

Not the most elegant solution, but it works, and only blinks once in a while. I think I can live with this.

 

Thanks again for the help and ideas fellas! smile.gif

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

Hmm, indeed not the most elegant method, I really suggest looking at the DirectHook orly.gifturn.gif

 

Ps. why not use the .net hook? ph34r.gif

Link to comment
Share on other sites

Hmm, indeed not the most elegant method, I really suggest looking at the DirectHook orly.gifturn.gif

 

Ps. why not use the .net hook? ph34r.gif

I just looked at the speedo example, and, um, no. That's a whole new language for me that I'm really not interested in learning right now.

 

Why not .NET? Don't know it. I know some C/C++, so that's what I use. My SanAnStudios mod was build on a C++ hook, so most of that (including a fairly massive save/load routine) is just being ported over to IV, changing the opcodes to natives and such.

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

Lets see.. your requirements are to show some text and you want to show it for some time. Presumably, you want to show more than one message? Why not just keep the stuff you want to draw in a list and display it for a specified period of time? I'm bored so I'm going to write some code for you off the top of my head, so I apologize in advance if it doesn't directly compile tounge.gif

 

So lets go about this logical way... first define a struct to hold the data you would like to be shown:

 

 

struct TextDrawInfo{  f32 x;  f32 y;  std::string text;  time_t endTime;};

 

 

Then write some global code to keep a list of TextDrawInfos in memory...

 

 

typedef std::list<TextDrawInfo> TextDrawInfoList;TextDrawInfoList g_TextDrawInfos;

 

 

Then a function to add text draws...

 

 

void AddTextDraw(f32 x, f32 y, const ch *text, u32 displayTimeInSeconds){  TextDrawInfo info;  info.x = x; info.y = y;  info.text = std::string(text);  info.endTime = time(NULL) + displayTimeInSeconds;  g_TextDrawInfos.push_back(info);}

 

 

Now in your standard CustomFiberThread loop...you'll want to display the stuff:

 

 

TextDrawInfoList::iterator it;// Draw itfor(it = g_TextDrawInfos.begin(); it != g_TextDrawInfos.end(); it++){  TextDrawInfo info = *it;  SetTextScale(0.40f,0.30f);  DisplayTextWithLiteralString(info.x, info.y, "STRING", info.text.c_str());}// Clean up any that we don't want showing anymoreit = g_TextDrawInfos.begin();while(it != g_TextDrawInfos.end()){  if (time(NULL) > info.endTime)  {     g_TextDrawInfos.erase(it);     it = g_TextDrawInfos.begin();  }  else  {     it++;  }}

 

 

To use it.. you just have to call AddTextDraw anywhere in the code.

 

And you'll probably need the following includes to get this to work:

 

 

#include <string>#include <list>#include <time.h>

 

 

Well, thats just one clean way to go about doing it smile.gif I'm sure there's more.

Link to comment
Share on other sites

Ok, let me show you what I'm doing now (BETA of the mod is here: http://www.gtaforums.com/index.php?showtopic=424007):

 

First, my function, related to the native:

 

 

void IVTextDraw(f32 x, f32 y, char CustomString[]){	SetTextScale(0.40f,0.30f);DisplayTextWithLiteralString(x, y, "STRING", CustomString);Wait(0);}

 

 

Next, the bits scattered throughout the code that are running:

 

 

CreateChar(Ped1T, modelHash, x,y,z, &Ped1, true);SetRoomForCharByKey(Ped1, roomKey);TaskTurnCharToFaceChar(Ped1, PlayerPed);MarkModelAsNoLongerNeeded(modelHash);SetCharHealth(Ped1, Ped1H);if (APed1WID != 0 && APed1 == 1){GiveWeapon(Ped1, APed1WID, 9999, 1);}GXTShow = 0;GXTShow = 8;BrowseOn = 0;

 

 

This is a tiny snippet and just one example of how I'm using it, but the GXTShow is an int (entry 0 in gtx.h is simply char gxtList0[] = " ";, which I use to blank the previous text for the next one to show) that I switch, into its own thread, here:

 

 

void TextDrawThread::RunScript(){while(IsThreadAlive()){ for(; { while(TextOn != 1) Wait(100); Wait(0); switch(GXTShow){ 	case 0:   IVTextDraw(0.025f, 0.960f, gxtList0);   break; 	case 8:   IVTextDraw(0.025f, 0.960f, gxtList8);   break; 	case 9:   IVTextDraw(0.025f, 0.960f, gxtList9);   break; 	case 10:   IVTextDraw(0.025f, 0.960f, gxtList10);   break; 	case 11:   IVTextDraw(0.025f, 0.960f, gxtList11);   break;<snip>case 130:   IVTextDraw(0.025f, 0.960f, gxtList130);   break; 	case 131:   IVTextDraw(0.025f, 0.960f, gxtList131);   break; } switch(GXTLook){ 	case 0:   IVTextDraw(0.925f, 0.960f, gxtList0);   break; 	case 1:   IVTextDraw(0.925f, 0.960f, gxtList38);   break; 	case 2:   IVTextDraw(0.925f, 0.960f, gxtList39);   break; } }}}

 

 

(GXTLook is something I want to run ALL the time; the keys are shared - LOOK tells the user that PED MODIFIER + PED NUMBER will make the ped turn its head to look at the other ped, while KILL will tell that same key combination to attack the ped.)

 

The gxtList is included in an...include file, gtx.h, a holdover from San An Studios 4, and in fact has roots all the way back to Vice Studios 1:

 

 

char gxtList7[] = "To disable the IV Text Helper, press ~y~DELETE + T~w~. Have Fun!";char gxtList8[] = "Ped 1 Created!";char gxtList9[] = "Ped 2 Created!";char gxtList10[] = "Ped 3 Created!";char gxtList11[] = "Ped 4 Created!";char gxtList12[] = "Ped 5 Created!";char gxtList13[] = "Ped 6 Created!";char gxtList14[] = "Ped 7 Created!";

 

 

So, the whole shebang is controlled by this:

 

 

ShowTextOn: if (KEYDOWN(VK_INSERT) && KEYDOWN(VK_T)) //INSERT + T {TextOn = 1; GXTShow = 0; GXTShow = 21; } else { 	goto ShowTextOff;}ShowTextOff: if (KEYDOWN(VK_DELETE) && KEYDOWN(VK_T)) //DELETE + T {GXTShow = 0; GXTShow = 22; Wait(5000); TextOn = 0; goto FreezeClock; } else { 	goto FreezeClock;}

 

 

The reason I posted all this is because it seems to work pretty well, and does fairly close to what the San Andreas TextDraw opcode did - show it on screen all the time until I decide to turn it off or change what is shown. What you posted my be great, but the trouble is that I don't really understand HOW it works, because back at the beginning (again, Vice Studios), I just wanted a fast way to film, so I hacked my way through some C++ to get it to work. That, and it's too big and slow to work in a standard main.scm, stripped or not. As you can see, I've got about 130ish different text messages now (and about two dozen more or so to add).

 

GTA code I know pretty well I think. Other languages I have to bend to my will to get them to work. I don't think what I've done is necessarily GOOD, but it's not terrible either, since it does what I want it to. If you think your code will be faster than what I'm doing now, I'm all ears, but I think I'd need it explained a bit better so I can understand it.

 

Love the discussion here, thanks for the tips and suggestions. smile.gif

 

EDIT: Oh yeah...

 

Why not just keep the stuff you want to draw in a list and display it for a specified period of time?

 

I can do that with PrintStringWithLiteralStringNow. But it's not really what I want, since I'd like the placement (x and y, as you described) and since I want it to display infinitely, or until I (or the user) shut it off. wink.gif

Edited by ceedj

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

Hm i understand why you would want to port over the old code as much as possible ( the same way). But its inevitable that you need to change code. In this case how the text is show.

 

Aru's method is pretty easy. All it does it is: everytime you call AddTextDraw(), the text is stored in a struct (it just groups vars togethers), then it stores the struct in a List (vector, dynamic array). Then on the bottom of your loop there is a function thatloops though the List showing all the text, incrementing the Y, so the text is shown below each other. Then it check if the the text is on screen for X seconds, if so, it removed it from the list.

 

No offence, but if you cant read that code, why are you using C++? I know C++ (not a pro), but i use the .net hook just because its OO heaven ^^

Link to comment
Share on other sites

Why is it "inevitable" that I change code? Have you noticed that R* has been using the same code for 8 years?

 

Perhaps it's the language barrier, but I don't think you read all of my post. I used C++ in the first hook in 2005 because it was WAY faster than SCM code. And the only thing available at the time. And again, I DON'T WANT THE TEXT TO BE TIMED. I WANT IT ON SCREEN ALL THE TIME.

 

I can "read" the code just fine. I don't UNDERSTAND why certain things are done, except that the for loop seems like it might be faster than a switch statement. This I might look into more.

 

 

Then on the bottom of your loop there is a function thatloops though the List showing all the text, incrementing the Y, so the text is shown below each other.

 

If what you're saying here is true, then I definitely don't want that either, as I want the text to show in the same position, just replacing it when something else happens.

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

Maybe I am missing something here (like all of it:) )

 

Why don't you simply use the display text natives, they come with positioning possibilities (and font color and other properties) and use bools to control their display ?

 

 

Link to comment
Share on other sites

 

Maybe I am missing something here (like all of it:) )

 

Why don't you simply use the display text natives, they come with positioning possibilities (and font color and other properties) and use bools to control their display ?

Yeah, um, you totally missed it. ALL of it. lol.gif

 

That's essentially what I AM doing. The problem is that because I'm using the fiber thread, the text only displays for one frame. So I slugged it into its own thread to compensate for that. What you're suggesting with the bools is exactly how it's set up for San An Studios 4.

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

Link to comment
Share on other sites

Sorry, missed the fiber thread part smile.gif

 

Luckily I personally don't use it. That approach works absolutely fine on the normal custom thread. Having said that, I am not sure why it wouldn't work in fiber as well.

 

 

Edited by sjaak327
Link to comment
Share on other sites

Ok, came up with a bit simpler solution...

 

 

void TextOffLeft(){SetTextScale(0.40f,0.30f);DisplayTextWithLiteralString(0.025f, 0.960f, "STRING", gxtList0);return;}void TextOffRight(){SetTextScale(0.40f,0.30f);DisplayTextWithLiteralString(0.925f, 0.960f, "STRING", gxtList0);return;}void TextLookKill(){SetTextScale(0.40f,0.30f);if (LookText == 1){DisplayTextWithLiteralString(0.925f, 0.960f, "STRING", gxtList38);return;} //KillDisplayTextWithLiteralString(0.925f, 0.960f, "STRING", gxtList39);return;//Look}void IVTextDrawLeft(char CustomString[]){	SetTextScale(0.40f,0.30f);DisplayTextWithLiteralString(0.025f, 0.960f, "STRING", CustomString);return;}

 

 

Then in the TextThread...

 

 

for(; { while(TextOn != 1) Wait(100); Wait(0); IVTextDrawLeft(TempText); TextLookKill(); }

 

 

Then wherever I need my text...

 

 

TextOffLeft();TempText = gxtList52;

 

(I use the TextOffRight to clear the text for the LOOK/KILL text in the other corner.)

 

Much cleaner, and uses my existing text entries. Win/win, me thinks.

 

BIG thanks to Intosia, for (rightfully so) telling me my code stunk. Hey, motivation works I guess. lol.gif

Edited by ceedj

I'm actually not against democracy though. I'm against things I think are f*cking stupid. I think this is f*cking stupid. - Sweets

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

  • 1 User Currently Viewing
    0 members, 0 Anonymous, 1 Guest

×
×
  • Create New...

Important Information

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