--- orig/rpggame/rpgent.h
+++ mod/rpggame/rpgent.h
@@ -139,6 +139,17 @@
 
     }
 
+    void r_attack(rpgobj &eo, rpgobj &weapon)
+    {
+        if (!eo.ent) return;
+
+        vec target;
+        if(raycubelos(o, eo.ent->o, target))
+        {
+            if(target.dist(o)<weapon.s_maxrange) tryattack(target, weapon);
+        }
+    }
+
     void updateprojectile(int curtime)
     {
         if(!magicprojectile) return;
--- orig/rpggame/rpgobjset.h
+++ mod/rpggame/rpgobjset.h
@@ -76,6 +76,7 @@
         CCOMMAND(r_z,           "f",   (rpgobjset *self, float *val), { if (self->stack[0]->ent) self->stack[0]->ent->o.z = *val; });
         CCOMMAND(r_sleep,       "is",  (rpgobjset *self, int *msec, char *cmd), { self->r_sleep(*msec, cmd); });
         CCOMMAND(r_loop_inrange,"is",  (rpgobjset *self, int *maxrange, char *body), { self->loop_inrange(*maxrange, body); });
+        CCOMMAND(r_attack,      "",    (rpgobjset *self), { self->r_attack(); });
         clearworld();
     }
 
@@ -306,6 +307,11 @@
         }
     }
 
+    void r_attack()
+    {
+        stack[1]->ent->r_attack(*stack[0], stack[1]->selectedweapon());
+    }
+
     char *stringpool(char *name)
     {
         char **n = names.access(name);
