Page 1 of 1

Forced damagefactor for a specific damagetype

Posted: Fri Aug 28, 2020 5:55 am
by Grey-Wolf
Hello!
I have a "bleeding" damagetype, and I want that all damage coming from it are always dealt at damagefactor 1.0 no matter what.
So I've put the "replacefactor" property into its definition, but the thing is, it is still affected by the global damagefactor of the difficulty level, so it ends up dealing more damage in those cases
What am I doing wrong?

Re: Forced damagefactor for a specific damagetype

Posted: Wed Oct 07, 2020 12:00 pm
by Grey-Wolf
Uhhh, can I bump this? I'm still having this problem...

Re: Forced damagefactor for a specific damagetype

Posted: Wed Oct 07, 2020 1:17 pm
by Player701
I think no one's answered this yet because your use case is unclear. Global damage factor is called that for a reason: it is intended to affect everything (in regards to player-received damage anyway). Why are you trying to bypass it?

If you're using ZScript, from the source code it looks like you can pass a flag called DMG_FORCED to DamageMobj when applying your damage to ignore all damage factors, even the global one. If you're not using DamageMobj, I guess you could divide your damage by G_SkillPropertyFloat(SKILLP_DamageFactor) before applying it, although since the damage is an int, it may not work as intended in all cases. For example, if the damage is 1 and the factor is 2, the resulting damage will be 0 because int(1/2) == 0, and 0 multiplied back by 2 is still 0.

Upd: Example player class to override global damage factor for a specific damage type using DMG_FORCED, tested in GZDoom 4.4.2

Code: Select all

class MyPlayer : DoomPlayer
{
    override int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags, double angle)
    {
        if (mod == 'Bleeding') // <- Replace with the name of your damage type if it's called differently
        {
            flags |= DMG_FORCED;
        }
        
        return Super.DamageMobj(inflictor, source, damage, mod, flags, angle);
    }
}

Re: Forced damagefactor for a specific damagetype

Posted: Wed Oct 07, 2020 1:49 pm
by Grey-Wolf
I'm using ACS, through the DamageActor command.
Now, this is the damagetype definition:
Spoiler:
And even though I won't post the whole bleeding script because it's very long, basically it should inflict damage on the player if some conditions are met, through this command:
Damageactor(0,0,1,0,3,"bleeding");

Thing is, if set my difficulty level at, let's say 200% damage taken, each proc of the bleeding will deal 6 damage instead of 3.
Since I'm not exactly well versed in zScript and I don't want to rewrite a very long script just because of this, is there some way to achieve this in ACS?

Re: Forced damagefactor for a specific damagetype

Posted: Wed Oct 07, 2020 2:00 pm
by Player701
As far as I'm aware, there is no way to pass DamageMobj flags via ACS. It is also not possible to retireve the values of skill properties in either ACS or DECORATE.

However, to make use of the above example, you don't have to rewrite your script. Just add the DamageMobj override to your player class and you should be all set... mostly. The thing is, DMG_FORCED also has some side effects, like bypassing invulnerability, so the example code should be slightly modified to account for that. If you are willing to use it, I believe I will be able to provide a more complete version tomorrow (it's 11 PM where I am, don't want to stay up late :P), or maybe someone else could do that while I'm unavailable.
Grey-Wolf wrote:Thing is, if set my difficulty level at, let's say 200% damage taken, each proc of the bleeding will deal 6 damage instead of 3.
But what's wrong with that? Just curious. IMO, it should work exactly like you're describing.

Upd: Here's the updated code

Code: Select all

class MyPlayer : DoomPlayer
{
    override int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags, double angle)
    {
        if (mod == 'Bleeding' && !((player.cheats & CF_GODMODE) || bInvulnerable))
        {
            flags |= DMG_FORCED;
        }
       
        return Super.DamageMobj(inflictor, source, damage, mod, flags, angle);
    }
}
I may have failed to account for some more specific conditions, because the original DamageMobj code is huge and not easily understandable... Sorry about that. But at least this won't damage the player when they are in god mode or have an invulnerability powerup. Please let me know if you have any issues with it.

