grumpypoo 3 Posted November 29, 2021 Share Posted November 29, 2021 (edited) Currently working on a mod. I'm a little lost and hope someone can point me in the right direction.. (C++) Is there a native function that checks whenever the player is eating/drinking? I've checked the scenarios (for drinking) to see if it'll return for me, but no luck. I've thought about checking the animation, but before I dig deep into that figured i'd ask first. Any help is much appreciated. ------------------------------------------------------------------------------------------------------------------------------------------ Here is the solution - Alright i've figured this out - Here is the code i'm using to check if someone drinks anything int tAnimationSet = 0; static int getGameTime() { return invoke<int>(0x4F67E8ECA7D3F667); } bool refillThirstCoreScenario() { const char* animations[] = { "face_human@gen_male@scenario@drinkbottle", "face_human@gen_male@scenario@drinkshot", "face_human@gen_male@scenario@drinkmug", "face_human@gen_male@scenario@drinkhand" }; for (const char* animation : animations) { if (STREAMING::HAS_ANIM_DICT_LOADED(animation)) { return true; tAnimationSet = getGameTime(); break; } } return false; } void update() { // Core refilling actions if (TASK::GET_IS_TASK_ACTIVE(PLAYER::PLAYER_PED_ID(), 471)) { // Thirst if (refillThirstCoreScenario()) { if (getGameTime() - tAnimationSet > 5000) { PrintSubtitle("You drank!"); } } } } This is a reliable way to check if someone has drank a liquid. For eating you can check the eating animation like I did with drinking. Feel free to copy/paste this code - If you do use it, give yourself a high five in my honor. Edited December 3, 2021 by grumpypoo Quote Link to comment Share on other sites More sharing options...
crossed99 43 Posted December 1, 2021 Share Posted December 1, 2021 I don't think there's a native for that. There's a scenario for pouring coffee at camp, probably one for taking stew, too, or you can check if you have a coffee mug or plate in your hand, but I doubt you can detect just normally eating something from your inventory that way. Checking your core values might be another way, when they're being refilled and the player is not sleeping then probably eating or drinking... I don't know if it's possible to do it reliably. Let me know if you find a way, I'd be interested, too 😄 Quote Link to comment Share on other sites More sharing options...
grumpypoo 3 Posted December 1, 2021 Author Share Posted December 1, 2021 (edited) Well I have discovered something yesterday - Whenever the cores get refilled it uses TASK 471. I haven't tested this against sleep, but eating/drinking from your provisions work. So I figured that would be my first check - Then I moved on to just seeing if an object was in the players hand (This went terribly) So I went through OpenIV looking for elixir because that's one of the drinks I have. I ended up finding the prop in levels_3\rdr3\props\lev_des\s_pickups.rpf I realized these were all the props that you use for provisions + other stuff. I got the bright idea to test IS_ENTITY_TOUCHING_MODEL(entity, hash) entity = PLAYER_PED_ID() hash = GET_HASH_KEY("s_ginsengelixir01x") Whenever I drank the elixir nothing happened, but once he dropped the bottle and the players foot touched it - The function actually returned true? So now i'm back to being confused, but I have a few more things I want to try. bool refillThirstCoreScenario() { const char* objs[] = { "s_brandy01x", "s_brandy_used01x", "s_ginsengelixir01x" }; for (const char* obj : objs) { if (ENTITY::IS_ENTITY_TOUCHING_MODEL(PLAYER::PLAYER_PED_ID(), MISC::GET_HASH_KEY(obj))) { //if (TASK::GET_IS_TASK_ACTIVE(PLAYER::PLAYER_PED_ID(), 471)) //{ return true; break; //} } } return false; } Here is the code i'm using to check if anyone is interested Edited December 1, 2021 by grumpypoo Quote Link to comment Share on other sites More sharing options...
crossed99 43 Posted December 2, 2021 Share Posted December 2, 2021 (edited) Maybe you could use GET_CLOSEST_OBJECT_OF_TYPE(float x, float y, float z, float radius, Hash modelHash, BOOL isMission, BOOL p6, BOOL p7) or one of script hook's 'get all' functions. worldGetAllPickups(pickups, pickupsArraySize); worldGetAllObjects(objects, objectsArraySize); Something like: const int arrSize{ 512 }; Object objects[arrSize]; int objCount = worldGetAllObjects(objects, arrSize); for (int i = 0; i < objCount; ++i) if (ENTITY::GET_ENTITY_MODEL(pickups[i]) == MISC::GET_HASH_KEY("s_brandy01x")) { // if bottle found // check distance to player ?? } I mean it's pretty convoluted, but if it finds the object while it's in the players hand then it could be used reliably. Edited December 2, 2021 by crossed99 Quote Link to comment Share on other sites More sharing options...
grumpypoo 3 Posted December 2, 2021 Author Share Posted December 2, 2021 Yea I tried that method to see if it was near the players hand/face etc, but nothing returned 😕 It seems like the object doesn't actually exist during the animation - Almost as if it is hidden. I found the animations but of course there were no objects (Ironically none of the animations I found actually load during the drinking animation?) I did find a reliable animation dictionary however - face_human@gen_male@scenario@drinkbottle This animation dictionary gets loaded whenever the player drinks from a bottle. The downside is - It doesn't ever seem to unload (So nothing as simple as "Oh well i'll just run a check for TASK 471 then check if the animation dictionary loaded" So now i'm looking if the player is actually using the animation - I have no idea what the taskflag is supposed to be for ENTITY::IS_ENTITY_PLAYING_ANIM I've tried the GTAV 3 flag or 2, but I fear this is not the case. I also found something about getting off a horse animation that used 1 << 18 (262144) I think I might just have to spawn a bunch of bottles and have a loop going to see if the animation hits Here is my current debug code for those that care const char* scenarios[] = { "loop_short", "loop_long", "opengulp", "enter", "strain_enter", "closegulp", "strain_gasp", "strain_loop_long", "strain_exit", "enter_short", "strain_loop_short", "exit" }; for (const char* scenario : scenarios) { if (ENTITY::IS_ENTITY_PLAYING_ANIM(PLAYER::PLAYER_PED_ID(), "face_human@gen_male@scenario@drinkbottle", scenario, 1 << 18)) { PrintSubtitle("Works"); break; } } Quote Link to comment Share on other sites More sharing options...
grumpypoo 3 Posted December 3, 2021 Author Share Posted December 3, 2021 Oh I'm silly 2 hours ago, grumpypoo said: I did find a reliable animation dictionary however - face_human@gen_male@scenario@drinkbottle This animation dictionary gets loaded whenever the player drinks from a bottle. The downside is - It doesn't ever seem to unload (So nothing as simple as "Oh well i'll just run a check for TASK 471 then check if the animation dictionary loaded" This turned out to be a false statement. I got frustrated by checking individual animations and decided to revisit this idea 2 hours ago, grumpypoo said: (So nothing as simple as "Oh well i'll just run a check for TASK 471 then check if the animation dictionary loaded") I tested this code - if (STREAMING::HAS_ANIM_DICT_LOADED("face_human@gen_male@scenario@drinkbottle")) { PrintSubtitle("DICT_LOADED"); } else { PrintSubtitle("DICT_NOT_LOADED"); } Turns out R* does remove the Animation Dictionary. A few things that are confusing - The DICT doesn't immediately unload I tried to force this by waiting say 10 seconds and running STREAMING::REMOVE_ANIM_DICT("face_human@gen_male@scenario@drinkbottle"); This lead to animations for drinking to be completely broken So you have to drink then do anything other than drink again At that point R* unloads the dict So how can we take advantage of this? We know the following information TASK ID 471 = Cores getting filled This works with drinking and eating - Sleeping is unknown Drinking from a bottle uses the following animation dictionary face_human@gen_male@scenario@drinkbottle The animation doesn't get unloaded until something other than drinking is done after the animation completes An initial check could look like this if (TASK::GET_IS_TASK_ACTIVE(PLAYER::PLAYER_PED_ID(), 471)) // Check that the core task is running { if (STREAMING::HAS_ANIM_DICT_LOADED("face_human@gen_male@scenario@drinkbottle")) // Is the Animation dictionary loaded? { // Do something here } } What this doesn't solve is the animation dictionary doesn't get unloaded until the player does something else Possible solutions? Force another animation after like 5 seconds This will need to be tested and it needs to be from another DICT outside of what we are trying to check I will continue to test this and once I come up with a final solution I will post the code here. Quote Link to comment Share on other sites More sharing options...
grumpypoo 3 Posted December 3, 2021 Author Share Posted December 3, 2021 Alright i've figured this out - Here is the code i'm using to check if someone drinks anything int tAnimationSet = 0; static int getGameTime() { return invoke<int>(0x4F67E8ECA7D3F667); } bool refillThirstCoreScenario() { const char* animations[] = { "face_human@gen_male@scenario@drinkbottle", "face_human@gen_male@scenario@drinkshot", "face_human@gen_male@scenario@drinkmug", "face_human@gen_male@scenario@drinkhand" }; for (const char* animation : animations) { if (STREAMING::HAS_ANIM_DICT_LOADED(animation)) { return true; tAnimationSet = getGameTime(); break; } } return false; } void update() { // Core refilling actions if (TASK::GET_IS_TASK_ACTIVE(PLAYER::PLAYER_PED_ID(), 471)) { // Thirst if (refillThirstCoreScenario()) { if (getGameTime() - tAnimationSet > 5000) { PrintSubtitle("You drank!"); } } } } This is a reliable way to check if someone has drank a liquid. For eating you can check the eating animation like I did with drinking. Feel free to copy/paste this code - If you do use it, give yourself a high five in my honor. 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.