Did you know that you can deal damage to the +NODAMAGE actors with any weapons?

Handy guides on how to do things, written by users for users.

Moderators: GZDoom Developers, Raze Developers

Forum rules
Please don't start threads here asking for help. This forum is not for requesting guides, only for posting them. If you need help, the Editing forum is for you.
Mozart27
Posts: 2
Joined: Wed Dec 27, 2023 8:59 am
Preferred Pronouns: He/Him

Did you know that you can deal damage to the +NODAMAGE actors with any weapons?

Post by Mozart27 »

Maybe you've known already: There is a trick to deal damage to +NODAMAGE actor flag
1. Create a "PowerUp" inventory
2. Override virtual function ModifyDamage, code as follow

Code: Select all

class ForceDamage: Powerup 
{
	Default
	{
		+INVENTORY.AUTOACTIVATE
		powerup.duration -30;
		+NoTimeFreeze
	}
	override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags)
	{	
		if(!passive && source && inflictor)
		{
			newdamage = 0; //Prevent duplicating damage
			source.DamageMobj(inflictor, owner, damage, damageType, DMG_FORCED);			
		}
	}
}
3. Give it to the player or any friendly actors. Now you can deal damage to any +NODAMAGE actors with any weapons.

Explanation:
- When you deal damage, the "source" parameter actually points to the actors who took the damage, not the damage dealer as Wiki says.
- The function ModifyDamage() is still called when you deal damage, just before the +NODAMAGE flag reduce damage to 0.
- Therefore, you can deal damage to the actor even if they have NODAMAGE flag by calling source.DamageMObj() in the overridden ModifyDamage() virtual function. Parameter "newdamage" needs to be set to 0 to prevent duplicating damage.
- However, if they also have +INVULNERABLE or +SPECTRAL, this PowerUp won't work on them since +INVULNERABLE and +SPECTRAL prevents ModifyDamage() being called, unless the puffs or missiles have +FOILINVUL and +SPECTRAL flags.

A broken version of this PowerUp can be as follow:

Code: Select all

class ForceMissileDamage: Powerup 
{
	Default
	{
		+INVENTORY.AUTOACTIVATE
		powerup.duration -30;
		+NoTimeFreeze
	}
	
	override void DoEffect()
	{
		let it =  ThinkerIterator.Create('Actor');
		Actor mo;			
		while ( (mo = Actor(it.Next())) )
		{
			if (mo == self || mo == Owner) 
			{ 
				continue; //Exclude originator and shooter
			}	
									
			if(!mo.bIsMonster && !(mo is "Inventory") && mo.bMissile && mo.target == owner) //Get the missile that the owner shoots
			{					
				mo.bFoilInvul = mo.bSpectral = true; //To make sure that the ModifyDamage() is called.
								
				mo.FriendPlayer = 666; //Spectral projectile can only deal damage if their FriendPlayer variable is non-zero.
				if(owner.player) 
					mo.SetFriendPlayer(owner.player);
				
			}
		}										
		super.Doeffect();
	}
	
	override void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive, Actor inflictor, Actor source, int flags)
	{	
		if(!passive && source && inflictor && inflictor.bMissile)
		{
			newdamage = 0; //Prevent duplicate damage
			source.DamageMobj(inflictor, owner, damage, damageType, DMG_FORCED);				
		}
	}
}
This ForceMissileDamage powerup can make any projectiles that you should to be able to deal damage to any shootable actors, even if they have +INVULNERABLE, +SPECTRAL and +NODAMAGE flags set simuntaneously.
Sadly, this doesn't work with hitscan attack though.
This trick still works with ZDoom 4.11.0.

Return to “Tutorials”