Re: Forced damagefactor for a specific damagetype

Posted: Thu Oct 08, 2020 9:11 am
by Grey-Wolf
I already have an actor replacing "doomplayer", won't this class mess with it?
But what's wrong with that? Just curious. IMO, it should work exactly like you're describing.
I just want bleeding damage to stay unaffected, I have good reasons for it, I swear XD

Re: Forced damagefactor for a specific damagetype

Posted: Thu Oct 08, 2020 9:19 am
by Player701
Grey-Wolf wrote:I already have an actor replacing "doomplayer", won't this class mess with it?
If you already have a player class, you should convert it to ZScript and add the DamageMobj override there.

Re: Forced damagefactor for a specific damagetype

Posted: Thu Oct 08, 2020 9:42 am
by Grey-Wolf
Hmm... as I already mentioned, I'm utterly terrible at Zscript, so I'd rather avoid that. On another note, I could have found a solution working for ACS, kind of a weird workaround, not gonna lie:
Spoiler:
This removes exactly 1 point of health at each proc. The only problem with this is that if the player dies because of this, it won't show the proper obituary message, but a really inappropriate "suicide" one (like "%o killed himself"). If I were to find a way to replace this obituary message, I would settle with that. Any ideas?

Re: Forced damagefactor for a specific damagetype

Posted: Thu Oct 08, 2020 9:55 am
by Player701
Grey-Wolf wrote:Hmm... as I already mentioned, I'm utterly terrible at Zscript, so I'd rather avoid that.
If you read the guide, and especially the examples, you'll see that the syntax is mostly the same, except that you have to put Default { ... } around the property values and add some semicolons. If you posted your code here, I'd probably be able to provide a converted version for you.
Grey-Wolf wrote:I could have found a solution working for ACS, kind of a weird workaround, not gonna lie:
Spoiler:
Note that this ignores whether the player is invulnerable or using the godmode cheat. While the former can be checked for with GetActorProperty(0, APROP_Invulnerable), I'm not sure if you can check for cheat usage in ACS.
Grey-Wolf wrote:The only problem with this is that if the player dies because of this, it won't show the proper obituary message, but a really inappropriate "suicide" one (like "%o killed himself").
From the source code, it looks like the engine considers the activator of the script as the damage inflictor. If the script is activated by the player, it's only logical that it will produce the suicide obituary. If you can change it so that the script is activated by something else, I suppose it will use the obituary of that something instead.

Re: Forced damagefactor for a specific damagetype

Posted: Thu Oct 08, 2020 10:07 am
by Grey-Wolf
Uh... are you sure? It's REAAALLY long.

https://pastebin.com/Mj21nj6P

And changing the activator of the script is not really an option because it would mess up various "giveinventory" and whatnot in that same script...

EDIT: what if the class just inherits from the current one while adding that commands you mentioned

Re: Forced damagefactor for a specific damagetype

Posted: Thu Oct 08, 2020 10:27 am
by Player701
Grey-Wolf wrote:Uh... are you sure? It's REAAALLY long.
Right.

So there is an even better solution that doesn't involve rewriting your DECORATE code. Use this ZScript code as your base class:

Code: Select all

class MyPlayer : PlayerPawn
{
    override int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags, double angle)
    {
        if (mod == 'Bleeding' && !((player.cheats & CF_GODMODE) || bInvulnerable))
        {
            flags |= DMG_FORCED;
        }
       
        return Super.DamageMobj(inflictor, source, damage, mod, flags, angle);
    }
}
and then in your DECORATE code, inherit your player class from MyPlayer, like this:

Code: Select all

actor Doomer : MyPlayer
{
    // Your overly long player class code goes here
}
As far as I'm aware, this should work because DECORATE is parsed after ZScript.

BTW, your player class does not need to replace DoomPlayer, because player classes aren't replaced this way. Adding it to MAPINFO is sufficient.

Re: Forced damagefactor for a specific damagetype

Posted: Thu Oct 08, 2020 11:17 am
by Grey-Wolf
Worked like a charm! Thank you !