+void nade_entrap_touch(entity this, entity toucher)
+{
+ if(DIFF_TEAM(toucher, this.realowner)) // TODO: what if realowner changes team or disconnects?
+ {
+ if (!isPushable(toucher))
+ return;
+
+ float pushdeltatime = time - toucher.lastpushtime;
+ if (pushdeltatime > 0.15) pushdeltatime = 0;
+ toucher.lastpushtime = time;
+ if(!pushdeltatime) return;
+
+ // div0: ticrate independent, 1 = identity (not 20)
+#ifdef SVQC
+ toucher.velocity = toucher.velocity * pow(autocvar_g_nades_entrap_strength, pushdeltatime);
+
+ UpdateCSQCProjectile(toucher);
+#elif defined(CSQC)
+ toucher.move_velocity = toucher.move_velocity * pow(autocvar_g_nades_entrap_strength, pushdeltatime);
+#endif
+ }
+
+ if ( IS_REAL_CLIENT(toucher) || IS_VEHICLE(toucher) || IS_MONSTER(toucher) )
+ {
+ entity show_tint = (IS_VEHICLE(toucher)) ? toucher.owner : toucher;
+ STAT(ENTRAP_ORB, show_tint) = time + 0.1;
+
+ float tint_alpha = 0.75;
+ if(SAME_TEAM(toucher, this.realowner))
+ tint_alpha = 0.45;
+ STAT(ENTRAP_ORB_ALPHA, show_tint) = tint_alpha * (this.ltime - time) / this.orb_lifetime;
+ }
+}
+
+void nade_entrap_boom(entity this)
+{
+ entity orb = nades_spawn_orb(this.owner, this.realowner, this.origin, autocvar_g_nades_entrap_time, autocvar_g_nades_entrap_radius);
+
+ settouch(orb, nade_entrap_touch);
+ orb.colormod = NADE_TYPE_ENTRAP.m_color;
+}
+
+void nade_heal_touch(entity this, entity toucher)
+{