Lambda 23 Posted October 31, 2020 Share Posted October 31, 2020 I offered it in the mapeditor thru the chaiscript implementation with a single line: Ped.PlayAmbientSpeech("FAREWELL_NO_SALE", "0078_U_M_M_BLWTRAINSTATIONWORKER_01"); But heres how you do it in c++ Spoiler struct ScriptedSpeechParams { const char* speechName; const char* voiceName; alignas(8) int v3; alignas(8) Hash speechParamHash; alignas(8) Entity entity; alignas(8) BOOL v6; alignas(8) int v7; alignas(8) int v8; }; void PlayAmbientSpeech(std::string speechline, std::string voice) { // Entity is not required.. ScriptedSpeechParams params{ speechline.c_str(), voice.c_str(), 1, 0x67F3AB43, 0, true, 1, 1 }; AUDIO::_PLAY_AMBIENT_SPEECH1(this->id, (Any*)¶ms); } 2 Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted November 1, 2020 Author Share Posted November 1, 2020 (edited) 18 hours ago, Lambda said: I offered it in the mapeditor thru the chaiscript implementation with a single line: Ped.PlayAmbientSpeech("FAREWELL_NO_SALE", "0078_U_M_M_BLWTRAINSTATIONWORKER_01"); But heres how you do it in c++ Reveal hidden contents struct ScriptedSpeechParams { const char* speechName; const char* voiceName; alignas(8) int v3; alignas(8) Hash speechParamHash; alignas(8) Entity entity; alignas(8) BOOL v6; alignas(8) int v7; alignas(8) int v8; }; void PlayAmbientSpeech(std::string speechline, std::string voice) { // Entity is not required.. ScriptedSpeechParams params{ speechline.c_str(), voice.c_str(), 1, 0x67F3AB43, 0, true, 1, 1 }; AUDIO::_PLAY_AMBIENT_SPEECH1(this->id, (Any*)¶ms); } First off, thanks for responding! Which entity plays the speech if none is passed to the function? Edit: Oh, the one which is passed to the native function? Edited November 1, 2020 by HughJanus Quote Link to comment Share on other sites More sharing options...
Lambda 23 Posted November 1, 2020 Share Posted November 1, 2020 Was problaby a bit unclear with that comment the ScriptedSpeechParams struct has an entity variable. That one is 0 in my example and that works just fine. In the native AUDIO::_PLAY_AMBIENT_SPEECH1 you pass the ped you want to be the source of the sound (where i use this->id). 1 Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted November 1, 2020 Author Share Posted November 1, 2020 @Lambda OK, so I tried it now and my code looks as follows; Helper file: struct ScriptedSpeechParams { const char* speechName; const char* voiceName; alignas(8) int v3; alignas(8) Hash speechParamHash; alignas(8) Entity entity; alignas(8) BOOL v6; alignas(8) int v7; alignas(8) int v8; }; void PlayAmbientSpeech(Ped ped, std::string speechline, std::string voice) { ScriptedSpeechParams params{ speechline.c_str(), voice.c_str(), 1, 0x67F3AB43, 0, true, 1, 1 }; AUDIO::x_PLAY_AMBIENT_SPEECH1(ped, (Any*)¶ms); } bool PedFearTest(Ped ped) { PlayAmbientSpeech(ped, "FAREWELL_NO_SALE", "0078_U_M_M_BLWTRAINSTATIONWORKER_01"); } Adapted native function wrapper: static BOOL _PLAY_AMBIENT_SPEECH1(Ped ped, char* speechName) { return invoke<BOOL>(0x8E04FEDD28D42462, ped, speechName); } static BOOL x_PLAY_AMBIENT_SPEECH1(Ped ped, Any* p1) { return invoke<BOOL>(0x8E04FEDD28D42462, ped, p1); } Main method (the relevant parts): int yolo = 0; while (true) { const int ARR_SIZE = 1024; Ped peds[ARR_SIZE]; int count = worldGetAllPeds(peds, ARR_SIZE); for (int i = 0; i < count; i++) { if (yolo < GAMEPLAY::GET_GAME_TIMER() && peds[i] != PLAYER::PLAYER_PED_ID()) { PedFearTest(peds[i]); yolo = GAMEPLAY::GET_GAME_TIMER() + 7000; } } } So what it should do is make the NPCs say the speech line every 7 seconds, but unfortunately it isnt working. Does the line only work for the ped model belonging to the voice? I tried setting the voice to 0, but that crashes script hook. Quote Link to comment Share on other sites More sharing options...
Lambda 23 Posted November 1, 2020 Share Posted November 1, 2020 (edited) There are several big warning signs here. Why do you call PedFearTest to only call another function? Not to mention it's return type is bool and you return nothing. And it should be quite obvious that you cant set the voice to be 0 when it expects a string representing a voice. Looking a bit closer i would not recommend you going thru the entire ped pool each frame to check the timer it's a massive waste of cpu time. Edited November 1, 2020 by Lambda 1 Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted November 2, 2020 Author Share Posted November 2, 2020 (edited) @Lambda I didnt have much time yesterday, so I just quickly adjusted the helper file and didnt fiddle with the main script at all (and apparently overlooked that I forgot to change the bool to void. The main script I posted here, was not copied and pasted, but I typed the stuff in here. The timer checkings are done before the ped loop, I dont know why I typed it that way yesterday, I just wanted to demonstrate what I do with your code. I will try to optimize the thing on the weekend and get back with the results. Please keep in mind, that I am a noob and do not code professionally. Thanks for responding so quickly! Edit: Is there a way to make NPCs speak each with their own voice (so a generic value for the voice parameter)? Edited November 2, 2020 by HughJanus Quote Link to comment Share on other sites More sharing options...
Lambda 23 Posted November 2, 2020 Share Posted November 2, 2020 (edited) 12 hours ago, HughJanus said: Edit: Is there a way to make NPCs speak each with their own voice (so a generic value for the voice parameter)? Not that i know of, you can set the ambient voice name for peds so it's likely that there is an for now unkown native to get the voice from a ped. Edited November 2, 2020 by Lambda 1 Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted November 7, 2020 Author Share Posted November 7, 2020 (edited) On 11/2/2020 at 7:41 PM, Lambda said: Not that i know of, you can set the ambient voice name for peds so it's likely that there is an for now unkown native to get the voice from a ped. OK, so I tested it (didnt have much time, though) and I think it works. I used the voice and the line you gave me and tried it in Blackwater with the 7 seconds delay. Only very few NPCs spoke the line (I suppose those who have this voice). Thanks for clearing things up! Unfortunately, this non-generic version does not help me. Maybe I can find some workaround, since it seems the voices have similar names to the NPC models? Edit: @Lambda LMS wrote a few posts back, that they implemented a method in the RagePluginHook where they dont pass a voice name and the native still works (with the respective voice of the ped passed to the function). Do you know how this could work in C++? Edit 2: Soooo, I tried a few things and this seems to work struct ScriptedSpeechParams { const char* speechName; const Any* voiceName; alignas(8) int v3; alignas(8) Hash speechParamHash; alignas(8) Entity entity; alignas(8) BOOL v6; alignas(8) int v7; alignas(8) int v8; }; void PedFearTest(Ped ped) { string speechline = "LAW_HAIL"; ScriptedSpeechParams params{ speechline.c_str(), 0, 1, 0x67F3AB43, 0, true, 1, 1 }; AUDIO::x_PLAY_AMBIENT_SPEECH1(ped, (Any*)¶ms); } I picked the line "LAW_HAIL" because a lot of NPCs seem to have it and also there are two versions of it (LAW_HAIL_01, LAW_HAIL_02). What's curious is, that only very few NPCs actually play that line (although I try to trigger it for each NPC) and they seem to repeat the same line over and over, so no switching between the two versions. If I use "LAW_HAIL_01" or the other one, nothing happens. I will try a bit more in the coming weeks and see if can get every NPC to speak. If you have more wisdom to drop on me, please do so. Thanks for all the help until now, guys! Edit 3: Had a faulty code part in my loop. Now everything works as intended (except for the thing where NPCs only speak one version of the line over and over again - so still no way to trigger LAW_HAIL_02). Thank you 🙂 Edited November 15, 2020 by HughJanus Quote Link to comment Share on other sites More sharing options...
MrEuphrates 1 Posted December 1, 2020 Share Posted December 1, 2020 Hi, I know this topic is solved but is there anyway I can use this in lua. Because lua version of PLAY_AMBIENT_SPEECH1 only accepts ped as param. Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted December 1, 2020 Author Share Posted December 1, 2020 7 hours ago, MrEuphrates said: Hi, I know this topic is solved but is there anyway I can use this in lua. Because lua version of PLAY_AMBIENT_SPEECH1 only accepts ped as param. Cant you change the native wrapper so the method is invoked with the type you specify? Quote Link to comment Share on other sites More sharing options...
MrEuphrates 1 Posted December 1, 2020 Share Posted December 1, 2020 2 hours ago, HughJanus said: Cant you change the native wrapper so the method is invoked with the type you specify? Since all of my resources are in lua I would like to do this in lua too. If there is no other way I can change it to c++. If you can think of any other way to do it in lua please tell. Thanks. Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted December 2, 2020 Author Share Posted December 2, 2020 8 hours ago, MrEuphrates said: Since all of my resources are in lua I would like to do this in lua too. If there is no other way I can change it to c++. If you can think of any other way to do it in lua please tell. Thanks. I was talking about lua. How do you call natives? You have a library of wrapper functions, I suppose? Is this library edit-able / can you edit the wrappers? Quote Link to comment Share on other sites More sharing options...
MrEuphrates 1 Posted December 2, 2020 Share Posted December 2, 2020 2 hours ago, HughJanus said: I was talking about lua. How do you call natives? You have a library of wrapper functions, I suppose? Is this library edit-able / can you edit the wrappers? Oh, I see... I am creating a resource in redm and I don't know if I can do that. Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted December 2, 2020 Author Share Posted December 2, 2020 51 minutes ago, MrEuphrates said: Oh, I see... I am creating a resource in redm and I don't know if I can do that. I dont know redm. What are the files that come with it? Is there a file including the native functions you are able to use? I would suggest searching there, if there is one. With ABs script hook there comes a file with natives, for example. This is the one I edit to make natives work with other types (like described in this thread). Quote Link to comment Share on other sites More sharing options...
MrEuphrates 1 Posted December 2, 2020 Share Posted December 2, 2020 3 hours ago, HughJanus said: I dont know redm. What are the files that come with it? Is there a file including the native functions you are able to use? I would suggest searching there, if there is one. With ABs script hook there comes a file with natives, for example. This is the one I edit to make natives work with other types (like described in this thread). There is this line in Natives local retval --[[ boolean ]], params --[[ Any ]] = PlayPedAmbientSpeechNative( ped --[[ Ped ]] ) And this as a description struct ScriptedSpeechParams { const char* speechName; const char* voiceName; alignas(8) int v3; alignas(8) Hash speechParamHash; alignas(8) Entity entity; alignas(8) BOOL v6; alignas(8) int v7; alignas(8) int v8; }; static_assert(sizeof(ScriptedSpeechParams) == 0x40, "incorrect ScriptedSpeechParams size"); Example: ScriptedSpeechParams params{"RE_PH_RHD_V3_AGGRO", "0405_U_M_M_RhdSheriff_01", 1, 0x67F3AB43, 0, true, 1, 1}; _PLAY_AMBIENT_SPEECH1(PLAYER_PED_ID(), (Any*)¶ms); When I found the code in the description here I thought there was a way to do it in lua for RedM but I guess not. I cannot give params to this function no matter what I do. I think this function just doesn't work in RedM. Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted December 3, 2020 Author Share Posted December 3, 2020 14 hours ago, MrEuphrates said: There is this line in Natives local retval --[[ boolean ]], params --[[ Any ]] = PlayPedAmbientSpeechNative( ped --[[ Ped ]] ) And this as a description struct ScriptedSpeechParams { const char* speechName; const char* voiceName; alignas(8) int v3; alignas(8) Hash speechParamHash; alignas(8) Entity entity; alignas(8) BOOL v6; alignas(8) int v7; alignas(8) int v8; }; static_assert(sizeof(ScriptedSpeechParams) == 0x40, "incorrect ScriptedSpeechParams size"); Example: ScriptedSpeechParams params{"RE_PH_RHD_V3_AGGRO", "0405_U_M_M_RhdSheriff_01", 1, 0x67F3AB43, 0, true, 1, 1}; _PLAY_AMBIENT_SPEECH1(PLAYER_PED_ID(), (Any*)¶ms); When I found the code in the description here I thought there was a way to do it in lua for RedM but I guess not. I cannot give params to this function no matter what I do. I think this function just doesn't work in RedM. How do you use natives in lua? Could you please post an example. For me the description doesnt match the code above, because the code above seems to describe a wrapper named "PlayPedAmbientSpeechNative" while the example uses a wrapper called "_PLAY_AMBIENT_SPEECH1". Quote Link to comment Share on other sites More sharing options...
MrEuphrates 1 Posted December 3, 2020 Share Posted December 3, 2020 (edited) 3 hours ago, HughJanus said: How do you use natives in lua? Could you please post an example. For me the description doesnt match the code above, because the code above seems to describe a wrapper named "PlayPedAmbientSpeechNative" while the example uses a wrapper called "_PLAY_AMBIENT_SPEECH1". This function PlayPedAmbientSpeechNative() Used to be called. PlayAmbientSpeech1() (They recently changed the name of the function.) And it basically invokes the native _PLAY_AMBIENT_SPEECH1. Here is a link to the native document: https://vespura.com/doc/natives/?_0x8E04FEDD28D42462 The problem is even though it's in the natives document I cannot pass any parameters into it. I see that you have to give it a struct that holds the parameters in c++ but you can't do that in lua. And here is a code example that spawn peds at pre-defined positions: Citizen.CreateThread(function() clerkHash = GetHashKey(store.ClerkModel) pos = Config.Stores[1].pos heading = Config.Stores[1].hdg if IsModelInCdimage(clerkHash) and IsModelValid(clerkHash) then RequestModel(clerkHash) while not HasModelLoaded(clerkHash) do RequestModel(clerkHash) Wait(0) end clerk = CreatePed(clerkHash, pos.x, pos.y, pos.z, hdg, 1, 1, 0, 0) SetModelAsNoLongerNeeded(clerkHash) Citizen.InvokeNative(0x283978a15512b2fe, clerk, true) -- You can invoke natives like this too end end) Edited December 3, 2020 by MrEuphrates Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted December 3, 2020 Author Share Posted December 3, 2020 @MrEuphrates OK, so I took a look at the document you linked. The definition of the native doesnt make sense to me. Heres what I mean: loading stream in C (return type is "bool", function name is "LOAD_STREAM", parameters are two char*): BOOL LOAD_STREAM(char* streamName, char* soundSet); loading stream in lua (return type is "bool", function name is "LoadStream", parameters are two strings): local retval --[[ boolean ]] = LoadStream( streamName --[[ string ]], soundSet --[[ string ]] ) ambient speech in C (return type is "bool", function name is "PLAY_PED_AMBIENT_SPEECH_NATIVE", parameters are Ped and Any*): BOOL PLAY_PED_AMBIENT_SPEECH_NATIVE(Ped ped, Any* params); ambient speech in lua (return type is "bool", function name is "PlayPedAmbientSpeechNative", parameters are ??): local retval --[[ boolean ]], params --[[ Any ]] = PlayPedAmbientSpeechNative( ped --[[ Ped ]] ) I dont even know how to interpret the definition. Quote Link to comment Share on other sites More sharing options...
MrEuphrates 1 Posted December 3, 2020 Share Posted December 3, 2020 (edited) 52 minutes ago, HughJanus said: @MrEuphrates OK, so I took a look at the document you linked. The definition of the native doesnt make sense to me. Heres what I mean: loading stream in C (return type is "bool", function name is "LOAD_STREAM", parameters are two char*): BOOL LOAD_STREAM(char* streamName, char* soundSet); loading stream in lua (return type is "bool", function name is "LoadStream", parameters are two strings): local retval --[[ boolean ]] = LoadStream( streamName --[[ string ]], soundSet --[[ string ]] ) ambient speech in C (return type is "bool", function name is "PLAY_PED_AMBIENT_SPEECH_NATIVE", parameters are Ped and Any*): BOOL PLAY_PED_AMBIENT_SPEECH_NATIVE(Ped ped, Any* params); ambient speech in lua (return type is "bool", function name is "PlayPedAmbientSpeechNative", parameters are ??): local retval --[[ boolean ]], params --[[ Any ]] = PlayPedAmbientSpeechNative( ped --[[ Ped ]] ) I dont even know how to interpret the definition. Exactly! It doesn't make any sense. and it's not only lua I thought I could write it in c# but it doesn't work either. They put your c++ solution in description but it can't be achieved with what they gave. In both lua and c# params is a returned value by the native. Edited December 3, 2020 by MrEuphrates Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted December 3, 2020 Author Share Posted December 3, 2020 55 minutes ago, MrEuphrates said: Exactly! It doesn't make any sense. and it's not only lua I thought I could write it in c# but it doesn't work either. They put your c++ solution in description but it can't be achieved with what they gave. In both lua and c# params is a returned value by the native. Is there an option in lua to invoke the native directly? Like in c++ it would be invoke<BOOL>(0x8E04FEDD28D42462, ped, params); Quote Link to comment Share on other sites More sharing options...
MrEuphrates 1 Posted December 3, 2020 Share Posted December 3, 2020 1 hour ago, HughJanus said: Is there an option in lua to invoke the native directly? Like in c++ it would be invoke<BOOL>(0x8E04FEDD28D42462, ped, params); Yes you can use this line I had in my example Citizen.InvokeNative(0x283978a15512b2fe, clerk, true) -- You can invoke natives like this too Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted December 3, 2020 Author Share Posted December 3, 2020 12 minutes ago, MrEuphrates said: Yes you can use this line I had in my example Citizen.InvokeNative(0x283978a15512b2fe, clerk, true) -- You can invoke natives like this too Why dont you try it that way? Pass the ped instead of the clerk and pass the struct instead of the bool (and use the hash of the speech native). Quote Link to comment Share on other sites More sharing options...
MrEuphrates 1 Posted December 3, 2020 Share Posted December 3, 2020 17 minutes ago, HughJanus said: Why dont you try it that way? Pass the ped instead of the clerk and pass the struct instead of the bool (and use the hash of the speech native). Ok so I tried this params = {} params.speechName = "FAREWELL" params.voiceName = "0479_U_M_M_VALGUNSMITH_01" params.v3 = 1 params.speechParamHash = 0x67F3AB43 params.entity = 0 params.v6 = true params.v7 = 1 params.v8 = 1 Citizen.InvokeNative(0x8E04FEDD28D42462, cl, params) and got this error SCRIPT ERROR: Invalid Lua type in __data Pointing to the line where I Invoked the native. Quote Link to comment Share on other sites More sharing options...
HughJanus 244 Posted December 3, 2020 Author Share Posted December 3, 2020 1 minute ago, MrEuphrates said: Ok so I tried this params = {} params.speechName = "FAREWELL" params.voiceName = "0479_U_M_M_VALGUNSMITH_01" params.v3 = 1 params.speechParamHash = 0x67F3AB43 params.entity = 0 params.v6 = true params.v7 = 1 params.v8 = 1 Citizen.InvokeNative(0x8E04FEDD28D42462, cl, params) and got this error SCRIPT ERROR: Invalid Lua type in __data Pointing to the line where I Invoked the native. I dont know which types are supported by lua, but only these worked for me in C++ struct ScriptedSpeechParams { const char* speechName; const Any* voiceName; alignas(8) int v3; alignas(8) Hash speechParamHash; alignas(8) Entity entity; alignas(8) BOOL v6; alignas(8) int v7; alignas(8) int v8; }; void PedFearTest(Ped ped) { string speechline = "LAW_HAIL"; ScriptedSpeechParams params{ speechline.c_str(), 0, 1, 0x67F3AB43, 0, true, 1, 1 }; AUDIO::x_PLAY_AMBIENT_SPEECH1(ped, (Any*)¶ms); } Quote Link to comment Share on other sites More sharing options...
MrEuphrates 1 Posted December 3, 2020 Share Posted December 3, 2020 3 hours ago, HughJanus said: I dont know which types are supported by lua, but only these worked for me in C++ struct ScriptedSpeechParams { const char* speechName; const Any* voiceName; alignas(8) int v3; alignas(8) Hash speechParamHash; alignas(8) Entity entity; alignas(8) BOOL v6; alignas(8) int v7; alignas(8) int v8; }; void PedFearTest(Ped ped) { string speechline = "LAW_HAIL"; ScriptedSpeechParams params{ speechline.c_str(), 0, 1, 0x67F3AB43, 0, true, 1, 1 }; AUDIO::x_PLAY_AMBIENT_SPEECH1(ped, (Any*)¶ms); } Ok thank you for your help I will try other things and if I find a solution I will share it here. 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.