]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into TimePath/debug_draw
authorTimePath <andrew.hardaker1995@gmail.com>
Sun, 1 Nov 2015 11:17:03 +0000 (22:17 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Sun, 1 Nov 2015 11:17:03 +0000 (22:17 +1100)
# Conflicts:
# qcsrc/common/effects/all.qc
# qcsrc/lib/net.qh

45 files changed:
1  2 
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/damage.qc
qcsrc/client/generator.qc
qcsrc/client/gibs.qc
qcsrc/client/hud.qh
qcsrc/client/main.qc
qcsrc/common/deathtypes/all.qh
qcsrc/common/effects/all.qc
qcsrc/common/effects/all.qh
qcsrc/common/effects/effect.qh
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/minigames/cl_minigames.qh
qcsrc/common/minigames/sv_minigames.qh
qcsrc/common/monsters/monster/shambler.qc
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/mutators/mutator/waypoints/all.qh
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
qcsrc/common/turrets/cl_turrets.qc
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/blaster.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/fireball.qc
qcsrc/common/weapons/weapon/hagar.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/mortar.qc
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/shockwave.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/lib/net.qh
qcsrc/lib/warpzone/common.qc
qcsrc/server/cheats.qc
qcsrc/server/cl_client.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qc
qcsrc/server/mutators/mutator/gamemode_keyhunt.qc
qcsrc/server/mutators/mutator/gamemode_onslaught.qc
qcsrc/server/mutators/mutator/mutator_nades.qc

index e7a6a6bb3e515eaa9ba95a9d954283c2e9056d34,807ebe4e5ec406ba4a8d747f4d6e49c4410dd77a..97297e7485e424689a33ac3f7becbfc39509398b
@@@ -136,7 -136,8 +136,7 @@@ void CSQCPlayer_ModelAppearance_Apply(b
        // which one is ALWAYS good?
        if (!forceplayermodels_goodmodel)
        {
 -              entity e;
 -              e = spawn();
 +              entity e = spawn();
                precache_model(cvar_defstring("_cl_playermodel"));
                _setmodel(e, cvar_defstring("_cl_playermodel"));
                forceplayermodels_goodmodel = e.model;
                forceplayermodels_attempted = 1;
  
                // only if this failed, find it out on our own
 -              entity e;
 -              e = spawn();
 +              entity e = spawn();
                _setmodel(e, autocvar__cl_playermodel); // this is harmless, see below
                forceplayermodels_modelisgoodmodel = fexists(e.model);
                forceplayermodels_model = e.model;
  
        if(autocvar_cl_forcemyplayermodel != "" && autocvar_cl_forcemyplayermodel != forceplayermodels_mymodel)
        {
 -              entity e;
 -              e = spawn();
 +              entity e = spawn();
                _setmodel(e, autocvar_cl_forcemyplayermodel); // this is harmless, see below
                forceplayermodels_myisgoodmodel = fexists(e.model);
                forceplayermodels_mymodel = e.model;
@@@ -529,9 -532,9 +529,9 @@@ void CSQCModel_Effects_Apply(void
        if(eff & EF_FULLBRIGHT)
                self.renderflags |= RF_FULLBRIGHT;
        if(eff & EF_FLAME)
-               pointparticles(particleeffectnum(EFFECT_EF_FLAME), self.origin, '0 0 0', bound(0, frametime, 0.1));
+               pointparticles(EFFECT_EF_FLAME, self.origin, '0 0 0', bound(0, frametime, 0.1));
        if(eff & EF_STARDUST)
-               pointparticles(particleeffectnum(EFFECT_EF_STARDUST), self.origin, '0 0 0', bound(0, frametime, 0.1));
+               pointparticles(EFFECT_EF_STARDUST, self.origin, '0 0 0', bound(0, frametime, 0.1));
        if(eff & EF_NOSHADOW)
                self.renderflags |= RF_NOSHADOW;
        if(eff & EF_NODEPTHTEST)
diff --combined qcsrc/client/damage.qc
index 2d7c4f2c180858dcebb5afcecb3cbb52f838dc21,803b241d09b7529bf4872fb4918c7c8cf7bc6556..b97b69a43f21fe24447dd3d5a62631f432a3c84d
@@@ -42,7 -42,7 +42,7 @@@ void DamageEffect_Think(
        // now generate the particles
        vector org;
        org = gettaginfo(self, 0); // origin at attached location
-       pointparticles(self.team, org, '0 0 0', 1);
+       __pointparticles(self.team, org, '0 0 0', 1);
  }
  
  void DamageEffect(vector hitorg, float thedamage, int type, int specnum)
                else { return; } // objects don't bleed
        }
  
 -      e = spawn();
 +      e = new(damage);
 +      make_pure(e);
        setmodel(e, MDL_Null); // necessary to attach and read origin
        setattachment(e, self, gettaginfo_name); // attach to the given bone
 -      e.classname = "damage";
        e.owner = self;
        e.cnt = time + life;
        e.team = _particleeffectnum(effectname);
  
  void Ent_DamageInfo(float isNew)
  {SELFPARAM();
 +      make_pure(this);
        float thedamage, rad, edge, thisdmg;
        bool hitplayer = false;
        int species, forcemul;
                        // spiderbot
                        case DEATH_VH_SPID_MINIGUN:
                                sound(self, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTEN_NORM);
-                               pointparticles(particleeffectnum(EFFECT_SPIDERBOT_MINIGUN_IMPACT), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_SPIDERBOT_MINIGUN_IMPACT, self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_SPID_ROCKET:
                                sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
-                               pointparticles(particleeffectnum(EFFECT_SPIDERBOT_ROCKET_EXPLODE), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_SPIDERBOT_ROCKET_EXPLODE, self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_SPID_DEATH:
                                sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_MIN);
-                               pointparticles(particleeffectnum(EFFECT_EXPLOSION_BIG), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_EXPLOSION_BIG, self.origin, w_backoff * 1000, 1);
                                break;
  
                        case DEATH_VH_WAKI_GUN:
                                sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_NORM);
-                               pointparticles(particleeffectnum(EFFECT_RACER_IMPACT), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_RACER_IMPACT, self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_WAKI_ROCKET:
                                sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
-                               pointparticles(particleeffectnum(EFFECT_RACER_ROCKET_EXPLODE), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_RACER_ROCKET_EXPLODE, self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_WAKI_DEATH:
                                sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_MIN);
-                               pointparticles(particleeffectnum(EFFECT_EXPLOSION_BIG), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_EXPLOSION_BIG, self.origin, w_backoff * 1000, 1);
                                break;
  
                        case DEATH_VH_RAPT_CANNON:
                                sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_NORM);
-                               pointparticles(particleeffectnum(EFFECT_RAPTOR_CANNON_IMPACT), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_RAPTOR_CANNON_IMPACT, self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_RAPT_FRAGMENT:
                                float i;
                                        RaptorCBShellfragToss(w_org, vel, ang + '0 0 1' * (120 * i));
                                }
                                sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
-                               pointparticles(particleeffectnum(EFFECT_RAPTOR_BOMB_SPREAD), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_RAPTOR_BOMB_SPREAD, self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_RAPT_BOMB:
                                sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
-                               pointparticles(particleeffectnum(EFFECT_RAPTOR_BOMB_IMPACT), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_RAPTOR_BOMB_IMPACT, self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_RAPT_DEATH:
                                sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_MIN);
-                               pointparticles(particleeffectnum(EFFECT_EXPLOSION_BIG), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_EXPLOSION_BIG, self.origin, w_backoff * 1000, 1);
                                break;
                        case DEATH_VH_BUMB_GUN:
                                sound(self, CH_SHOTS, SND_FIREBALL_IMPACT2, VOL_BASE, ATTEN_NORM);
-                               pointparticles(particleeffectnum(EFFECT_BIGPLASMA_IMPACT), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_BIGPLASMA_IMPACT, self.origin, w_backoff * 1000, 1);
                                break;
                }
        }
                {
                         case DEATH_TURRET_EWHEEL:
                                sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTEN_MIN);
-                               pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_BLASTER_IMPACT, self.origin, w_backoff * 1000, 1);
                                break;
  
                         case DEATH_TURRET_FLAC:
-                               pointparticles(particleeffectnum(EFFECT_HAGAR_EXPLODE), w_org, '0 0 0', 1);
+                               pointparticles(EFFECT_HAGAR_EXPLODE, w_org, '0 0 0', 1);
                                sound(self, CH_SHOTS, SND_HAGEXP_RANDOM(), VOL_BASE, ATTEN_NORM);
                                break;
  
                         case DEATH_TURRET_WALK_ROCKET:
                         case DEATH_TURRET_HELLION:
                                sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_MIN);
-                               pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_ROCKET_EXPLODE, self.origin, w_backoff * 1000, 1);
                                break;
  
                         case DEATH_TURRET_MACHINEGUN:
                         case DEATH_TURRET_WALK_GUN:
                                sound(self, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTEN_NORM);
-                               pointparticles(particleeffectnum(EFFECT_MACHINEGUN_IMPACT), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_MACHINEGUN_IMPACT, self.origin, w_backoff * 1000, 1);
                                break;
  
                         case DEATH_TURRET_PLASMA:
                                sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_MIN);
-                               pointparticles(particleeffectnum(EFFECT_ELECTRO_IMPACT), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_ELECTRO_IMPACT, self.origin, w_backoff * 1000, 1);
                                break;
  
                         case DEATH_TURRET_WALK_MELEE:
                                sound(self, CH_SHOTS, SND_RIC1, VOL_BASE, ATTEN_MIN);
-                               pointparticles(particleeffectnum(EFFECT_TE_SPARK), self.origin, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_TE_SPARK, self.origin, w_backoff * 1000, 1);
                                break;
  
                         case DEATH_TURRET_PHASER:
