ceedj Posted August 31, 2009 Share Posted August 31, 2009 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! 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 More sharing options...
Intosia Posted August 31, 2009 Share Posted August 31, 2009 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 More sharing options...
ceedj Posted August 31, 2009 Author Share Posted August 31, 2009 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 More sharing options...
ech3lon Posted August 31, 2009 Share Posted August 31, 2009 (edited) 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 August 31, 2009 by ech3lon Link to comment Share on other sites More sharing options...
Intosia Posted August 31, 2009 Share Posted August 31, 2009 (edited) 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 Edited August 31, 2009 by Intosia Link to comment Share on other sites More sharing options...
ceedj Posted August 31, 2009 Author Share Posted August 31, 2009 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! 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 More sharing options...
Intosia Posted August 31, 2009 Share Posted August 31, 2009 Hmm, indeed not the most elegant method, I really suggest looking at the DirectHook Ps. why not use the .net hook? Link to comment Share on other sites More sharing options...
ceedj Posted August 31, 2009 Author Share Posted August 31, 2009 Hmm, indeed not the most elegant method, I really suggest looking at the DirectHook Ps. why not use the .net hook? 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 More sharing options...
aru Posted September 2, 2009 Share Posted September 2, 2009 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 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 I'm sure there's more. Link to comment Share on other sites More sharing options...
Intosia Posted September 2, 2009 Share Posted September 2, 2009 Like aways Aru. Nice clean code, have a cookie Link to comment Share on other sites More sharing options...
ceedj Posted September 2, 2009 Author Share Posted September 2, 2009 (edited) 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. 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. Edited September 2, 2009 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 More sharing options...
Intosia Posted September 3, 2009 Share Posted September 3, 2009 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 More sharing options...
ceedj Posted September 3, 2009 Author Share Posted September 3, 2009 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 More sharing options...
sjaak327 Posted September 3, 2009 Share Posted September 3, 2009 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 More sharing options...
ceedj Posted September 3, 2009 Author Share Posted September 3, 2009 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. 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 More sharing options...
sjaak327 Posted September 3, 2009 Share Posted September 3, 2009 (edited) Sorry, missed the fiber thread part 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 September 3, 2009 by sjaak327 Link to comment Share on other sites More sharing options...
ceedj Posted September 7, 2009 Author Share Posted September 7, 2009 (edited) 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. Edited September 7, 2009 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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now