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);
}
}
}
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);
}
}
}
Sadly, this doesn't work with hitscan attack though.
This trick still works with ZDoom 4.11.0.