index 226d13dc3a9be43cbfa321d7cecf08a62140226e,77e1c545ac5b671afca4ee369012d0fa148eb58c..281687963000c68f3b47c3951b08ce7330438a55
@@@ -32,7 -32,9 +32,7 @@@ void ons_generator_ray_draw(entity this
  
  void ons_generator_ray_spawn(vector org)
  {
 -      entity e;
 -      e = spawn();
 -      e.classname = "ons_ray";
 +      entity e = new(ons_ray);
        setmodel(e, MDL_ONS_RAY);
        setorigin(e, org);
        e.angles = randomvec() * 360;
@@@ -56,11 -58,11 +56,11 @@@ void generator_draw(entity this
                if(random() < 0.9 - self.health / self.max_health)
                if(random() < 0.01)
                {
-                       pointparticles(particleeffectnum(EFFECT_ELECTRO_BALLEXPLODE), self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1);
+                       pointparticles(EFFECT_ELECTRO_BALLEXPLODE, self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1);
                        sound(self, CH_TRIGGER, SND_ONS_ELECTRICITY_EXPLODE, VOL_BASE, ATTEN_NORM);
                }
                else
-                       pointparticles(particleeffectnum(EFFECT_ONS_GENERATOR_DAMAGED), self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1);
+                       pointparticles(EFFECT_ONS_GENERATOR_DAMAGED, self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1);
  
                self.move_time = time + 0.1;
  
@@@ -77,7 -79,7 +77,7 @@@
        if(self.count==40||self.count==20)
        {
                sound(self, CH_TRIGGER, SND_ONS_SHOCKWAVE, VOL_BASE, ATTEN_NORM);
-               pointparticles(particleeffectnum(EFFECT_ELECTRO_COMBO), self.origin, '0 0 0', 6);
+               pointparticles(EFFECT_ELECTRO_COMBO, self.origin, '0 0 0', 6);
        }
  
        // rays
@@@ -90,7 -92,7 +90,7 @@@
        for(i=0;i < 10;++i)
        {
                org = self.origin + randompos('-30 -30 -30' * i + '0 0 -20', '30 30 30' * i + '0 0 20');
-               pointparticles(particleeffectnum(EFFECT_ONS_GENERATOR_GIB), org, '0 0 0', 1);
+               pointparticles(EFFECT_ONS_GENERATOR_GIB, org, '0 0 0', 1);
        }
  
        // Short explosion sound + small explosion
  
        // Particles
        org = self.origin + randompos(self.mins + '8 8 8', self.maxs + '-8 -8 -8');
-       pointparticles(particleeffectnum(EFFECT_ONS_GENERATOR_EXPLODE), org, '0 0 0', 1);
+       pointparticles(EFFECT_ONS_GENERATOR_EXPLODE, org, '0 0 0', 1);
  
        // Final explosion
        if(self.count==1)
        {
                org = self.origin;
                te_explosion(org);
-               pointparticles(particleeffectnum(EFFECT_ONS_GENERATOR_EXPLODE2), org, '0 0 0', 1);
+               pointparticles(EFFECT_ONS_GENERATOR_EXPLODE2, org, '0 0 0', 1);
                sound(self, CH_TRIGGER, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
        }
  
diff --combined qcsrc/client/gibs.qc
index 5c5e69f1f38cfefb0bb65a92461ce3e204000421,6b27d0a41a0d2349a7f879d78c76ca426c612934..73d7f04968e9a5ff44c88efb8402d7a8994d71b3
@@@ -61,7 -61,7 +61,7 @@@ void new_te_bloodshower (int ef, vecto
        float i, pmod;
        pmod = autocvar_cl_particles_quality;
        for (i = 0; i < 50 * pmod; ++i)
-               pointparticles(ef, org, randomvec() * explosionspeed, howmany / 50);
+               __pointparticles(ef, org, randomvec() * explosionspeed, howmany / 50);
  }
  
  void SUB_RemoveOnNoImpact()
@@@ -82,7 -82,7 +82,7 @@@ void Gib_Touch(
  
        if(!self.silent)
                sound(self, CH_PAIN, SND_GIB_SPLAT_RANDOM(), VOL_BASE, ATTEN_NORM);
-       pointparticles(_particleeffectnum(strcat(species_prefix(self.cnt), "blood")), self.origin + '0 0 1', '0 0 30', 10);
+       __pointparticles(_particleeffectnum(strcat(species_prefix(self.cnt), "blood")), self.origin + '0 0 1', '0 0 30', 10);
  
        Gib_Delete();
  }
@@@ -98,9 -98,9 +98,9 @@@ void Gib_Draw(entity this
  
        if(self.touch == Gib_Touch) // don't do this for the "chunk" thingie...
                // TODO somehow make it spray in a direction dependent on self.angles
-               trailparticles(self, _particleeffectnum(strcat(species_prefix(self.cnt), EFFECT_TR_SLIGHTBLOOD.eent_eff_name)), oldorg, self.origin);
+               __trailparticles(self, _particleeffectnum(strcat(species_prefix(self.cnt), EFFECT_TR_SLIGHTBLOOD.eent_eff_name)), oldorg, self.origin);
        else
-               trailparticles(self, _particleeffectnum(strcat(species_prefix(self.cnt), EFFECT_TR_BLOOD.eent_eff_name)), oldorg, self.origin);
+               __trailparticles(self, _particleeffectnum(strcat(species_prefix(self.cnt), EFFECT_TR_BLOOD.eent_eff_name)), oldorg, self.origin);
  
        self.renderflags = 0;
  
@@@ -123,6 -123,7 +123,6 @@@ void TossGib (string mdlname, vector sa
  
        // TODO remove some gibs according to cl_nogibs
        gib = RubbleNew("gib");
 -      gib.classname = "gib";
        gib.move_movetype = MOVETYPE_BOUNCE;
        gib.gravity = 1;
        gib.solid = SOLID_CORPSE;
        RubbleLimit("gib", autocvar_cl_gibs_maxcount, Gib_Delete);
  }
  
 -void Ent_GibSplash(bool isNew)
 -{SELFPARAM();
 -      int amount, type, specnum;
 -      vector org, vel;
 -      string specstr;
 -      bool issilent;
 -      string gentle_prefix = "morphed_";
 +REGISTER_NET_TEMP(net_gibsplash, bool isNew)
 +{
 +      Net_Accept(net_gibsplash);
  
 -      float randomvalue;
 -      int c;
 +      string gentle_prefix = "morphed_";
  
 -      type = ReadByte(); // gibbage type
 -      amount = ReadByte() / 16.0; // gibbage amount
 +      int type = ReadByte(); // gibbage type
 +      int amount = ReadByte() / 16.0; // gibbage amount
 +      vector org;
        org.x = ReadShort() * 4 + 2;
        org.y = ReadShort() * 4 + 2;
        org.z = ReadShort() * 4 + 2;
 -      vel = decompressShortVector(ReadShort());
 +      vector vel = decompressShortVector(ReadShort());
  
        float cl_gentle_gibs = autocvar_cl_gentle_gibs;
        if(cl_gentle_gibs || autocvar_cl_gentle)
        if(amount <= 0 || !isNew)
                return;
  
 -      setorigin(self, org); // for the sounds
 +      setorigin(this, org); // for the sounds
  
 -      specnum = (type & 0x78) / 8; // blood/gibmodel type: using four bits (0..7, bit indexes 3,4,5)
 -      issilent = (type & 0x40);
 +      int specnum = (type & 0x78) / 8; // blood/gibmodel type: using four bits (0..7, bit indexes 3,4,5)
 +      bool issilent = (type & 0x40);
        type = type & 0x87; // remove the species bits: bit 7 = gentle, bit 0,1,2 = kind of gib
 -      specstr = species_prefix(specnum);
 +      string specstr = species_prefix(specnum);
  
        switch(type)
        {
                case 0x01:
                        if(!issilent)
 -                              sound (self, CH_PAIN, SND_GIB, VOL_BASE, ATTEN_NORM);
 +                              sound (this, CH_PAIN, SND_GIB, VOL_BASE, ATTEN_NORM);
  
                        if(prandom() < amount)
                                TossGib ("models/gibs/eye.md3", org, org, vel, prandomvec() * 150, specnum, 0, issilent);
                        if(prandom() < amount)
                                TossGib ("models/gibs/bloodyskull.md3", org, org + 16 * prandomvec(), vel, prandomvec() * 100, specnum, 0, issilent);
  
 -                      for(c = 0; c < amount; ++c)
 +                      for(int c = 0; c < amount; ++c)
                        {
 -                              randomvalue = amount - c;
 +                              int randomvalue = amount - c;
  
                                if(prandom() < randomvalue)
                                        TossGib ("models/gibs/arm.md3", org, org + 16 * prandomvec() + '0 0 8', vel, prandomvec() * (prandom() * 120 + 90), specnum,0, issilent);
                        }
                        break;
                case 0x02:
-                       pointparticles(_particleeffectnum(strcat(specstr, "blood")), org, vel, amount * 16);
+                       __pointparticles(_particleeffectnum(strcat(specstr, "blood")), org, vel, amount * 16);
                        break;
                case 0x03:
                        if(prandom() < amount)
                                TossGib ("models/gibs/chunk.mdl", org, org, vel, prandomvec() * (prandom() * 30 + 20), specnum, 1, issilent); // TODO maybe adjust to more randomization?
                        break;
                case 0x81:
-                       pointparticles(_particleeffectnum(strcat(gentle_prefix, "damage_dissolve")), org, vel, amount);
+                       __pointparticles(_particleeffectnum(strcat(gentle_prefix, "damage_dissolve")), org, vel, amount);
                        break;
                case 0x82:
-                       pointparticles(_particleeffectnum(strcat(gentle_prefix, "damage_hit")), org, vel, amount * 16);
+                       __pointparticles(_particleeffectnum(strcat(gentle_prefix, "damage_hit")), org, vel, amount * 16);
                        break;
                case 0x83:
                        // no gibs in gentle mode, sorry
                        break;
        }
 +      remove(this);
  }
diff --combined qcsrc/client/hud.qh
index cbdfb0c47868f2b2a43b54c2fc1162cc3bd711a9,60386ac1e683c1f2e26e1678ca309e67eed569e0..06eea919dc939026d6dead7f2bc86212893713dc
@@@ -6,13 -6,13 +6,14 @@@
  bool HUD_Radar_Clickable();
  void HUD_Radar_Mouse();
  
- REGISTRY(hud_panels, 24)
+ REGISTRY(hud_panels, BITS(6))
+ #define hud_panels_from(i) _hud_panels_from(i, NULL)
  REGISTER_REGISTRY(Registerhud_panels)
  
  #define REGISTER_HUD_PANEL(id, draw_func, name, configflags, showflags) \
        void draw_func(); \
        REGISTER(Registerhud_panels, HUD_PANEL, hud_panels, id, m_id, new(hud_panel)) { \
 +              make_pure(this); \
                this.panel_id = this.m_id; \
                this.panel_draw = draw_func; \
                this.panel_name = #name; \
diff --combined qcsrc/client/main.qc
index fd5da629d2966aa7b83f796747fe880627b0759b,20f949bf3fc70b68f6e513c1412503a20531bc6d..6be7fa0474e2a158379fe6bbdf58f494995d2660
@@@ -42,7 -42,8 +42,7 @@@ void clearentity(entity e
  {
        if (!clearentity_ent)
        {
 -              clearentity_ent = spawn();
 -              clearentity_ent.classname = "clearentity";
 +              clearentity_ent = new(clearentity);
        }
        int n = e.entnum;
        copyentity(clearentity_ent, e);
@@@ -130,6 -131,7 +130,7 @@@ void CSQC_Init(void
        // needs to be done so early because of the constants they create
        static_init();
        static_init_late();
+       static_init_precache();
  
        // precaches
  
@@@ -296,10 -298,7 +297,10 @@@ void Playerchecker_Think(
                        {
                                // player connected
                                if (!e)
 -                                      playerslots[i] = e = spawn();
 +                              {
 +                                      playerslots[i] = e = new(playerslot);
 +                                      make_pure(e);
 +                              }
                                e.sv_entnum = i;
                                e.ping = 0;
                                e.ping_packetloss = 0;
@@@ -318,8 -317,8 +319,8 @@@ void Porto_Init()
  void TrueAim_Init();
  void PostInit(void)
  {
 -      entity playerchecker;
 -      playerchecker = spawn();
 +      entity playerchecker = new(playerchecker);
 +      make_pure(playerchecker);
        playerchecker.think = Playerchecker_Think;
        playerchecker.nextthink = time + 0.2;
  
@@@ -375,9 -374,8 +376,9 @@@ void Ent_RemoveEntCS(
  }
  void Ent_ReadEntCS()
  {SELFPARAM();
 +      make_pure(this);
 +      this.classname = "entcs_receiver";
        InterpolateOrigin_Undo();
 -      self.classname = "entcs_receiver";
        int sf = ReadByte();
  
        if(sf & BIT(0))
@@@ -421,7 -419,6 +422,7 @@@ void Ent_RemovePlayerScore(
  
  void Ent_ReadPlayerScore()
  {SELFPARAM();
 +      make_pure(this);
        int i, n;
        bool isNew;
        entity o;
  
        self.sv_entnum = n;
  
 -      if (!(playerslots[self.sv_entnum]))
 -              playerslots[self.sv_entnum] = spawn();
 -      o = self.owner = playerslots[self.sv_entnum];
 +      o = playerslots[self.sv_entnum];
 +      if (!o)
 +      {
 +              o = playerslots[self.sv_entnum] = new(playerslot);
 +              make_pure(o);
 +      }
 +      self.owner = o;
        o.sv_entnum = self.sv_entnum;
        o.gotscores = 1;
  
  
  void Ent_ReadTeamScore()
  {SELFPARAM();
 +      make_pure(this);
        int i;
        entity o;
  
  
  void Ent_ClientData()
  {
 +      make_pure(self);
        float newspectatee_status;
  
      int f = ReadByte();
  
  void Ent_Nagger()
  {
 +      make_pure(self);
      int i, j, b, f;
  
      int nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS
  
  void Ent_EliminatedPlayers()
  {
 +      make_pure(self);
      int i, j, b, f;
  
      int sf = ReadByte();
  
  void Ent_RandomSeed()
  {
 -      float s;
 +      make_pure(self);
        prandom_debug();
 -      s = ReadShort();
 +      float s = ReadShort();
        psrandom(s);
  }
  
  void Ent_ReadAccuracy()
  {
 +      make_pure(self);
      int sf = ReadInt24_t();
        if (sf == 0) {
                for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
  
  void Spawn_Draw(entity this)
  {
-       pointparticles(this.cnt, this.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1));
+       __pointparticles(this.cnt, this.origin + '0 0 28', '0 0 2', bound(0, frametime, 0.1));
  }
  
  void Ent_ReadSpawnPoint(float is_new) // entity for spawnpoint
@@@ -745,11 -733,11 +746,11 @@@ void Ent_ReadSpawnEvent(float is_new
                        {
                                switch(teamnum)
                                {
-                                       case NUM_TEAM_1: pointparticles(particleeffectnum(EFFECT_SPAWN_RED), self.origin, '0 0 0', 1); break;
-                                       case NUM_TEAM_2: pointparticles(particleeffectnum(EFFECT_SPAWN_BLUE), self.origin, '0 0 0', 1); break;
-                                       case NUM_TEAM_3: pointparticles(particleeffectnum(EFFECT_SPAWN_YELLOW), self.origin, '0 0 0', 1); break;
-                                       case NUM_TEAM_4: pointparticles(particleeffectnum(EFFECT_SPAWN_PINK), self.origin, '0 0 0', 1); break;
-                                       default: pointparticles(particleeffectnum(EFFECT_SPAWN_NEUTRAL), self.origin, '0 0 0', 1); break;
+                                       case NUM_TEAM_1: pointparticles(EFFECT_SPAWN_RED, self.origin, '0 0 0', 1); break;
+                                       case NUM_TEAM_2: pointparticles(EFFECT_SPAWN_BLUE, self.origin, '0 0 0', 1); break;
+                                       case NUM_TEAM_3: pointparticles(EFFECT_SPAWN_YELLOW, self.origin, '0 0 0', 1); break;
+                                       case NUM_TEAM_4: pointparticles(EFFECT_SPAWN_PINK, self.origin, '0 0 0', 1); break;
+                                       default: pointparticles(EFFECT_SPAWN_NEUTRAL, self.origin, '0 0 0', 1); break;
                                }
                        }
                        if(autocvar_cl_spawn_event_sound)
@@@ -781,12 -769,11 +782,12 @@@ void Ent_RadarLink()
  void Ent_Init();
  void Ent_ScoresInfo();
  void CSQC_Ent_Update(float bIsNewEntity)
 -{SELFPARAM();
 +{
 +      SELFPARAM();
        int t = ReadByte();
  
        if(autocvar_developer_csqcentities)
 -              LOG_INFOF("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t);
 +              LOG_INFOF("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, this, this.entnum, this.enttype, t);
  
        // set up the "time" global for received entities to be correct for interpolation purposes
        float savetime = time;
        }
  
  #ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
 -      if(self.enttype)
 +      if(this.enttype)
        {
 -              if(t != self.enttype || bIsNewEntity)
 +              if(t != this.enttype || bIsNewEntity)
                {
 -                      LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t);
 +                      LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(this), this.entnum, this.enttype, t);
                        Ent_Remove();
 -                      clearentity(self);
 +                      clearentity(this);
                        bIsNewEntity = 1;
                }
        }
        {
                if(!bIsNewEntity)
                {
 -                      LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t);
 +                      LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(this), this.entnum, t);
                        bIsNewEntity = 1;
                }
        }
  #endif
 -      self.enttype = t;
 +      this.enttype = t;
        bool done = false;
        FOREACH(LinkedEntities, it.m_id == t, LAMBDA(
 -              it.m_read(self, bIsNewEntity);
 +              it.m_read(this, bIsNewEntity);
                done = true;
                break;
        ));
        if (!done)
        switch(t)
        {
 -              case ENT_CLIENT_MUTATOR: {
 +              #define HANDLE(t) case t: this.classname = #t; this.sourceLocFile = __FILE__; this.sourceLocLine = __LINE__;
 +              HANDLE(ENT_CLIENT_MUTATOR) {
                        int mutID = ReadMutator();
                        if (!MUTATOR_CALLHOOK(CSQC_Ent_Update, mutID, bIsNewEntity))
 -                      error(sprintf("Unknown mutator type in CSQC_Ent_Update (mutID: %d, edict: %d, classname: %s)\n", mutID, num_for_edict(self), self.classname));
 +                      error(sprintf("Unknown mutator type in CSQC_Ent_Update (mutID: %d, edict: %d, classname: %s)\n", mutID, num_for_edict(this), this.classname));
                        break;
                }
 -              case ENT_CLIENT_ENTCS: Ent_ReadEntCS(); break;
 -              case ENT_CLIENT_SCORES: Ent_ReadPlayerScore(); break;
 -              case ENT_CLIENT_TEAMSCORES: Ent_ReadTeamScore(); break;
 -              case ENT_CLIENT_POINTPARTICLES: Ent_PointParticles(); break;
 -              case ENT_CLIENT_RAINSNOW: Ent_RainOrSnow(); break;
 -              case ENT_CLIENT_LASER: Ent_Laser(); break;
 -              case ENT_CLIENT_NAGGER: Ent_Nagger(); break;
 -              case ENT_CLIENT_ELIMINATEDPLAYERS: Ent_EliminatedPlayers(); break;
 -              case ENT_CLIENT_RADARLINK: Ent_RadarLink(); break;
 -              case ENT_CLIENT_PROJECTILE: Ent_Projectile(); break;
 -              case ENT_CLIENT_GIBSPLASH: Ent_GibSplash(bIsNewEntity); break;
 -              case ENT_CLIENT_DAMAGEINFO: Ent_DamageInfo(bIsNewEntity); break;
 -              case ENT_CLIENT_INIT: Ent_Init(); break;
 -              case ENT_CLIENT_SCORES_INFO: Ent_ScoresInfo(); break;
 -              case ENT_CLIENT_MAPVOTE: Ent_MapVote(); break;
 -              case ENT_CLIENT_CLIENTDATA: Ent_ClientData(); break;
 -              case ENT_CLIENT_RANDOMSEED: Ent_RandomSeed(); break;
 -              case ENT_CLIENT_WALL: Ent_Wall(); break;
 -              case ENT_CLIENT_MODELEFFECT: Ent_ModelEffect(bIsNewEntity); break;
 -              case ENT_CLIENT_TUBANOTE: Ent_TubaNote(bIsNewEntity); break;
 -              case ENT_CLIENT_WARPZONE: WarpZone_Read(bIsNewEntity); break;
 -              case ENT_CLIENT_WARPZONE_CAMERA: WarpZone_Camera_Read(bIsNewEntity); break;
 -              case ENT_CLIENT_WARPZONE_TELEPORTED: WarpZone_Teleported_Read(bIsNewEntity); break;
 -              case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break;
 -              case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break;
 -              case ENT_CLIENT_INVENTORY: Inventory_Read(self); break;
 -              case ENT_CLIENT_ARC_BEAM: Ent_ReadArcBeam(bIsNewEntity); break;
 -              case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
 -              case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
 -              case ENT_CLIENT_TURRET: ent_turret(); break;
 -              case ENT_CLIENT_GENERATOR: ent_generator(); break;
 -              case ENT_CLIENT_CONTROLPOINT_ICON: ent_cpicon(this); break;
 -              case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
 -              case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
 -              case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
 -              case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break;
 -              case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break;
 -              case ENT_CLIENT_NOTIFICATION: Read_Notification(bIsNewEntity); break;
 -              case ENT_CLIENT_MINIGAME: ent_read_minigame(); break;
 -              case ENT_CLIENT_VIEWLOC: ent_viewloc(); break;
 -              case ENT_CLIENT_VIEWLOC_TRIGGER: ent_viewloc_trigger(); break;
 -              case ENT_CLIENT_LADDER: ent_func_ladder(); break;
 -              case ENT_CLIENT_TRIGGER_PUSH: ent_trigger_push(); break;
 -              case ENT_CLIENT_TARGET_PUSH: ent_target_push(); break;
 -              case ENT_CLIENT_CONVEYOR: ent_conveyor(); break;
 -              case ENT_CLIENT_DOOR: ent_door(); break;
 -              case ENT_CLIENT_PLAT: ent_plat(); break;
 -              case ENT_CLIENT_SWAMP: ent_swamp(); break;
 -              case ENT_CLIENT_CORNER: ent_corner(); break;
 -              case ENT_CLIENT_KEYLOCK: ent_keylock(); break;
 -              case ENT_CLIENT_TRAIN: ent_train(); break;
 -              case ENT_CLIENT_TRIGGER_IMPULSE: ent_trigger_impulse(); break;
 -              case ENT_CLIENT_EFFECT: Read_Effect(bIsNewEntity); break;
 -
 +              HANDLE(ENT_CLIENT_ENTCS)                                        Ent_ReadEntCS();                                                                break;
 +              HANDLE(ENT_CLIENT_SCORES)                                       Ent_ReadPlayerScore();                                                  break;
 +              HANDLE(ENT_CLIENT_TEAMSCORES)                           Ent_ReadTeamScore();                                                    break;
 +              HANDLE(ENT_CLIENT_POINTPARTICLES)                       Ent_PointParticles();                                                   break;
 +              HANDLE(ENT_CLIENT_RAINSNOW)                                     Ent_RainOrSnow();                                                               break;
 +              HANDLE(ENT_CLIENT_LASER)                                        Ent_Laser();                                                                    break;
 +              HANDLE(ENT_CLIENT_NAGGER)                                       Ent_Nagger();                                                                   break;
 +              HANDLE(ENT_CLIENT_ELIMINATEDPLAYERS)            Ent_EliminatedPlayers();                                                break;
 +              HANDLE(ENT_CLIENT_RADARLINK)                            Ent_RadarLink();                                                                break;
 +              HANDLE(ENT_CLIENT_PROJECTILE)                           Ent_Projectile();                                                               break;
 +              HANDLE(ENT_CLIENT_DAMAGEINFO)                           Ent_DamageInfo(bIsNewEntity);                                   break;
 +              HANDLE(ENT_CLIENT_INIT)                                         Ent_Init();                                                                             break;
 +              HANDLE(ENT_CLIENT_SCORES_INFO)                          Ent_ScoresInfo();                                                               break;
 +              HANDLE(ENT_CLIENT_MAPVOTE)                                      Ent_MapVote();                                                                  break;
 +              HANDLE(ENT_CLIENT_CLIENTDATA)                           Ent_ClientData();                                                               break;
 +              HANDLE(ENT_CLIENT_RANDOMSEED)                           Ent_RandomSeed();                                                               break;
 +              HANDLE(ENT_CLIENT_WALL)                                         Ent_Wall();                                                                             break;
 +              HANDLE(ENT_CLIENT_MODELEFFECT)                          Ent_ModelEffect(bIsNewEntity);                                  break;
 +              HANDLE(ENT_CLIENT_TUBANOTE)                                     Ent_TubaNote(bIsNewEntity);                                             break;
 +              HANDLE(ENT_CLIENT_WARPZONE)                                     WarpZone_Read(bIsNewEntity);                                    break;
 +              HANDLE(ENT_CLIENT_WARPZONE_CAMERA)                      WarpZone_Camera_Read(bIsNewEntity);                             break;
 +              HANDLE(ENT_CLIENT_WARPZONE_TELEPORTED)          WarpZone_Teleported_Read(bIsNewEntity);                 break;
 +              HANDLE(ENT_CLIENT_TRIGGER_MUSIC)                        Ent_ReadTriggerMusic();                                                 break;
 +              HANDLE(ENT_CLIENT_HOOK)                                         Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK);    break;
 +              HANDLE(ENT_CLIENT_INVENTORY)                            Inventory_Read(this);                                                   break;
 +              HANDLE(ENT_CLIENT_ARC_BEAM)                                     Ent_ReadArcBeam(bIsNewEntity);                                  break;
 +              HANDLE(ENT_CLIENT_ACCURACY)                                     Ent_ReadAccuracy();                                                             break;
 +              HANDLE(ENT_CLIENT_AUXILIARYXHAIR)                       Net_AuXair2(bIsNewEntity);                                              break;
 +              HANDLE(ENT_CLIENT_TURRET)                                       ent_turret();                                                                   break;
 +              HANDLE(ENT_CLIENT_GENERATOR)                            ent_generator();                                                                break;
 +              HANDLE(ENT_CLIENT_CONTROLPOINT_ICON)            ent_cpicon(this);                                                               break;
 +              HANDLE(ENT_CLIENT_MODEL)                                        CSQCModel_Read(bIsNewEntity);                                   break;
 +              HANDLE(ENT_CLIENT_ITEM)                                         ItemRead(bIsNewEntity);                                                 break;
 +              HANDLE(ENT_CLIENT_BUMBLE_RAYGUN)                        bumble_raygun_read(bIsNewEntity);                               break;
 +              HANDLE(ENT_CLIENT_SPAWNPOINT)                           Ent_ReadSpawnPoint(bIsNewEntity);                               break;
 +              HANDLE(ENT_CLIENT_SPAWNEVENT)                           Ent_ReadSpawnEvent(bIsNewEntity);                               break;
 +              HANDLE(ENT_CLIENT_NOTIFICATION)                         Read_Notification(bIsNewEntity);                                break;
 +              HANDLE(ENT_CLIENT_MINIGAME)                                     ent_read_minigame();                                                    break;
 +              HANDLE(ENT_CLIENT_VIEWLOC)                                      ent_viewloc();                                                                  break;
 +              HANDLE(ENT_CLIENT_VIEWLOC_TRIGGER)                      ent_viewloc_trigger();                                                  break;
 +              HANDLE(ENT_CLIENT_LADDER)                                       ent_func_ladder();                                                              break;
 +              HANDLE(ENT_CLIENT_TRIGGER_PUSH)                         ent_trigger_push();                                                             break;
 +              HANDLE(ENT_CLIENT_TARGET_PUSH)                          ent_target_push();                                                              break;
 +              HANDLE(ENT_CLIENT_CONVEYOR)                                     ent_conveyor();                                                                 break;
 +              HANDLE(ENT_CLIENT_DOOR)                                         ent_door();                                                                             break;
 +              HANDLE(ENT_CLIENT_PLAT)                                         ent_plat();                                                                             break;
 +              HANDLE(ENT_CLIENT_SWAMP)                                        ent_swamp();                                                                    break;
 +              HANDLE(ENT_CLIENT_CORNER)                                       ent_corner();                                                                   break;
 +              HANDLE(ENT_CLIENT_KEYLOCK)                                      ent_keylock();                                                                  break;
 +              HANDLE(ENT_CLIENT_TRAIN)                                        ent_train();                                                                    break;
 +              HANDLE(ENT_CLIENT_TRIGGER_IMPULSE)                      ent_trigger_impulse();                                                  break;
 +              #undef HANDLE
                default:
 -                      //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype));
 -                      error(sprintf("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n", self.enttype, num_for_edict(self), self.classname));
 +                      //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), this.enttype));
 +                      error(sprintf("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n", this.enttype, num_for_edict(this), this.classname));
                        break;
        }
  
@@@ -991,7 -979,7 +992,7 @@@ void Gamemode_Init()
  void Ent_ScoresInfo()
  {SELFPARAM();
      int i;
 -      self.classname = "ent_client_scores_info";
 +      make_pure(this);
        gametype = ReadInt24_t();
        HUD_ModIcons_SetFunc();
        for(i = 0; i < MAX_SCORE; ++i)
  
  void Ent_Init()
  {SELFPARAM();
 -      self.classname = "ent_client_init";
 +      make_pure(this);
  
        nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th
  
index 05548c9e168d4d7b551cc6fe566991a60ffebf78,28f5a16b782522a5164b084722fe442bcbb3fc42..42aa6bb52b29ddd568bb8a180b5eb9c1303aded4
@@@ -3,7 -3,8 +3,8 @@@
  
  #include "../notifications.qh"
  
- REGISTRY(Deathtypes, BIT(6))
+ REGISTRY(Deathtypes, BITS(8))
+ #define Deathtypes_from(i) _Deathtypes_from(i, NULL)
  REGISTER_REGISTRY(RegisterDeathtypes)
  
  .entity death_msgself;
@@@ -12,7 -13,6 +13,7 @@@
  
  #define REGISTER_DEATHTYPE(id, msg_death, msg_death_by, extra) \
      REGISTER(RegisterDeathtypes, DEATH, Deathtypes, id, m_id, new(deathtype)) { \
 +        make_pure(this); \
          this.m_id += DT_FIRST; \
          this.nent_name = #id; \
          this.death_msgextra = extra; \
@@@ -33,11 -33,11 +34,11 @@@ const int DEATH_HITTYPEMASK = HITTYPE_S
  const int DT_FIRST = BIT(13);
  
  #define DEATH_ISSPECIAL(t)      (t >= DT_FIRST)
- #define DEATH_IS(t, dt)         (DEATH_ISSPECIAL(t) && (Deathtypes[t - DT_FIRST]) == dt)
- #define DEATH_ENT(t)            (DEATH_ISSPECIAL(t) ?  (Deathtypes[t - DT_FIRST]) : NULL)
- #define DEATH_ISVEHICLE(t)      (DEATH_ISSPECIAL(t) && (Deathtypes[t - DT_FIRST]).death_msgextra == "vehicle")
- #define DEATH_ISTURRET(t)       (DEATH_ISSPECIAL(t) && (Deathtypes[t - DT_FIRST]).death_msgextra == "turret")
- #define DEATH_ISMONSTER(t)      (DEATH_ISSPECIAL(t) && (Deathtypes[t - DT_FIRST]).death_msgextra == "monster")
+ #define DEATH_IS(t, dt)         (DEATH_ISSPECIAL(t) && (Deathtypes_from(t - DT_FIRST)) == dt)
+ #define DEATH_ENT(t)            (DEATH_ISSPECIAL(t) ?  (Deathtypes_from(t - DT_FIRST)) : NULL)
+ #define DEATH_ISVEHICLE(t)      (DEATH_ISSPECIAL(t) && (Deathtypes_from(t - DT_FIRST)).death_msgextra == "vehicle")
+ #define DEATH_ISTURRET(t)       (DEATH_ISSPECIAL(t) && (Deathtypes_from(t - DT_FIRST)).death_msgextra == "turret")
+ #define DEATH_ISMONSTER(t)      (DEATH_ISSPECIAL(t) && (Deathtypes_from(t - DT_FIRST)).death_msgextra == "monster")
  #define DEATH_WEAPONOF(t)       (DEATH_ISSPECIAL(t) ? WEP_Null : get_weaponinfo((t) & DEATH_WEAPONMASK))
  #define DEATH_ISWEAPON(t, w)    (DEATH_WEAPONOF(t) == (w))
  
index 7172a202abda3008109bdfc412ca20e81263ec7f,a18d741f61a0c8571905ab435c13d11a885e8cab..bc739192245ce8beadc88a30fec8a04d3811bc19
@@@ -1,16 -1,15 +1,16 @@@
  #include "all.qh"
  
 +REGISTER_NET_TEMP(net_effect, bool isNew)
  #ifdef CSQC
 -void Read_Effect(bool is_new)
  {
        int net_name = (Effects_COUNT >= 255) ? ReadShort() : ReadByte();
  
-       entity eff = Effects[net_name];
+       entity eff = Effects_from(net_name);
  
 -      vector v, vel = '0 0 0';
 +      vector vel = '0 0 0';
        int eff_cnt = 1;
        bool eff_trail = eff.eent_eff_trail;
 +      vector v;
        v_x = ReadCoord();
        v_y = ReadCoord();
        v_z = ReadCoord();
        if(!eff_trail)
                eff_cnt = ReadByte();
  
 -      if(is_new)
 -      {
 -              if(eff_trail)
 -                      WarpZone_TrailParticles(world, particleeffectnum(eff), v, vel);
 -              else
 -                      pointparticles(eff, v, vel, eff_cnt);
 -      }
 +      if(eff_trail)
 +              WarpZone_TrailParticles(world, particleeffectnum(eff), v, vel);
 +      else
-               pointparticles(particleeffectnum(eff), v, vel, eff_cnt);
++              pointparticles(eff, v, vel, eff_cnt);
  }
  #endif
  
  #ifdef SVQC
  bool Net_Write_Effect(entity this, entity client, int sf)
  {
 -      WriteByte(MSG_ENTITY, ENT_CLIENT_EFFECT);
 +      int channel = MSG_ONE;
 +      msg_entity = client;
 +      WriteHeader(channel, net_effect);
        (Effects_COUNT >= 255)
 -      ? WriteShort(MSG_ENTITY, self.m_id)
 -      : WriteByte(MSG_ENTITY, self.m_id);
 -      WriteCoord(MSG_ENTITY, self.eent_net_location_x);
 -      WriteCoord(MSG_ENTITY, self.eent_net_location_y);
 -      WriteCoord(MSG_ENTITY, self.eent_net_location_z);
 +      ? WriteShort(channel, this.m_id)
 +      : WriteByte(channel, this.m_id);
 +      WriteCoord(channel, this.eent_net_location_x);
 +      WriteCoord(channel, this.eent_net_location_y);
 +      WriteCoord(channel, this.eent_net_location_z);
  
        // attempt to save a tiny bit more bandwidth by not sending velocity if it isn't set
 -      if(self.eent_net_velocity)
 +      if(this.eent_net_velocity)
        {
 -              WriteByte(MSG_ENTITY, true);
 -              WriteCoord(MSG_ENTITY, self.eent_net_velocity_x);
 -              WriteCoord(MSG_ENTITY, self.eent_net_velocity_y);
 -              WriteCoord(MSG_ENTITY, self.eent_net_velocity_z);
 +              WriteByte(channel, true);
 +              WriteCoord(channel, this.eent_net_velocity_x);
 +              WriteCoord(channel, this.eent_net_velocity_y);
 +              WriteCoord(channel, this.eent_net_velocity_z);
        }
 -      else { WriteByte(MSG_ENTITY, false); }
 +      else { WriteByte(channel, false); }
  
 -      if(!self.eent_eff_trail) { WriteByte(MSG_ENTITY, self.eent_net_count); }
 +      if(!this.eent_eff_trail) { WriteByte(channel, this.eent_net_count); }
        return true;
  }
  
@@@ -64,9 -64,9 +64,9 @@@ void Send_Effect(entity eff, vector eff
  {
        if(!eff) { return; }
        if(!eff.eent_eff_trail && !eff_cnt) { return; } // effect has no count!
 -      entity net_eff = spawn();
 +      entity net_eff = new(net_effect);
 +      make_pure(net_eff);
        net_eff.owner = eff;
 -      net_eff.classname = "net_effect";
        //net_eff.eent_broadcast = broadcast;
        net_eff.m_id = eff.m_id;
        net_eff.eent_net_velocity = eff_vel;
        net_eff.eent_net_count = eff_cnt;
        net_eff.eent_eff_trail = eff.eent_eff_trail;
  
 -      net_eff.think = SUB_Remove;
 -      net_eff.nextthink = time + 0.2; // don't need to keep this long
 -
 -      Net_LinkEntity(net_eff, false, 0, Net_Write_Effect);
 +      entity e; FOR_EACH_REALCLIENT(e) Net_Write_Effect(net_eff, e, 0);
 +      remove(net_eff);
  }
  
  void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
@@@ -86,6 -88,6 +86,6 @@@
                return;
        ));
        // revert to engine handling
-       pointparticles(_particleeffectnum(eff_name), eff_loc, eff_vel, eff_cnt);
+       __pointparticles(_particleeffectnum(eff_name), eff_loc, eff_vel, eff_cnt);
  }
  #endif
index 1e6b3cbf2432c7d588d87bd04a2758d2a3a1e176,5006ff090390c8e48bc6386b35df4c2215b44739..87bd63e757ee52794d89b08361c8eef0ed644e4c
@@@ -3,12 -3,15 +3,13 @@@
  
  #include "effect.qh"
  
 -#ifdef CSQC
 -void Read_Effect(bool is_new);
 -#elif defined(SVQC)
 +#ifdef SVQC
  void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt);
  void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt);
  #endif
  
- REGISTRY(Effects, BIT(8))
+ REGISTRY(Effects, BITS(8))
+ #define Effects_from(i) _Effects_from(i, EFFECT_Null)
  REGISTER_REGISTRY(RegisterEffects)
  #define EFFECT(istrail, name, realname) \
      REGISTER(RegisterEffects, EFFECT, Effects, name, m_id, Create_Effect_Entity(realname, istrail));
index bc8f8483e3a2fcee09c17973489b0d43eb67369a,088136492b48954b2b151bd25df5f6a045cb2763..0ae9b489360d84b58df2ecddbef48f9af100ca22
@@@ -1,7 -1,21 +1,21 @@@
  #ifndef EFFECT_H
  #define EFFECT_H
  
- #define particleeffectnum(e) _particleeffectnum(e.eent_eff_name)
+ #define particleeffectnum(e) \
+       _particleeffectnum(e.eent_eff_name)
+ #if defined(SVQC)
+       #define pointparticles(effect, org, vel, howmany) \
+               Send_Effect(effect, org, vel, howmany)
+       #define trailparticles(e, effect, org, vel) \
+               ((!e) ? Send_Effect(effect, org, vel, 0) \
+               : __trailparticles(e, particleeffectnum(effect), org, vel))
+ #elif defined(CSQC)
+       #define pointparticles(effect, org, vel, howmany) \
+               __pointparticles(particleeffectnum(effect), org, vel, howmany)
+       #define trailparticles(e, effect, org, vel) \
+               __trailparticles(e, particleeffectnum(effect), org, vel)
+ #endif
  
  .int m_id;
  .string eent_eff_name;
@@@ -14,7 -28,6 +28,7 @@@
  entity Create_Effect_Entity(string eff_name, bool eff_trail)
  {
        entity this = new(effect_entity);
 +      make_pure(this);
        this.eent_eff_name = eff_name;
        this.eent_eff_trail = eff_trail;
        return this;
index dc158a69a6d0b85078f2dd944fbe938639bd3178,9a8df7854666d17508dfae51a38d7450bdc07bad..3dc5c107fe9a26e29513600eb7b203713c1aebf4
@@@ -451,7 -451,9 +451,7 @@@ spawnfunc(nexball_team
  void nb_spawnteam(string teamname, float teamcolor)
  {
        LOG_TRACE("^2spawned team ", teamname, "\n");
 -      entity e;
 -      e = spawn();
 -      e.classname = "nexball_team";
 +      entity e = new(nexball_team);
        e.netname = teamname;
        e.cnt = teamcolor;
        e.team = e.cnt + 1;
@@@ -802,9 -804,10 +802,9 @@@ void W_Nexball_Attack2(void
                return;
  
        W_SetupShot(self, false, 2, SND(NB_SHOOT2), CH_WEAPON_A, 0);
 -      entity missile = spawn();
 +      entity missile = new(ballstealer);
  
        missile.owner = self;
 -      missile.classname = "ballstealer";
  
        missile.movetype = MOVETYPE_FLY;
        PROJECTILE_MAKETRIGGER(missile);
@@@ -1066,10 -1069,6 +1066,6 @@@ MUTATOR_HOOKFUNCTION(nb, SendWaypoint
  
  REGISTER_MUTATOR(nb, g_nexball)
  {
-       ActivateTeamplay();
-       SetLimits(autocvar_g_nexball_goallimit, autocvar_g_nexball_goalleadlimit, -1, -1);
-       have_team_spawns = -1; // request team spawns
        MUTATOR_ONADD
        {
                g_nexball_meter_period = autocvar_g_nexball_meter_period;
  
                InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE);
                WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
+               ActivateTeamplay();
+               SetLimits(autocvar_g_nexball_goallimit, autocvar_g_nexball_goalleadlimit, -1, -1);
+               have_team_spawns = -1; // request team spawns
        }
  
        MUTATOR_ONROLLBACK_OR_REMOVE
index 223e2c0b95902a56b59cd264ac8f03cb0595c3a3,9a5131995ef210e1916a979894bbf775375c4658..aacfc2309f6950f436f83881b4ad5922f4cb56f0
@@@ -114,15 -114,16 +114,16 @@@ void HUD_MinigameMenu_CustomEntry(entit
        while( (entityvar = findentity(entityvar,owner,active_minigame)) )
  
  
- REGISTRY(Minigames, BIT(3))
+ REGISTRY(Minigames, BITS(3))
+ #define Minigames_from(i) _Minigames_from(i, NULL)
  REGISTER_REGISTRY(RegisterMinigames)
  #define REGISTER_MINIGAME(name,nicename) \
 -    REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, spawn()); \
 +    REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, new(minigame_descriptor)); \
      void name##_hud_board(vector, vector); \
      void name##_hud_status(vector, vector); \
      int name##_client_event(entity, string, ...); \
      REGISTER_INIT_POST(MINIGAME, name) { \
 -        this.classname = "minigame_descriptor"; \
 +        make_pure(this); \
          this.netname = strzone(strtolower(#name)); \
          this.message = nicename; \
          this.minigame_hud_board = name##_hud_board; \
index b3a6ce2ee3efbffd8fda9ff41c79ad9cddec43c2,02c3c82fa32d399017de992346958fd8daa3273d..422e780819957e536fe5f845db6a4df7ffdd7767
@@@ -46,13 -46,14 +46,14 @@@ entity minigame_sessions
  
  bool minigame_SendEntity(entity this, entity to, int sf);
  
- REGISTRY(Minigames, BIT(3))
+ REGISTRY(Minigames, BITS(3))
+ #define Minigames_from(i) _Minigames_from(i, NULL)
  REGISTER_REGISTRY(RegisterMinigames)
  #define REGISTER_MINIGAME(name,nicename) \
 -    REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, spawn()); \
 +    REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, new(minigame_descriptor)); \
      int name##_server_event(entity, string, ...); \
      REGISTER_INIT_POST(MINIGAME, name) { \
 -        this.classname = "minigame_descriptor"; \
 +        make_pure(this); \
          this.netname = strzone(strtolower(#name)); \
          this.message = nicename; \
                this.minigame_event = name##_server_event; \
index 58ae391be9625edd93806466bda018c531ae5bdd,767cb97904035adbef0500dec457e618baf102f9..bb7577de88b8ac887eaca08decdeebbf02d5e711
@@@ -2,7 -2,7 +2,7 @@@
  #define SHAMBLER_H
  
  #ifndef MENUQC
- MODEL(MON_SHAMBLER, "models/monsters/shambler.mdl");
+ MODEL(MON_SHAMBLER, M_Model("shambler.mdl"));
  #endif
  
  CLASS(Shambler, Monster)
@@@ -149,8 -149,9 +149,8 @@@ void M_Shambler_Attack_Lightning(
  
        monster_makevectors(self.enemy);
  
 -      gren = spawn ();
 +      gren = new(grenade);
        gren.owner = gren.realowner = self;
 -      gren.classname = "grenade";
        gren.bot_dodge = true;
        gren.bot_dodgerating = (autocvar_g_monster_shambler_attack_lightning_damage);
        gren.movetype = MOVETYPE_BOUNCE;
index e29fe57b961a69d459cc24b460b2b2456efa7f14,01a006e13f85c478653006e205cab5bb6b16514e..bb58533c4dcc122f284bb9ee8ef552f82aee399a
@@@ -2,7 -2,7 +2,7 @@@
  #define SPIDER_H
  
  #ifndef MENUQC
- MODEL(MON_SPIDER, "models/monsters/spider.dpm");
+ MODEL(MON_SPIDER, M_Model("spider.dpm"));
  #endif
  
  CLASS(Spider, Monster)
@@@ -121,7 -121,8 +121,7 @@@ void M_Spider_Attack_Web(
  
        sound(self, CH_SHOTS, SND_ELECTRO_FIRE2, VOL_BASE, ATTEN_NORM);
  
 -      entity proj = spawn ();
 -      proj.classname = "plasma";
 +      entity proj = new(plasma);
        proj.owner = proj.realowner = self;
        proj.use = M_Spider_Attack_Web_Explode;
        proj.think = adaptor_think2use_hittype_splash;
index 7dbc9e3269bceac03b6127e16fe9b858f78da7a5,c91d0d0762e2f268a1e77f55ff93b6bd9e4cea42..a202486719c359fb19a53bc1f662bca4bb8af72d
@@@ -36,7 -36,7 +36,7 @@@ void monster_dropitem(
                return;
  
        vector org = self.origin + ((self.mins + self.maxs) * 0.5);
 -      entity e = spawn();
 +      entity e = new(droppedweapon); // use weapon handling to remove it on touch
        e.spawnfunc_checked = true;
  
        e.monster_loot = self.monster_loot;
@@@ -55,6 -55,7 +55,6 @@@
                setorigin(e, org);
                e.velocity = randomvec() * 175 + '0 0 325';
                e.item_spawnshieldtime = time + 0.7;
 -              e.classname = "droppedweapon"; // use weapon handling to remove it on touch
                SUB_SetFade(e, time + autocvar_g_monsters_drop_time, 1);
                setself(this);
        }
@@@ -1376,9 -1377,15 +1376,15 @@@ bool Monster_Spawn(int mon_id
                self.movetype = MOVETYPE_FLY;
        }
  
-       if(mon.spawnflags & MONSTER_SIZE_BROKEN)
        if(!(self.spawnflags & MONSTERFLAG_RESPAWNED))
-               self.scale *= 1.3;
+       {
+               if(mon.spawnflags & MONSTER_SIZE_BROKEN)
+                       self.scale *= 1.3;
+               if(mon.spawnflags & MONSTER_SIZE_QUAKE)
+               if(autocvar_g_monsters_quake_resize)
+                       self.scale *= 1.3;
+       }
  
        setsize(self, mon.mins * self.scale, mon.maxs * self.scale);
  
index 6bc672902c0e50f49ae9bba70b0e9ea5f8d4c80a,d5187b4b868399bdaa0356368f554649ab59a8d6..e04629b6f2c8f9220639bf3469f24de2a175f515
@@@ -3,7 -3,8 +3,8 @@@
  
  #include "waypointsprites.qh"
  
- REGISTRY(Waypoints, BIT(6))
+ REGISTRY(Waypoints, BITS(6))
+ #define Waypoints_from(i) _Waypoints_from(i, WP_Null)
  REGISTER_REGISTRY(RegisterWaypoints)
  /** If you register a new waypoint, make sure to add it to all.inc */
  #define REGISTER_WAYPOINT_(id, init) REGISTER(RegisterWaypoints, WP, Waypoints, id, m_id, init)
@@@ -26,9 -27,10 +27,10 @@@ ENDCLASS(Waypoint
  #define REGISTER_WAYPOINT(id, text, color, blink) REGISTER_WAYPOINT_(id, NEW(Waypoint, #id, text, color, blink))
  
  REGISTRY(RadarIcons, BITS(7))
+ #define RadarIcons_from(i) _RadarIcons_from(i, RADARICON_NONE)
  REGISTER_REGISTRY(RegisterRadarIcons)
  .int m_radaricon;
 -#define REGISTER_RADARICON(id, num) REGISTER(RegisterRadarIcons, RADARICON, RadarIcons, id, m_id, new(RadarIcon)) { this.m_radaricon = num; this.netname = #id; }
 +#define REGISTER_RADARICON(id, num) REGISTER(RegisterRadarIcons, RADARICON, RadarIcons, id, m_id, new(RadarIcon)) { make_pure(this); this.m_radaricon = num; this.netname = #id; }
  
  REGISTER_WAYPOINT(Null, "", '0 0 0', 1);
  
index 5dcecc03c5a4c715fee6ad87f200a367b3f4fb36,491bff1c810646d1b2c6d4f425aa3c080828459e..54eec3c9afa721095767f64ae14bfaa30f8f0f64
@@@ -224,7 -224,7 +224,7 @@@ float spritelookupblinkvalue(string s
          if (get_weaponinfo(self.wp_extra).spawnflags & WEP_FLAG_SUPERWEAPON)
              return 2;
      }
-     if (s == WP_Item.netname) return Items[self.wp_extra].m_waypointblink;
+     if (s == WP_Item.netname) return Items_from(self.wp_extra).m_waypointblink;
  
      return 1;
  }
  vector spritelookupcolor(entity this, string s, vector def)
  {
      if (s == WP_Weapon.netname  || s == RADARICON_Weapon.netname) return get_weaponinfo(this.wp_extra).wpcolor;
-     if (s == WP_Item.netname    || s == RADARICON_Item.netname) return Items[this.wp_extra].m_color;
-     if (s == WP_Buff.netname    || s == RADARICON_Buff.netname) return Buffs[this.wp_extra].m_color;
+     if (s == WP_Item.netname    || s == RADARICON_Item.netname) return Items_from(this.wp_extra).m_color;
+     if (s == WP_Buff.netname    || s == RADARICON_Buff.netname) return Buffs_from(this.wp_extra).m_color;
      return def;
  }
  
@@@ -241,8 -241,8 +241,8 @@@ string spritelookuptext(string s
  {SELFPARAM();
      if (s == WP_RaceStartFinish.netname) return (race_checkpointtime || race_mycheckpointtime) ? _("Finish") : _("Start");
      if (s == WP_Weapon.netname) return get_weaponinfo(self.wp_extra).m_name;
-     if (s == WP_Item.netname) return Items[self.wp_extra].m_waypoint;
-     if (s == WP_Buff.netname) return Buffs[self.wp_extra].m_prettyName;
+     if (s == WP_Item.netname) return Items_from(self.wp_extra).m_waypoint;
+     if (s == WP_Buff.netname) return Buffs_from(self.wp_extra).m_prettyName;
      if (s == WP_Monster.netname) return get_monsterinfo(self.wp_extra).monster_name;
  
      // need to loop, as our netname could be one of three
@@@ -993,7 -993,6 +993,7 @@@ entity WaypointSprite_Spawn
  )
  {
      entity wp = new(sprite_waypoint);
 +    make_pure(wp);
      wp.teleport_time = time + _lifetime;
      wp.fade_time = _lifetime;
      wp.exteriormodeltoclient = ref;
index 6b0dbeeea1060f65b0c6375ffe7408ac5a550f65,a38445b634cb3334f25b4a26a4e5cc30acce9ee0..449dd1f3a260432ebfc090cf2d0fb4038c2aa883
@@@ -45,11 -45,11 +45,11 @@@ void turret_draw(entity this
  
        if(self.health < 85)
        if(dt < 0.01)
-               pointparticles(particleeffectnum(EFFECT_SMOKE_LARGE), (self.origin + (randomvec() * 80)), '0 0 0', 1);
+               pointparticles(EFFECT_SMOKE_LARGE, (self.origin + (randomvec() * 80)), '0 0 0', 1);
  
        if(self.health < 32)
        if(dt < 0.015)
-               pointparticles(particleeffectnum(EFFECT_SMOKE_SMALL), (self.origin + (randomvec() * 80)), '0 0 0', 1);
+               pointparticles(EFFECT_SMOKE_SMALL, (self.origin + (randomvec() * 80)), '0 0 0', 1);
  
  }
  
@@@ -273,7 -273,7 +273,7 @@@ void turret_gibboom(
        float i;
  
        sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
-       pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, '0 0 0', 1);
+       pointparticles(EFFECT_ROCKET_EXPLODE, self.origin, '0 0 0', 1);
  
        for (i = 1; i < 5; i = i + 1)
                turret_gibtoss(strcat("models/turrets/head-gib", ftos(i), ".md3"), self.origin + '0 0 2', self.velocity + randomvec() * 700, '0 0 0', false);
@@@ -287,7 -287,7 +287,7 @@@ entity turret_gibtoss(string _model, ve
        if(trace_startsolid)
                return world;
  
 -      gib = spawn();
 +      gib = new(turret_gib);
        setorigin(gib, _from);
        _setmodel(gib, _model);
        gib.colormod    = _cmod;
        gib.move_avelocity  = prandomvec() * 32;
        gib.move_time      = time;
        gib.damageforcescale = 1;
 -      gib.classname = "turret_gib";
  
        return gib;
  }
  void turret_die()
  {SELFPARAM();
        sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
-       pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, '0 0 0', 1);
+       pointparticles(EFFECT_ROCKET_EXPLODE, self.origin, '0 0 0', 1);
        if (!autocvar_cl_nogibs)
        {
                // Base
index e1a5f1f726df650b2d51814ab2d761052ce31f08,1a315f4f4c70ac4e1e2a3fe6567e72da43856fb5..eb13fae3924c154d698d94919edb6c5019de3161
@@@ -455,8 -455,10 +455,8 @@@ void vehicles_reset_colors(
  
  void vehicles_clearreturn(entity veh)
  {
 -      entity ret;
        // Remove "return helper", if any.
 -      ret = findchain(classname, "vehicle_return");
 -      while(ret)
 +      for (entity ret = findchain(classname, "vehicle_return"); ret; ret = ret.chain)
        {
                if(ret.wp00 == veh)
                {
  
                        return;
                }
 -              ret = ret.chain;
        }
  }
  
@@@ -545,7 -548,8 +545,7 @@@ void vehicles_setreturn(entity veh
  
        vehicles_clearreturn(veh);
  
 -      ret = spawn();
 -      ret.classname   = "vehicle_return";
 +      ret = new(vehicle_return);
        ret.wp00           = veh;
        ret.team                = veh.team;
        ret.think          = vehicles_showwp;
@@@ -630,7 -634,7 +630,7 @@@ void vehicles_painframe(
                float _ftmp;
                _ftmp = self.owner.vehicle_health / 50;
                self.pain_frame = time + 0.1 + (random() * 0.5 * _ftmp);
-               pointparticles(particleeffectnum(EFFECT_SMOKE_SMALL), (self.origin + (randomvec() * 80)), '0 0 0', 1);
+               pointparticles(EFFECT_SMOKE_SMALL, (self.origin + (randomvec() * 80)), '0 0 0', 1);
  
                if(self.vehicle_flags & VHF_DMGSHAKE)
                        self.velocity += randomvec() * 30;
@@@ -1230,9 -1234,9 +1230,9 @@@ bool vehicle_initialize(entity veh, boo
  
        self.vehicle_flags |= VHF_ISVEHICLE;
  
 -      self.vehicle_viewport           = spawn();
 -      self.vehicle_hudmodel           = spawn();
 -      self.tur_head                           = spawn();
 +      self.vehicle_viewport           = new(vehicle_viewport);
 +      self.vehicle_hudmodel           = new(vehicle_hudmodel);
 +      self.tur_head                           = new(tur_head);
        self.tur_head.owner                     = self;
        self.takedamage                         = DAMAGE_NO;
        self.bot_attack                         = true;
index bc770804e2c51130dddd63e6d627a182cd1e3e7e,07ddea83317a6bcc09179830fa0a6279085227d7..b5415b3d1ce1279303289b04f5d213799b9e9079
@@@ -101,10 -101,10 +101,10 @@@ void Ent_ReadArcBeam(float isnew)
  .vector beam_color;
  .float beam_alpha;
  .float beam_thickness;
- .float beam_traileffect;
- .float beam_hiteffect;
+ .entity beam_traileffect;
+ .entity beam_hiteffect;
  .float beam_hitlight[4]; // 0: radius, 123: rgb
- .float beam_muzzleeffect;
+ .entity beam_muzzleeffect;
  .float beam_muzzlelight[4]; // 0: radius, 123: rgb
  .string beam_image;
  
@@@ -584,7 -584,8 +584,7 @@@ void W_Arc_Beam(float burst
        if(time - self.beam_prev > 1)
                sound(self, CH_WEAPON_A, SND_ARC_FIRE, VOL_BASE, ATTN_NORM);
  
 -      entity beam = self.arc_beam = spawn();
 -      beam.classname = "W_Arc_Beam";
 +      entity beam = self.arc_beam = new(W_Arc_Beam);
        beam.solid = SOLID_NOT;
        beam.think = W_Arc_Beam_Think;
        beam.owner = self;
@@@ -1257,18 -1258,18 +1257,18 @@@ void Ent_ReadArcBeam(float isnew
                                self.beam_color = '1 1 1';
                                self.beam_alpha = 0.5;
                                self.beam_thickness = 8;
-                               self.beam_traileffect = particleeffectnum(EFFECT_ARC_BEAM);
-                               self.beam_hiteffect = particleeffectnum(EFFECT_ARC_LIGHTNING);
+                               self.beam_traileffect = (EFFECT_ARC_BEAM);
+                               self.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
                                self.beam_hitlight[0] = 0;
                                self.beam_hitlight[1] = 1;
                                self.beam_hitlight[2] = 1;
                                self.beam_hitlight[3] = 1;
-                               self.beam_muzzleeffect = -1; //particleeffectnum(EFFECT_VORTEX_MUZZLEFLASH);
+                               self.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
                                self.beam_muzzlelight[0] = 0;
                                self.beam_muzzlelight[1] = 1;
                                self.beam_muzzlelight[2] = 1;
                                self.beam_muzzlelight[3] = 1;
-                               if(self.beam_muzzleeffect >= 0)
+                               if(self.beam_muzzleeffect)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                self.beam_color = '1 1 1';
                                self.beam_alpha = 0.5;
                                self.beam_thickness = 8;
-                               self.beam_traileffect = particleeffectnum(EFFECT_ARC_BEAM);
-                               self.beam_hiteffect = particleeffectnum(EFFECT_ARC_LIGHTNING);
+                               self.beam_traileffect = (EFFECT_ARC_BEAM);
+                               self.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
                                self.beam_hitlight[0] = 0;
                                self.beam_hitlight[1] = 1;
                                self.beam_hitlight[2] = 1;
                                self.beam_hitlight[3] = 1;
-                               self.beam_muzzleeffect = -1; // particleeffectnum(EFFECT_GRENADE_MUZZLEFLASH);
+                               self.beam_muzzleeffect = NULL; // (EFFECT_GRENADE_MUZZLEFLASH);
                                self.beam_muzzlelight[0] = 0;
                                self.beam_muzzlelight[1] = 1;
                                self.beam_muzzlelight[2] = 1;
                                self.beam_muzzlelight[3] = 1;
                                self.beam_image = "particles/lgbeam";
-                               if(self.beam_muzzleeffect >= 0)
+                               if(self.beam_muzzleeffect)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                self.beam_color = '1 1 1';
                                self.beam_alpha = 0.5;
                                self.beam_thickness = 8;
-                               self.beam_traileffect = particleeffectnum(EFFECT_ARC_BEAM_HEAL);
-                               self.beam_hiteffect = particleeffectnum(EFFECT_ARC_BEAM_HEAL_IMPACT);
+                               self.beam_traileffect = (EFFECT_ARC_BEAM_HEAL);
+                               self.beam_hiteffect = (EFFECT_ARC_BEAM_HEAL_IMPACT);
                                self.beam_hitlight[0] = 0;
                                self.beam_hitlight[1] = 1;
                                self.beam_hitlight[2] = 1;
                                self.beam_hitlight[3] = 1;
-                               self.beam_muzzleeffect = -1; //particleeffectnum(EFFECT_VORTEX_MUZZLEFLASH);
+                               self.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
                                self.beam_muzzlelight[0] = 0;
                                self.beam_muzzlelight[1] = 1;
                                self.beam_muzzlelight[2] = 1;
                                self.beam_muzzlelight[3] = 1;
                                self.beam_image = "particles/lgbeam";
-                               if(self.beam_muzzleeffect >= 0)
+                               if(self.beam_muzzleeffect)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                self.beam_color = '1 1 1';
                                self.beam_alpha = 0.5;
                                self.beam_thickness = 8;
-                               self.beam_traileffect = particleeffectnum(EFFECT_ARC_BEAM);
-                               self.beam_hiteffect = particleeffectnum(EFFECT_ARC_LIGHTNING);
+                               self.beam_traileffect = (EFFECT_ARC_BEAM);
+                               self.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
                                self.beam_hitlight[0] = 20;
                                self.beam_hitlight[1] = 1;
                                self.beam_hitlight[2] = 0;
                                self.beam_hitlight[3] = 0;
-                               self.beam_muzzleeffect = -1; //particleeffectnum(EFFECT_VORTEX_MUZZLEFLASH);
+                               self.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
                                self.beam_muzzlelight[0] = 50;
                                self.beam_muzzlelight[1] = 1;
                                self.beam_muzzlelight[2] = 0;
                                self.beam_muzzlelight[3] = 0;
                                self.beam_image = "particles/lgbeam";
-                               if(self.beam_muzzleeffect >= 0)
+                               if(self.beam_muzzleeffect)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                self.beam_color = '1 1 1';
                                self.beam_alpha = 0.5;
                                self.beam_thickness = 14;
-                               self.beam_traileffect = particleeffectnum(EFFECT_ARC_BEAM);
-                               self.beam_hiteffect = particleeffectnum(EFFECT_ARC_LIGHTNING);
+                               self.beam_traileffect = (EFFECT_ARC_BEAM);
+                               self.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
                                self.beam_hitlight[0] = 0;
                                self.beam_hitlight[1] = 1;
                                self.beam_hitlight[2] = 1;
                                self.beam_hitlight[3] = 1;
-                               self.beam_muzzleeffect = -1; //particleeffectnum(EFFECT_VORTEX_MUZZLEFLASH);
+                               self.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
                                self.beam_muzzlelight[0] = 0;
                                self.beam_muzzlelight[1] = 1;
                                self.beam_muzzlelight[2] = 1;
                                self.beam_muzzlelight[3] = 1;
                                self.beam_image = "particles/lgbeam";
-                               if(self.beam_muzzleeffect >= 0)
+                               if(self.beam_muzzleeffect)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                self.beam_color = '1 1 1';
                                self.beam_alpha = 0.5;
                                self.beam_thickness = 14;
-                               self.beam_traileffect = particleeffectnum(EFFECT_ARC_BEAM);
-                               self.beam_hiteffect = particleeffectnum(EFFECT_ARC_LIGHTNING);
+                               self.beam_traileffect = (EFFECT_ARC_BEAM);
+                               self.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
                                self.beam_hitlight[0] = 0;
                                self.beam_hitlight[1] = 1;
                                self.beam_hitlight[2] = 1;
                                self.beam_hitlight[3] = 1;
-                               self.beam_muzzleeffect = -1; //particleeffectnum(EFFECT_VORTEX_MUZZLEFLASH);
+                               self.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
                                self.beam_muzzlelight[0] = 0;
                                self.beam_muzzlelight[1] = 1;
                                self.beam_muzzlelight[2] = 1;
                                self.beam_muzzlelight[3] = 1;
                                self.beam_image = "particles/lgbeam";
-                               if(self.beam_muzzleeffect >= 0)
+                               if(self.beam_muzzleeffect)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                self.beam_color = '1 1 1';
                                self.beam_alpha = 0.5;
                                self.beam_thickness = 14;
-                               self.beam_traileffect = particleeffectnum(EFFECT_ARC_BEAM_HEAL);
-                               self.beam_hiteffect = particleeffectnum(EFFECT_ARC_BEAM_HEAL_IMPACT2);
+                               self.beam_traileffect = (EFFECT_ARC_BEAM_HEAL);
+                               self.beam_hiteffect = (EFFECT_ARC_BEAM_HEAL_IMPACT2);
                                self.beam_hitlight[0] = 0;
                                self.beam_hitlight[1] = 1;
                                self.beam_hitlight[2] = 1;
                                self.beam_hitlight[3] = 1;
-                               self.beam_muzzleeffect = -1; //particleeffectnum(EFFECT_VORTEX_MUZZLEFLASH);
+                               self.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
                                self.beam_muzzlelight[0] = 0;
                                self.beam_muzzlelight[1] = 1;
                                self.beam_muzzlelight[2] = 1;
                                self.beam_muzzlelight[3] = 1;
                                self.beam_image = "particles/lgbeam";
-                               if(self.beam_muzzleeffect >= 0)
+                               if(self.beam_muzzleeffect)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                self.beam_color = '1 1 1';
                                self.beam_alpha = 0.5;
                                self.beam_thickness = 14;
-                               self.beam_traileffect = particleeffectnum(EFFECT_ARC_BEAM);
-                               self.beam_hiteffect = particleeffectnum(EFFECT_ARC_LIGHTNING);
+                               self.beam_traileffect = (EFFECT_ARC_BEAM);
+                               self.beam_hiteffect = (EFFECT_ARC_LIGHTNING);
                                self.beam_hitlight[0] = 0;
                                self.beam_hitlight[1] = 1;
                                self.beam_hitlight[2] = 1;
                                self.beam_hitlight[3] = 1;
-                               self.beam_muzzleeffect = -1; //particleeffectnum(EFFECT_VORTEX_MUZZLEFLASH);
+                               self.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
                                self.beam_muzzlelight[0] = 0;
                                self.beam_muzzlelight[1] = 1;
                                self.beam_muzzlelight[2] = 1;
                                self.beam_muzzlelight[3] = 1;
                                self.beam_image = "particles/lgbeam";
-                               if(self.beam_muzzleeffect >= 0)
+                               if(self.beam_muzzleeffect)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
                                self.beam_color = randomvec();
                                self.beam_alpha = 1;
                                self.beam_thickness = 8;
-                               self.beam_traileffect = false;
-                               self.beam_hiteffect = false;
+                               self.beam_traileffect = NULL;
+                               self.beam_hiteffect = NULL;
                                self.beam_hitlight[0] = 0;
                                self.beam_hitlight[1] = 1;
                                self.beam_hitlight[2] = 1;
                                self.beam_hitlight[3] = 1;
-                               self.beam_muzzleeffect = -1; //particleeffectnum(EFFECT_VORTEX_MUZZLEFLASH);
+                               self.beam_muzzleeffect = NULL; //(EFFECT_VORTEX_MUZZLEFLASH);
                                self.beam_muzzlelight[0] = 0;
                                self.beam_muzzlelight[1] = 1;
                                self.beam_muzzlelight[2] = 1;
                                self.beam_muzzlelight[3] = 1;
                                self.beam_image = "particles/lgbeam";
-                               if(self.beam_muzzleeffect >= 0)
+                               if(self.beam_muzzleeffect)
                                {
                                        setmodel(flash, MDL_ARC_MUZZLEFLASH);
                                        flash.alpha = self.beam_alpha;
index 51eeec3b120ee48f7fdd3a9597308709daefbbce,8c483b346a5c6e2b6acf4066c321347719b878ba..0cb358b54779034939fbea552453378f9ee23e02
@@@ -101,8 -101,9 +101,8 @@@ void W_Blaster_Attack
        W_SetupShot_Dir(actor, s_forward, false, 3, SND(LASERGUN_FIRE), CH_WEAPON_B, atk_damage);
        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      entity missile = spawn();
 +      entity missile = new(blasterbolt);
        missile.owner = missile.realowner = actor;
 -      missile.classname = "blasterbolt";
        missile.bot_dodge = true;
        missile.bot_dodgerating = atk_damage;
        PROJECTILE_MAKETRIGGER(missile);
                {
                        vector org2;
                        org2 = w_org + w_backoff * 6;
-                       pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
+                       pointparticles(EFFECT_BLASTER_IMPACT, org2, w_backoff * 1000, 1);
                        if(!w_issilent) { sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }
                }
  
index 75eb2f710061dfa0632cb2c283ec5c69e549fbc2,11e6924d81360585208297ba95eebed0672c27ff..efb7e9a926ef7766aa28099a88134dcbc182277c
@@@ -366,9 -366,10 +366,9 @@@ void W_Crylink_Attack(Weapon thiswep
        proj = prevproj = firstproj = world;
        for(counter = 0; counter < shots; ++counter)
        {
 -              proj = spawn();
 +              proj = new(spike);
                proj.reset = W_Crylink_Reset;
                proj.realowner = proj.owner = self;
 -              proj.classname = "spike";
                proj.bot_dodge = true;
                proj.bot_dodgerating = WEP_CVAR_PRI(crylink, damage);
                if(shots == 1) {
@@@ -474,9 -475,10 +474,9 @@@ void W_Crylink_Attack2(Weapon thiswep
        proj = prevproj = firstproj = world;
        for(counter = 0; counter < shots; ++counter)
        {
 -              proj = spawn();
 +              proj = new(spike);
                proj.reset = W_Crylink_Reset;
                proj.realowner = proj.owner = self;
 -              proj.classname = "spike";
                proj.bot_dodge = true;
                proj.bot_dodgerating = WEP_CVAR_SEC(crylink, damage);
                if(shots == 1) {
  
                                                pos = W_Crylink_LinkJoin(actor.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed));
  
 -                                              linkjoineffect = spawn();
 +                                              linkjoineffect = new(linkjoineffect);
                                                linkjoineffect.think = W_Crylink_LinkJoinEffect_Think;
 -                                              linkjoineffect.classname = "linkjoineffect";
                                                linkjoineffect.nextthink = time + w_crylink_linkjoin_time;
                                                linkjoineffect.owner = actor;
                                                setorigin(linkjoineffect, pos);
                        org2 = w_org + w_backoff * 2;
                        if(w_deathtype & HITTYPE_SECONDARY)
                        {
-                               pointparticles(particleeffectnum(EFFECT_CRYLINK_IMPACT2), org2, '0 0 0', 1);
+                               pointparticles(EFFECT_CRYLINK_IMPACT2, org2, '0 0 0', 1);
                                if(!w_issilent)
                                        sound(self, CH_SHOTS, SND_CRYLINK_IMPACT2, VOL_BASE, ATTN_NORM);
                        }
                        else
                        {
-                               pointparticles(particleeffectnum(EFFECT_CRYLINK_IMPACT), org2, '0 0 0', 1);
+                               pointparticles(EFFECT_CRYLINK_IMPACT, org2, '0 0 0', 1);
                                if(!w_issilent)
                                        sound(self, CH_SHOTS, SND_CRYLINK_IMPACT, VOL_BASE, ATTN_NORM);
                        }
index f5f6001dd4eb92d4bb91daa1fbe1c36374c0dcfc,8ae3f3e3c02231730afe8eeb5bd87f1e46689c20..af83b4e1d78a8100bd7ef83db7d6014c6e142e46
@@@ -264,7 -264,8 +264,7 @@@ void W_Electro_Attack_Bolt(Weapon thisw
  
        Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      proj = spawn();
 -      proj.classname = "electro_bolt";
 +      proj = new(electro_bolt);
        proj.owner = proj.realowner = self;
        proj.bot_dodge = true;
        proj.bot_dodgerating = WEP_CVAR_PRI(electro, damage);
@@@ -363,7 -364,8 +363,7 @@@ void W_Electro_Attack_Orb(Weapon thiswe
  
        Send_Effect(EFFECT_ELECTRO_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      entity proj = spawn();
 -      proj.classname = "electro_orb";
 +      entity proj = new(electro_orb);
        proj.owner = proj.realowner = self;
        proj.use = W_Electro_Explode;
        proj.think = adaptor_think2use_hittype_splash;
@@@ -555,7 -557,7 +555,7 @@@ void W_Electro_CheckAttack(Weapon thisw
                        org2 = w_org + w_backoff * 6;
                        if(w_deathtype & HITTYPE_SECONDARY)
                        {
-                               pointparticles(particleeffectnum(EFFECT_ELECTRO_BALLEXPLODE), org2, '0 0 0', 1);
+                               pointparticles(EFFECT_ELECTRO_BALLEXPLODE, org2, '0 0 0', 1);
                                if(!w_issilent)
                                        sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_NORM);
                        }
                                if(w_deathtype & HITTYPE_BOUNCE)
                                {
                                        // this is sent as "primary (w_deathtype & HITTYPE_BOUNCE)" to distinguish it from (w_deathtype & HITTYPE_SECONDARY) bounced balls
-                                       pointparticles(particleeffectnum(EFFECT_ELECTRO_COMBO), org2, '0 0 0', 1);
+                                       pointparticles(EFFECT_ELECTRO_COMBO, org2, '0 0 0', 1);
                                        if(!w_issilent)
                                                sound(self, CH_SHOTS, SND_ELECTRO_IMPACT_COMBO, VOL_BASE, ATTEN_NORM);
                                }
                                else
                                {
-                                       pointparticles(particleeffectnum(EFFECT_ELECTRO_IMPACT), org2, '0 0 0', 1);
+                                       pointparticles(EFFECT_ELECTRO_IMPACT, org2, '0 0 0', 1);
                                        if(!w_issilent)
                                                sound(self, CH_SHOTS, SND_ELECTRO_IMPACT, VOL_BASE, ATTEN_NORM);
                                }
index df9eb22307be9a49ab9bdf7270662eafa9a22eed,a2ff0de5963b0476dc9b3e531a6786ebeab7b68e..24f4fc3dbb729f93a1d02ce67879317a8e5f7990
@@@ -188,7 -188,8 +188,7 @@@ void W_Fireball_Attack1(void
  
        Send_Effect(EFFECT_FIREBALL_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      proj = spawn();
 -      proj.classname = "plasma_prim";
 +      proj = new(plasma_prim);
        proj.owner = proj.realowner = self;
        proj.bot_dodge = true;
        proj.bot_dodgerating = WEP_CVAR_PRI(fireball, damage);
@@@ -323,8 -324,9 +323,8 @@@ void W_Fireball_Attack2(void
  
        Send_Effect(EFFECT_FIREBALL_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      proj = spawn();
 +      proj = new(grenade);
        proj.owner = proj.realowner = self;
 -      proj.classname = "grenade";
        proj.bot_dodge = true;
        proj.bot_dodgerating = WEP_CVAR_SEC(fireball, damage);
        proj.movetype = MOVETYPE_BOUNCE;
                        else
                        {
                                org2 = w_org + w_backoff * 16;
-                               pointparticles(particleeffectnum(EFFECT_FIREBALL_EXPLODE), org2, '0 0 0', 1);
+                               pointparticles(EFFECT_FIREBALL_EXPLODE, org2, '0 0 0', 1);
                                if(!w_issilent)
                                        sound(self, CH_SHOTS, SND_FIREBALL_IMPACT2, VOL_BASE, ATTEN_NORM * 0.25); // long range boom
                        }
index 2544100df9cec869563691868c693dd5c7552b24,e7621c241c9a9eac2a04d712f5588b2139725026..4046be972b5de76d709aefeed7931b981371eece
@@@ -133,8 -133,9 +133,8 @@@ void W_Hagar_Attack(Weapon thiswep
  
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      missile = spawn();
 +      missile = new(missile);
        missile.owner = missile.realowner = self;
 -      missile.classname = "missile";
        missile.bot_dodge = true;
        missile.bot_dodgerating = WEP_CVAR_PRI(hagar, damage);
  
@@@ -175,8 -176,9 +175,8 @@@ void W_Hagar_Attack2(Weapon thiswep
  
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      missile = spawn();
 +      missile = new(missile);
        missile.owner = missile.realowner = self;
 -      missile.classname = "missile";
        missile.bot_dodge = true;
        missile.bot_dodgerating = WEP_CVAR_SEC(hagar, damage);
  
@@@ -234,8 -236,9 +234,8 @@@ void W_Hagar_Attack2_Load_Release(int s
        missile = world;
        for(counter = 0; counter < shots; ++counter)
        {
 -              missile = spawn();
 +              missile = new(missile);
                missile.owner = missile.realowner = self;
 -              missile.classname = "missile";
                missile.bot_dodge = true;
                missile.bot_dodgerating = WEP_CVAR_SEC(hagar, damage);
  
@@@ -506,7 -509,7 +506,7 @@@ void W_Hagar_Attack2_Load(Weapon thiswe
                {
                        vector org2;
                        org2 = w_org + w_backoff * 6;
-                       pointparticles(particleeffectnum(EFFECT_HAGAR_EXPLODE), org2, '0 0 0', 1);
+                       pointparticles(EFFECT_HAGAR_EXPLODE, org2, '0 0 0', 1);
                        if(!w_issilent)
                        {
                                if(w_random<0.15)
index 4bd4656b8443590a4ef368331de10e4c54b845db,5a91976ff4ad7bc48576eb3b834727c94779f8ea..383c40f5de6edf461e25ba9172334d7e82c0ec50
@@@ -87,8 -87,9 +87,8 @@@ void W_HLAC_Attack(Weapon thiswep
                self.punchangle_y = random() - 0.5;
        }
  
 -      missile = spawn();
 +      missile = new(hlacbolt);
        missile.owner = missile.realowner = self;
 -      missile.classname = "hlacbolt";
        missile.bot_dodge = true;
  
      missile.bot_dodgerating = WEP_CVAR_PRI(hlac, damage);
@@@ -129,8 -130,9 +129,8 @@@ void W_HLAC_Attack2(void
        W_SetupShot(self, false, 3, SND(LASERGUN_FIRE), CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage));
        Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      missile = spawn();
 +      missile = new(hlacbolt);
        missile.owner = missile.realowner = self;
 -      missile.classname = "hlacbolt";
        missile.bot_dodge = true;
  
      missile.bot_dodgerating = WEP_CVAR_SEC(hlac, damage);
@@@ -273,7 -275,7 +273,7 @@@ void W_HLAC_Attack2_Frame(Weapon thiswe
                {
                        vector org2;
                        org2 = w_org + w_backoff * 6;
-                       pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
+                       pointparticles(EFFECT_BLASTER_IMPACT, org2, w_backoff * 1000, 1);
                        if(!w_issilent)
                                sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM);
                }
index 4ea2e94617c02c110015906560ea4654f486f775,938f20390b2a09964f072d9e86bcc541bbc88095..3175367a19d1e7b4a00f512ac16b49dcce75b4b7
@@@ -67,7 -67,8 +67,7 @@@ void W_MineLayer_Stick(entity to
  
        // in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile
  
 -      entity newmine;
 -      newmine = spawn();
 +      entity newmine = spawn();
        newmine.classname = self.classname;
  
        newmine.bot_dodge = self.bot_dodge;
@@@ -576,7 -577,7 +576,7 @@@ float W_MineLayer_PlacedMines(float det
                {
                        vector org2;
                        org2 = w_org + w_backoff * 12;
-                       pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), org2, '0 0 0', 1);
+                       pointparticles(EFFECT_ROCKET_EXPLODE, org2, '0 0 0', 1);
                        if(!w_issilent)
                                sound(self, CH_SHOTS, SND_MINE_EXP, VOL_BASE, ATTN_NORM);
                }
index f78ea609a342008cc22b69a5b8268b618f39bea5,f2e2013d8b5b14501292ca15ffb5d0ec011607c5..69758641fac2d5be63f0ab002457a80b6de46df9
@@@ -209,8 -209,9 +209,8 @@@ void W_Mortar_Attack(Weapon thiswep
  
        Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      gren = spawn();
 +      gren = new(grenade);
        gren.owner = gren.realowner = self;
 -      gren.classname = "grenade";
        gren.bot_dodge = true;
        gren.bot_dodgerating = WEP_CVAR_PRI(mortar, damage);
        gren.movetype = MOVETYPE_BOUNCE;
@@@ -257,8 -258,9 +257,8 @@@ void W_Mortar_Attack2(Weapon thiswep
  
        Send_Effect(EFFECT_GRENADE_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      gren = spawn();
 +      gren = new(grenade);
        gren.owner = gren.realowner = self;
 -      gren.classname = "grenade";
        gren.bot_dodge = true;
        gren.bot_dodgerating = WEP_CVAR_SEC(mortar, damage);
        gren.movetype = MOVETYPE_BOUNCE;
                {
                        vector org2;
                        org2 = w_org + w_backoff * 12;
-                       pointparticles(particleeffectnum(EFFECT_GRENADE_EXPLODE), org2, '0 0 0', 1);
+                       pointparticles(EFFECT_GRENADE_EXPLODE, org2, '0 0 0', 1);
                        if(!w_issilent)
                                sound(self, CH_SHOTS, SND_GRENADE_IMPACT, VOL_BASE, ATTN_NORM);
                }
index d4bfae505e2927d5988ed00fedb36e179d75fb37,8fd7aa89678f596373ca2430dc9ec5cc5a48f0d3..e67beaed961e955cd0130a7c15cd9c8522d4b99f
@@@ -258,8 -258,9 +258,8 @@@ void W_Seeker_Fire_Missile(Weapon thisw
  
        //self.detornator         = false;
  
 -      missile                 = spawn();
 +      missile                 = new(seeker_missile);
        missile.owner           = missile.realowner = self;
 -      missile.classname       = "seeker_missile";
        missile.bot_dodge       = true;
        missile.bot_dodgerating = WEP_CVAR(seeker, missile_damage);
  
@@@ -347,8 -348,9 +347,8 @@@ void W_Seeker_Fire_Flac(Weapon thiswep
  
        Send_Effect(EFFECT_HAGAR_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
  
 -      missile                                 = spawn();
 +      missile                                 = new(missile);
        missile.owner                   = missile.realowner = self;
 -      missile.classname               = "missile";
        missile.bot_dodge               = true;
        missile.bot_dodgerating = WEP_CVAR(seeker, flac_damage);
        missile.touch                   = W_Seeker_Flac_Explode;
@@@ -522,8 -524,9 +522,8 @@@ void W_Seeker_Tag_Touch(void
                else
                {
                        //sprint(self.realowner, strcat("You just tagged ^2", other.netname, "^7 with a tracking device!\n"));
 -                      e             = spawn();
 +                      e             = new(tag_tracker);
                        e.cnt         = WEP_CVAR(seeker, missile_count);
 -                      e.classname   = "tag_tracker";
                        e.owner       = self.owner;
                        e.realowner   = self.realowner;
  
@@@ -560,8 -563,9 +560,8 @@@ void W_Seeker_Fire_Tag(Weapon thiswep
  
        W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, SND(TAG_FIRE), CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count));
  
 -      missile                 = spawn();
 +      missile                 = new(seeker_tag);
        missile.owner           = missile.realowner = self;
 -      missile.classname       = "seeker_tag";
        missile.bot_dodge       = true;
        missile.bot_dodgerating = 50;
        missile.touch           = W_Seeker_Tag_Touch;
                                }
                                else
                                {
-                                       pointparticles(particleeffectnum(EFFECT_HAGAR_EXPLODE), org2, '0 0 0', 1);
+                                       pointparticles(EFFECT_HAGAR_EXPLODE, org2, '0 0 0', 1);
                                        if(!w_issilent)
                                        {
                                                if(w_random<0.15)
                        }
                        else
                        {
-                               pointparticles(particleeffectnum(EFFECT_HAGAR_EXPLODE), org2, '0 0 0', 1);
+                               pointparticles(EFFECT_HAGAR_EXPLODE, org2, '0 0 0', 1);
                                if(!w_issilent)
                                {
                                        if(w_random<0.15)
index 0df4f456e5e1ef51f577f93f481f264051c54027,a16c2d68ba0c2f922990912972276c7e516b71b1..8d2edb81464334a4daaf7c7bd15bf82a5beecca8
@@@ -234,8 -234,8 +234,8 @@@ void W_Shockwave_Melee(Weapon thiswep, 
        sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTN_NORM);
        weapon_thinkf(actor, slot, WFRAME_FIRE2, WEP_CVAR(shockwave, melee_animtime), w_ready);
  
 -      entity meleetemp;
 -      meleetemp = spawn();
 +      entity meleetemp = new(meleetemp);
 +      make_pure(meleetemp);
        meleetemp.owner = meleetemp.realowner = actor;
        meleetemp.think = W_Shockwave_Melee_Think;
        meleetemp.nextthink = time + WEP_CVAR(shockwave, melee_delay) * W_WeaponRateFactor();
@@@ -856,7 -856,7 +856,7 @@@ void Net_ReadShockwaveParticle(void
                        // handled by Net_ReadShockwaveParticle
                        //vector org2;
                        //org2 = w_org + w_backoff * 2;
-                       //pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
+                       //pointparticles(EFFECT_BLASTER_IMPACT, org2, w_backoff * 1000, 1);
                }
  
  #endif
index bdcef419201ff74ee601d91bbf65e8168a02cb1b,da08705eedc48a4d5a5a444226a65e077079c095..5d9023d3476e1e650da3d57d0e712f1c47499df5
@@@ -186,8 -186,8 +186,8 @@@ void W_Shotgun_Attack2(Weapon thiswep, 
        sound(actor, CH_WEAPON_A, SND_SHOTGUN_MELEE, VOL_BASE, ATTEN_NORM);
        weapon_thinkf(actor, slot, WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready);
  
 -      entity meleetemp;
 -      meleetemp = spawn();
 +      entity meleetemp = new(meleetemp);
 +      make_pure(meleetemp);
        meleetemp.realowner = actor;
        meleetemp.think = W_Shotgun_Melee_Think;
        meleetemp.nextthink = time + WEP_CVAR_SEC(shotgun, melee_delay) * W_WeaponRateFactor();
@@@ -339,7 -339,7 +339,7 @@@ void W_Shotgun_Attack3_Frame1(Weapon th
                METHOD(Shotgun, wr_impacteffect, void(entity thiswep))
                {
                        vector org2 = w_org + w_backoff * 2;
-                       pointparticles(particleeffectnum(EFFECT_SHOTGUN_IMPACT), org2, w_backoff * 1000, 1);
+                       pointparticles(EFFECT_SHOTGUN_IMPACT, org2, w_backoff * 1000, 1);
                        if(!w_issilent && time - self.prevric > 0.25)
                        {
                                if(w_random < 0.0165)
index ecf38d2fd136b142e5dd2feb21b7b4f98dacedd4,6830c90016fa0acd5021af517e1a7702e8242111..dafb3e7fd4bc015ec0d6c71aa5b30db0fba995b4
@@@ -150,7 -150,8 +150,7 @@@ void W_RocketMinsta_Attack2(void
  
      while(counter < total)
        {
 -        proj = spawn ();
 -        proj.classname = "plasma_prim";
 +        proj = new(plasma_prim);
          proj.owner = proj.realowner = self;
          proj.bot_dodge = true;
          proj.bot_dodgerating = autocvar_g_rm_laser_damage;
@@@ -202,7 -203,8 +202,7 @@@ void W_RocketMinsta_Attack3 (void
  
      while(counter < total)
        {
 -        proj = spawn ();
 -        proj.classname = "plasma_prim";
 +        proj = new(plasma_prim);
          proj.owner = proj.realowner = self;
          proj.bot_dodge = true;
          proj.bot_dodgerating = autocvar_g_rm_laser_damage;
                        vector org2 = w_org + w_backoff * 6;
                        if(w_deathtype & HITTYPE_SECONDARY)
                        {
-                               pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
+                               pointparticles(EFFECT_BLASTER_IMPACT, org2, w_backoff * 1000, 1);
                                if(!w_issilent) { sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }
                        }
                        else
                        {
-                               pointparticles(particleeffectnum(EFFECT_VORTEX_IMPACT), org2, '0 0 0', 1);
+                               pointparticles(EFFECT_VORTEX_IMPACT, org2, '0 0 0', 1);
                                if(!w_issilent) { sound(self, CH_SHOTS, SND_NEXIMPACT, VOL_BASE, ATTN_NORM); }
                        }
                }
diff --combined qcsrc/lib/net.qh
index 615aa5162e3ce13e2d2193df6e3b03690ab24467,1739ec69e4e04190094ccdf68174c9c18de0d550..35d5b38530fce4b929f50b182e988359955a2771
  .void(entity this, bool isNew)m_read;
  
  #ifdef CSQC
 -      #define Net_Accept() \
 +      #define Net_Accept(classname) \
                do \
                { \
 -                      if (!this)    this = spawn(); \
 +                      if (!this)    this = new(classname); \
                } \
                while (0)
        #define Net_Reject() \
                void Ent_Read##id(entity this, param) \
                { \
                        this = self; \
 +                      this.sourceLocFile = __FILE__; \
 +                      this.sourceLocLine = __LINE__; \
                } \
 -              REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) \
 +              REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, new(net_linked_packet)) \
                { \
 +                      make_pure(this); \
                        this.netname = #id; \
                        this.m_read = Ent_Read##id; \
                } \
  #else
        #define REGISTER_NET_LINKED(id, param) \
                const bool NET_##id##_istemp = false; \
 -              REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) \
 +              REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, new(net_linked_packet)) \
                { \
 +                      make_pure(this); \
                        this.netname = #id; \
                }
  #endif
  
- REGISTRY(LinkedEntities, BITS(2))
+ REGISTRY(LinkedEntities, BITS(4))
+ #define LinkedEntities_from(i) _LinkedEntities_from(i, NULL)
  REGISTER_REGISTRY(RegisterLinkedEntities)
  REGISTRY_SORT(LinkedEntities, netname, 0)
  STATIC_INIT(RegisterLinkedEntities_renumber)
  {
        for (int i = 0; i < LinkedEntities_COUNT; ++i)
-               LinkedEntities[i].m_id = 100 + i;
+               LinkedEntities_from(i).m_id = 100 + i;
  }
  
  #ifdef CSQC
        #define REGISTER_NET_TEMP(id, param) \
                void Net_Read##id(entity this, param); \
 -              REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) \
 +              REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, new(net_temp_packet)) \
                { \
 +                      make_pure(this); \
                        this.netname = #id; \
                        this.m_read = Net_Read##id; \
                } \
  #else
        #define REGISTER_NET_TEMP(id, param) \
                const bool NET_##id##_istemp = true; \
 -              REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) \
 +              REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, new(net_temp_packet)) \
                { \
 +                      make_pure(this); \
                        this.netname = #id; \
                }
  #endif
  
- REGISTRY(TempEntities, BITS(2))
+ REGISTRY(TempEntities, BITS(4))
+ #define TempEntities_from(i) _TempEntities_from(i, NULL)
  REGISTER_REGISTRY(RegisterTempEntities)
  REGISTRY_SORT(TempEntities, netname, 0)
  STATIC_INIT(RegisterTempEntities_renumber)
  {
        for (int i = 0; i < TempEntities_COUNT; ++i)
-               TempEntities[i].m_id = 115 + i;
+               TempEntities_from(i).m_id = 115 + i;
  }
  
  #ifndef MENUQC
                        return v;
                }
        #else
 +              const int MSG_ENTITY = 5;
 +
                void WriteInt24_t(float dst, float val)
                {
                        float v;
index a142b8209281f599ca59118f2815a8bae0e9658c,a04ee59e4b94642ff3957a12b8623f4d1a2c289f..50339a73038121a5b8541200be0aede37db6bd1a
@@@ -186,8 -186,8 +186,8 @@@ void WarpZone_Trace_InitTransform(
  {
        if(!WarpZone_trace_transform)
        {
 -              WarpZone_trace_transform = spawn();
 -              WarpZone_trace_transform.classname = "warpzone_trace_transform";
 +              WarpZone_trace_transform = new(warpzone_trace_transform);
 +              make_pure(WarpZone_trace_transform);
        }
        WarpZone_Accumulator_Clear(WarpZone_trace_transform);
  }
@@@ -457,7 -457,7 +457,7 @@@ entity WarpZone_TrailParticles_trace_ca
  float WarpZone_TrailParticles_trace_callback_eff;
  void WarpZone_TrailParticles_trace_callback(vector from, vector endpos, vector to)
  {
-       trailparticles(WarpZone_TrailParticles_trace_callback_own, WarpZone_TrailParticles_trace_callback_eff, from, endpos);
+       __trailparticles(WarpZone_TrailParticles_trace_callback_own, WarpZone_TrailParticles_trace_callback_eff, from, endpos);
  }
  
  void WarpZone_TrailParticles(entity own, float eff, vector org, vector end)
@@@ -572,20 -572,37 +572,20 @@@ vector WarpZoneLib_NearestPointOnBox(ve
  
  bool WarpZoneLib_BadEntity(entity e)
  {
 -      string myclassname = e.classname;
 -      if (e.instanceOfObject) return true;
 -      switch(myclassname)
 +      string s = e.classname;
 +      if (is_pure(e)) return true;
 +      switch (s)
        {
 -              case "deathtype":
 -              case "weaponentity":
 -              case "exteriorweaponentity":
 -              case "csqc_score_team":
 -              case "pingplreport":
 -              case "ent_client_scoreinfo":
 -              case "saved_cvar_value":
 -              case "accuracy":
                case "entcs_sender":
                case "entcs_receiver":
 -              case "clientinit":
 -              case "sprite_waypoint":
 -              case "waypoint":
 -              case "gibsplash":
 -              //case "net_linked": // actually some real entities are linked without classname, fail
 +              // case "net_linked": // actually some real entities are linked without classname, fail
                case "":
                        return true;
        }
  
 -      if(startsWith(myclassname, "msg_"))
 -              return true;
 +      if (startsWith(s, "target_")) return true;
  
 -      if(startsWith(myclassname, "target_"))
 -              return true;
 -
 -      if(startsWith(myclassname, "info_"))
 -              return true;
 +      if (startsWith(s, "info_")) return true;
  
        return false;
  }
@@@ -686,7 -703,8 +686,7 @@@ void WarpZone_RefSys_CheckCreate(entit
  {
        if(me.WarpZone_refsys.owner != me)
        {
 -              me.WarpZone_refsys = spawn();
 -              me.WarpZone_refsys.classname = "warpzone_refsys";
 +              me.WarpZone_refsys = new(warpzone_refsys);
                me.WarpZone_refsys.owner = me;
                me.WarpZone_refsys.think = WarpZone_RefSys_GC;
                me.WarpZone_refsys.nextthink = time + 1;
diff --combined qcsrc/server/cheats.qc
index 1313cb7f2ba310132257801e151257f7ba30ea00,dc6d63b0c863710396bb092f24dbf8211b428bcf..00826b1226e3bd0a1d7177fdaec8cad0c8e082b3
@@@ -150,7 -150,8 +150,7 @@@ float CheatImpulse(float i
                        // shared with regular waypoint init, so this is not a cheat by itself
                        if(!self.personal)
                        {
 -                              self.personal = spawn();
 -                              self.personal.classname = "personal_wp";
 +                              self.personal = new(personal_wp);
                        }
                        self.personal.origin = self.origin;
                        self.personal.v_angle = self.v_angle;
@@@ -337,7 -338,7 +337,7 @@@ float CheatCommand(float argc
                                effectnum = _particleeffectnum(argv(1));
                                W_SetupShot(self, false, false, "", CH_WEAPON_A, 0);
                                traceline(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, MOVE_NORMAL, self);
-                               trailparticles(self, effectnum, w_shotorg, trace_endpos);
+                               __trailparticles(self, effectnum, w_shotorg, trace_endpos);
                                DID_CHEAT();
                                break;
                        }
                        break;
                case "dragbox_spawn": {
                        IS_CHEAT(0, argc, 0);
 -                      entity e = spawn();
 -                      e.classname = "dragbox_box";
 +                      entity e = new(dragbox_box);
                        e.think = DragBox_Think;
                        e.nextthink = time;
                        e.solid = -1; // black
                        else
                                e.cnt = max(0, drag_lastcnt);
  
 -                      e.aiment = spawn();
 -                      e.aiment.classname = "dragbox_corner_1";
 +                      e.aiment = new(dragbox_corner_1);
                        e.aiment.owner = e;
                        setmodel(e.aiment, MDL_MARKER);
                        e.aiment.skin = 0;
                                setorigin(e.aiment, trace_endpos);
                        }
  
 -                      e.enemy = spawn();
 -                      e.enemy.classname = "dragbox_corner_2";
 +                      e.enemy = new(dragbox_corner_2);
                        e.enemy.owner = e;
                        setmodel(e.enemy, MDL_MARKER);
                        e.enemy.skin = 1;
                        else
                                setorigin(e.enemy, e.aiment.origin + 32 * end);
  
 -                      e.killindicator = spawn();
 -                      e.killindicator.classname = "drag_digit";
 +                      e.killindicator = new(drag_digit);
                        e.killindicator.owner = e;
                        setattachment(e.killindicator, e, "");
                        setorigin(e.killindicator, '0 0 -8');
 -                      e.killindicator.killindicator = spawn();
 -                      e.killindicator.killindicator.classname = "drag_digit";
 +                      e.killindicator.killindicator = new(drag_digit);
                        e.killindicator.killindicator.owner = e;
                        setattachment(e.killindicator.killindicator, e, "");
                        setorigin(e.killindicator.killindicator, '0 0 8');
                }
                case "dragpoint_spawn": {
                        IS_CHEAT(0, argc, 0);
 -                      entity e = spawn();
 -                      e.classname = "dragpoint";
 +                      entity e = new(dragpoint);
                        e.think = DragBox_Think;
                        e.nextthink = time;
                        e.solid = 0; // nothing special
                                move_out_of_solid(e);
                        }
  
 -                      e.killindicator = spawn();
 -                      e.killindicator.classname = "drag_digit";
 +                      e.killindicator = new(drag_digit);
                        e.killindicator.owner = e;
                        setattachment(e.killindicator, e, "");
                        setorigin(e.killindicator, '0 0 40');
 -                      e.killindicator.killindicator = spawn();
 -                      e.killindicator.killindicator.classname = "drag_digit";
 +                      e.killindicator.killindicator = new(drag_digit);
                        e.killindicator.killindicator.owner = e;
                        setattachment(e.killindicator.killindicator, e, "");
                        setorigin(e.killindicator.killindicator, '0 0 56');
                        break;
                case "teleporttotarget":
                        IS_CHEAT(0, argc, 0);
 -                      setself(spawn());
 +                      setself(new(cheattriggerteleport));
                        setorigin(self, self.origin);
 -                      self.classname = "cheattriggerteleport";
                        self.target = argv(1);
                        teleport_findtarget();
                        if(!wasfreed(self))
index 8f1e3e9be84c1c7840bc09784ac1269f56a3d088,7a18231392b3216e6a596fe71b48048d012c3b60..c104091979a709578477e48c10f18c679b76098c
@@@ -96,10 -96,9 +96,10 @@@ bool ClientData_Send(entity this, entit
  
  void ClientData_Attach()
  {SELFPARAM();
 -      Net_LinkEntity(self.clientdata = spawn(), false, 0, ClientData_Send);
 -      self.clientdata.drawonlytoclient = self;
 -      self.clientdata.owner = self;
 +      Net_LinkEntity(this.clientdata = new(clientdata), false, 0, ClientData_Send);
 +      make_pure(this.clientdata);
 +      self.clientdata.drawonlytoclient = this;
 +      self.clientdata.owner = this;
  }
  
  void ClientData_Detach()
@@@ -536,8 -535,7 +536,8 @@@ void PutClientInServer(
                this.revival_time = 0;
                this.air_finished = time + 12;
  
 -              entity spawnevent = spawn();
 +              entity spawnevent = new(spawnevent);
 +              make_pure(spawnevent);
                spawnevent.owner = this;
                Net_LinkEntity(spawnevent, false, 0.5, SpawnEvent_Send);
  
@@@ -695,9 -693,8 +695,9 @@@ void ClientInit_CheckUpdate(
  
  void ClientInit_Spawn()
  {SELFPARAM();
 -      entity e = spawn();
 -      e.classname = "clientinit";
 +
 +      entity e = new(clientinit);
 +      make_pure(e);
        e.think = ClientInit_CheckUpdate;
        Net_LinkEntity(e, false, 0, ClientInit_SendEntity);
  
@@@ -1341,7 -1338,7 +1341,7 @@@ void UpdateChatBubble(
        // spawn a chatbubble entity if needed
        if (!self.chatbubbleentity)
        {
 -              self.chatbubbleentity = spawn();
 +              self.chatbubbleentity = new(chatbubbleentity);
                self.chatbubbleentity.owner = self;
                self.chatbubbleentity.exteriormodeltoclient = self;
                self.chatbubbleentity.think = ChatBubbleThink;
@@@ -1993,7 -1990,7 +1993,7 @@@ void PrintWelcomeMessage(
        {
                if(self.BUTTON_INFO) // BUTTON_INFO hides initial MOTD
                        self.motd_actived_time = -2; // wait until BUTTON_INFO gets released
-               else if(self.motd_actived_time == -2 || IS_PLAYER(self))
+               else if(self.motd_actived_time == -2 || IS_PLAYER(self) || IS_SPEC(self))
                {
                        // instanctly hide MOTD
                        self.motd_actived_time = 0;
index fe7b05b126dbae470a49ce2c7478635d2ddfc57b,4b972f0dec76304030bde9eb74acafebe96b03a9..2165cb016b098e964f9503730824dfb680557317
@@@ -1000,7 -1000,8 +1000,7 @@@ void GameCommand_make_mapinfo(float req
                {
                        entity tmp_entity;
  
 -                      tmp_entity = spawn();
 -                      tmp_entity.classname = "make_mapinfo";
 +                      tmp_entity = new(make_mapinfo);
                        tmp_entity.think = make_mapinfo_Think;
                        tmp_entity.nextthink = time;
                        MapInfo_Enumerate();
@@@ -1664,8 -1665,8 +1664,8 @@@ void GameCommand_trace(float request, f
                                                vv = stov(argv(2));
                                                dv = stov(argv(3));
                                                traceline(vv, dv, MOVE_NORMAL, world);
-                                               trailparticles(world, particleeffectnum(EFFECT_TR_NEXUIZPLASMA), vv, trace_endpos);
-                                               trailparticles(world, particleeffectnum(EFFECT_TR_CRYLINKPLASMA), trace_endpos, dv);
+                                               __trailparticles(world, particleeffectnum(EFFECT_TR_NEXUIZPLASMA), vv, trace_endpos);
+                                               __trailparticles(world, particleeffectnum(EFFECT_TR_CRYLINKPLASMA), trace_endpos, dv);
                                                return;
                                        }
                                }
diff --combined qcsrc/server/g_damage.qc
index 36495a11cbffd0c57cd29b4c5262015cd6123864,e1bd4e0abcd07efe741daece956f4156c169473c..efd59e940ba9dbf2a38064aacbba42cd9863a2d3
@@@ -49,8 -49,7 +49,8 @@@ void Damage_DamageInfo(vector org, floa
        if(!sound_allowed(MSG_BROADCAST, dmgowner))
                deathtype |= 0x8000;
  
 -      e = spawn();
 +      e = new(damageinfo);
 +      make_pure(e);
        setorigin(e, org);
        e.projectiledeathtype = deathtype;
        e.dmg = coredamage;
@@@ -115,7 -114,8 +115,7 @@@ void GiveFrags (entity attacker, entit
                {
                        if(!GiveFrags_randomweapons)
                        {
 -                              GiveFrags_randomweapons = spawn();
 -                              GiveFrags_randomweapons.classname = "GiveFrags_randomweapons";
 +                              GiveFrags_randomweapons = new(GiveFrags_randomweapons);
                        }
  
                        if(warmup_stage)
@@@ -204,7 -204,7 +204,7 @@@ void Obituary_SpecialDeath
  {
        if(DEATH_ISSPECIAL(deathtype))
        {
-               entity deathent = Deathtypes[deathtype - DT_FIRST];
+               entity deathent = Deathtypes_from(deathtype - DT_FIRST);
                if (!deathent) { backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n"); return; }
  
                if(murder)
@@@ -563,8 -563,10 +563,8 @@@ void Freeze (entity targ, float freeze_
        targ.revive_speed = freeze_time;
        self.bot_attack = false;
  
 -      entity ice, head;
 -      ice = spawn();
 +      entity ice = new(ice);
        ice.owner = targ;
 -      ice.classname = "ice";
        ice.scale = targ.scale;
        ice.think = Ice_Think;
        ice.nextthink = time;
  
        RemoveGrapplingHook(targ);
  
 +      entity head;
        FOR_EACH_PLAYER(head)
        if(head.hook.aiment == targ)
                RemoveGrapplingHook(head);
@@@ -888,7 -889,9 +888,7 @@@ void Damage (entity targ, entity inflic
                vector farce = damage_explosion_calcpush(self.damageforcescale * force, self.velocity, autocvar_g_balance_damagepush_speedfactor);
                if(self.movetype == MOVETYPE_PHYSICS)
                {
 -                      entity farcent;
 -                      farcent = spawn();
 -                      farcent.classname = "farce";
 +                      entity farcent = new(farce);
                        farcent.enemy = self;
                        farcent.movedir = farce * 10;
                        if(self.mass)
@@@ -1137,7 -1140,8 +1137,7 @@@ float Fire_AddDamage(entity e, entity o
                if(!e.fire_burner)
                {
                        // print("adding a fire burner to ", e.classname, "\n");
 -                      e.fire_burner = spawn();
 -                      e.fire_burner.classname = "fireburner";
 +                      e.fire_burner = new(fireburner);
                        e.fire_burner.think = fireburner_think;
                        e.fire_burner.nextthink = time;
                        e.fire_burner.owner = e;
diff --combined qcsrc/server/g_world.qc
index 25fcdfd007b95c5c04aba33a54dc0d4869f7f31e,e6641947c28204415136b484150964db85c28bca..b89f361506f6b6a8a05e2a61bf87bfbb8a5b688f
@@@ -83,8 -83,8 +83,8 @@@ void PingPLReport_Think(
  }
  void PingPLReport_Spawn()
  {
 -      pingplreport = spawn();
 -      pingplreport.classname = "pingplreport";
 +      pingplreport = new(pingplreport);
 +      make_pure(pingplreport);
        pingplreport.think = PingPLReport_Think;
        pingplreport.nextthink = time;
  }
@@@ -528,8 -528,7 +528,8 @@@ void RandomSeed_Think(
  }
  void RandomSeed_Spawn()
  {SELFPARAM();
 -      randomseed = spawn();
 +      randomseed = new(randomseed);
 +      make_pure(randomseed);
        randomseed.think = RandomSeed_Think;
        Net_LinkEntity(randomseed, false, 0, RandomSeed_Send);
  
@@@ -547,17 -546,20 +547,18 @@@ spawnfunc(__init_dedicated_server
  
        remove = remove_unsafely;
  
 -      entity e;
 -      e = spawn();
 +      entity e = spawn();
        e.think = GotoFirstMap;
        e.nextthink = time; // this is usually 1 at this point
  
 -      e = spawn();
 -      e.classname = "info_player_deathmatch"; // safeguard against player joining
 +      e = new(info_player_deathmatch);  // safeguard against player joining
  
        self.classname = "worldspawn"; // safeguard against various stuff ;)
  
        // needs to be done so early because of the constants they create
        static_init();
        static_init_late();
+       static_init_precache();
  
        MapInfo_Enumerate();
        MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
@@@ -657,6 -659,7 +658,7 @@@ spawnfunc(worldspawn
  
        InitGameplayMode();
        static_init_late();
+       static_init_precache();
        readlevelcvars();
        GrappleHookInit();
  
index f756622bf880e091ae74fd6629be180410e3e2f3,87aeb4ee0298e29b96490c2fb7d0f6d1a0bb0b45..a21864f07ec57a2c352b4f3b2afba6ae37cf17c7
@@@ -296,7 -296,7 +296,7 @@@ string formatmessage(string msg
                        case "l": replacement = NearestLocation(self.origin); break;
                        case "y": replacement = NearestLocation(cursor); break;
                        case "d": replacement = NearestLocation(self.death_origin); break;
-                       case "w": replacement = WEP_NAME((!self.weapon) ? (!self.switchweapon ? self.cnt : self.switchweapon) : self.weapon); break;
+                       case "w": replacement = WEP_NAME(((!self.weapon) ? (!self.switchweapon ? self.cnt : self.switchweapon) : self.weapon)); break;
                        case "W": replacement = ammoitems; break;
                        case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break;
                        case "s": replacement = ftos(vlen(self.velocity - self.velocity_z * '0 0 1')); break;
@@@ -1649,7 -1649,10 +1649,7 @@@ bool modeleffect_SendEntity(entity this
  
  void modeleffect_spawn(string m, float s, float f, vector o, vector v, vector ang, vector angv, float s0, float s2, float a, float t1, float t2)
  {
 -      entity e;
 -      float sz;
 -      e = spawn();
 -      e.classname = "modeleffect";
 +      entity e = new(modeleffect);
        _setmodel(e, m);
        e.frame = f;
        setorigin(e, o);
                e.scale2 = s2 / max6(-e.mins.x, -e.mins.y, -e.mins.z, e.maxs.x, e.maxs.y, e.maxs.z);
        else
                e.scale2 = -s2;
 -      sz = max(e.scale, e.scale2);
 +      float sz = max(e.scale, e.scale2);
        setsize(e, e.mins * sz, e.maxs * sz);
        Net_LinkEntity(e, false, 0.1, modeleffect_SendEntity);
  }
index 58194f378b88d524ad6fc4f874b997ae12085632,13dec008e059f63bc34106a9addd212242c415cb..71db4feba2a8d0528095c1bf18fe9230cf69c0c3
@@@ -6,15 -6,15 +6,15 @@@ void ctf_Initialize()
  
  REGISTER_MUTATOR(ctf, false)
  {
-       ActivateTeamplay();
-       SetLimits(autocvar_capturelimit_override, -1, autocvar_captureleadlimit_override, -1);
-       have_team_spawns = -1; // request team spawns
        MUTATOR_ONADD
        {
                if (time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
                ctf_Initialize();
+               ActivateTeamplay();
+               SetLimits(autocvar_capturelimit_override, -1, autocvar_captureleadlimit_override, -1);
+               have_team_spawns = -1; // request team spawns
        }
  
        MUTATOR_ONROLLBACK_OR_REMOVE
@@@ -474,12 -474,13 +474,12 @@@ void ctf_CaptureShield_Touch(
  
  void ctf_CaptureShield_Spawn(entity flag)
  {SELFPARAM();
 -      entity shield = spawn();
 +      entity shield = new(ctf_captureshield);
  
        shield.enemy = self;
        shield.team = self.team;
        shield.touch = ctf_CaptureShield_Touch;
        shield.customizeentityforclient = ctf_CaptureShield_Customize;
 -      shield.classname = "ctf_captureshield";
        shield.effects = EF_ADDITIVE;
        shield.movetype = MOVETYPE_NOCLIP;
        shield.solid = SOLID_TRIGGER;
index 6f46cef37aee199cc6c333c6d0218f9471614ea2,acc7d88733e6d282fba0a09e27b6c0165436ca13..bcc14eca962d64b13c9d1197294a3b87aaac43ce
@@@ -8,16 -8,16 +8,16 @@@ void kh_Initialize()
  
  REGISTER_MUTATOR(kh, false)
  {
-       ActivateTeamplay();
-       SetLimits(autocvar_g_keyhunt_point_limit, autocvar_g_keyhunt_point_leadlimit, -1, -1);
-       if (autocvar_g_keyhunt_team_spawns)
-               have_team_spawns = -1; // request team spawns
        MUTATOR_ONADD
        {
                if (time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
                kh_Initialize();
+               ActivateTeamplay();
+               SetLimits(autocvar_g_keyhunt_point_limit, autocvar_g_keyhunt_point_leadlimit, -1, -1);
+               if (autocvar_g_keyhunt_team_spawns)
+                       have_team_spawns = -1; // request team spawns
        }
  
        MUTATOR_ONROLLBACK_OR_REMOVE
@@@ -802,7 -802,8 +802,7 @@@ void key_reset(
  const string STR_ITEM_KH_KEY = "item_kh_key";
  void kh_Key_Spawn(entity initial_owner, float angle, float i)  // runs every time a new flag is created, ie after all the keys have been collected
  {
 -      entity key;
 -      key = spawn();
 +      entity key = spawn();
        key.count = i;
        key.classname = STR_ITEM_KH_KEY;
        key.touch = kh_Key_Touch;
index 02f1dffbcf07969295d366237ea5004e789c8204,78e6430181be8f5a460ac0ba057fd344fa167bcf..bd4bb7af6a1a3bec5878ed6c5458067b91733034
@@@ -6,15 -6,15 +6,15 @@@ void ons_Initialize()
  
  REGISTER_MUTATOR(ons, false)
  {
-       ActivateTeamplay();
-       SetLimits(autocvar_g_onslaught_point_limit, -1, -1, -1);
-       have_team_spawns = -1; // request team spawns
        MUTATOR_ONADD
        {
                if (time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
                ons_Initialize();
+               ActivateTeamplay();
+               SetLimits(autocvar_g_onslaught_point_limit, -1, -1, -1);
+               have_team_spawns = -1; // request team spawns
        }
  
        MUTATOR_ONROLLBACK_OR_REMOVE
@@@ -203,7 -203,7 +203,7 @@@ void ons_CaptureShield_Reset(
  
  void ons_CaptureShield_Spawn(entity generator, bool is_generator)
  {
 -      entity shield = spawn();
 +      entity shield = new(ons_captureshield);
  
        shield.enemy = generator;
        shield.team = generator.team;
        shield.reset = ons_CaptureShield_Reset;
        shield.touch = ons_CaptureShield_Touch;
        shield.customizeentityforclient = ons_CaptureShield_Customize;
 -      shield.classname = "ons_captureshield";
        shield.effects = EF_ADDITIVE;
        shield.movetype = MOVETYPE_NOCLIP;
        shield.solid = SOLID_TRIGGER;
@@@ -529,7 -530,7 +529,7 @@@ void ons_ControlPoint_Icon_Damage(entit
                WaypointSprite_UpdateBuildFinished(self.owner.sprite, time + (self.max_health - self.health) / (self.count / ONS_CP_THINKRATE));
        self.pain_finished = time + 1;
        // particles on every hit
-       pointparticles(particleeffectnum(EFFECT_SPARKS), hitloc, force*-1, 1);
+       pointparticles(EFFECT_SPARKS, hitloc, force*-1, 1);
        //sound on every hit
        if (random() < 0.5)
                sound(self, CH_TRIGGER, SND_ONS_HIT1, VOL_BASE+0.3, ATTEN_NORM);
        if (self.health < 0)
        {
                sound(self, CH_TRIGGER, SND_GRENADE_IMPACT, VOL_BASE, ATTEN_NORM);
-               pointparticles(particleeffectnum(EFFECT_ROCKET_EXPLODE), self.origin, '0 0 0', 1);
+               pointparticles(EFFECT_ROCKET_EXPLODE, self.origin, '0 0 0', 1);
                Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_CPDESTROYED_), self.owner.message, attacker.netname);
  
                PlayerScore_Add(attacker, SP_ONS_TAKES, 1);
@@@ -711,11 -712,12 +711,11 @@@ void onslaught_controlpoint_icon_link(e
  
  void ons_ControlPoint_Icon_Spawn(entity cp, entity player)
  {
 -      entity e = spawn();
 +      entity e = new(onslaught_controlpoint_icon);
  
        setsize(e, CPICON_MIN, CPICON_MAX);
        setorigin(e, cp.origin + CPICON_OFFSET);
  
 -      e.classname = "onslaught_controlpoint_icon";
        e.owner = cp;
        e.max_health = autocvar_g_onslaught_cp_health;
        e.health = autocvar_g_onslaught_cp_buildhealth;
index ccbf9e3ee201b3951569a593ff06d51a24f36d17,c14ab12410de60bd73533fe4cebef99a9dd58e69..407662f22f5d631de0a1857af2f073eb321c6d75
@@@ -64,14 -64,15 +64,14 @@@ void nade_timer_think(
  
  void nade_burn_spawn(entity _nade)
  {
-       CSQCProjectile(_nade, true, Nades[_nade.nade_type].m_projectile[true], true);
+       CSQCProjectile(_nade, true, Nades_from(_nade.nade_type).m_projectile[true], true);
  }
  
  void nade_spawn(entity _nade)
  {
 -      entity timer = spawn();
 +      entity timer = new(nade_timer);
        setmodel(timer, MDL_NADE_TIMER);
        setattachment(timer, _nade, "");
 -      timer.classname = "nade_timer";
        timer.colormap = _nade.colormap;
        timer.glowmod = _nade.glowmod;
        timer.think = nade_timer_think;
@@@ -82,7 -83,7 +82,7 @@@
  
        _nade.effects |= EF_LOWPRECISION;
  
-       CSQCProjectile(_nade, true, Nades[_nade.nade_type].m_projectile[false], true);
+       CSQCProjectile(_nade, true, Nades_from(_nade.nade_type).m_projectile[false], true);
  }
  
  void napalm_damage(float dist, float damage, float edgedamage, float burntime)
@@@ -163,10 -164,11 +163,10 @@@ void nade_napalm_ball(
  
        spamsound(self, CH_SHOTS, SND(FIREBALL_FIRE), VOL_BASE, ATTEN_NORM);
  
 -      proj = spawn ();
 +      proj = new(grenade);
        proj.owner = self.owner;
        proj.realowner = self.realowner;
        proj.team = self.owner.team;
 -      proj.classname = "grenade";
        proj.bot_dodge = true;
        proj.bot_dodgerating = autocvar_g_nades_napalm_ball_damage;
        proj.movetype = MOVETYPE_BOUNCE;
@@@ -358,9 -360,10 +358,9 @@@ void nade_ice_boom(
        if ( autocvar_g_nades_ice_explode )
        {
                setmodel(fountain, MDL_PROJECTILE_GRENADE);
 -              entity timer = spawn();
 +              entity timer = new(nade_timer);
                setmodel(timer, MDL_NADE_TIMER);
                setattachment(timer, fountain, "");
 -              timer.classname = "nade_timer";
                timer.colormap = self.colormap;
                timer.glowmod = self.glowmod;
                timer.think = nade_timer_think;
@@@ -510,7 -513,7 +510,7 @@@ void nade_boom(
        entity expef = NULL;
        bool nade_blast = true;
  
-       switch ( Nades[self.nade_type] )
+       switch ( Nades_from(self.nade_type) )
        {
                case NADE_TYPE_NAPALM:
                        nade_blast = autocvar_g_nades_napalm_blast;
        }
  
        if(self.takedamage)
-       switch ( Nades[self.nade_type] )
+       switch ( Nades_from(self.nade_type) )
        {
                case NADE_TYPE_NAPALM: nade_napalm_boom(); break;
                case NADE_TYPE_ICE: nade_ice_boom(); break;
@@@ -805,7 -808,7 +805,7 @@@ float nade_customize(
        {
                //self.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
                if(!self.traileffectnum)
-                       self.traileffectnum = _particleeffectnum(Nade_TrailEffect(Nades[self.nade_type].m_projectile[false], self.team).eent_eff_name);
+                       self.traileffectnum = _particleeffectnum(Nade_TrailEffect(Nades_from(self.nade_type).m_projectile[false], self.team).eent_eff_name);
                self.alpha = 1;
        }
  
@@@ -824,7 -827,10 +824,7 @@@ void nade_prime(
        if(self.fake_nade)
                remove(self.fake_nade);
  
 -      entity n = spawn(), fn = spawn();
 -
 -      n.classname = "nade";
 -      fn.classname = "fake_nade";
 +      entity n = new(nade), fn = new(fake_nade);
  
        if(self.items & ITEM_Strength.m_itemid && autocvar_g_nades_bonus_onstrength)
                n.nade_type = self.nade_type;
        //setattachment(n, self, "bip01 l hand");
        n.exteriormodeltoclient = self;
        n.customizeentityforclient = nade_customize;
-       n.traileffectnum = _particleeffectnum(Nade_TrailEffect(Nades[n.nade_type].m_projectile[false], self.team).eent_eff_name);
-       n.colormod = Nades[n.nade_type].m_color;
+       n.traileffectnum = _particleeffectnum(Nade_TrailEffect(Nades_from(n.nade_type).m_projectile[false], self.team).eent_eff_name);
+       n.colormod = Nades_from(n.nade_type).m_color;
        n.realowner = self;
        n.colormap = self.colormap;
        n.glowmod = self.glowmod;
        int slot = 0; // TODO: unhardcode
        setattachment(fn, self.weaponentity[slot], "");
        fn.realowner = fn.owner = self;
-       fn.colormod = Nades[n.nade_type].m_color;
+       fn.colormod = Nades_from(n.nade_type).m_color;
        fn.colormap = self.colormap;
        fn.glowmod = self.glowmod;
        fn.think = SUB_Remove;