Armor hit sound?

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Armor hit sound?

Postby Graaicko » Thu Oct 15, 2020 7:51 pm

I want to make it where if you have armor, and get shot by an enemy, it makes a different sound then player pain sounds. (Exactly like Shadow Warrior for instance.) How Would I do this?
User avatar
Graaicko
I don't do requests. Working on Shadow Elite. I miss Windows 7. :(
 
Joined: 18 Jun 2014
Location: Somewhere, somehow.
Discord: private
Twitch ID: lol why?
Github ID: gitgud, pleb
Operating System: Windows 10/8.1/8/201x 64-bit
Graphics Processor: nVidia (Legacy GZDoom)

Re: Armor hit sound?

Postby Player701 » Thu Oct 15, 2020 11:43 pm

This is not quite a trivial task, but it is still doable. The problem is that GZDoom's armor system is set up in such a way that when you pick up an armor, it doesn't actually go into your inventory. Instead, it adjusts the parameters of an inventory item called BasicArmor - you always receive this item when you start the game, but if you lack it for some reason, it will be automatically added to your inventory when picking up an armor item.

Considering that references to BasicArmor are hard-coded in many places of the internal code, it's not really feasible to replace it. However, this limitation can be circumvented by implementing another inventory item that would play the sound effect every time the player is hit while wearing the armor. My own mod uses this technique to play a sound and display a screen flash (via GetBlend) for a special armor that protects from 100% of incoming damage.

Here's some example code:

Code: Select allExpand view
class MyArmor : BasicArmorPickup
{
    // TODO: Your other code goes here

    override bool Use(bool pickup)
    {
        bool result = Super.Use(pickup);

        // If pickup has succeeded, give the FX item too.
        if (result)
        {
            Owner.GiveInventory('MyArmorFX', 1);
        }

        return result;
    }
}

class MyArmorFX : Inventory
{
    Default
    {
        // Prevent sudden removal of the item.
        +INVENTORY.UNCLEARABLE;
    }

    override void AbsorbDamage(int damage, Name damageType, out int newdamage, Actor inflictor, Actor source, int flags)
    {
        // If the player is wearing the armor, play the special sound.
        if (OwnerHasMyArmor())
        {
            Owner.A_StartSound("armor/hit", CHAN_BODY);
        }
    }

    override void Tick()
    {
        Super.Tick();
       
        // If the player doesn't have the armor anymore, destroy the FX item.
        if (!OwnerHasMyArmor())
        {
            Destroy();
        }
    }

    private bool OwnerHasMyArmor()
    {
        // Check that the player still has the corresponding armor type
        // and the amount is non-zero.
        if (Owner != null)
        {
            let ba = BasicArmor(Owner.FindInventory('BasicArmor'));
           
            if (ba != null)
            {
                return ba.Amount > 0 && ba.ArmorType == 'MyArmor';
            }
        }

        return false;
    }
}


Explanation:

  • When the player picks up your armor, they will also be given a special item that processes the sound effect.
  • The special item automatically destroys itself when the player is not wearing the armor anymore.
  • The engine routes all incoming damage through the player's inventory item chain by calling AbsorbDamage for each of them. This includes BasicArmor as well as our special item. We don't actually absorb any damage, but instead use this method as an entry point to check if the player is wearing the armor and play a sound.

Note that if you have other items that have damage absorption effects, then you must reposition the special item in the inventory chain so that it is immediately precedes BasicArmor. Otherwise, you'll hear a sound even when the incoming damage doesn't reach the armor at all, having been fully absorbed on the way by something else. But AFAIK, vanilla Doom II doesn't have any such items (invulnerability and radiation suit work differently and don't require any special handling).
User avatar
Player701
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Armor hit sound?

Postby Graaicko » Fri Oct 16, 2020 7:39 am

Is this Zscript or ACS? Still learning how to work with both.
User avatar
Graaicko
I don't do requests. Working on Shadow Elite. I miss Windows 7. :(
 
Joined: 18 Jun 2014
Location: Somewhere, somehow.
Discord: private
Twitch ID: lol why?
Github ID: gitgud, pleb
Operating System: Windows 10/8.1/8/201x 64-bit
Graphics Processor: nVidia (Legacy GZDoom)

Re: Armor hit sound?

Postby Player701 » Fri Oct 16, 2020 7:49 am

This is ZScript. You have to put the properties and states of your armor item instead of the line "//TODO: Your other code goes here". If you're familiar with DECORAE, see Converting DECORATE code to ZScript for more details - it's basically just a few more curly braces, double quotes, and semicolons here and there.

Another way to use this code is to inherit your DECORATE armor pickup class from MyArmor, in this case you don't have to write any ZScript code yourself. However, then you will have to replace "MyArmor" in the following line of code for MyArmorFX with your armor class name:

Code: Select allExpand view
return ba.Amount > 0 && ba.ArmorType == 'MyArmor'; // <- Replace MyArmor with your armor class name


Example (DECORATE):

Code: Select allExpand view
actor MyDecorateArmor : MyArmor
{
    // TODO: Your code here
}

and change the line in the code sample from my previous post to:

Code: Select allExpand view
return ba.Amount > 0 && ba.ArmorType == 'MyDecorateArmor';


In both cases, you should also define a sound called "armor/hit", which will be played when the player receives damage while wearing the armor.
User avatar
Player701
 
Joined: 13 May 2009
Location: Russia
Discord: Player701#8214
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support


Return to Scripting

Who is online

Users browsing this forum: No registered users and 0 guests