Log in to reply
 

CleanWoundsBlood.asi stopped working?


  • MODERATOR

    Wut?! CleanWoundsBlood.asi suddenly stopped working (as of today). It's being loaded just fine:

    ASI: Loading "I:\SteamLibrary\steamapps\common\Grand Theft Auto V\CleanWoundsBlood.asi"
     "CleanWoundsBlood.asi" => 00007FFF76910000
    

    Haven't installed anything new. Just moved my ped collection to my own ped DLC; shouldn't make a difference, though: they're all spawned with the same hash ID. Very strange.


  • MODERATOR

    Hmm, I think it's always been this way. Script works fine, except when you change your ped id hash to another one (presumably because it will now keep cleaning, say, Michael, whilst you're not truly running around with his body, so to speak).

    I have the source code of this mod, so I could probably adapt it. Has anyone experience compiling to .asi, though?


  • MODERATOR

    @meimeiriver An ASI plugin is a DLL which was simply renamed to *.asi


  • MODERATOR

    @Unknown-Modder Cool. :) Thx!



  • @Unknown-Modder Isn't it also exclusively C++?


  • MODERATOR

    @LeeC2202 Yes, because Alex's .asi loader is designed to only load that (via LoadLibrary etc).


  • MODERATOR

    Got it working again. :) I took a LUA approach, as I didn't really feel like installing VS 2015 on my SSD, and trying to get the C version working. The idea is basically to detect whether you switched hashes, and then to always clean the last 'hash' too. Like:

    local RemoveBlood = {}
    
    function RemoveBlood.unload ()
    end
    function RemoveBlood.init ()
    end
    
    function RemoveBlood.tick ()
    	local playerPed = PLAYER.PLAYER_PED_ID ()
        if (playerPed ~= previous_playerPed) then
            previous_playerPed = playerPed
        end
        if ((ENTITY.DOES_ENTITY_EXIST (playerPed)) or (ENTITY.GET_ENTITY_HEALTH (playerPed) >= 200) or (PED.IS_PED_SWIMMING (playerPed))) then
    		PED.CLEAR_PED_BLOOD_DAMAGE (playerPed)
    		PED.RESET_PED_VISIBLE_DAMAGE (playerPed)
    		WEAPON.CLEAR_PED_LAST_WEAPON_DAMAGE (playerPed)
    		PED.CLEAR_PED_BLOOD_DAMAGE (previous_playerPed)
    		PED.RESET_PED_VISIBLE_DAMAGE (previous_playerPed)
    		WEAPON.CLEAR_PED_LAST_WEAPON_DAMAGE (previous_playerPed)
    	end
    end
    return RemoveBlood
    

    Works like a charm. :) What does NOT work, however, is the LUA.asi file. Raking my head over it for hours; but LUA_SDK.asi, however, is fully functional.


  • MODERATOR

    @meimeiriver said in CleanWoundsBlood.asi stopped working?:

    Got it working again. :) I took a LUA approach, as I didn't really feel like installing VS 2015 on my SSD, and trying to get the C version working. The idea is basically to detect whether you switched hashes, and then to always clean the last 'hash' too. Like:

    local RemoveBlood = {}
    
    function RemoveBlood.unload ()
    end
    function RemoveBlood.init ()
    end
    
    function RemoveBlood.tick ()
    	local playerPed = PLAYER.PLAYER_PED_ID ()
        if (playerPed ~= previous_playerPed) then
            previous_playerPed = playerPed
        end
        if ((ENTITY.DOES_ENTITY_EXIST (playerPed)) or (ENTITY.GET_ENTITY_HEALTH (playerPed) >= 200) or (PED.IS_PED_SWIMMING (playerPed))) then
    		PED.CLEAR_PED_BLOOD_DAMAGE (playerPed)
    		PED.RESET_PED_VISIBLE_DAMAGE (playerPed)
    		WEAPON.CLEAR_PED_LAST_WEAPON_DAMAGE (playerPed)
    		PED.CLEAR_PED_BLOOD_DAMAGE (previous_playerPed)
    		PED.RESET_PED_VISIBLE_DAMAGE (previous_playerPed)
    		WEAPON.CLEAR_PED_LAST_WEAPON_DAMAGE (previous_playerPed)
    	end
    end
    return RemoveBlood
    

    Works like a charm. :) What does NOT work, however, is the LUA.asi file. Raking my head over it for hours; but LUA_SDK.asi, however, is fully functional.

    Okay, I'm hesitant to post this, as I was just looking good above, LOL, but that code makes no sense. Yes, it detects the hash change, but by the time the ENTITY.DOES_ENTITY_EXIST check starts, previous_playerPed will always be identical to playerPed! Doh. So, the correct code should simply be:

    local RemoveBlood = {}
    
    function RemoveBlood.unload ()
    end
    function RemoveBlood.init ()
    end
    
    function RemoveBlood.tick ()
    	local playerPed = PLAYER.PLAYER_PED_ID ()
        if ((ENTITY.DOES_ENTITY_EXIST (playerPed)) or (ENTITY.GET_ENTITY_HEALTH (playerPed) >= 200) or (PED.IS_PED_SWIMMING (playerPed))) then
    		PED.CLEAR_PED_BLOOD_DAMAGE (playerPed)
    		PED.RESET_PED_VISIBLE_DAMAGE (playerPed)
    		WEAPON.CLEAR_PED_LAST_WEAPON_DAMAGE (playerPed)
    	end
    end
    return RemoveBlood
    

    One things about that baffle me, though. My initial thinking wasn't really wrong, I think: if you swap out your player ped id, like from a_f_y_bevhills_02 to Michael, you'd expect Michael to be cleaned then, right? And no longer a_f_y_bevhills_02. Yet, using the corrected code, my current a_f_y_bevhills_02 shape, as it were (which hasn't changed), still gets cleaned! I mean, the code works, LOL, but actually shouldn't.

    Maybe I'm too old for this shit!? :P


  • MODERATOR

    Here we go again. :)

    Thing is, I don't like LUA; and I think it may be causing system crashes. So, I asked Lee about C#. Knowing shit about it myself, he spent the better part of his valuable afternoon answering my noob question, for which I am very grateful! The upshot of it all is, I got a working setup now. :)

    One of the lines in the original C++ code was:

    	if  (ENTITY::GET_ENTITY_HEALTH (PLAYER::PLAYER_PED_ID ()) >= 200 || PED::IS_PED_SWIMMING (PLAYER::PLAYER_PED_ID ())) {
    

    As Lee explained to me, a tick(), at 60Hz, means this is being polled ever 16ms, which means that conditional pretty much causes you to be cleaning yourself constantly (especially in godmode). Not only is it ugly, but it can potentially crash your system (like when switching peds). So, with Lee having helped me to set up a proper VS 2017 envirionment, I finally found a useful conditional, being HasCollidedWithAnything (for when you're bumping into something).

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using GTA;
    using GTA.Native;
    
    namespace NoBloodV {
        public class NoBlood : Script {
            public NoBlood () {
                Tick += onTick;
            }
    
            private void onTick (object sender, EventArgs e) {
                Ped playerPed = Game.Player.Character;
                if ((playerPed.HasCollidedWithAnything) || (playerPed.IsInCombat) || (playerPed.IsSwimming)) {
                    playerPed.ClearBloodDamage ();
                    playerPed.ResetVisibleDamage ();
                    Function.Call (Hash.CLEAR_PED_LAST_WEAPON_DAMAGE, playerPed);
                }
            }
        }
    }
    

    There's another conditional, (playerPed.IsInCombat). Strangely, that doesn't get triggered at all.

    So, nearly there. :)



  • @meimeiriver said in CleanWoundsBlood.asi stopped working?:

    There's another conditional, (playerPed.IsInCombat). Strangely, that doesn't get triggered at all.

    What I usually do with things like that, is I use a UI.ShowSubtitle(playerPed.IsInCombat.ToString()); in the OnTick. And that constantly displays the status of that flag on the screen.

    It might trigger when someone shoots, it might trigger when you get into a melee fight but if you can always see the value of it, you can see when it gets triggered.


  • MODERATOR

    @LeeC2202 said in CleanWoundsBlood.asi stopped working?:

    @meimeiriver said in CleanWoundsBlood.asi stopped working?:

    There's another conditional, (playerPed.IsInCombat). Strangely, that doesn't get triggered at all.

    What I usually do with things like that, is I use a UI.ShowSubtitle(playerPed.IsInCombat.ToString()); in the OnTick. And that constantly displays the status of that flag on the screen.

    It might trigger when someone shoots, it might trigger when you get into a melee fight but if you can always see the value of it, you can see when it gets triggered.

    Thanks! I'll be doing that!


  • MODERATOR

    @LeeC2202 said in CleanWoundsBlood.asi stopped working?:

    UI.ShowSubtitle(playerPed.IsInCombat.ToString());

    As expected, IsInCombat always returns False. IsSwimming returns True, nicely, when you're swimming. But IsInCombat remains False, under every circumstance: getting shot at, firing yourself, when wanted and the Police come, when spawning attacking peds, etc.

    EDIT: While in melee combat returns False too, btw.



  • @meimeiriver Maybe those two flags only apply to npc peds, so that the scripting can make AI decisions based on their status.


  • MODERATOR

    @LeeC2202 said in CleanWoundsBlood.asi stopped working?:

    @meimeiriver Maybe those two flags only apply to npc peds, so that the scripting can make AI decisions based on their status.

    But, if so, then why is IsInCombat a boolean of Game.Player.Character?! Besides, like I say, IsSwimming works just fine on Game.Player.Character. Strange. IsInjured() does nothing either, btw (even with godmode off, of course).

    I think I'm going to mention this to the author of ScriptHookVDotNet. Looks like In a few days he may need to redo his tool anyway.



  • @meimeiriver said in CleanWoundsBlood.asi stopped working?:

    But, if so, then why is IsInCombat a boolean of Game.Player.Character?

    Becaue Game.Player.Character is simply an instance of the Ped entity, just one that you control, instead of the game controlling.


  • MODERATOR

    @LeeC2202 said in CleanWoundsBlood.asi stopped working?:

    IsInCombat

    I just looked at the source. Seem IsInCombat is, in fact,

    	public bool IsInCombat
    	{
    		get
    		{
    			return Function.Call<bool>(Hash.IS_PED_IN_COMBAT, Handle);
    		}
    	}

  • MODERATOR

    @LeeC2202 All of which brought me to finding this little gem:

    bool IsInCombat(Ped ped)
    {
        foreach (Ped target in World.GetAllPeds())
        {
            if (target.IsAlive && GTA.Native.Function.Call<bool>(GTA.Native.Hash.IS_PED_IN_COMBAT, target, ped))
            {
                return true;
            }
        }
        return false;
    }
    

    Which seems to indicate IS_PED_IN_COMBAT requires two parameters, a 'target' and your own 'ped' id.



  • @meimeiriver Yep, it's defintely a 2 Ped thing based on what the native says.

    My advice, if in doubt, use the natives... a lot. SHVDN adds a nice wrapper to some things but in a lot of cases, it just does it badly. I find myself using the SHVDN function, then checking the Natives and then writing my own wrapper function if required.

    The World.GetGroundHeight() function is a classic case, the SHVDN version is broken because it assumes one of the parameters and sets the value to something you can't change. That's not how you write a wrapper function.


  • MODERATOR

    @LeeC2202 Yep, seems like I actually found a real bug. :) It's a wonderful thing when you start looking at the source files.



  • @meimeiriver It's probably not worth reporting because you'll just get fobbed off with some excuse. Just work around it... it's something you'll get used to doing.

    There are bugs in some of the ped tasks as well, because they decided critically important bool flags weren't worth implementing.


  • MODERATOR

    @LeeC2202 said in CleanWoundsBlood.asi stopped working?:

    @meimeiriver It's probably not worth reporting because you'll just get fobbed off with some excuse. Just work around it... it's something you'll get used to doing.

    Yeah, this is probably true.

    This new IsInCombat requires a lot of iterations, though (until the early-out, when you're in combat); which mean 99% of the time the entire peds array is being traversed. Not sure I want that on every tick either. Hmm.



  • @meimeiriver So you're testing to see if the player is in combat with every ped you can see? That's going to be a performance hit...

    Can I ask what you are using the result of that for? I mean I do have an optimised Ped and Vehicle collector that can help but maybe there are other, less intensive operations.


  • MODERATOR

    @LeeC2202 said in CleanWoundsBlood.asi stopped working?:

    @meimeiriver So you're testing to see if the player is in combat with every ped you can see? That's going to be a performance hit...

    Can I ask what you are using the result of that for? I mean I do have an optimised Ped and Vehicle collector that can help but maybe there are other, less intensive operations.

    Well, the idea, of course, was, to not clean yourself on every tick (). To that end I only wanted to do so when you're in actual combat (or hit something); but it seems the remedy (adding a conditional to check for IsInCombat() with the self-rolled function) is worse than the original solution.

    EDIT: Or I can simply always clean my ped, and just set 'Interval = 100' or something, and just call it the day. :)



  • @meimeiriver said in CleanWoundsBlood.asi stopped working?:

    Or I can simply always clean my ped, and just set 'Interval = 100' or something, and just call it the day

    Having done vehicle collection, that ^^^ is the best way to keep your mod running fast... collecting entities really isn't a pleasant task if performance is a concern. It would be my choice, that's for sure. :D


Log in to reply
 

Looks like your connection to GTA5-Mods.com Forums was lost, please wait while we try to reconnect.