diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp
index b6ffcb699..43cafeebc 100644
--- a/src/p_interaction.cpp
+++ b/src/p_interaction.cpp
@@ -952,7 +952,7 @@ static inline bool isFakePain(AActor *target, AActor *inflictor, int damage)
 
 // Returns the amount of damage actually inflicted upon the target, or -1 if
 // the damage was cancelled.
-int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags, DAngle angle)
+static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags, DAngle angle)
 {
 	DAngle ang;
 	player_t *player = NULL;
@@ -1589,9 +1589,24 @@ DEFINE_ACTION_FUNCTION(AActor, DamageMobj)
 	PARAM_NAME(mod);
 	PARAM_INT_DEF(flags);
 	PARAM_FLOAT_DEF(angle);
-	ACTION_RETURN_INT(P_DamageMobj(self, inflictor, source, damage, mod, flags, angle));
+	ACTION_RETURN_INT(DamageMobj(self, inflictor, source, damage, mod, flags, angle));
 }
 
+int P_DamageMobj(AActor *target, AActor *inflictor, AActor *source, int damage, FName mod, int flags, DAngle angle)
+{
+	IFVIRTUALPTR(target, AActor, DamageMobj)
+	{
+		VMValue params[7] = { target, inflictor, source, damage, mod.GetIndex(), flags, angle.Degrees };
+		VMReturn ret;
+		int retval;
+		ret.IntAt(&retval);
+		GlobalVMStack.Call(func, params, 7, &ret, 1, nullptr);
+		return retval;
+	}
+	else return DamageMobj(target, inflictor, source, damage, mod, flags, angle);
+}
+
+
 void P_PoisonMobj (AActor *target, AActor *inflictor, AActor *source, int damage, int duration, int period, FName type)
 {
 	// Check for invulnerability.
diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt
index 4635105cb..8370f9637 100644
--- a/wadsrc/static/zscript/actor.txt
+++ b/wadsrc/static/zscript/actor.txt
@@ -364,7 +364,7 @@ class Actor : Thinker native
 	native void SetIdle(bool nofunction = false);
 	native bool CheckMeleeRange();
 	native bool CheckMeleeRange2();
-	native int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0);
+	native virtual int DamageMobj(Actor inflictor, Actor source, int damage, Name mod, int flags = 0, double angle = 0);
 	native void PoisonMobj (Actor inflictor, Actor source, int damage, int duration, int period, Name type);
 	native double AimLineAttack(double angle, double distance, out FTranslatedLineTarget pLineTarget = null, double vrange = 0., int flags = 0, Actor target = null, Actor friender = null);
 	native Actor, int LineAttack(double angle, double distance, double pitch, int damage, Name damageType, class<Actor> pufftype, int flags = 0, out FTranslatedLineTarget victim = null);