Merge branches 'TimePath/weaponsys' and 'Mario/modpack'
authorTimePath <andrew.hardaker1995@gmail.com>
Fri, 21 Aug 2015 06:47:39 +0000 (16:47 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Fri, 21 Aug 2015 06:47:39 +0000 (16:47 +1000)
45 files changed:
1  2  3 
qcsrc/Makefile
qcsrc/client/main.qc
qcsrc/client/progs.src
qcsrc/common/monsters/monster/shambler.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/physics.qc
qcsrc/common/weapons/all.qc
qcsrc/common/weapons/w_arc.qc
qcsrc/common/weapons/w_blaster.qc
qcsrc/common/weapons/w_crylink.qc
qcsrc/common/weapons/w_devastator.qc
qcsrc/common/weapons/w_electro.qc
qcsrc/common/weapons/w_fireball.qc
qcsrc/common/weapons/w_hagar.qc
qcsrc/common/weapons/w_hlac.qc
qcsrc/common/weapons/w_hmg.qc
qcsrc/common/weapons/w_hook.qc
qcsrc/common/weapons/w_machinegun.qc
qcsrc/common/weapons/w_minelayer.qc
qcsrc/common/weapons/w_mortar.qc
qcsrc/common/weapons/w_porto.qc
qcsrc/common/weapons/w_rifle.qc
qcsrc/common/weapons/w_rpc.qc
qcsrc/common/weapons/w_seeker.qc
qcsrc/common/weapons/w_shockwave.qc
qcsrc/common/weapons/w_shotgun.qc
qcsrc/common/weapons/w_tuba.qc
qcsrc/common/weapons/w_vaporizer.qc
qcsrc/menu/menu.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_player.qc
qcsrc/server/g_damage.qc
qcsrc/server/g_hook.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/mutators/gamemode_nexball.qc
qcsrc/server/mutators/mutator_buffs.qc
qcsrc/server/mutators/mutator_instagib.qc
qcsrc/server/mutators/mutator_nades.qc
qcsrc/server/mutators/mutator_nix.qc
qcsrc/server/mutators/mutator_overkill.qc
qcsrc/server/progs.src
qcsrc/server/vehicles/vehicle.qc
qcsrc/server/weapons/weaponsystem.qc

diff --combined qcsrc/Makefile
@@@@ -13,14 -13,14 -13,15 +13,15 @@@@ QCCFLAGS ?= 
        -std=gmqcc \
        -O3 -flno \
        -Werror -fno-bail-on-werror -Wall \
--      -fftepp -fftepp-predefs -Wcpp -futf8 -frelaxed-switch \
  -     -fftepp -fftepp-predefs -Wcpp -futf8 -freturn-assignments \
+++     -fftepp -fftepp-predefs -Wcpp -futf8 -frelaxed-switch -freturn-assignments \
        $(QCCFLAGS_WTFS) \
        $(QCCFLAGS_FEATURES) \
        $(QCCFLAGS_EXTRA) $(QCCFLAGS_WATERMARK)
   
   QCCFLAGS_FEATURES ?= \
        -DVEHICLES_ENABLED=1 \
--      -DVEHICLES_USE_ODE=0
++      -DVEHICLES_USE_ODE=0 \
++      -DBUILD_MOD=$(BUILD_MOD)
   
   # xonotic build system overrides this by command line argument to turn off the update-cvarcount step
   XON_BUILDSYSTEM =
diff --combined qcsrc/client/main.qc
   
   #include "../common/buffs.qh"
   #include "../common/deathtypes.qh"
 ++#include "../common/effects.qh"
   #include "../common/mapinfo.qh"
   #include "../common/monsters/all.qh"
   #include "../common/nades.qh"
   
   #include "../common/items/all.qh"
   
++ #include "../common/mutators/base.qh"
++ 
   #include "../common/weapons/all.qh"
   
   #include "../csqcmodellib/cl_model.qh"
@@@@ -142,11 -141,9 -143,10 +144,10 @@@@ void CSQC_Init(void
   
        // needs to be done so early because of the constants they create
        static_init();
- -     CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
        CALL_ACCUMULATED_FUNCTION(RegisterHUD_Panels);
 ++     CALL_ACCUMULATED_FUNCTION(RegisterEffects);
   
        WaypointSprite_Load();
   
@@@@ -888,7 -885,6 -888,6 +889,7 @@@@ void CSQC_Ent_Update(float bIsNewEntity
                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;
   
                default:
                        //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype));
diff --combined qcsrc/client/progs.src
@@@@ -44,7 -44,6 -44,6 +44,7 @@@@ weapons/projectile.qc // TOD
   
   ../common/animdecide.qc
   ../common/buffs.qc
 ++../common/effects.qc
   ../common/mapinfo.qc
   ../common/movetypes/include.qc
   ../common/nades.qc
   ../warpzonelib/common.qc
   ../warpzonelib/mathlib.qc
   ../warpzonelib/util_server.qc
++ 
++ ../../mod/client/progs.inc
@@@@ -43,7 -43,7 -43,7 +43,7 @@@@ const float shambler_anim_death               = 8
   void shambler_smash()
   {
        makevectors(self.angles);
 --     pointparticles(particleeffectnum("explosion_medium"), (self.origin + (v_forward * 150)) - ('0 0 1' * self.maxs.z), '0 0 0', 1);
 ++     Send_Effect("explosion_medium", (self.origin + (v_forward * 150)) - ('0 0 1' * self.maxs.z), '0 0 0', 1);
        sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
   
        tracebox(self.origin + v_forward * 50, self.mins * 0.5, self.maxs * 0.5, self.origin + v_forward * 500, MOVE_NORMAL, self);
@@@@ -68,7 -68,7 -68,7 +68,7 @@@@ void shambler_lightning_explode(
        entity head;
   
        sound(self, CH_SHOTS, "weapons/electro_impact.wav", VOL_BASE, ATTEN_NORM);
 --     pointparticles(particleeffectnum("electro_impact"), '0 0 0', '0 0 0', 1);
 ++     Send_Effect("electro_impact", '0 0 0', '0 0 0', 1);
   
        self.event_damage = func_null;
        self.takedamage = DAMAGE_NO;
@@@@ -226,7 -226,7 -226,7 +226,7 @@@@ float m_shambler(float req
                        self.monster_loot = spawnfunc_item_health_mega;
                        self.monster_attackfunc = shambler_attack;
                        self.frame = shambler_anim_stand;
- -                     self.weapon = WEP_VORTEX;
+ +                     self.weapon = WEP_VORTEX.m_id;
   
                        return true;
                }
@@@@ -40,7 -40,8 -40,7 +40,7 @@@@ void monster_dropitem(
   
        e.monster_loot = self.monster_loot;
   
 -      other = e;
 -      MUTATOR_CALLHOOK(MonsterDropItem);
 +      MUTATOR_CALLHOOK(MonsterDropItem, e);
        e = other;
   
        if(e && e.monster_loot)
@@@@ -80,7 -81,7 -80,7 +80,7 @@@@ float monster_isvalidtarget (entity tar
        //if(trace_ent != targ)
                //return false;
   
 --     if(targ.vehicle_flags & VHF_ISVEHICLE)
 ++     if(IS_VEHICLE(targ))
        if(!((get_monsterinfo(ent.monsterid)).spawnflags & MON_FLAG_RANGED))
                return false; // melee attacks are useless against vehicles
   
        if(IS_SPEC(targ) || IS_OBSERVER(targ))
                return false; // enemy is a spectator
   
 --     if(!(targ.vehicle_flags & VHF_ISVEHICLE))
 ++     if(!IS_VEHICLE(targ))
        if(targ.deadflag != DEAD_NO || ent.deadflag != DEAD_NO || targ.health <= 0 || ent.health <= 0)
                return false; // enemy/self is dead
   
        if(targ.monster_owner == ent)
                return false; // don't attack our pet
   
 --     if(!(targ.vehicle_flags & VHF_ISVEHICLE))
 ++     if(!IS_VEHICLE(targ))
        if(targ.flags & FL_NOTARGET)
                return false; // enemy can't be targeted
   
@@@@ -181,7 -182,7 -181,7 +181,7 @@@@ void MonsterTouch (
                return;
   
        if(self.enemy != other)
 --     if(!(other.flags & FL_MONSTER))
 ++     if(!IS_MONSTER(other))
        if(monster_isvalidtarget(other, self))
                self.enemy = other;
   }
@@@@ -361,7 -362,7 -361,7 +361,7 @@@@ void Monster_CheckMinibossFlag (
                self.health += autocvar_g_monsters_miniboss_healthboost;
                self.effects |= EF_RED;
                if(!self.weapon)
- -                     self.weapon = WEP_VORTEX;
+ +                     self.weapon = WEP_VORTEX.m_id;
        }
   }
   
@@@@ -369,7 -370,7 -369,7 +369,7 @@@@ float Monster_CanRespawn(entity ent
   {
        other = ent;
        if(ent.deadflag == DEAD_DEAD) // don't call when monster isn't dead
 -      if(MUTATOR_CALLHOOK(MonsterRespawn))
 +      if(MUTATOR_CALLHOOK(MonsterRespawn, ent))
                return true; // enabled by a mutator
   
        if(ent.spawnflags & MONSTERFLAG_NORESPAWN)
@@@@ -591,7 -592,7 -591,7 +591,7 @@@@ void monster_CalculateVelocity(entity m
   {
        float current_distance = vlen((('1 0 0' * to.x) + ('0 1 0' * to.y)) - (('1 0 0' * from.x) + ('0 1 0' * from.y))); // for the sake of this check, exclude Z axis
        float initial_height = 0; //min(50, (targ_distance * tanh(20)));
 --     float current_height = (initial_height * min(1, (current_distance / self.pass_distance)));
 ++     float current_height = (initial_height * min(1, self.pass_distance ? (current_distance / self.pass_distance) : 0));
        //print("current_height = ", ftos(current_height), ", initial_height = ", ftos(initial_height), ".\n");
   
        vector targpos;
@@@@ -715,13 -716,11 -715,13 +715,13 @@@@ void monster_move(float runspeed, floa
   
        targ = self.goalentity;
   
 -      monster_target = targ;
 -      monster_speed_run = runspeed;
 -      monster_speed_walk = walkspeed;
 - 
 -      if(MUTATOR_CALLHOOK(MonsterMove) || gameover || self.draggedby != world || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || time < game_starttime || (autocvar_g_campaign && !campaign_bots_may_start) || time < self.spawn_time)
 +      if (MUTATOR_CALLHOOK(MonsterMove, runspeed, walkspeed, targ)
 +              || gameover
 +              || self.draggedby != world
 +              || (round_handler_IsActive() && !round_handler_IsRoundStarted())
 +              || time < game_starttime
 +              || (autocvar_g_campaign && !campaign_bots_may_start)
 +              || time < self.spawn_time)
        {
                runspeed = walkspeed = 0;
                if(time >= self.spawn_time)
                return;
        }
   
 -      targ = monster_target;
        runspeed = bound(0, monster_speed_run * Monster_SkillModifier(), runspeed * 2); // limit maxspeed to prevent craziness
        walkspeed = bound(0, monster_speed_walk * Monster_SkillModifier(), walkspeed * 2); // limit maxspeed to prevent craziness
   
@@@@ -842,7 -842,7 -842,7 +842,7 @@@@ void monster_remove(entity mon
        if(!mon)
                return; // nothing to remove
   
 --     pointparticles(particleeffectnum("item_pickup"), mon.origin, '0 0 0', 1);
 ++     Send_Effect("item_pickup", mon.origin, '0 0 0', 1);
   
        if(mon.weaponentity)
                remove(mon.weaponentity);
@@@@ -1039,8 -1039,9 -1039,8 +1039,8 @@@@ void monsters_damage (entity inflictor
   
                WaypointSprite_Kill(self.sprite);
   
 -              frag_attacker = attacker;
                frag_target = self;
 -              MUTATOR_CALLHOOK(MonsterDies);
 +              MUTATOR_CALLHOOK(MonsterDies, attacker);
   
                if(self.health <= -100 || deathtype == DEATH_KILL) // check if we're already gibbed
                {
diff --combined qcsrc/common/physics.qc
@@@@ -553,12 -553,12 -553,12 +553,12 @@@@ bool PlayerJump (void
        bool doublejump = false;
        float mjumpheight = PHYS_JUMPVELOCITY;
   
 -      player_multijump = doublejump;
 -      player_jumpheight = mjumpheight;
   #ifdef SVQC
 -      if (MUTATOR_CALLHOOK(PlayerJump))
 +      if (MUTATOR_CALLHOOK(PlayerJump, doublejump, mjumpheight))
   #elif defined(CSQC)
 -      if(PM_multijump_checkjump())
 +      player_multijump = doublejump;
 +      player_jumpheight = mjumpheight;
 +      if (PM_multijump_checkjump())
   #endif
                return true;
   
@@@@ -709,7 -709,7 -709,7 +709,7 @@@@ void CheckPlayerJump(
                float activate = JETPACK_JUMP(self) && air_jump && PHYS_INPUT_BUTTON_JUMP(self) || PHYS_INPUT_BUTTON_JETPACK(self);
                float has_fuel = !PHYS_JETPACK_FUEL || PHYS_AMMO_FUEL(self) || ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO;
   
 --             if (!(ITEMS_STAT(self) & IT_JETPACK)) { }
 ++             if (!(ITEMS_STAT(self) & ITEM_Jetpack.m_itemid)) { }
                else if (self.jetpack_stopped) { }
                else if (!has_fuel)
                {
@@@@ -1193,7 -1193,7 -1193,7 +1193,7 @@@@ void PM_check_vortex(void
   #ifdef SVQC
        // WEAPONTODO
        float xyspeed = vlen(vec2(self.velocity));
- -     if (self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
+ +     if (self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
        {
                // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
                xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
   #ifndef MENUQC
   #include "calculations.qc"
   #endif
+ +#define IMPLEMENTATION
   #include "all.inc"
+ +#undef IMPLEMENTATION
   
   // WEAPON PLUGIN SYSTEM
- -entity weapon_info[WEP_MAXCOUNT];
- -entity dummy_weapon_info;
   
   #if WEP_MAXCOUNT > 72
   # error Kein Weltraum links auf dem Gerät
@@@@ -149,77 -149,13 -149,77 +149,13 @@@@ WepSet ReadWepSet(
   }
   #endif
   
- -void register_weapon(
- -     int id,
- -     WepSet bit,
- -     bool(int) func,
- -     .int ammotype,
- -     int i,
- -     int weapontype,
- -     float pickupbasevalue,
- -     vector clr,
- -     string modelname,
- -     string simplemdl,
- -     string crosshair,
- -     string wepimg,
- -     string refname,
- -     string wepname)
- -{
- -     entity e;
- -     weapon_info[id - 1] = e = spawn();
- -     e.classname = "weapon_info";
- -     e.weapon = id;
- -     e.weapons = bit;
- -     e.weapon_func = func;
- -     e.ammo_field = ammotype;
- -     e.impulse = i;
- -     e.spawnflags = weapontype;
- -     e.bot_pickupbasevalue = pickupbasevalue;
- -     e.wpcolor = clr;
- -     e.wpmodel = strzone(strcat("wpn-", ftos(id)));
- -     e.mdl = modelname;
- -     e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
- -     e.w_simplemdl = strzone(simplemdl); // simpleitems weapon model/image
- -     e.w_crosshair = strzone(car(crosshair));
- -     string s = cdr(crosshair);
- -     e.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat)
- -     e.model2 = strzone(wepimg);
- -     e.netname = refname;
- -     e.message = wepname;
- -
- -     #ifdef CSQC
- -     func(WR_INIT);
- -     #endif
- -}
- -bool w_null(int dummy)
- -{
- -     return 0;
- -}
   void register_weapons_done()
   {
- -     dummy_weapon_info = spawn();
- -     dummy_weapon_info.classname = "weapon_info";
- -     dummy_weapon_info.weapon = 0; // you can recognize dummies by this
- -     dummy_weapon_info.weapons = '0 0 0';
- -     dummy_weapon_info.netname = "";
- -     dummy_weapon_info.message = "AOL CD Thrower";
- -     dummy_weapon_info.weapon_func = w_null;
- -     dummy_weapon_info.wpmodel = "";
- -     dummy_weapon_info.mdl = "";
- -     dummy_weapon_info.model = "";
- -     dummy_weapon_info.spawnflags = 0;
- -     dummy_weapon_info.impulse = -1;
- -     dummy_weapon_info.bot_pickupbasevalue = 0;
- -     dummy_weapon_info.ammo_field = ammo_none;
- -
- -     dummy_weapon_info.w_crosshair = "gfx/crosshair1";
- -     dummy_weapon_info.w_crosshair_size = 1;
- -     dummy_weapon_info.model2 = "";
+ +     dummy_weapon_info = NEW(Weapon);
   
- -     int i;
        weaponorder_byid = "";
- -     for(i = WEP_MAXCOUNT; i >= 1; --i)
- -             if(weapon_info[i-1])
+ +     for (int i = WEP_MAXCOUNT - 1; i >= 0; --i)
+ +             if (weapon_info[i])
                        weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
        weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
   }
@@@@ -353,14 -289,14 -353,14 +289,14 @@@@ void W_RandomWeapons(entity e, float n
   
   string GetAmmoPicture(.int ammotype)
   {
 --     switch(ammotype)
 ++     switch (ammotype)
        {
 --             case ammo_shells:  return "ammo_shells";
 --             case ammo_nails:   return "ammo_bullets";
 --             case ammo_rockets: return "ammo_rockets";
 --             case ammo_cells:   return "ammo_cells";
 --             case ammo_plasma:  return "ammo_cells";
 --             case ammo_fuel:    return "ammo_fuel";
 ++             case ammo_shells:  return ITEM_Shells.m_ammoPic;
 ++             case ammo_nails:   return ITEM_Bullets.m_ammoPic;
 ++             case ammo_rockets: return ITEM_Rockets.m_ammoPic;
 ++             case ammo_cells:   return ITEM_Cells.m_ammoPic;
 ++             case ammo_plasma:  return ITEM_Plasma.m_ammoPic;
 ++             case ammo_fuel:    return ITEM_JetpackFuel.m_ammoPic;
                default: return ""; // wtf, no ammo type?
        }
   }
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ ARC,
   /* function  */ W_Arc,
@@@@ -123,9 -123,10 -123,9 +123,10 @@@@ float Draw_ArcBeam_callback_last_thickn
   vector Draw_ArcBeam_callback_last_top; // NOTE: in same coordinate system as player.
   vector Draw_ArcBeam_callback_last_bottom; // NOTE: in same coordinate system as player.
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_arc(void) { weapon_defaultspawnfunc(WEP_ARC); }
+ +void spawnfunc_weapon_arc(void) { weapon_defaultspawnfunc(WEP_ARC.m_id); }
   
   float W_Arc_Beam_Send(entity to, int sf)
   {
@@@@ -264,7 -265,7 -264,7 +265,7 @@@@ void W_Arc_Beam_Think(void
   
                        if ( WEP_CVAR(arc, overheat_max) > 0 && self.beam_heat >= WEP_CVAR(arc, overheat_max) )
                        {
 --                             pointparticles( particleeffectnum("arc_overheat"),
 ++                             Send_Effect("arc_overheat",
                                        self.beam_start, self.beam_wantdir, 1 );
                                sound(self, CH_WEAPON_A, "weapons/arc_stop.wav", VOL_BASE, ATTN_NORM);
                        }
                if(self == self.owner.arc_beam) { self.owner.arc_beam = world; }
                entity oldself = self;
                self = self.owner;
- -             if(!WEP_ACTION(WEP_ARC, WR_CHECKAMMO1) && !WEP_ACTION(WEP_ARC, WR_CHECKAMMO2))
+ +             if(!WEP_ACTION(WEP_ARC.m_id, WR_CHECKAMMO1) && !WEP_ACTION(WEP_ARC.m_id, WR_CHECKAMMO2))
                if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
                {
                        // note: this doesn't force the switch
                new_dir = WarpZone_TransformVelocity(WarpZone_trace_transform, new_dir);
   
                float is_player = (
 --                     trace_ent.classname == "player"
 ++                     IS_PLAYER(trace_ent)
                        ||
                        trace_ent.classname == "body"
                        ||
 --                     (trace_ent.flags & FL_MONSTER)
 ++                     IS_MONSTER(trace_ent)
                );
   
                if(trace_ent && trace_ent.takedamage && (is_player || WEP_CVAR(arc, beam_nonplayerdamage)))
                                {
                                        accuracy_add(
                                                self.owner,
- -                                             WEP_ARC,
+ +                                             WEP_ARC.m_id,
                                                0,
                                                rootdamage * coefficient * falloff
                                        );
                                        self.owner,
                                        self.owner,
                                        rootdamage * coefficient * falloff,
- -                                     WEP_ARC,
+ +                                     WEP_ARC.m_id,
                                        hitorigin,
                                        WEP_CVAR(arc, beam_force) * new_dir * coefficient * falloff
                                );
@@@@ -609,10 -610,10 -609,10 +610,10 @@@@ void Arc_Smoke(
        if ( self.arc_overheat > time )
        {
                if ( random() < self.arc_heat_percent )
 --                     pointparticles( particleeffectnum("arc_smoke"), smoke_origin, '0 0 0', 1 );
 ++                     Send_Effect("arc_smoke", smoke_origin, '0 0 0', 1 );
                if ( self.BUTTON_ATCK || self.BUTTON_ATCK2 )
                {
 --                     pointparticles( particleeffectnum("arc_overheat_fire"), smoke_origin, w_shotdir, 1 );
 ++                     Send_Effect("arc_overheat_fire", smoke_origin, w_shotdir, 1 );
                        if ( !self.arc_smoke_sound )
                        {
                                self.arc_smoke_sound = 1;
        {
                if ( random() < (self.arc_beam.beam_heat-WEP_CVAR(arc, overheat_min)) /
                                ( WEP_CVAR(arc, overheat_max)-WEP_CVAR(arc, overheat_min) ) )
 --                     pointparticles( particleeffectnum("arc_smoke"), smoke_origin, '0 0 0', 1 );
 ++                     Send_Effect("arc_smoke", smoke_origin, '0 0 0', 1 );
        }
   
        if (  self.arc_smoke_sound && ( self.arc_overheat <= time ||
- -             !( self.BUTTON_ATCK || self.BUTTON_ATCK2 ) ) || self.switchweapon != WEP_ARC )
+ +             !( self.BUTTON_ATCK || self.BUTTON_ATCK2 ) ) || self.switchweapon != WEP_ARC.m_id )
        {
                self.arc_smoke_sound = 0;
                sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
@@@@ -730,10 -731,10 -730,10 +731,10 @@@@ bool W_Arc(int req
                        precache_sound("weapons/arc_loop_overheat.wav");
                        if(!arc_shotorigin[0])
                        {
- -                             arc_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), false, false, 1);
- -                             arc_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), false, false, 2);
- -                             arc_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), false, false, 3);
- -                             arc_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), false, false, 4);
+ +                             arc_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC.m_id), false, false, 1);
+ +                             arc_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC.m_id), false, false, 2);
+ +                             arc_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC.m_id), false, false, 3);
+ +                             arc_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC.m_id), false, false, 4);
                        }
                        ARC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
                        return true;
                }
                case WR_PICKUP:
                {
- -                     if ( !client_hasweapon(self, WEP_ARC, false, false) &&
+ +                     if ( !client_hasweapon(self, WEP_ARC.m_id, false, false) &&
                                weapon_dropevent_item.arc_overheat > time )
                        {
                                self.arc_overheat = weapon_dropevent_item.arc_overheat;
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ BLASTER,
   /* function  */ W_Blaster,
@@@@ -45,9 -45,10 -45,9 +45,10 @@@@ BLASTER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_
   .float blaster_force;
   .float blaster_lifetime;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_blaster(void) { weapon_defaultspawnfunc(WEP_BLASTER); }
+ +void spawnfunc_weapon_blaster(void) { weapon_defaultspawnfunc(WEP_BLASTER.m_id); }
   void spawnfunc_weapon_laser(void) { spawnfunc_weapon_blaster(); }
   
   void W_Blaster_Touch(void)
@@@@ -95,7 -96,7 -95,7 +96,7 @@@@ void W_Blaster_Attack
        vector s_forward = v_forward * cos(atk_shotangle * DEG2RAD) + v_up * sin(atk_shotangle * DEG2RAD);
   
        W_SetupShot_Dir(self, s_forward, false, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, atk_damage);
 --     pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("laser_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        entity missile = spawn();
        missile.owner = missile.realowner = self;
        missile.think = W_Blaster_Think;
        missile.nextthink = time + atk_delay;
   
 -      other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, missile);
   
        if(time >= missile.nextthink)
        {
@@@@ -173,7 -174,7 -173,7 +174,7 @@@@ bool W_Blaster(int request
                                if(weapon_prepareattack(0, WEP_CVAR_PRI(blaster, refire)))
                                {
                                        W_Blaster_Attack(
- -                                             WEP_BLASTER,
+ +                                             WEP_BLASTER.m_id,
                                                WEP_CVAR_PRI(blaster, shotangle),
                                                WEP_CVAR_PRI(blaster, damage),
                                                WEP_CVAR_PRI(blaster, edgedamage),
                                {
                                        case 0: // switch to last used weapon
                                        {
- -                                             if(self.switchweapon == WEP_BLASTER) // don't do this if already switching
+ +                                             if(self.switchweapon == WEP_BLASTER.m_id) // don't do this if already switching
                                                        W_LastWeapon();
                                                break;
                                        }
                                                if(weapon_prepareattack(1, WEP_CVAR_SEC(blaster, refire)))
                                                {
                                                        W_Blaster_Attack(
- -                                                             WEP_BLASTER | HITTYPE_SECONDARY,
+ +                                                             WEP_BLASTER.m_id | HITTYPE_SECONDARY,
                                                                WEP_CVAR_SEC(blaster, shotangle),
                                                                WEP_CVAR_SEC(blaster, damage),
                                                                WEP_CVAR_SEC(blaster, edgedamage),
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ CRYLINK,
   /* function  */ W_Crylink,
@@@@ -61,9 -61,10 -61,9 +61,10 @@@@ CRYLINK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_
   .entity queuenext;
   .entity queueprev;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_crylink(void) { weapon_defaultspawnfunc(WEP_CRYLINK); }
+ +void spawnfunc_weapon_crylink(void) { weapon_defaultspawnfunc(WEP_CRYLINK.m_id); }
   
   void W_Crylink_CheckLinks(entity e)
   {
@@@@ -257,7 -258,7 -257,7 +258,7 @@@@ void W_Crylink_LinkJoinEffect_Think(voi
                                        e.projectiledeathtype,
                                        other
                                );
 --                             pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n);
 ++                             Send_Effect("crylink_joinexplode", self.origin, '0 0 0', n);
                        }
                }
        }
@@@@ -359,7 -360,7 -359,7 +360,7 @@@@ void W_Crylink_Attack(void
        up = v_up;
   
        shots = WEP_CVAR_PRI(crylink, shots);
 --     pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots);
 ++     Send_Effect("crylink_muzzleflash", w_shotorg, w_shotdir * 1000, shots);
        proj = prevproj = firstproj = world;
        for(counter = 0; counter < shots; ++counter)
        {
   
                proj.movetype = MOVETYPE_BOUNCEMISSILE;
                PROJECTILE_MAKETRIGGER(proj);
- -             proj.projectiledeathtype = WEP_CRYLINK;
+ +             proj.projectiledeathtype = WEP_CRYLINK.m_id;
                //proj.gravity = 0.001;
   
                setorigin(proj, w_shotorg);
   
                CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
   
 -              other = proj; MUTATOR_CALLHOOK(EditProjectile);
 +              MUTATOR_CALLHOOK(EditProjectile, self, proj);
        }
        if(WEP_CVAR_PRI(crylink, joinspread) != 0)
        {
@@@@ -468,7 -469,7 -468,7 +469,7 @@@@ void W_Crylink_Attack2(void
        up = v_up;
   
        shots = WEP_CVAR_SEC(crylink, shots);
 --     pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots);
 ++     Send_Effect("crylink_muzzleflash", w_shotorg, w_shotdir * 1000, shots);
        proj = prevproj = firstproj = world;
        for(counter = 0; counter < shots; ++counter)
        {
   
                proj.movetype = MOVETYPE_BOUNCEMISSILE;
                PROJECTILE_MAKETRIGGER(proj);
- -             proj.projectiledeathtype = WEP_CRYLINK | HITTYPE_SECONDARY;
+ +             proj.projectiledeathtype = WEP_CRYLINK.m_id | HITTYPE_SECONDARY;
                //proj.gravity = 0.001;
   
                setorigin(proj, w_shotorg);
   
                CSQCProjectile(proj, true, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), true);
   
 -              other = proj; MUTATOR_CALLHOOK(EditProjectile);
 +              MUTATOR_CALLHOOK(EditProjectile, self, proj);
        }
        if(WEP_CVAR_SEC(crylink, joinspread) != 0)
        {
@@@@ -627,7 -628,7 -627,7 +628,7 @@@@ bool W_Crylink(int req
                                        if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
                                        {
                                                // ran out of ammo!
- -                                             self.cnt = WEP_CRYLINK;
+ +                                             self.cnt = WEP_CRYLINK.m_id;
                                                self.switchweapon = w_getbestweapon(self);
                                        }
                                }
                                return true;
   
                        ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_PRI(crylink, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= WEP_CVAR_PRI(crylink, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_PRI(crylink, ammo);
                        return ammo_amount;
                }
                case WR_CHECKAMMO2:
                                return true;
   
                        ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_SEC(crylink, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= WEP_CVAR_SEC(crylink, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_CRYLINK.m_id]) >= WEP_CVAR_SEC(crylink, ammo);
                        return ammo_amount;
                }
                case WR_CONFIG:
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ DEVASTATOR,
   /* function  */ W_Devastator,
@@@@ -59,9 -59,10 -59,9 +59,10 @@@@ DEVASTATOR_SETTINGS(WEP_ADD_CVAR, WEP_A
   .float rl_release;
   .float rl_detonate_later;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_devastator(void) { weapon_defaultspawnfunc(WEP_DEVASTATOR); }
+ +void spawnfunc_weapon_devastator(void) { weapon_defaultspawnfunc(WEP_DEVASTATOR.m_id); }
   void spawnfunc_weapon_rocketlauncher(void) { spawnfunc_weapon_devastator(); }
   
   void W_Devastator_Unregister(void)
@@@@ -100,12 -101,12 -100,12 +101,12 @@@@ void W_Devastator_Explode(void
                other
        );
   
- -     if(self.realowner.weapon == WEP_DEVASTATOR)
+ +     if(self.realowner.weapon == WEP_DEVASTATOR.m_id)
        {
                if(self.realowner.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
                if(!(self.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
                {
- -                     self.realowner.cnt = WEP_DEVASTATOR;
+ +                     self.realowner.cnt = WEP_DEVASTATOR.m_id;
                        ATTACK_FINISHED(self.realowner) = time;
                        self.realowner.switchweapon = w_getbestweapon(self.realowner);
                }
@@@@ -179,12 -180,12 -179,12 +180,12 @@@@ void W_Devastator_DoRemoteExplode(void
                world
        );
   
- -     if(self.realowner.weapon == WEP_DEVASTATOR)
+ +     if(self.realowner.weapon == WEP_DEVASTATOR.m_id)
        {
                if(self.realowner.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
                if(!(self.realowner.items & IT_UNLIMITED_WEAPON_AMMO))
                {
- -                     self.realowner.cnt = WEP_DEVASTATOR;
+ +                     self.realowner.cnt = WEP_DEVASTATOR.m_id;
                        ATTACK_FINISHED(self.realowner) = time;
                        self.realowner.switchweapon = w_getbestweapon(self.realowner);
                }
@@@@ -260,7 -261,7 -260,7 +261,7 @@@@ void W_Devastator_Think(void
                self.velocity = self.velocity + v_forward * min(WEP_CVAR(devastator, speedaccel) * W_WeaponSpeedFactor() * frametime, velspeed);
   
        // laser guided, or remote detonation
- -     if(self.realowner.weapon == WEP_DEVASTATOR)
+ +     if(self.realowner.weapon == WEP_DEVASTATOR.m_id)
        {
                if(self == self.realowner.lastrocket)
                if(!self.realowner.rl_release)
   
                        if(!self.count)
                        {
 --                             pointparticles(particleeffectnum("rocket_guide"), self.origin, self.velocity, 1);
 ++                             Send_Effect("rocket_guide", self.origin, self.velocity, 1);
                                // TODO add a better sound here
                                sound(self.realowner, CH_WEAPON_B, "weapons/rocket_mode.wav", VOL_BASE, ATTN_NORM);
                                self.count = 1;
@@@@ -342,7 -343,7 -342,7 +343,7 @@@@ void W_Devastator_Attack(void
        W_DecreaseAmmo(WEP_CVAR(devastator, ammo));
   
        W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, WEP_CVAR(devastator, damage));
 --     pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("rocketlauncher_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        missile = WarpZone_RefSys_SpawnSameRefSys(self);
        missile.owner = missile.realowner = self;
   
        missile.movetype = MOVETYPE_FLY;
        PROJECTILE_MAKETRIGGER(missile);
- -     missile.projectiledeathtype = WEP_DEVASTATOR;
+ +     missile.projectiledeathtype = WEP_DEVASTATOR.m_id;
        setsize(missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
   
        setorigin(missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point
        W_AttachToShotorg(flash, '5 0 0');
   
        // common properties
 -      other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, missile);
   }
   
   bool W_Devastator(int req)
                                        self.rl_release = 1;
   
                                if(self.BUTTON_ATCK2)
- -                             if(self.switchweapon == WEP_DEVASTATOR)
+ +                             if(self.switchweapon == WEP_DEVASTATOR.m_id)
                                {
                                        rockfound = 0;
                                        for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self)
                {
                        #if 0
                        // don't switch while guiding a missile
- -                     if(ATTACK_FINISHED(self) <= time || self.weapon != WEP_DEVASTATOR)
+ +                     if(ATTACK_FINISHED(self) <= time || self.weapon != WEP_DEVASTATOR.m_id)
                        {
                                ammo_amount = false;
                                if(WEP_CVAR(devastator, reload_ammo))
                                {
- -                                     if(self.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo) && self.(weapon_load[WEP_DEVASTATOR]) < WEP_CVAR(devastator, ammo))
+ +                                     if(self.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo) && self.(weapon_load[WEP_DEVASTATOR.m_id]) < WEP_CVAR(devastator, ammo))
                                                ammo_amount = true;
                                }
                                else if(self.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
                        else
                        {
                                ammo_amount = self.WEP_AMMO(DEVASTATOR) >= WEP_CVAR(devastator, ammo);
- -                             ammo_amount += self.(weapon_load[WEP_DEVASTATOR]) >= WEP_CVAR(devastator, ammo);
+ +                             ammo_amount += self.(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
                                printf("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: %s\n", self.rl_release, self.WEP_AMMO(DEVASTATOR), WEP_CVAR(devastator, ammo), (ammo_amount ? "TRUE" : "FALSE"));
                                return ammo_amount;
                        }
                        #else
                        ammo_amount = self.WEP_AMMO(DEVASTATOR) >= WEP_CVAR(devastator, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_DEVASTATOR]) >= WEP_CVAR(devastator, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo);
                        return ammo_amount;
                        #endif
                }
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ ELECTRO,
   /* function  */ W_Electro,
@@@@ -64,9 -64,10 -64,9 +64,10 @@@@ ELECTRO_SETTINGS(WEP_ADD_CVAR, WEP_ADD_
   .float electro_secondarytime;
   void W_Electro_ExplodeCombo(void);
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_electro(void) { weapon_defaultspawnfunc(WEP_ELECTRO); }
+ +void spawnfunc_weapon_electro(void) { weapon_defaultspawnfunc(WEP_ELECTRO.m_id); }
   
   void W_Electro_TriggerCombo(vector org, float rad, entity own)
   {
@@@@ -130,7 -131,7 -130,7 +131,7 @@@@ void W_Electro_ExplodeCombo(void
                world,
                world,
                WEP_CVAR(electro, combo_force),
- -             WEP_ELECTRO | HITTYPE_BOUNCE, // use THIS type for a combo because primary can't bounce
+ +             WEP_ELECTRO.m_id | HITTYPE_BOUNCE, // use THIS type for a combo because primary can't bounce
                world
        );
   
@@@@ -259,7 -260,7 -259,7 +260,7 @@@@ void W_Electro_Attack_Bolt(void
                WEP_CVAR_PRI(electro, damage)
        );
   
 --     pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("electro_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        proj = spawn();
        proj.classname = "electro_bolt";
        proj.nextthink = time;
        proj.ltime = time + WEP_CVAR_PRI(electro, lifetime);
        PROJECTILE_MAKETRIGGER(proj);
- -     proj.projectiledeathtype = WEP_ELECTRO;
+ +     proj.projectiledeathtype = WEP_ELECTRO.m_id;
        setorigin(proj, w_shotorg);
   
        proj.movetype = MOVETYPE_FLY;
   
        CSQCProjectile(proj, true, PROJECTILE_ELECTRO_BEAM, true);
   
 -      other = proj; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, proj);
   }
   
   void W_Electro_Orb_Touch(void)
@@@@ -359,7 -360,7 -359,7 +360,7 @@@@ void W_Electro_Attack_Orb(void
   
        w_shotdir = v_forward; // no TrueAim for grenades please
   
 --     pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("electro_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        entity proj = spawn();
        proj.classname = "electro_orb";
        proj.bot_dodgerating = WEP_CVAR_SEC(electro, damage);
        proj.nextthink = time + WEP_CVAR_SEC(electro, lifetime);
        PROJECTILE_MAKETRIGGER(proj);
- -     proj.projectiledeathtype = WEP_ELECTRO | HITTYPE_SECONDARY;
+ +     proj.projectiledeathtype = WEP_ELECTRO.m_id | HITTYPE_SECONDARY;
        setorigin(proj, w_shotorg);
   
        //proj.glow_size = 50;
   
        CSQCProjectile(proj, true, PROJECTILE_ELECTRO, false); // no culling, it has sound
   
 -      other = proj; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, proj);
   }
   
   void W_Electro_CheckAttack(void)
@@@@ -511,7 -512,7 -511,7 +512,7 @@@@ bool W_Electro(int req
                case WR_CHECKAMMO1:
                {
                        ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_PRI(electro, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= WEP_CVAR_PRI(electro, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_PRI(electro, ammo);
                        return ammo_amount;
                }
                case WR_CHECKAMMO2:
                        if(WEP_CVAR(electro, combo_safeammocheck)) // true if you can fire at least one secondary blob AND one primary shot after it, otherwise false.
                        {
                                ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
- -                             ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
+ +                             ammo_amount += self.(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
                        }
                        else
                        {
                                ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_SEC(electro, ammo);
- -                             ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= WEP_CVAR_SEC(electro, ammo);
+ +                             ammo_amount += self.(weapon_load[WEP_ELECTRO.m_id]) >= WEP_CVAR_SEC(electro, ammo);
                        }
                        return ammo_amount;
                }
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ FIREBALL,
   /* function  */ W_Fireball,
@@@@ -52,9 -52,10 -52,9 +52,10 @@@@ FIREBALL_SETTINGS(WEP_ADD_CVAR, WEP_ADD
   .vector fireball_impactvec;
   .float fireball_primarytime;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_fireball(void) { weapon_defaultspawnfunc(WEP_FIREBALL); }
+ +void spawnfunc_weapon_fireball(void) { weapon_defaultspawnfunc(WEP_FIREBALL.m_id); }
   
   void W_Fireball_Explode(void)
   {
                        dir = normalize(e.origin + e.view_ofs - self.origin);
   
                        if(accuracy_isgooddamage(self.realowner, e))
- -                             accuracy_add(self.realowner, WEP_FIREBALL, 0, WEP_CVAR_PRI(fireball, bfgdamage) * points);
+ +                             accuracy_add(self.realowner, WEP_FIREBALL.m_id, 0, WEP_CVAR_PRI(fireball, bfgdamage) * points);
   
                        Damage(e, self, self.realowner, WEP_CVAR_PRI(fireball, bfgdamage) * points, self.projectiledeathtype | HITTYPE_BOUNCE | HITTYPE_SPLASH, e.origin + e.view_ofs, WEP_CVAR_PRI(fireball, bfgforce) * dir);
 --                     pointparticles(particleeffectnum("fireball_bfgdamage"), e.origin, -1 * dir, 1);
 ++                     Send_Effect("fireball_bfgdamage", e.origin, -1 * dir, 1);
                }
        }
   
@@@@ -142,7 -143,7 -142,7 +143,7 @@@@ void W_Fireball_LaserPlay(float dt, flo
                d = damage + (edgedamage - damage) * (d / dist);
                Fire_AddDamage(RandomSelection_chosen_ent, self.realowner, d * burntime, burntime, self.projectiledeathtype | HITTYPE_BOUNCE);
                //trailparticles(self, particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec);
 --             pointparticles(particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec - self.origin, 1);
 ++             Send_Effect("fireball_laser", self.origin, RandomSelection_chosen_ent.fireball_impactvec - self.origin, 1);
        }
   }
   
@@@@ -183,7 -184,7 -183,7 +184,7 @@@@ void W_Fireball_Attack1(void
   
        W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', false, 2, "weapons/fireball_fire2.wav", CH_WEAPON_A, WEP_CVAR_PRI(fireball, damage) + WEP_CVAR_PRI(fireball, bfgdamage));
   
 --     pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("fireball_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        proj = spawn();
        proj.classname = "plasma_prim";
        proj.takedamage = DAMAGE_YES;
        proj.damageforcescale = WEP_CVAR_PRI(fireball, damageforcescale);
        PROJECTILE_MAKETRIGGER(proj);
- -     proj.projectiledeathtype = WEP_FIREBALL;
+ +     proj.projectiledeathtype = WEP_FIREBALL.m_id;
        setorigin(proj, w_shotorg);
   
        proj.movetype = MOVETYPE_FLY;
   
        CSQCProjectile(proj, true, PROJECTILE_FIREBALL, true);
   
 -      other = proj; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, proj);
   }
   
   void W_Fireball_AttackEffect(float i, vector f_diff)
   {
        W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', false, 0, "", 0, 0);
        w_shotorg += f_diff.x * v_up + f_diff.y * v_right;
 --     pointparticles(particleeffectnum("fireball_preattack_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("fireball_preattack_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   }
   
   void W_Fireball_Attack1_Frame4(void)
@@@@ -319,7 -320,7 -319,7 +320,7 @@@@ void W_Fireball_Attack2(void
        traceline(w_shotorg, w_shotorg + f_diff.x * v_up + f_diff.y * v_right, MOVE_NORMAL, self);
        w_shotorg = trace_endpos;
   
 --     pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("fireball_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        proj = spawn();
        proj.owner = proj.realowner = self;
        proj.bot_dodge = true;
        proj.bot_dodgerating = WEP_CVAR_SEC(fireball, damage);
        proj.movetype = MOVETYPE_BOUNCE;
- -     proj.projectiledeathtype = WEP_FIREBALL | HITTYPE_SECONDARY;
+ +     proj.projectiledeathtype = WEP_FIREBALL.m_id | HITTYPE_SECONDARY;
        proj.touch = W_Fireball_Firemine_Touch;
        PROJECTILE_MAKETRIGGER(proj);
        setsize(proj, '-4 -4 -4', '4 4 4');
   
        CSQCProjectile(proj, true, PROJECTILE_FIREMINE, true);
   
 -      other = proj; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, proj);
   }
   
   bool W_Fireball(int req)
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ HAGAR,
   /* function  */ W_Hagar,
   #ifdef SVQC
   HAGAR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_hagar(void) { weapon_defaultspawnfunc(WEP_HAGAR); }
+ +void spawnfunc_weapon_hagar(void) { weapon_defaultspawnfunc(WEP_HAGAR.m_id); }
   
   // NO bounce protection, as bounces are limited!
   
@@@@ -113,7 -114,7 -113,7 +114,7 @@@@ void W_Hagar_Touch2(void
                self.use();
        } else {
                self.cnt++;
 --             pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1);
 ++             Send_Effect("hagar_bounce", self.origin, self.velocity, 1);
                self.angles = vectoangles(self.velocity);
                self.owner = world;
                self.projectiledeathtype |= HITTYPE_BOUNCE;
@@@@ -128,7 -129,7 -128,7 +129,7 @@@@ void W_Hagar_Attack(void
   
        W_SetupShot(self, false, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
   
 --     pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("hagar_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        missile = spawn();
        missile.owner = missile.realowner = self;
        missile.think = adaptor_think2use_hittype_splash;
        missile.nextthink = time + WEP_CVAR_PRI(hagar, lifetime);
        PROJECTILE_MAKETRIGGER(missile);
- -     missile.projectiledeathtype = WEP_HAGAR;
+ +     missile.projectiledeathtype = WEP_HAGAR.m_id;
        setorigin(missile, w_shotorg);
        setsize(missile, '0 0 0', '0 0 0');
   
   
        CSQCProjectile(missile, true, PROJECTILE_HAGAR, true);
   
 -      other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, missile);
   }
   
   void W_Hagar_Attack2(void)
   
        W_SetupShot(self, false, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
   
 --     pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("hagar_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        missile = spawn();
        missile.owner = missile.realowner = self;
        missile.think = adaptor_think2use_hittype_splash;
        missile.nextthink = time + WEP_CVAR_SEC(hagar, lifetime_min) + random() * WEP_CVAR_SEC(hagar, lifetime_rand);
        PROJECTILE_MAKETRIGGER(missile);
- -     missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY;
+ +     missile.projectiledeathtype = WEP_HAGAR.m_id | HITTYPE_SECONDARY;
        setorigin(missile, w_shotorg);
        setsize(missile, '0 0 0', '0 0 0');
   
   
        CSQCProjectile(missile, true, PROJECTILE_HAGAR_BOUNCING, true);
   
 -      other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, missile);
   }
   
   .float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning;
@@@@ -223,7 -224,7 -223,7 +224,7 @@@@ void W_Hagar_Attack2_Load_Release(void
        weapon_prepareattack_do(1, WEP_CVAR_SEC(hagar, refire));
   
        W_SetupShot(self, false, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
 --     pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("hagar_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        forward = v_forward;
        right = v_right;
                missile.think = adaptor_think2use_hittype_splash;
                missile.nextthink = time + WEP_CVAR_SEC(hagar, lifetime_min) + random() * WEP_CVAR_SEC(hagar, lifetime_rand);
                PROJECTILE_MAKETRIGGER(missile);
- -             missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY;
+ +             missile.projectiledeathtype = WEP_HAGAR.m_id | HITTYPE_SECONDARY;
                setorigin(missile, w_shotorg);
                setsize(missile, '0 0 0', '0 0 0');
                missile.movetype = MOVETYPE_FLY;
   
                CSQCProjectile(missile, true, PROJECTILE_HAGAR, true);
   
 -              other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +              MUTATOR_CALLHOOK(EditProjectile, self, missile);
        }
   
        weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hagar, load_animtime), w_ready);
@@@@ -302,7 -303,7 -302,7 +303,7 @@@@ void W_Hagar_Attack2_Load(void
        if(self.items & IT_UNLIMITED_WEAPON_AMMO)
                enough_ammo = true;
        else if(autocvar_g_balance_hagar_reload_ammo)
- -             enough_ammo = self.(weapon_load[WEP_HAGAR]) >= WEP_CVAR_SEC(hagar, ammo);
+ +             enough_ammo = self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
        else
                enough_ammo = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo);
   
@@@@ -472,13 -473,13 -472,13 +473,13 @@@@ bool W_Hagar(int req
                case WR_CHECKAMMO1:
                {
                        ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_PRI(hagar, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_HAGAR]) >= WEP_CVAR_PRI(hagar, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_PRI(hagar, ammo);
                        return ammo_amount;
                }
                case WR_CHECKAMMO2:
                {
                        ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_HAGAR]) >= WEP_CVAR_SEC(hagar, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_HAGAR.m_id]) >= WEP_CVAR_SEC(hagar, ammo);
                        return ammo_amount;
                }
                case WR_CONFIG:
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ HLAC,
   /* function  */ W_HLAC,
   #ifdef SVQC
   HLAC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_hlac(void) { weapon_defaultspawnfunc(WEP_HLAC); }
+ +void spawnfunc_weapon_hlac(void) { weapon_defaultspawnfunc(WEP_HLAC.m_id); }
   
   void W_HLAC_Touch(void)
   {
@@@@ -77,7 -78,7 -77,7 +78,7 @@@@ void W_HLAC_Attack(void
           spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod);
   
        W_SetupShot(self, false, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage));
 --     pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("laser_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
        if(!autocvar_g_norecoil)
        {
                self.punchangle_x = random() - 0.5;
       missile.nextthink = time + WEP_CVAR_PRI(hlac, lifetime);
   
        missile.flags = FL_PROJECTILE;
- -     missile.projectiledeathtype = WEP_HLAC;
+ +     missile.projectiledeathtype = WEP_HLAC.m_id;
   
        CSQCProjectile(missile, true, PROJECTILE_HLAC, true);
   
 -      other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, missile);
   }
   
   void W_HLAC_Attack2(void)
           spread = spread * WEP_CVAR_SEC(hlac, spread_crouchmod);
   
        W_SetupShot(self, false, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage));
 --     pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("laser_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        missile = spawn();
        missile.owner = missile.realowner = self;
   
        missile.flags = FL_PROJECTILE;
        missile.missile_flags = MIF_SPLASH;
- -     missile.projectiledeathtype = WEP_HLAC | HITTYPE_SECONDARY;
+ +     missile.projectiledeathtype = WEP_HLAC.m_id | HITTYPE_SECONDARY;
   
        CSQCProjectile(missile, true, PROJECTILE_HLAC, true);
   
 -      other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, missile);
   }
   
   // weapon frames
@@@@ -250,13 -251,13 -250,13 +251,13 @@@@ bool W_HLAC(int req
                case WR_CHECKAMMO1:
                {
                        ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_PRI(hlac, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_HLAC]) >= WEP_CVAR_PRI(hlac, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_PRI(hlac, ammo);
                        return ammo_amount;
                }
                case WR_CHECKAMMO2:
                {
                        ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_SEC(hlac, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_HLAC]) >= WEP_CVAR_SEC(hlac, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_SEC(hlac, ammo);
                        return ammo_amount;
                }
                case WR_CONFIG:
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id   */ HMG,
   /* function   */ W_HeavyMachineGun,
   #ifdef SVQC
   HMG_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
   
- -void spawnfunc_weapon_hmg() { weapon_defaultspawnfunc(WEP_HMG); }
+ +void spawnfunc_weapon_hmg() { weapon_defaultspawnfunc(WEP_HMG.m_id); }
   
   void W_HeavyMachineGun_Attack_Auto()
   {
        }
   
        float hmg_spread = bound(WEP_CVAR(hmg, spread_min), WEP_CVAR(hmg, spread_min) + (WEP_CVAR(hmg, spread_add) * self.misc_bulletcounter), WEP_CVAR(hmg, spread_max));
- -     fireBullet(w_shotorg, w_shotdir, hmg_spread, WEP_CVAR(hmg, solidpenetration), WEP_CVAR(hmg, damage), WEP_CVAR(hmg, force), WEP_HMG, 0);
+ +     fireBullet(w_shotorg, w_shotdir, hmg_spread, WEP_CVAR(hmg, solidpenetration), WEP_CVAR(hmg, damage), WEP_CVAR(hmg, force), WEP_HMG.m_id, 0);
   
        self.misc_bulletcounter = self.misc_bulletcounter + 1;
   
 --     pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("uzi_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        W_MachineGun_MuzzleFlash();
        W_AttachToShotorg(self.muzzle_flash, '5 0 0');
@@@@ -130,7 -131,7 -130,7 +131,7 @@@@ bool W_HeavyMachineGun(int req
                        ammo_amount = self.ammo_nails >= WEP_CVAR(hmg, ammo);
   
                        if(autocvar_g_balance_hmg_reload_ammo)
- -                             ammo_amount += self.(weapon_load[WEP_HMG]) >= WEP_CVAR(hmg, ammo);
+ +                             ammo_amount += self.(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
   
                        return ammo_amount;
                }
                        ammo_amount = self.ammo_nails >= WEP_CVAR(hmg, ammo);
   
                        if(autocvar_g_balance_hmg_reload_ammo)
- -                             ammo_amount += self.(weapon_load[WEP_HMG]) >= WEP_CVAR(hmg, ammo);
+ +                             ammo_amount += self.(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
   
                        return ammo_amount;
                }
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ HOOK,
   /* function  */ W_Hook,
@@@@ -55,7 -55,8 -55,7 +55,8 @@@@ HOOK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PRO
   .float hook_time_hooked;
   .float hook_time_fueldecrease;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
   
   void spawnfunc_weapon_hook(void)
                remove(self);
                return;
        }
- -     weapon_defaultspawnfunc(WEP_HOOK);
+ +     weapon_defaultspawnfunc(WEP_HOOK.m_id);
   }
   
   void W_Hook_ExplodeThink(void)
@@@@ -142,7 -143,7 -142,7 +143,7 @@@@ void W_Hook_Attack2(void
        gren.bot_dodgerating = WEP_CVAR_SEC(hook, damage);
        gren.movetype = MOVETYPE_TOSS;
        PROJECTILE_MAKETRIGGER(gren);
- -     gren.projectiledeathtype = WEP_HOOK | HITTYPE_SECONDARY;
+ +     gren.projectiledeathtype = WEP_HOOK.m_id | HITTYPE_SECONDARY;
        setorigin(gren, w_shotorg);
        setsize(gren, '0 0 0', '0 0 0');
   
   
        CSQCProjectile(gren, true, PROJECTILE_HOOKBOMB, true);
   
 -      other = gren; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, gren);
   }
   
   bool W_Hook(int req)
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ MACHINEGUN,
   /* function  */ W_MachineGun,
   #ifdef SVQC
   MACHINEGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
   
   void spawnfunc_weapon_machinegun(void)
        if(autocvar_sv_q3acompat_machineshotgunswap)
        if(self.classname != "droppedweapon")
        {
- -             weapon_defaultspawnfunc(WEP_SHOCKWAVE);
+ +             weapon_defaultspawnfunc(WEP_SHOCKWAVE.m_id);
                return;
        }
- -     weapon_defaultspawnfunc(WEP_MACHINEGUN);
+ +     weapon_defaultspawnfunc(WEP_MACHINEGUN.m_id);
   }
   void spawnfunc_weapon_uzi(void) { spawnfunc_weapon_machinegun(); }
   
@@@@ -118,7 -119,7 -118,7 +119,7 @@@@ void W_MachineGun_Attack(int deathtype
        else
                fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, sustained_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), deathtype, 0);
   
 --     pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("uzi_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        W_MachineGun_MuzzleFlash();
        W_AttachToShotorg(self.muzzle_flash, '5 0 0');
@@@@ -151,7 -152,7 -151,7 +152,7 @@@@ void W_MachineGun_Attack_Frame(void
                        return;
                }
                self.misc_bulletcounter = self.misc_bulletcounter + 1;
- -             W_MachineGun_Attack(WEP_MACHINEGUN);
+ +             W_MachineGun_Attack(WEP_MACHINEGUN.m_id);
                weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
        }
        else
@@@@ -187,11 -188,11 -187,11 +188,11 @@@@ void W_MachineGun_Attack_Auto(void
        }
   
        machinegun_spread = bound(WEP_CVAR(machinegun, spread_min), WEP_CVAR(machinegun, spread_min) + (WEP_CVAR(machinegun, spread_add) * self.misc_bulletcounter), WEP_CVAR(machinegun, spread_max));
- -     fireBullet(w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN, 0);
+ +     fireBullet(w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
   
        self.misc_bulletcounter = self.misc_bulletcounter + 1;
   
 --     pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("uzi_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        W_MachineGun_MuzzleFlash();
        W_AttachToShotorg(self.muzzle_flash, '5 0 0');
@@@@ -212,9 -213,9 -212,9 +213,9 @@@@ void W_MachineGun_Attack_Burst(void
                self.punchangle_y = random() - 0.5;
        }
   
- -     fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_speed), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN, 0);
+ +     fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_speed), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN.m_id, 0);
   
 --     pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("uzi_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        W_MachineGun_MuzzleFlash();
        W_AttachToShotorg(self.muzzle_flash, '5 0 0');
@@@@ -286,7 -287,7 -286,7 +287,7 @@@@ bool W_MachineGun(int req
                                if(weapon_prepareattack(0, 0))
                                {
                                        self.misc_bulletcounter = 1;
- -                                     W_MachineGun_Attack(WEP_MACHINEGUN); // sets attack_finished
+ +                                     W_MachineGun_Attack(WEP_MACHINEGUN.m_id); // sets attack_finished
                                        weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
                                }
   
                                if(weapon_prepareattack(1, 0))
                                {
                                        self.misc_bulletcounter = 1;
- -                                     W_MachineGun_Attack(WEP_MACHINEGUN | HITTYPE_SECONDARY); // sets attack_finished
+ +                                     W_MachineGun_Attack(WEP_MACHINEGUN.m_id | HITTYPE_SECONDARY); // sets attack_finished
                                        weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, first_refire), w_ready);
                                }
                        }
                        if(WEP_CVAR(machinegun, reload_ammo))
                        {
                                if(WEP_CVAR(machinegun, mode) == 1)
- -                                     ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, sustained_ammo);
+ +                                     ammo_amount += self.(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, sustained_ammo);
                                else
- -                                     ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, first_ammo);
+ +                                     ammo_amount += self.(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, first_ammo);
                        }
                        return ammo_amount;
                }
                        if(WEP_CVAR(machinegun, reload_ammo))
                        {
                                if(WEP_CVAR(machinegun, mode) == 1)
- -                                     ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, burst_ammo);
+ +                                     ammo_amount += self.(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, burst_ammo);
                                else
- -                                     ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, first_ammo);
+ +                                     ammo_amount += self.(weapon_load[WEP_MACHINEGUN.m_id]) >= WEP_CVAR(machinegun, first_ammo);
                        }
                        return ammo_amount;
                }
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ MINE_LAYER,
   /* function  */ W_MineLayer,
@@@@ -54,9 -54,10 -54,9 +54,10 @@@@ void W_MineLayer_Think(void)
   .float mine_time;
   .vector mine_orientation;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_minelayer(void) { weapon_defaultspawnfunc(WEP_MINE_LAYER); }
+ +void spawnfunc_weapon_minelayer(void) { weapon_defaultspawnfunc(WEP_MINE_LAYER.m_id); }
   
   void W_MineLayer_Stick(entity to)
   {
@@@@ -119,14 -120,14 -119,14 +120,14 @@@@ void W_MineLayer_Explode(void
   
        RadiusDamage(self, self.realowner, WEP_CVAR(minelayer, damage), WEP_CVAR(minelayer, edgedamage), WEP_CVAR(minelayer, radius), world, world, WEP_CVAR(minelayer, force), self.projectiledeathtype, other);
   
- -     if(self.realowner.weapon == WEP_MINE_LAYER)
+ +     if(self.realowner.weapon == WEP_MINE_LAYER.m_id)
        {
                entity oldself;
                oldself = self;
                self = self.realowner;
- -             if(!WEP_ACTION(WEP_MINE_LAYER, WR_CHECKAMMO1))
+ +             if(!WEP_ACTION(WEP_MINE_LAYER.m_id, WR_CHECKAMMO1))
                {
- -                     self.cnt = WEP_MINE_LAYER;
+ +                     self.cnt = WEP_MINE_LAYER.m_id;
                        ATTACK_FINISHED(self) = time;
                        self.switchweapon = w_getbestweapon(self);
                }
@@@@ -146,14 -147,14 -146,14 +147,14 @@@@ void W_MineLayer_DoRemoteExplode(void
   
        RadiusDamage(self, self.realowner, WEP_CVAR(minelayer, remote_damage), WEP_CVAR(minelayer, remote_edgedamage), WEP_CVAR(minelayer, remote_radius), world, world, WEP_CVAR(minelayer, remote_force), self.projectiledeathtype | HITTYPE_BOUNCE, world);
   
- -     if(self.realowner.weapon == WEP_MINE_LAYER)
+ +     if(self.realowner.weapon == WEP_MINE_LAYER.m_id)
        {
                entity oldself;
                oldself = self;
                self = self.realowner;
- -             if(!WEP_ACTION(WEP_MINE_LAYER, WR_CHECKAMMO1))
+ +             if(!WEP_ACTION(WEP_MINE_LAYER.m_id, WR_CHECKAMMO1))
                {
- -                     self.cnt = WEP_MINE_LAYER;
+ +                     self.cnt = WEP_MINE_LAYER.m_id;
                        ATTACK_FINISHED(self) = time;
                        self.switchweapon = w_getbestweapon(self);
                }
@@@@ -261,7 -262,7 -261,7 +262,7 @@@@ void W_MineLayer_Think(void
        }
   
        // remote detonation
- -     if(self.realowner.weapon == WEP_MINE_LAYER)
+ +     if(self.realowner.weapon == WEP_MINE_LAYER.m_id)
        if(self.realowner.deadflag == DEAD_NO)
        if(self.minelayer_detonate)
                W_MineLayer_RemoteExplode();
@@@@ -327,7 -328,7 -327,7 +328,7 @@@@ void W_MineLayer_Attack(void
        W_DecreaseAmmo(WEP_CVAR(minelayer, ammo));
   
        W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', false, 5, "weapons/mine_fire.wav", CH_WEAPON_A, WEP_CVAR(minelayer, damage));
 --     pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("rocketlauncher_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        mine = WarpZone_RefSys_SpawnSameRefSys(self);
        mine.owner = mine.realowner = self;
   
        mine.movetype = MOVETYPE_TOSS;
        PROJECTILE_MAKETRIGGER(mine);
- -     mine.projectiledeathtype = WEP_MINE_LAYER;
+ +     mine.projectiledeathtype = WEP_MINE_LAYER.m_id;
        setsize(mine, '-4 -4 -4', '4 4 4'); // give it some size so it can be shot
   
        setorigin(mine, w_shotorg - v_forward * 4); // move it back so it hits the wall at the right point
   
        // common properties
   
 -      other = mine; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, mine);
   
        self.minelayer_mines = W_MineLayer_Count(self);
   }
@@@@ -548,10 -549,10 -548,10 +549,10 @@@@ bool W_MineLayer(int req
                case WR_CHECKAMMO1:
                {
                        // don't switch while placing a mine
- -                     if(ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER)
+ +                     if(ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER.m_id)
                        {
                                ammo_amount = self.WEP_AMMO(MINE_LAYER) >= WEP_CVAR(minelayer, ammo);
- -                             ammo_amount += self.(weapon_load[WEP_MINE_LAYER]) >= WEP_CVAR(minelayer, ammo);
+ +                             ammo_amount += self.(weapon_load[WEP_MINE_LAYER.m_id]) >= WEP_CVAR(minelayer, ammo);
                                return ammo_amount;
                        }
                        return true;
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ MORTAR,
   /* function  */ W_Mortar,
@@@@ -52,10 -52,11 -52,10 +52,11 @@@@ MORTAR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_P
   .float gl_detonate_later;
   .float gl_bouncecnt;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
   
- -void spawnfunc_weapon_mortar(void) { weapon_defaultspawnfunc(WEP_MORTAR); }
+ +void spawnfunc_weapon_mortar(void) { weapon_defaultspawnfunc(WEP_MORTAR.m_id); }
   void spawnfunc_weapon_grenadelauncher(void) { spawnfunc_weapon_mortar(); }
   
   void W_Mortar_Grenade_Explode(void)
@@@@ -150,7 -151,7 -150,7 +151,7 @@@@ void W_Mortar_Grenade_Touch1(void
                        spamsound(self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM);
                else
                        spamsound(self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM);
 --             pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1);
 ++             Send_Effect("hagar_bounce", self.origin, self.velocity, 1);
                self.projectiledeathtype |= HITTYPE_BOUNCE;
                self.gl_bouncecnt += 1;
        }
@@@@ -195,7 -196,7 -195,7 +196,7 @@@@ void W_Mortar_Grenade_Touch2(void
                        spamsound(self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM);
                else
                        spamsound(self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM);
 --             pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1);
 ++             Send_Effect("hagar_bounce", self.origin, self.velocity, 1);
                self.projectiledeathtype |= HITTYPE_BOUNCE;
                self.gl_bouncecnt += 1;
   
@@@@ -230,7 -231,7 -230,7 +231,7 @@@@ void W_Mortar_Attack(void
        W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage));
        w_shotdir = v_forward; // no TrueAim for grenades please
   
 --     pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("grenadelauncher_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        gren = spawn();
        gren.owner = gren.realowner = self;
        gren.bouncefactor = WEP_CVAR(mortar, bouncefactor);
        gren.bouncestop = WEP_CVAR(mortar, bouncestop);
        PROJECTILE_MAKETRIGGER(gren);
- -     gren.projectiledeathtype = WEP_MORTAR;
+ +     gren.projectiledeathtype = WEP_MORTAR.m_id;
        setorigin(gren, w_shotorg);
        setsize(gren, '-3 -3 -3', '3 3 3');
   
        else
                CSQCProjectile(gren, true, PROJECTILE_GRENADE_BOUNCING, true);
   
 -      other = gren; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, gren);
   }
   
   void W_Mortar_Attack2(void)
        W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage));
        w_shotdir = v_forward; // no TrueAim for grenades please
   
 --     pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("grenadelauncher_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        gren = spawn();
        gren.owner = gren.realowner = self;
        gren.bouncefactor = WEP_CVAR(mortar, bouncefactor);
        gren.bouncestop = WEP_CVAR(mortar, bouncestop);
        PROJECTILE_MAKETRIGGER(gren);
- -     gren.projectiledeathtype = WEP_MORTAR | HITTYPE_SECONDARY;
+ +     gren.projectiledeathtype = WEP_MORTAR.m_id | HITTYPE_SECONDARY;
        setorigin(gren, w_shotorg);
        setsize(gren, '-3 -3 -3', '3 3 3');
   
        else
                CSQCProjectile(gren, true, PROJECTILE_GRENADE_BOUNCING, true);
   
 -      other = gren; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, gren);
   }
   
   .float bot_secondary_grenademooth;
@@@@ -421,13 -422,13 -421,13 +422,13 @@@@ bool W_Mortar(int req
                case WR_CHECKAMMO1:
                {
                        ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_PRI(mortar, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_MORTAR]) >= WEP_CVAR_PRI(mortar, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_PRI(mortar, ammo);
                        return ammo_amount;
                }
                case WR_CHECKAMMO2:
                {
                        ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_SEC(mortar, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_MORTAR]) >= WEP_CVAR_SEC(mortar, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_MORTAR.m_id]) >= WEP_CVAR_SEC(mortar, ammo);
                        return ammo_amount;
                }
                case WR_CONFIG:
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ PORTO,
   /* function  */ W_Porto,
@@@@ -36,11 -36,12 -36,11 +36,12 @@@@ PORTO_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PR
   .float porto_v_angle_held;
   .vector right_vector;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
   #include "../triggers/trigger/jumppads.qh"
   
- -void spawnfunc_weapon_porto(void) { weapon_defaultspawnfunc(WEP_PORTO); }
+ +void spawnfunc_weapon_porto(void) { weapon_defaultspawnfunc(WEP_PORTO.m_id); }
   
   void W_Porto_Success(void)
   {
@@@@ -82,7 -83,7 -82,7 +83,7 @@@@ void W_Porto_Fail(float failhard
                        tracetoss(self, self);
                        if(vlen(trace_endpos - self.realowner.origin) < 128)
                        {
- -                             W_ThrowNewWeapon(self.realowner, WEP_PORTO, 0, self.origin, self.velocity);
+ +                             W_ThrowNewWeapon(self.realowner, WEP_PORTO.m_id, 0, self.origin, self.velocity);
                                Send_Notification(NOTIF_ONE, self.realowner, MSG_CENTER, CENTER_PORTO_FAILED);
                        }
                }
@@@@ -242,7 -243,7 -242,7 +243,7 @@@@ void W_Porto_Attack(float type
        w_shotdir = v_forward;
        w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
   
 --     //pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     //Send_Effect("grenadelauncher_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        gren = spawn();
        gren.cnt = type;
        gren.think = W_Porto_Think;
        gren.touch = W_Porto_Touch;
   
 --     if(self.items & IT_STRENGTH)
 ++     if(self.items & ITEM_Strength.m_itemid)
                W_SetupProjVelocity_Basic(gren, WEP_CVAR_BOTH(porto, (type <= 0), speed) * autocvar_g_balance_powerup_strength_force, 0);
        else
                W_SetupProjVelocity_Basic(gren, WEP_CVAR_BOTH(porto, (type <= 0), speed), 0);
        else
                CSQCProjectile(gren, true, PROJECTILE_PORTO_RED, true);
   
 -      other = gren; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, gren);
   }
   
   bool w_nexball_weapon(int req); // WEAPONTODO
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ RIFLE,
   /* function  */ W_Rifle,
   RIFLE_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
   .float rifle_accumulator;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_rifle(void) { weapon_defaultspawnfunc(WEP_RIFLE); }
+ +void spawnfunc_weapon_rifle(void) { weapon_defaultspawnfunc(WEP_RIFLE.m_id); }
   void spawnfunc_weapon_campingrifle(void) { spawnfunc_weapon_rifle(); }
   void spawnfunc_weapon_sniperrifle(void) { spawnfunc_weapon_rifle(); }
   
@@@@ -58,7 -59,7 -58,7 +59,7 @@@@ void W_Rifle_FireBullet(float pSpread, 
   
        W_SetupShot(self, true, 2, pSound, CH_WEAPON_A, pDamage * pShots);
   
 --     pointparticles(particleeffectnum("rifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
 ++     Send_Effect("rifle_muzzleflash", w_shotorg, w_shotdir * 2000, 1);
   
        if(self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) // if zoomed, shoot from the eye
        {
   
   void W_Rifle_Attack(void)
   {
- -     W_Rifle_FireBullet(WEP_CVAR_PRI(rifle, spread), WEP_CVAR_PRI(rifle, damage), WEP_CVAR_PRI(rifle, force), WEP_CVAR_PRI(rifle, solidpenetration), WEP_CVAR_PRI(rifle, ammo), WEP_RIFLE, WEP_CVAR_PRI(rifle, tracer), WEP_CVAR_PRI(rifle, shots), "weapons/campingrifle_fire.wav");
+ +     W_Rifle_FireBullet(WEP_CVAR_PRI(rifle, spread), WEP_CVAR_PRI(rifle, damage), WEP_CVAR_PRI(rifle, force), WEP_CVAR_PRI(rifle, solidpenetration), WEP_CVAR_PRI(rifle, ammo), WEP_RIFLE.m_id, WEP_CVAR_PRI(rifle, tracer), WEP_CVAR_PRI(rifle, shots), "weapons/campingrifle_fire.wav");
   }
   
   void W_Rifle_Attack2(void)
   {
- -     W_Rifle_FireBullet(WEP_CVAR_SEC(rifle, spread), WEP_CVAR_SEC(rifle, damage), WEP_CVAR_SEC(rifle, force), WEP_CVAR_SEC(rifle, solidpenetration), WEP_CVAR_SEC(rifle, ammo), WEP_RIFLE | HITTYPE_SECONDARY, WEP_CVAR_SEC(rifle, tracer), WEP_CVAR_SEC(rifle, shots), "weapons/campingrifle_fire2.wav");
+ +     W_Rifle_FireBullet(WEP_CVAR_SEC(rifle, spread), WEP_CVAR_SEC(rifle, damage), WEP_CVAR_SEC(rifle, force), WEP_CVAR_SEC(rifle, solidpenetration), WEP_CVAR_SEC(rifle, ammo), WEP_RIFLE.m_id | HITTYPE_SECONDARY, WEP_CVAR_SEC(rifle, tracer), WEP_CVAR_SEC(rifle, shots), "weapons/campingrifle_fire2.wav");
   }
   
   .void(void) rifle_bullethail_attackfunc;
@@@@ -214,13 -215,13 -214,13 +215,13 @@@@ bool W_Rifle(int req
                case WR_CHECKAMMO1:
                {
                        ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_PRI(rifle, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_RIFLE]) >= WEP_CVAR_PRI(rifle, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_PRI(rifle, ammo);
                        return ammo_amount;
                }
                case WR_CHECKAMMO2:
                {
                        ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_SEC(rifle, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_RIFLE]) >= WEP_CVAR_SEC(rifle, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_RIFLE.m_id]) >= WEP_CVAR_SEC(rifle, ammo);
                        return ammo_amount;
                }
                case WR_CONFIG:
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id   */ RPC,
   /* function   */ W_RocketPropelledChainsaw,
   #ifdef SVQC
   RPC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_rpc() { weapon_defaultspawnfunc(WEP_RPC); }
+ +void spawnfunc_weapon_rpc() { weapon_defaultspawnfunc(WEP_RPC.m_id); }
   
   void W_RocketPropelledChainsaw_Explode()
   {
@@@@ -108,7 -109,7 -108,7 +109,7 @@@@ void W_RocketPropelledChainsaw_Attack (
   
        W_DecreaseAmmo(WEP_CVAR(rpc, ammo));
        W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', false, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, WEP_CVAR(rpc, damage));
 --     pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("rocketlauncher_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
        PROJECTILE_MAKETRIGGER(missile);
   
        missile.owner = missile.realowner = self;
        missile.damagedbycontents = true;
        missile.movetype = MOVETYPE_FLY;
   
- -     missile.projectiledeathtype = WEP_RPC;
+ +     missile.projectiledeathtype = WEP_RPC.m_id;
        setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
   
        setorigin (missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point
        W_AttachToShotorg(flash, '5 0 0');
        missile.pos1 = missile.velocity;
   
 -      other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, missile);
   }
   
   bool W_RocketPropelledChainsaw(int req)
                case WR_CHECKAMMO1:
                {
                        ammo_amount = self.WEP_AMMO(RPC) >= WEP_CVAR(rpc, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_RPC]) >= WEP_CVAR(rpc, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR(rpc, ammo);
                        return ammo_amount;
                }
                case WR_CHECKAMMO2:
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ SEEKER,
   /* function  */ W_Seeker,
@@@@ -81,9 -81,10 -81,9 +81,10 @@@@ SEEKER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_P
   .entity tag_target, wps_tag_tracker;
   .float tag_time;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_seeker(void) { weapon_defaultspawnfunc(WEP_SEEKER); }
+ +void spawnfunc_weapon_seeker(void) { weapon_defaultspawnfunc(WEP_SEEKER.m_id); }
   
   // ============================
   // Begin: Missile functions, these are general functions to be manipulated by other code
@@@@ -251,7 -252,7 -251,7 +252,7 @@@@ void W_Seeker_Fire_Missile(vector f_dif
        makevectors(self.v_angle);
        W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, "weapons/seeker_fire.wav", CH_WEAPON_A, 0);
        w_shotorg += f_diff;
 --     pointparticles(particleeffectnum("seeker_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("seeker_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        //self.detornator         = false;
   
        //missile.think           = W_Seeker_Missile_Animate; // csqc projectiles.
   
        if(missile.enemy != world)
- -             missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
+ +             missile.projectiledeathtype = WEP_SEEKER.m_id | HITTYPE_SECONDARY;
        else
- -             missile.projectiledeathtype = WEP_SEEKER;
+ +             missile.projectiledeathtype = WEP_SEEKER.m_id;
   
   
        setorigin(missile, w_shotorg);
   
        CSQCProjectile(missile, false, PROJECTILE_SEEKER, true);
   
 -      other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, missile);
   }
   
   // ============================
@@@@ -343,7 -344,7 -343,7 +344,7 @@@@ void W_Seeker_Fire_Flac(void
        W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', false, 2, "weapons/flac_fire.wav", CH_WEAPON_A, WEP_CVAR(seeker, flac_damage));
        w_shotorg += f_diff;
   
 --     pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("hagar_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        missile                                 = spawn();
        missile.owner                   = missile.realowner = self;
        missile.nextthink               = time + WEP_CVAR(seeker, flac_lifetime) + WEP_CVAR(seeker, flac_lifetime_rand);
        missile.solid                   = SOLID_BBOX;
        missile.movetype                = MOVETYPE_FLY;
- -     missile.projectiledeathtype = WEP_SEEKER;
- -     missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
+ +     missile.projectiledeathtype = WEP_SEEKER.m_id;
+ +     missile.projectiledeathtype = WEP_SEEKER.m_id | HITTYPE_SECONDARY;
        missile.flags                           = FL_PROJECTILE;
        missile.missile_flags       = MIF_SPLASH;
   
        W_SetupProjVelocity_UP_PRE(missile, seeker, flac_);
        CSQCProjectile(missile, true, PROJECTILE_FLAC, true);
   
 -      other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, missile);
   }
   
   // ============================
@@@@ -416,7 -417,7 -416,7 +417,7 @@@@ void W_Seeker_Vollycontroller_Think(voi
        entity oldself,oldenemy;
        self.cnt = self.cnt - 1;
   
- -     if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.WEP_AMMO(SEEKER) < WEP_CVAR(seeker, missile_ammo)) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER))
+ +     if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.WEP_AMMO(SEEKER) < WEP_CVAR(seeker, missile_ammo)) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER.m_id))
        {
                remove(self);
                return;
   void W_Seeker_Tracker_Think(void)
   {
        // commit suicide if: You die OR target dies OR you switch away from the seeker OR commit suicide if lifetime is up
- -     if((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER)
+ +     if((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER.m_id)
        || (time > self.tag_time + WEP_CVAR(seeker, tag_tracker_lifetime)))
        {
                if(self)
@@@@ -477,7 -478,7 -477,7 +478,7 @@@@ void W_Seeker_Tag_Explode(void
   {
        //if(other==self.realowner)
        //    return;
- -     Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE, other.species, self);
+ +     Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE, other.species, self);
   
        remove(self);
   }
@@@@ -505,7 -506,7 -505,7 +506,7 @@@@ void W_Seeker_Tag_Touch(void
        te_knightspike(org2);
   
        self.event_damage = func_null;
- -     Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE | HITTYPE_SECONDARY, other.species, self);
+ +     Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER.m_id | HITTYPE_BOUNCE | HITTYPE_SECONDARY, other.species, self);
   
        if(other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO)
        {
@@@@ -589,7 -590,7 -589,7 +590,7 @@@@ void W_Seeker_Fire_Tag(void
   
        CSQCProjectile(missile, true, PROJECTILE_TAG, false); // has sound
   
 -      other = missile; MUTATOR_CALLHOOK(EditProjectile);
 +      MUTATOR_CALLHOOK(EditProjectile, self, missile);
   }
   
   // ============================
@@@@ -676,12 -677,12 -676,12 +677,12 @@@@ bool W_Seeker(int req
                        if(WEP_CVAR(seeker, type) == 1)
                        {
                                ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, missile_ammo);
- -                             ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, missile_ammo);
+ +                             ammo_amount += self.(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, missile_ammo);
                        }
                        else
                        {
                                ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, tag_ammo);
- -                             ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, tag_ammo);
+ +                             ammo_amount += self.(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, tag_ammo);
                        }
                        return ammo_amount;
                }
                        if(WEP_CVAR(seeker, type) == 1)
                        {
                                ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, tag_ammo);
- -                             ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, tag_ammo);
+ +                             ammo_amount += self.(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, tag_ammo);
                        }
                        else
                        {
                                ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, flac_ammo);
- -                             ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, flac_ammo);
+ +                             ammo_amount += self.(weapon_load[WEP_SEEKER.m_id]) >= WEP_CVAR(seeker, flac_ammo);
                        }
                        return ammo_amount;
                }
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ SHOCKWAVE,
   /* function  */ W_Shockwave,
@@@@ -79,7 -79,8 -79,7 +79,8 @@@@ void Net_ReadShockwaveParticle(void)
   .float sw_spread_min;
   .float sw_time;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
   void spawnfunc_weapon_shockwave(void)
   {
        if(autocvar_sv_q3acompat_machineshotgunswap)
        if(self.classname != "droppedweapon")
        {
- -             weapon_defaultspawnfunc(WEP_MACHINEGUN);
+ +             weapon_defaultspawnfunc(WEP_MACHINEGUN.m_id);
                return;
        }
- -     weapon_defaultspawnfunc(WEP_SHOCKWAVE);
+ +     weapon_defaultspawnfunc(WEP_SHOCKWAVE.m_id);
   }
   
   const float MAX_SHOCKWAVE_HITS = 10;
@@@@ -158,7 -159,7 -158,7 +159,7 @@@@ void W_Shockwave_Melee_Think(void
                te_customflash(targpos, 40,  2, '1 1 1');
   #endif
   
 --             is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || (trace_ent.flags & FL_MONSTER));
 ++             is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || IS_MONSTER(trace_ent));
   
                if((trace_fraction < 1) // if trace is good, apply the damage and remove self if necessary
                        && (trace_ent.takedamage == DAMAGE_AIM)
                                self.realowner,
                                self.realowner,
                                swing_damage,
- -                             (WEP_SHOCKWAVE | HITTYPE_SECONDARY),
+ +                             (WEP_SHOCKWAVE.m_id | HITTYPE_SECONDARY),
                                (self.realowner.origin + self.realowner.view_ofs),
                                (v_forward * WEP_CVAR(shockwave, melee_force))
                        );
   
                        // handle accuracy
                        if(accuracy_isgooddamage(self.realowner, target_victim))
- -                             { accuracy_add(self.realowner, WEP_SHOCKWAVE, 0, swing_damage); }
+ +                             { accuracy_add(self.realowner, WEP_SHOCKWAVE.m_id, 0, swing_damage); }
   
                        #ifdef DEBUG_SHOCKWAVE
                        print(sprintf(
@@@@ -375,7 -376,7 -375,7 +376,7 @@@@ void W_Shockwave_Attack(void
                WEP_CVAR(shockwave, blast_splash_edgedamage),
                WEP_CVAR(shockwave, blast_splash_radius),
                w_shotdir * WEP_CVAR(shockwave, blast_splash_force),
- -             WEP_SHOCKWAVE,
+ +             WEP_SHOCKWAVE.m_id,
                0,
                self
        );
                                        self,
                                        self,
                                        final_damage,
- -                                     WEP_SHOCKWAVE,
+ +                                     WEP_SHOCKWAVE.m_id,
                                        head.origin,
                                        final_force
                                );
                        self,
                        self,
                        final_damage,
- -                     WEP_SHOCKWAVE,
+ +                     WEP_SHOCKWAVE.m_id,
                        head.origin,
                        final_force
                );
                if(accuracy_isgooddamage(self.realowner, head))
                {
                        print("wtf\n");
- -                     accuracy_add(self.realowner, WEP_SHOCKWAVE, 0, final_damage);
+ +                     accuracy_add(self.realowner, WEP_SHOCKWAVE.m_id, 0, final_damage);
                }
   
                #ifdef DEBUG_SHOCKWAVE
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ SHOTGUN,
   /* function  */ W_Shotgun,
   #ifdef SVQC
   SHOTGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_shotgun(void) { weapon_defaultspawnfunc(WEP_SHOTGUN); }
+ +void spawnfunc_weapon_shotgun(void) { weapon_defaultspawnfunc(WEP_SHOTGUN.m_id); }
   
   void W_Shotgun_Attack(float isprimary)
   {
   
        W_SetupShot(self, true, 5, "weapons/shotgun_fire.wav", ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets));
        for(sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1)
- -             fireBullet(w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, solidpenetration), WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN, 0);
+ +             fireBullet(w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, solidpenetration), WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN.m_id, 0);
   
 --     pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, WEP_CVAR_PRI(shotgun, ammo));
 ++     Send_Effect("shotgun_muzzleflash", w_shotorg, w_shotdir * 1000, WEP_CVAR_PRI(shotgun, ammo));
   
        // casing code
        if(autocvar_g_casings >= 1)
@@@@ -125,7 -126,7 -125,7 +126,7 @@@@ void W_Shotgun_Melee_Think(void
                //te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5);
                //te_customflash(targpos, 40,  2, '1 1 1');
   
 --             is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || (trace_ent.flags & FL_MONSTER));
 ++             is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || IS_MONSTER(trace_ent));
   
                if((trace_fraction < 1) // if trace is good, apply the damage and remove self
                        && (trace_ent.takedamage == DAMAGE_AIM)
                        //print(strcat(self.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n"));
   
                        Damage(target_victim, self.realowner, self.realowner,
- -                             swing_damage, WEP_SHOTGUN | HITTYPE_SECONDARY,
+ +                             swing_damage, WEP_SHOTGUN.m_id | HITTYPE_SECONDARY,
                                self.realowner.origin + self.realowner.view_ofs,
                                v_forward * WEP_CVAR_SEC(shotgun, force));
   
- -                     if(accuracy_isgooddamage(self.realowner, target_victim)) { accuracy_add(self.realowner, WEP_SHOTGUN, 0, swing_damage); }
+ +                     if(accuracy_isgooddamage(self.realowner, target_victim)) { accuracy_add(self.realowner, WEP_SHOTGUN.m_id, 0, swing_damage); }
   
                        // draw large red flash for debugging
                        //te_customflash(targpos, 200, 2, '15 0 0');
@@@@ -303,7 -304,7 -303,7 +304,7 @@@@ float W_Shotgun(float req
                case WR_CHECKAMMO1:
                {
                        ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_SHOTGUN]) >= WEP_CVAR_PRI(shotgun, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
                        return ammo_amount;
                }
                case WR_CHECKAMMO2:
                                case 2: // secondary triple shot
                                {
                                        ammo_amount = self.WEP_AMMO(SHOTGUN) >= WEP_CVAR_PRI(shotgun, ammo);
- -                                     ammo_amount += self.(weapon_load[WEP_SHOTGUN]) >= WEP_CVAR_PRI(shotgun, ammo);
+ +                                     ammo_amount += self.(weapon_load[WEP_SHOTGUN.m_id]) >= WEP_CVAR_PRI(shotgun, ammo);
                                        return ammo_amount;
                                }
                                default: return false; // secondary unavailable
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ TUBA,
   /* function  */ W_Tuba,
@@@@ -51,9 -51,10 -51,9 +51,10 @@@@ float W_Tuba_MarkClientOnlyFieldsAsUsed
   .float tuba_lastnotes_cnt; // over
   .vector tuba_lastnotes[MAX_TUBANOTES];
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_tuba(void) { weapon_defaultspawnfunc(WEP_TUBA); }
+ +void spawnfunc_weapon_tuba(void) { weapon_defaultspawnfunc(WEP_TUBA.m_id); }
   
   bool W_Tuba_HasPlayed(entity pl, string melody, int instrument, bool ignorepitch, float mintempo, float maxtempo)
   {
@@@@ -357,12 -358,12 -357,12 +358,12 @@@@ void W_Tuba_NoteOn(float hittype
        self.tuba_note.teleport_time = time + WEP_CVAR(tuba, refire) * 2 * W_WeaponRateFactor(); // so it can get prolonged safely
   
        //sound(self, c, TUBA_NOTE(n), bound(0, VOL_BASE * cvar("g_balance_tuba_volume"), 1), autocvar_g_balance_tuba_attenuation);
- -     RadiusDamage(self, self, WEP_CVAR(tuba, damage), WEP_CVAR(tuba, edgedamage), WEP_CVAR(tuba, radius), world, world, WEP_CVAR(tuba, force), hittype | WEP_TUBA, world);
+ +     RadiusDamage(self, self, WEP_CVAR(tuba, damage), WEP_CVAR(tuba, edgedamage), WEP_CVAR(tuba, radius), world, world, WEP_CVAR(tuba, force), hittype | WEP_TUBA.m_id, world);
   
        o = gettaginfo(self.exteriorweaponentity, 0);
        if(time > self.tuba_smoketime)
        {
 --             pointparticles(particleeffectnum("smoke_ring"), o + v_up * 45 + v_right * -6 + v_forward * 8, v_up * 100, 1);
 ++             Send_Effect("smoke_ring", o + v_up * 45 + v_right * -6 + v_forward * 8, v_up * 100, 1);
                self.tuba_smoketime = time + 0.25;
        }
   }
@@@@ -453,7 -454,7 -453,7 +454,7 @@@@ bool W_Tuba(int req
                                                break;
                                }
                                W_SetupShot(self, false, 0, "", 0, 0);
 --                             pointparticles(particleeffectnum("teleport"), w_shotorg, '0 0 0', 1);
 ++                             Send_Effect("teleport", w_shotorg, '0 0 0', 1);
                                self.weaponentity.state = WS_INUSE;
                                weapon_thinkf(WFRAME_RELOAD, 0.5, w_ready);
                        }
@@@@ -1,4 -1,4 -1,4 +1,4 @@@@
- -#ifdef REGISTER_WEAPON
+ +#ifndef IMPLEMENTATION
   REGISTER_WEAPON(
   /* WEP_##id  */ VAPORIZER,
   /* function  */ W_Vaporizer,
@@@@ -46,9 -46,10 -46,9 +46,10 @@@@ VAPORIZER_SETTINGS(WEP_ADD_CVAR, WEP_AD
   .float vaporizer_lasthit;
   .float jump_interval;
   #endif
- -#else
+ +#endif
+ +#ifdef IMPLEMENTATION
   #ifdef SVQC
- -void spawnfunc_weapon_vaporizer(void) { weapon_defaultspawnfunc(WEP_VAPORIZER); }
+ +void spawnfunc_weapon_vaporizer(void) { weapon_defaultspawnfunc(WEP_VAPORIZER.m_id); }
   void spawnfunc_weapon_minstanex(void) { spawnfunc_weapon_vaporizer(); }
   
   void W_Vaporizer_Attack(void)
   
        yoda = 0;
        damage_goodhits = 0;
- -     FireRailgunBullet(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, 10000, 800, 0, 0, 0, 0, WEP_VAPORIZER);
+ +     FireRailgunBullet(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, 10000, 800, 0, 0, 0, 0, WEP_VAPORIZER.m_id);
   
        if(yoda && flying)
                Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
   
        self.vaporizer_lasthit = damage_goodhits;
   
 --     pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++     Send_Effect("nex_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
   
        // teamcolor / hit beam effect
        vector v;
        {
                case NUM_TEAM_1:   // Red
                        if(damage_goodhits)
 --                             WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, v);
 ++                             Send_Effect("TE_TEI_G3RED_HIT", w_shotorg, v, 1);
                        else
 --                             WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, v);
 ++                             Send_Effect("TE_TEI_G3RED", w_shotorg, v, 1);
                        break;
                case NUM_TEAM_2:   // Blue
                        if(damage_goodhits)
 --                             WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, v);
 ++                             Send_Effect("TE_TEI_G3BLUE_HIT", w_shotorg, v, 1);
                        else
 --                             WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, v);
 ++                             Send_Effect("TE_TEI_G3BLUE", w_shotorg, v, 1);
                        break;
                case NUM_TEAM_3:   // Yellow
                        if(damage_goodhits)
 --                             WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, v);
 ++                             Send_Effect("TE_TEI_G3YELLOW_HIT", w_shotorg, v, 1);
                        else
 --                             WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, v);
 ++                             Send_Effect("TE_TEI_G3YELLOW", w_shotorg, v, 1);
                        break;
                case NUM_TEAM_4:   // Pink
                        if(damage_goodhits)
 --                             WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, v);
 ++                             Send_Effect("TE_TEI_G3PINK_HIT", w_shotorg, v, 1);
                        else
 --                             WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), w_shotorg, v);
 ++                             Send_Effect("TE_TEI_G3PINK", w_shotorg, v, 1);
                        break;
                default:
                        if(damage_goodhits)
 --                             WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3_HIT"), w_shotorg, v);
 ++                             Send_Effect("TE_TEI_G3_HIT", w_shotorg, v, 1);
                        else
 --                             WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, v);
 ++                             Send_Effect("TE_TEI_G3", w_shotorg, v, 1);
                        break;
        }
   
@@@@ -165,9 -166,9 -165,9 +166,9 @@@@ float W_Vaporizer(float req
   
                                        // ugly instagib hack to reuse the fire mode of the laser
                                        int oldwep = self.weapon; // we can't avoid this hack
- -                                     self.weapon = WEP_BLASTER;
+ +                                     self.weapon = WEP_BLASTER.m_id;
                                        W_Blaster_Attack(
- -                                             WEP_BLASTER | HITTYPE_SECONDARY,
+ +                                             WEP_BLASTER.m_id | HITTYPE_SECONDARY,
                                                WEP_CVAR_SEC(vaporizer, shotangle),
                                                WEP_CVAR_SEC(vaporizer, damage),
                                                WEP_CVAR_SEC(vaporizer, edgedamage),
                case WR_CHECKAMMO1:
                {
                        ammo_amount = self.WEP_AMMO(VAPORIZER) >= vaporizer_ammo;
- -                     ammo_amount += self.(weapon_load[WEP_VAPORIZER]) >= vaporizer_ammo;
+ +                     ammo_amount += self.(weapon_load[WEP_VAPORIZER.m_id]) >= vaporizer_ammo;
                        return ammo_amount;
                }
                case WR_CHECKAMMO2:
                        if(!WEP_CVAR_SEC(vaporizer, ammo))
                                return true;
                        ammo_amount = self.WEP_AMMO(VAPORIZER) >= WEP_CVAR_SEC(vaporizer, ammo);
- -                     ammo_amount += self.(weapon_load[WEP_VAPORIZER]) >= WEP_CVAR_SEC(vaporizer, ammo);
+ +                     ammo_amount += self.(weapon_load[WEP_VAPORIZER.m_id]) >= WEP_CVAR_SEC(vaporizer, ammo);
                        return ammo_amount;
                }
                case WR_CONFIG:
diff --combined qcsrc/menu/menu.qc
@@@@ -5,6 -5,6 -5,7 +5,7 @@@@
   #include "../common/items/all.qh"
   #include "../common/weapons/all.qh"
   #include "../common/mapinfo.qh"
++ #include "../common/mutators/base.qh"
   
   ///////////////////////////////////////////////
   // Menu Source File
@@@@ -81,7 -81,6 -82,7 +82,6 @@@@ void m_init(
   
        // needs to be done so early because of the constants they create
        static_init();
- -     CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
   
        RegisterSLCategories();
   
   #include "../common/net_notice.qh"
   #include "../common/physics.qh"
   
 ++#include "../common/items/all.qc"
 ++
   #include "../common/triggers/subs.qh"
   #include "../common/triggers/triggers.qh"
   #include "../common/triggers/trigger/secret.qh"
@@@@ -188,7 -186,7 -186,7 +188,7 @@@@ void PutObserverInServer (void
        entity  spot;
       self.hud = HUD_NORMAL;
   
 --     if(IS_PLAYER(self)) { pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); }
 ++     if(IS_PLAYER(self)) { Send_Effect("spawn_event_neutral", self.origin, '0 0 0', 1); }
   
        spot = SelectSpawnPoint (true);
        if(!spot)
@@@@ -424,7 -422,7 -422,7 +424,7 @@@@ void PutClientInServer (void
        // reset player keys
        self.itemkeys = 0;
   
 -      MUTATOR_CALLHOOK(PutClientInServer);
 +      MUTATOR_CALLHOOK(PutClientInServer, self);
   
        if(gameover)
                self.classname = "observer";
   
                Unfreeze(self);
   
 -              spawn_spot = spot;
 -              MUTATOR_CALLHOOK(PlayerSpawn);
 +              MUTATOR_CALLHOOK(PlayerSpawn, spot);
   
                if(autocvar_spawn_debug)
                {
@@@@ -1281,7 -1280,7 -1279,7 +1281,7 @@@@ void ClientConnect (void
                self = oldself;
        }
   
 -      MUTATOR_CALLHOOK(ClientConnect);
 +      MUTATOR_CALLHOOK(ClientConnect, self);
   }
   /*
   =============
@@@@ -1305,7 -1304,7 -1303,7 +1305,7 @@@@ void ClientDisconnect (void
   
        PlayerStats_GameReport_FinalizePlayer(self);
   
 --     if(IS_PLAYER(self)) { pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); }
 ++     if(IS_PLAYER(self)) { Send_Effect("spawn_event_neutral", self.origin, '0 0 0', 1); }
   
        CheatShutdownClient();
   
@@@@ -1442,7 -1441,7 -1440,7 +1442,7 @@@@ void respawn(void
                self.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed;
                self.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3;
                self.effects |= CSQCMODEL_EF_RESPAWNGHOST;
 --             pointparticles(particleeffectnum("respawn_ghost"), self.origin, '0 0 0', 1);
 ++             Send_Effect("respawn_ghost", self.origin, '0 0 0', 1);
                if(autocvar_g_respawn_ghosts_maxtime)
                        SUB_SetFade (self, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5);
        }
@@@@ -1464,7 -1463,7 -1462,7 +1464,7 @@@@ void play_countdown(float finished, str
   void player_powerups (void)
   {
        // add a way to see what the items were BEFORE all of these checks for the mutator hook
 -      olditems = self.items;
 +      int items_prev = self.items;
   
        if((self.items & IT_USING_JETPACK) && !self.deadflag && !gameover)
                self.modelflags |= MF_ROCKET;
   
        if (!g_instagib)
        {
 --             if (self.items & IT_STRENGTH)
 ++             if (self.items & ITEM_Strength.m_itemid)
                {
                        play_countdown(self.strength_finished, "misc/poweroff.wav");
                        self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
                        if (time > self.strength_finished)
                        {
 --                             self.items = self.items - (self.items & IT_STRENGTH);
 ++                             self.items = self.items - (self.items & ITEM_Strength.m_itemid);
                                //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_STRENGTH, self.netname);
                                Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_STRENGTH);
                        }
                {
                        if (time < self.strength_finished)
                        {
 --                             self.items = self.items | IT_STRENGTH;
 ++                             self.items = self.items | ITEM_Strength.m_itemid;
                                Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_STRENGTH, self.netname);
                                Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_STRENGTH);
                        }
                }
 --             if (self.items & IT_INVINCIBLE)
 ++             if (self.items & ITEM_Shield.m_itemid)
                {
                        play_countdown(self.invincible_finished, "misc/poweroff.wav");
                        self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
                        if (time > self.invincible_finished)
                        {
 --                             self.items = self.items - (self.items & IT_INVINCIBLE);
 ++                             self.items = self.items - (self.items & ITEM_Shield.m_itemid);
                                //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_SHIELD, self.netname);
                                Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SHIELD);
                        }
                {
                        if (time < self.invincible_finished)
                        {
 --                             self.items = self.items | IT_INVINCIBLE;
 ++                             self.items = self.items | ITEM_Shield.m_itemid;
                                Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SHIELD, self.netname);
                                Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SHIELD);
                        }
        if (time < self.spawnshieldtime)
                self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT);
   
 -      MUTATOR_CALLHOOK(PlayerPowerups);
 +      MUTATOR_CALLHOOK(PlayerPowerups, self, items_prev);
   }
   
   float CalcRegen(float current, float stable, float regenfactor, float regenframetime)
@@@@ -1628,7 -1627,11 -1626,7 +1628,7 @@@@ void player_regen (void
   {
        float max_mod, regen_mod, rot_mod, limit_mod;
        max_mod = regen_mod = rot_mod = limit_mod = 1;
 -      regen_mod_max = max_mod;
 -      regen_mod_regen = regen_mod;
 -      regen_mod_rot = rot_mod;
 -      regen_mod_limit = limit_mod;
 -      if(!MUTATOR_CALLHOOK(PlayerRegen))
 +      if(!MUTATOR_CALLHOOK(PlayerRegen, max_mod, regen_mod, rot_mod, limit_mod))
        if(!self.frozen)
        {
                float minh, mina, maxh, maxa, limith, limita;
                minf = autocvar_g_balance_fuel_regenstable;
                limitf = autocvar_g_balance_fuel_limit;
   
 --             self.ammo_fuel = CalcRotRegen(self.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, frametime * (time > self.pauseregen_finished) * ((self.items & IT_FUEL_REGEN) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > self.pauserotfuel_finished), limitf);
 ++             self.ammo_fuel = CalcRotRegen(self.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, frametime * (time > self.pauseregen_finished) * ((self.items & ITEM_JetpackRegen.m_itemid) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > self.pauserotfuel_finished), limitf);
        }
   }
   
@@@@ -1703,7 -1706,8 -1701,7 +1703,7 @@@@ spectate mode routine
   */
   
   void SpectateCopy(entity spectatee) {
 -      other = spectatee;
 -      MUTATOR_CALLHOOK(SpectateCopy);
 +      MUTATOR_CALLHOOK(SpectateCopy, spectatee, self);
        self.armortype = spectatee.armortype;
        self.armorvalue = spectatee.armorvalue;
        self.ammo_cells = spectatee.ammo_cells;
@@@@ -2363,7 -2367,7 -2361,7 +2363,7 @@@@ void PlayerPreThink (void
   
                if(frametime)
                {
- -                     if(self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge))
+ +                     if(self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge))
                        {
                                self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
                                self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
   
                // WEAPONTODO: THIS SHIT NEEDS TO GO EVENTUALLY
                // It cannot be predicted by the engine!
- -             if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink)
+ +             if((self.weapon == WEP_SHOCKWAVE.m_id || self.weapon == WEP_SHOTGUN.m_id) && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink)
                        do_crouch = 0;
   
                if (do_crouch)
                        W_WeaponFrame();
   
                        self.items_added = 0;
 --                     if(self.items & IT_JETPACK)
 --                             if(self.items & IT_FUEL_REGEN || self.ammo_fuel >= 0.01)
 ++                     if(self.items & ITEM_Jetpack.m_itemid)
 ++                             if(self.items & ITEM_JetpackRegen.m_itemid || self.ammo_fuel >= 0.01)
                                        self.items_added |= IT_FUEL;
   
                        self.items |= self.items_added;
   
        // WEAPONTODO: Add weapon request for this
        if(!zoomstate_set)
- -             SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_VORTEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)); // WEAPONTODO
+ +             SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_VORTEX.m_id) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE.m_id && WEP_CVAR(rifle, secondary) == 0)); // WEAPONTODO
   
        float oldspectatee_status;
        oldspectatee_status = self.spectatee_status;
@@@@ -322,7 -322,7 -322,7 +322,7 @@@@ void PlayerDamage (entity inflictor, en
                        damage /= sqrt(bound(1.0, attacker.cvar_cl_handicap, 100.0));
        }
   
- -     if(DEATH_ISWEAPON(deathtype, WEP_TUBA))
+ +     if(DEATH_ISWEAPON(deathtype, WEP_TUBA.m_id))
        {
                // tuba causes blood to come out of the ears
                vector ear1, ear2;
                self.istypefrag = 0;
        }
   
 -      frag_inflictor = inflictor;
 -      frag_attacker = attacker;
 -      frag_target = self;
        frag_damage = damage;
 -      damage_take = take;
 -      damage_save = save;
 -      damage_force = force;
 -      MUTATOR_CALLHOOK(PlayerDamage_SplitHealthArmor);
 +      MUTATOR_CALLHOOK(PlayerDamage_SplitHealthArmor, inflictor, attacker, self, force, take, save);
        take = bound(0, damage_take, self.health);
        save = bound(0, damage_save, self.armorvalue);
        excess = max(0, damage - take - save);
                        if(deathtype == DEATH_KILL)
                        {
                                // for the lemmings fans, a small harmless explosion
 --                             pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
 ++                             Send_Effect("rocket_explode", self.origin, '0 0 0', 1);
                        }
                }
   
        if(accuracy_isgooddamage(attacker, self))
           attacker.accuracy.(accuracy_frags[w-1]) += 1;
   
 -              frag_attacker = attacker;
 -              frag_inflictor = inflictor;
 -              frag_target = self;
 -              frag_deathtype = deathtype;
 -              MUTATOR_CALLHOOK(PlayerDies);
 +              MUTATOR_CALLHOOK(PlayerDies, inflictor, attacker, self, deathtype);
   
                WEP_ACTION(self.weapon, WR_PLAYERDEATH);
   
diff --combined qcsrc/server/g_damage.qc
@@@@ -107,7 -107,7 -107,7 +107,7 @@@@ void GiveFrags (entity attacker, entit
                else if(!(attacker.weapons & WepSet_FromWeapon(culprit)))
                        culprit = attacker.weapon;
   
- -             if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator?
+ +             if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER.m_id) // WEAPONTODO: Shouldn't this be in a mutator?
                {
                        // no exchange
                }
        entity oldself;
        oldself = self;
        self = attacker;
 -      frag_attacker = attacker;
 -      frag_target = targ;
 -      frag_score = f;
 -      if(MUTATOR_CALLHOOK(GiveFragsForKill))
 +      if(MUTATOR_CALLHOOK(GiveFragsForKill, attacker, targ, f))
        {
                f = frag_score;
                self = oldself;
@@@@ -554,13 -557,13 -554,13 +554,13 @@@@ void Ice_Think(
   
   void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypoint)
   {
 --     if(!IS_PLAYER(targ) && !(targ.flags & FL_MONSTER)) // only specified entities can be freezed
 ++     if(!IS_PLAYER(targ) && !IS_MONSTER(targ)) // only specified entities can be freezed
                return;
   
        if(targ.frozen)
                return;
   
 --     float targ_maxhealth = ((targ.flags & FL_MONSTER) ? targ.max_health : start_health);
 ++     float targ_maxhealth = ((IS_MONSTER(targ)) ? targ.max_health : start_health);
   
        targ.frozen = frozen_type;
        targ.revive_progress = ((frozen_type == 3) ? 1 : 0);
@@@@ -648,7 -651,7 -648,7 +648,7 @@@@ void Damage (entity targ, entity inflic
                                        RemoveGrapplingHook(targ); // STOP THAT, you parasite!
   
        // special rule: gravity bomb does not hit team mates (other than for disconnecting the hook)
- -     if(DEATH_ISWEAPON(deathtype, WEP_HOOK) || DEATH_ISWEAPON(deathtype, WEP_TUBA))
+ +     if(DEATH_ISWEAPON(deathtype, WEP_HOOK.m_id) || DEATH_ISWEAPON(deathtype, WEP_TUBA.m_id))
        {
                if(IS_PLAYER(targ))
                        if(SAME_TEAM(targ, attacker))
                }
   
                // should this be changed at all? If so, in what way?
 -              frag_attacker = attacker;
 -              frag_target = targ;
 -              frag_damage = damage;
 -              frag_force = force;
 -              frag_deathtype = deathtype;
 -              frag_mirrordamage = mirrordamage;
 -              MUTATOR_CALLHOOK(PlayerDamage_Calculate);
 +              MUTATOR_CALLHOOK(PlayerDamage_Calculate, attacker, targ, deathtype, damage, mirrordamage, force);
                damage = frag_damage;
                mirrordamage = frag_mirrordamage;
                force = frag_force;
                        {
                                Unfreeze(targ);
                                targ.health = autocvar_g_freezetag_revive_falldamage_health;
 --                             pointparticles(particleeffectnum("iceorglass"), targ.origin, '0 0 0', 3);
 ++                             Send_Effect("iceorglass", targ.origin, '0 0 0', 3);
                                Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_FREEZETAG_REVIVED_FALL, targ.netname);
                                Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_FREEZETAG_REVIVE_SELF);
                        }
   
                if(targ.frozen && deathtype == DEATH_HURTTRIGGER && !autocvar_g_freezetag_frozen_damage_trigger)
                {
 --                     pointparticles(particleeffectnum("teleport"), targ.origin, '0 0 0', 1);
 ++                     Send_Effect("teleport", targ.origin, '0 0 0', 1);
   
                        entity oldself = self;
                        self = targ;
                                self.oldorigin = self.origin;
                                self.prevorigin = self.origin;
   
 --                             pointparticles(particleeffectnum("teleport"), self.origin, '0 0 0', 1);
 ++                             Send_Effect("teleport", self.origin, '0 0 0', 1);
                        }
   
                        self = oldself;
                if(!g_instagib)
                {
                        // apply strength multiplier
 --                     if (attacker.items & IT_STRENGTH)
 ++                     if (attacker.items & ITEM_Strength.m_itemid)
                        {
                                if(targ == attacker)
                                {
                        }
   
                        // apply invincibility multiplier
 --                     if (targ.items & IT_INVINCIBLE)
 ++                     if (targ.items & ITEM_Shield.m_itemid)
                                damage = damage * autocvar_g_balance_powerup_invincible_takedamage;
                }
   
                if(targ != attacker)
                {
                        entity victim;
 --                     if((targ.vehicle_flags & VHF_ISVEHICLE) && targ.owner)
 ++                     if(IS_VEHICLE(targ) && targ.owner)
                                victim = targ.owner;
                        else
                                victim = targ;
   
 --                     if(IS_PLAYER(victim) || (victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET) || (victim.flags & FL_MONSTER))
 ++                     if(IS_PLAYER(victim) || IS_TURRET(victim) || IS_MONSTER(victim))
                        {
                                if(DIFF_TEAM(victim, attacker) && !victim.frozen)
                                {
@@@@ -958,8 -967,8 -958,8 +958,8 @@@@ float RadiusDamageForSource (entity inf
   
        total_damage_to_creatures = 0;
   
- -     if(deathtype != (WEP_HOOK | HITTYPE_SECONDARY | HITTYPE_BOUNCE)) // only send gravity bomb damage once
- -             if(DEATH_WEAPONOF(deathtype) != WEP_TUBA) // do not send tuba damage (bandwidth hog)
+ +     if(deathtype != (WEP_HOOK.m_id | HITTYPE_SECONDARY | HITTYPE_BOUNCE)) // only send gravity bomb damage once
+ +             if(DEATH_WEAPONOF(deathtype) != WEP_TUBA.m_id) // do not send tuba damage (bandwidth hog)
                {
                        force = inflictorvelocity;
                        if(vlen(force) == 0)
                                        force = force * (finaldmg / coredamage) * forceintensity;
                                        hitloc = nearest;
   
- -                                     if(deathtype & WEP_BLASTER)
+ +                                     if(deathtype & WEP_BLASTER.m_id)
                                                force *= WEP_CVAR_BOTH(blaster, !(deathtype & HITTYPE_SECONDARY), force_zscale);
   
                                        if(targ != directhitentity)
diff --combined qcsrc/server/g_hook.qc
@@@@ -90,7 -90,7 -90,7 +90,7 @@@@ void GrapplingHookReset(void
   void GrapplingHookThink();
   void GrapplingHook_Stop()
   {
 --     pointparticles(particleeffectnum("grapple_impact"), self.origin, '0 0 0', 1);
 ++     Send_Effect("grapple_impact", self.origin, '0 0 0', 1);
        sound (self, CH_SHOTS, "weapons/hook_impact.wav", VOL_BASE, ATTEN_NORM);
   
        self.state = 1;
@@@@ -333,7 -333,7 -333,7 +333,7 @@@@ void FireGrapplingHook (void
        tracebox(self.origin + self.view_ofs, '-3 -3 -3', '3 3 3', org, MOVE_NORMAL, self);
        org = trace_endpos;
   
 --     pointparticles(particleeffectnum("grapple_muzzleflash"), org, '0 0 0', 1);
 ++     Send_Effect("grapple_muzzleflash", org, '0 0 0', 1);
   
        missile = WarpZone_RefSys_SpawnSameRefSys(self);
        missile.owner = missile.realowner = self;
   
   void GrapplingHookFrame()
   {
- -     if(g_grappling_hook && timeout_status != TIMEOUT_ACTIVE && self.weapon != WEP_HOOK)
+ +     if(g_grappling_hook && timeout_status != TIMEOUT_ACTIVE && self.weapon != WEP_HOOK.m_id)
        {
                // offhand hook controls
                if(self.BUTTON_HOOK)
                        //self.hook_state &= ~HOOK_RELEASING;
                }
        }
- -     else if(!g_grappling_hook && self.switchweapon != WEP_HOOK)
+ +     else if(!g_grappling_hook && self.switchweapon != WEP_HOOK.m_id)
        {
                if(self.BUTTON_HOOK && !self.hook_switchweapon)
- -                     W_SwitchWeapon(WEP_HOOK);
+ +                     W_SwitchWeapon(WEP_HOOK.m_id);
        }
        self.hook_switchweapon = self.BUTTON_HOOK;
   
- -     if(!g_grappling_hook && self.weapon != WEP_HOOK)
+ +     if(!g_grappling_hook && self.weapon != WEP_HOOK.m_id)
        {
                self.hook_state &= ~HOOK_FIRING;
                self.hook_state |= HOOK_REMOVING;
@@@@ -492,11 -492,11 -492,11 +492,11 @@@@ void GrappleHookInit(
        }
        else
        {
- -             WEP_ACTION(WEP_HOOK, WR_INIT);
- -             hook_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK), false, false, 1);
- -             hook_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK), false, false, 2);
- -             hook_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK), false, false, 3);
- -             hook_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK), false, false, 4);
+ +             WEP_ACTION(WEP_HOOK.m_id, WR_INIT);
+ +             hook_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 1);
+ +             hook_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 2);
+ +             hook_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 3);
+ +             hook_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 4);
        }
   }
   
diff --combined qcsrc/server/g_world.qc
   #include "../common/buffs.qh"
   #include "../common/constants.qh"
   #include "../common/deathtypes.qh"
 ++#include "../common/effects.qh"
   #include "../common/mapinfo.qh"
   #include "../common/monsters/all.qh"
   #include "../common/monsters/sv_monsters.qh"
@@@@ -561,10 -560,8 -560,9 +561,9 @@@@ void spawnfunc___init_dedicated_server(
   
        // needs to be done so early because of the constants they create
        static_init();
- -     CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
 ++     CALL_ACCUMULATED_FUNCTION(RegisterEffects);
   
        MapInfo_Enumerate();
        MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
@@@@ -610,10 -607,8 -608,9 +609,9 @@@@ void spawnfunc_worldspawn (void
   
        // needs to be done so early because of the constants they create
        static_init();
- -     CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
 ++     CALL_ACCUMULATED_FUNCTION(RegisterEffects);
   
        ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
   
                GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s));
                s = ":gameinfo:mutators:LIST";
   
 -              ret_string = s;
 -              MUTATOR_CALLHOOK(BuildMutatorsString);
 +              MUTATOR_CALLHOOK(BuildMutatorsString, s);
                s = ret_string;
   
                // simple, probably not good in the mutator system
@@@@ -303,11 -303,11 -303,11 +303,11 @@@@ string formatmessage(string msg
                                wep = self.cnt;
                        replacement = WEP_NAME(wep);
                } else if (escape == "W") {
 --                     if (self.items & IT_SHELLS) replacement = "shells";
 --                     else if (self.items & IT_NAILS) replacement = "bullets";
 --                     else if (self.items & IT_ROCKETS) replacement = "rockets";
 --                     else if (self.items & IT_CELLS) replacement = "cells";
 --                     else if (self.items & IT_PLASMA) replacement = "plasma";
 ++                     if (self.items & ITEM_Shells.m_itemid) replacement = "shells";
 ++                     else if (self.items & ITEM_Bullets.m_itemid) replacement = "bullets";
 ++                     else if (self.items & ITEM_Rockets.m_itemid) replacement = "rockets";
 ++                     else if (self.items & ITEM_Cells.m_itemid) replacement = "cells";
 ++                     else if (self.items & ITEM_Plasma.m_itemid) replacement = "plasma";
                        else replacement = "batteries"; // ;)
                } else if (escape == "x") {
                        replacement = cursor_ent.netname;
@@@@ -427,6 -427,7 -427,6 +427,6 @@@@ void GetCvars(float f
   
        get_cvars_f = f;
        get_cvars_s = s;
 - 
        MUTATOR_CALLHOOK(GetCvars);
   
        Notification_GetCvars();
@@@@ -515,14 -516,14 -515,14 +515,14 @@@@ float want_weapon(entity weaponinfo, fl
                        d = false;
        }
        else if (g_cts)
- -             d = (i == WEP_SHOTGUN);
+ +             d = (i == WEP_SHOTGUN.m_id);
        else if (g_nexball)
                d = 0; // weapon is set a few lines later
        else
                d = !(!weaponinfo.weaponstart);
   
        if(g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
- -             d |= (i == WEP_HOOK);
+ +             d |= (i == WEP_HOOK.m_id);
        if(!g_cts && (weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED)) // never default mutator blocked guns
                d = 0;
   
@@@@ -724,13 -725,13 -724,13 +724,13 @@@@ void readplayerstartcvars(
        }
   
        if (g_jetpack)
 --             start_items |= IT_JETPACK;
 ++             start_items |= ITEM_Jetpack.m_itemid;
   
        MUTATOR_CALLHOOK(SetStartItems);
   
 --     if ((start_items & IT_JETPACK) || (g_grappling_hook && (start_weapons & WEPSET_HOOK)))
 ++     if ((start_items & ITEM_Jetpack.m_itemid) || (g_grappling_hook && (start_weapons & WEPSET_HOOK)))
        {
 --             start_items |= IT_FUEL_REGEN;
 ++             start_items |= ITEM_JetpackRegen.m_itemid;
                start_ammo_fuel = max(start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
                warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
        }
@@@@ -3,7 -3,7 -3,7 +3,7 @@@@
   
   #include "t_items.qh"
   
-- #include "mutators/base.qh"
++ #include "mutators/events.qh"
   #include "mutators/gamemode_race.qh"
   
   #include "../common/constants.qh"
@@@@ -75,7 -75,7 -75,6 +75,6 @@@@ vector shotorg_adjust(vector vecs, floa
   
   float DistributeEvenly_amount;
   float DistributeEvenly_totalweight;
-- var void remove(entity e);
   void objerror(string s);
   void droptofloor();
   void() spawnfunc_info_player_deathmatch; // needed for the other spawnpoints
@@@@ -158,10 -158,6 -157,6 +157,10 @@@@ const string STR_OBSERVER = "observer"
   #define IS_REAL_CLIENT(v)            (clienttype(v) == CLIENTTYPE_REAL)
   #define IS_NOT_A_CLIENT(v)           (clienttype(v) == CLIENTTYPE_NOTACLIENT)
   
 ++#define IS_MONSTER(v)                        (v.flags & FL_MONSTER)
 ++#define IS_VEHICLE(v)                        (v.vehicle_flags & VHF_ISVEHICLE)
 ++#define IS_TURRET(v)                 (v.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
 ++
   #define FOR_EACH_CLIENTSLOT(v) for(v = world; (v = nextent(v)) && (num_for_edict(v) <= maxclients); )
   #define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(IS_CLIENT(v))
   #define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(IS_REAL_CLIENT(v))
@@@@ -158,9 -158,9 -158,9 +158,9 @@@@ void GiveBall(entity plyr, entity ball
        self.weaponentity.weapons = self.weapons;
        self.weaponentity.switchweapon = self.weapon;
        self.weapons = WEPSET_PORTO;
- -     WEP_ACTION(WEP_PORTO, WR_RESETPLAYER);
- -     self.switchweapon = WEP_PORTO;
- -     W_SwitchWeapon(WEP_PORTO);
+ +     WEP_ACTION(WEP_PORTO.m_id, WR_RESETPLAYER);
+ +     self.switchweapon = WEP_PORTO.m_id;
+ +     W_SwitchWeapon(WEP_PORTO.m_id);
        self = ownr;
   }
   
@@@@ -777,7 -777,7 -777,7 +777,7 @@@@ void W_Nexball_Attack2(void
        if(!(balls & BALL_BASKET))
                return;
        W_SetupShot(self, false, 2, "nexball/shoot2.wav", CH_WEAPON_A, 0);
 --//   pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
 ++//   Send_Effect("grenadelauncher_muzzleflash", w_shotorg, w_shotdir * 1000, 1);
        missile = spawn();
   
        missile.owner = self;
@@@@ -873,7 -873,7 -873,7 +873,7 @@@@ float w_nexball_weapon(float req
        }
        else if(req == WR_SETUP)
        {
- -             //weapon_setup(WEP_PORTO);
+ +             //weapon_setup(WEP_PORTO.m_id);
        }
        // No need to check WR_CHECKAMMO* or WR_AIM, it should always return true
        return true;
@@@@ -936,7 -936,7 -936,7 +936,7 @@@@ MUTATOR_HOOKFUNCTION(nexball_PlayerPreT
                        if(self.weaponentity.weapons)
                        {
                                self.weapons = self.weaponentity.weapons;
- -                             WEP_ACTION(WEP_PORTO, WR_RESETPLAYER);
+ +                             WEP_ACTION(WEP_PORTO.m_id, WR_RESETPLAYER);
                                self.switchweapon = self.weaponentity.switchweapon;
                                W_SwitchWeapon(self.switchweapon);
   
@@@@ -982,7 -982,7 -982,7 +982,7 @@@@ MUTATOR_HOOKFUNCTION(nexball_SetStartIt
   
   MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing)
   {
- -     if(self.weapon == WEP_MORTAR)
+ +     if(self.weapon == WEP_MORTAR.m_id)
                return true;
   
        return false;
   MUTATOR_HOOKFUNCTION(nexball_FilterItem)
   {
        if(self.classname == "droppedweapon")
- -     if(self.weapon == WEP_MORTAR)
+ +     if(self.weapon == WEP_MORTAR.m_id)
                return true;
   
        return false;
@@@@ -67,7 -67,7 -67,7 +67,7 @@@@ void buff_Effect(entity player, string 
   
        if(time >= self.buff_effect_delay)
        {
 --             pointparticles(particleeffectnum(eff), player.origin + ((player.mins + player.maxs) * 0.5), '0 0 0', 1);
 ++             Send_Effect(eff, player.origin + ((player.mins + player.maxs) * 0.5), '0 0 0', 1);
                self.buff_effect_delay = time + 0.05; // prevent spam
        }
   }
@@@@ -131,8 -131,8 -131,8 +131,8 @@@@ void buff_Respawn(entity ent
        if(autocvar_g_buffs_random_lifetime > 0)
                ent.lifetime = time + autocvar_g_buffs_random_lifetime;
   
 --     pointparticles(particleeffectnum("electro_combo"), oldbufforigin + ((ent.mins + ent.maxs) * 0.5), '0 0 0', 1);
 --     pointparticles(particleeffectnum("electro_combo"), CENTER_OR_VIEWOFS(ent), '0 0 0', 1);
 ++     Send_Effect("electro_combo", oldbufforigin + ((ent.mins + ent.maxs) * 0.5), '0 0 0', 1);
 ++     Send_Effect("electro_combo", CENTER_OR_VIEWOFS(ent), '0 0 0', 1);
   
        WaypointSprite_Ping(ent.buff_waypoint);
   
@@@@ -181,7 -181,7 -181,7 +181,7 @@@@ void buff_Touch(
        Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_BUFF_GOT, buffid);
        Send_Notification(NOTIF_ALL_EXCEPT, other, MSG_INFO, INFO_ITEM_BUFF, other.netname, buffid);
   
 --     pointparticles(particleeffectnum("item_pickup"), CENTER_OR_VIEWOFS(self), '0 0 0', 1);
 ++     Send_Effect("item_pickup", CENTER_OR_VIEWOFS(self), '0 0 0', 1);
        sound(other, CH_TRIGGER, "misc/shield_respawn.wav", VOL_BASE, ATTN_NORM);
        other.buffs |= (self.buffs);
   }
@@@@ -263,7 -263,7 -263,7 +263,7 @@@@ void buff_Think(
                {
                        self.buff_active = true;
                        sound(self, CH_TRIGGER, "misc/strength_respawn.wav", VOL_BASE, ATTN_NORM);
 --                     pointparticles(particleeffectnum("item_respawn"), CENTER_OR_VIEWOFS(self), '0 0 0', 1);
 ++                     Send_Effect("item_respawn", CENTER_OR_VIEWOFS(self), '0 0 0', 1);
                }
        }
   
@@@@ -469,7 -469,7 -469,7 +469,7 @@@@ MUTATOR_HOOKFUNCTION(buffs_PlayerDamage
                frag_target.buff_disability_time = time + autocvar_g_buffs_disability_slowtime;
   
        if(frag_attacker.buffs & BUFF_MEDIC.m_itemid)
- -     if(DEATH_WEAPONOF(frag_deathtype) != WEP_ARC)
+ +     if(DEATH_WEAPONOF(frag_deathtype) != WEP_ARC.m_id)
        if(SAME_TEAM(frag_attacker, frag_target))
        if(frag_attacker != frag_target)
        {
        // this... is ridiculous (TODO: fix!)
        if(frag_attacker.buffs & BUFF_VAMPIRE.m_itemid)
        if(!frag_target.vehicle)
- -     if(DEATH_WEAPONOF(frag_deathtype) != WEP_ARC)
+ +     if(DEATH_WEAPONOF(frag_deathtype) != WEP_ARC.m_id)
        if(!ITEM_DAMAGE_NEEDKILL(frag_deathtype))
        if(frag_target.deadflag == DEAD_NO)
 --     if(IS_PLAYER(frag_target) || (frag_target.flags & FL_MONSTER))
 ++     if(IS_PLAYER(frag_target) || IS_MONSTER(frag_target))
        if(frag_attacker != frag_target)
        if(!frag_target.frozen)
        if(frag_target.takedamage)
@@@@ -629,7 -629,7 -629,7 +629,7 @@@@ MUTATOR_HOOKFUNCTION(buffs_PlayerThrowK
                        if(closest.flagcarried) { ctf_Handle_Throw(closest, world, DROP_THROW); }
                        if(closest.nade) { toss_nade(closest, '0 0 0', time + 0.05); }
   
 -                      MUTATOR_CALLHOOK(PortalTeleport); // initiate flag dropper
 +                      MUTATOR_CALLHOOK(PortalTeleport, self); // initiate flag dropper
   
                        setorigin(self, their_org);
                        setorigin(closest, my_org);
                        closest.pushltime = time + autocvar_g_maxpushtime;
                        closest.istypefrag = closest.BUTTON_CHAT;
   
 --                     pointparticles(particleeffectnum("electro_combo"), their_org, '0 0 0', 1);
 --                     pointparticles(particleeffectnum("electro_combo"), my_org, '0 0 0', 1);
 ++                     Send_Effect("electro_combo", their_org, '0 0 0', 1);
 ++                     Send_Effect("electro_combo", my_org, '0 0 0', 1);
   
                        sound(self, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NORM);
                        sound(closest, CH_TRIGGER, "keepaway/respawn.wav", VOL_BASE, ATTEN_NORM);
@@@@ -739,7 -739,7 -739,7 +739,7 @@@@ MUTATOR_HOOKFUNCTION(buffs_PlayerThink
        if(time < self.buff_disability_time)
        if(time >= self.buff_disability_effect_time)
        {
 --             pointparticles(particleeffectnum("smoking"), self.origin + ((self.mins + self.maxs) * 0.5), '0 0 0', 1);
 ++             Send_Effect("smoking", self.origin + ((self.mins + self.maxs) * 0.5), '0 0 0', 1);
                self.buff_disability_effect_time = time + 0.5;
        }
   
@@@@ -132,7 -132,7 -132,7 +132,7 @@@@ MUTATOR_HOOKFUNCTION(instagib_MonsterSp
   
   MUTATOR_HOOKFUNCTION(instagib_BotShouldAttack)
   {
 --     if(checkentity.items & IT_STRENGTH)
 ++     if(checkentity.items & ITEM_Strength.m_itemid)
                return true;
   
        return false;
@@@@ -167,14 -167,14 -167,14 +167,14 @@@@ MUTATOR_HOOKFUNCTION(instagib_PlayerPow
        if (!(self.effects & EF_FULLBRIGHT))
                self.effects |= EF_FULLBRIGHT;
   
 --     if (self.items & IT_STRENGTH)
 ++     if (self.items & ITEM_Strength.m_itemid)
        {
                play_countdown(self.strength_finished, "misc/poweroff.wav");
                if (time > self.strength_finished)
                {
                        self.alpha = default_player_alpha;
                        self.exteriorweaponentity.alpha = default_weapon_alpha;
 --                     self.items &= ~IT_STRENGTH;
 ++                     self.items &= ~ITEM_Strength.m_itemid;
                        Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_INVISIBILITY);
                }
        }
                {
                        self.alpha = autocvar_g_instagib_invis_alpha;
                        self.exteriorweaponentity.alpha = autocvar_g_instagib_invis_alpha;
 --                     self.items |= IT_STRENGTH;
 ++                     self.items |= ITEM_Strength.m_itemid;
                        Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_INVISIBILITY, self.netname);
                        Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_INVISIBILITY);
                }
        }
   
 --     if (self.items & IT_INVINCIBLE)
 ++     if (self.items & ITEM_Shield.m_itemid)
        {
                play_countdown(self.invincible_finished, "misc/poweroff.wav");
                if (time > self.invincible_finished)
                {
 --                     self.items &= ~IT_INVINCIBLE;
 ++                     self.items &= ~ITEM_Shield.m_itemid;
                        Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SPEED);
                }
        }
        {
                if (time < self.invincible_finished)
                {
 --                     self.items |= IT_INVINCIBLE;
 ++                     self.items |= ITEM_Shield.m_itemid;
                        Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SPEED, self.netname);
                        Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SPEED);
                }
   
   MUTATOR_HOOKFUNCTION(instagib_PlayerPhysics)
   {
 --     if(self.items & IT_INVINCIBLE)
 ++     if(self.items & ITEM_Shield.m_itemid)
                self.stat_sv_maxspeed = self.stat_sv_maxspeed * autocvar_g_instagib_speed_highspeed;
   
        return false;
@@@@ -250,7 -250,7 -250,7 +250,7 @@@@ MUTATOR_HOOKFUNCTION(instagib_PlayerDam
                }
   
                if(IS_PLAYER(frag_attacker))
- -             if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER))
+ +             if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER.m_id))
                {
                        if(frag_target.armorvalue)
                        {
                        }
                }
   
- -             if(IS_PLAYER(frag_attacker) && DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER))
+ +             if(IS_PLAYER(frag_attacker) && DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER.m_id))
                {
                        if(frag_deathtype & HITTYPE_SECONDARY)
                        {
                frag_mirrordamage = 0;
        }
   
 --     if((frag_target.buffs & BUFF_INVISIBLE.m_itemid) || (frag_target.items & IT_STRENGTH))
 ++     if((frag_target.buffs & BUFF_INVISIBLE.m_itemid) || (frag_target.items & ITEM_Strength.m_itemid))
                yoda = 1;
   
        return false;
@@@@ -319,13 -319,13 -319,13 +319,13 @@@@ MUTATOR_HOOKFUNCTION(instagib_FilterIte
        if(self.classname == "item_cells")
                return true; // no normal cells?
   
- -     if(self.weapon == WEP_VAPORIZER && self.classname == "droppedweapon")
+ +     if(self.weapon == WEP_VAPORIZER.m_id && self.classname == "droppedweapon")
        {
                self.ammo_cells = autocvar_g_instagib_ammo_drop;
                return false;
        }
   
- -     if(self.weapon == WEP_DEVASTATOR || self.weapon == WEP_VORTEX)
+ +     if(self.weapon == WEP_DEVASTATOR.m_id || self.weapon == WEP_VORTEX.m_id)
        {
                entity e = spawn();
                setorigin(e, self.origin);
@@@@ -355,7 -355,7 -355,7 +355,7 @@@@ MUTATOR_HOOKFUNCTION(instagib_Customize
   
        // if you have the invisibility powerup, sprites ALWAYS are restricted to your team
        // but only apply this to real players, not to spectators
 --     if((self.owner.flags & FL_CLIENT) && (self.owner.items & IT_STRENGTH) && (e == other))
 ++     if((self.owner.flags & FL_CLIENT) && (self.owner.items & ITEM_Strength.m_itemid) && (e == other))
        if(DIFF_TEAM(self.owner, e))
                return true;
   
   
   MUTATOR_HOOKFUNCTION(instagib_ItemCountdown)
   {
 --     switch(self.items)
 ++     switch (self.items)
        {
 --             case IT_STRENGTH:   item_name = "item-invis"; item_color = '0 0 1'; break;
 --             case IT_NAILS:      item_name = "item-extralife"; item_color = '1 0 0'; break;
 --             case IT_INVINCIBLE: item_name = "item-speed"; item_color = '1 0 1'; break;
 ++             case ITEM_Strength.m_itemid:  item_name = "item-invis";     item_color = '0 0 1'; break;
 ++             case ITEM_ExtraLife.m_itemid: item_name = "item-extralife"; item_color = '1 0 0'; break;
 ++             case ITEM_Shield.m_itemid:    item_name = "item-speed";     item_color = '1 0 1'; break;
        }
        return false;
   }
@@@@ -405,7 -405,7 -405,7 +405,7 @@@@ MUTATOR_HOOKFUNCTION(instagib_ItemTouch
   MUTATOR_HOOKFUNCTION(instagib_OnEntityPreSpawn)
   {
        if (!autocvar_g_powerups) { return false; }
 --     if (!(self.classname == "item_strength" || self.classname == "item_invincible" || self.classname == "item_health_mega"))
 ++     if (!(self.classname == "item_strength" || self.classname == "item_invincible" || self.itemdef == ITEM_HealthMega))
                return false;
   
        entity e = spawn();
@@@@ -78,7 -78,7 -78,7 +78,7 @@@@ void napalm_damage(float dist, float da
                d = damage + (edgedamage - damage) * (d / dist);
                Fire_AddDamage(RandomSelection_chosen_ent, self.realowner, d * burntime, burntime, self.projectiledeathtype | HITTYPE_BOUNCE);
                //trailparticles(self, particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec);
 --             pointparticles(particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec - self.origin, 1);
 ++             Send_Effect("fireball_laser", self.origin, RandomSelection_chosen_ent.fireball_impactvec - self.origin, 1);
        }
   }
   
@@@@ -225,7 -225,7 -225,7 +225,7 @@@@ void nade_napalm_boom(
   void nade_ice_freeze(entity freezefield, entity frost_target, float freeze_time)
   {
        frost_target.frozen_by = freezefield.realowner;
 --     pointparticles(particleeffectnum("electro_impact"), frost_target.origin, '0 0 0', 1);
 ++     Send_Effect("electro_impact", frost_target.origin, '0 0 0', 1);
        Freeze(frost_target, 1/freeze_time, 3, false);
        if(frost_target.ballcarried)
        if(g_keepaway) { ka_DropEvent(frost_target); }
@@@@ -259,7 -259,7 -259,7 +259,7 @@@@ void nade_ice_think(
                                case NUM_TEAM_4: expef = "nade_pink_explode"; break;
                                default:                 expef = "nade_neutral_explode"; break;
                        }
 --                     pointparticles(particleeffectnum(expef), self.origin + '0 0 1', '0 0 0', 1);
 ++                     Send_Effect(expef, self.origin + '0 0 1', '0 0 0', 1);
                        sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
   
                        RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
        randomp.x = randomr*cos(randomw);
        randomp.y = randomr*sin(randomw);
        randomp.z = 1;
 --     pointparticles(particleeffectnum("electro_muzzleflash"), self.origin + randomp, '0 0 0', 1);
 ++     Send_Effect("electro_muzzleflash", self.origin + randomp, '0 0 0', 1);
   
        if(time >= self.nade_special_time)
        {
                self.nade_special_time = time+0.7;
   
   
 --             pointparticles(particleeffectnum("electro_impact"), self.origin, '0 0 0', 1);
 --             pointparticles(particleeffectnum("icefield"), self.origin, '0 0 0', 1);
 ++             Send_Effect("electro_impact", self.origin, '0 0 0', 1);
 ++             Send_Effect("icefield", self.origin, '0 0 0', 1);
        }
   
   
@@@@ -360,7 -360,11 -360,7 +360,7 @@@@ void nade_translocate_boom(
   
        makevectors(self.realowner.angles);
   
 -      entity oldself = self;
 -      self = self.realowner;
 -      MUTATOR_CALLHOOK(PortalTeleport);
 -      self.realowner = self;
 -      self = oldself;
 +      MUTATOR_CALLHOOK(PortalTeleport, self.realowner);
   
        TeleportPlayer(self, self.realowner, locout, self.realowner.angles, v_forward * vlen(self.realowner.velocity), '0 0 0', '0 0 0', TELEPORT_FLAGS_TELEPORTER);
   }
@@@@ -408,7 -412,7 -408,7 +408,7 @@@@ void nade_heal_touch(
   {
        float maxhealth;
        float health_factor;
 --     if(IS_PLAYER(other) || (other.flags & FL_MONSTER))
 ++     if(IS_PLAYER(other) || IS_MONSTER(other))
        if(other.deadflag == DEAD_NO)
        if(!other.frozen)
        {
                }
                if ( health_factor > 0 )
                {
 --                     maxhealth = (other.flags & FL_MONSTER) ? other.max_health : g_pickup_healthmega_max;
 ++                     maxhealth = (IS_MONSTER(other)) ? other.max_health : g_pickup_healthmega_max;
                        if ( other.health < maxhealth )
                        {
                                if ( self.nade_show_particles )
 --                                     pointparticles(particleeffectnum("healing_fx"), other.origin, '0 0 0', 1);
 ++                                     Send_Effect("healing_fx", other.origin, '0 0 0', 1);
                                other.health = min(other.health+health_factor, maxhealth);
                        }
                        other.pauserothealth_finished = max(other.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot);
   
        }
   
 --     if ( IS_REAL_CLIENT(other) || (other.vehicle_flags & VHF_ISVEHICLE) )
 ++     if ( IS_REAL_CLIENT(other) || IS_VEHICLE(other) )
        {
 --             entity show_red = (other.vehicle_flags & VHF_ISVEHICLE) ? other.owner : other;
 ++             entity show_red = (IS_VEHICLE(other)) ? other.owner : other;
                show_red.stat_healing_orb = time+0.1;
                show_red.stat_healing_orb_alpha = 0.75 * (self.ltime - time) / self.healer_lifetime;
        }
@@@@ -530,7 -534,7 -530,7 +530,7 @@@@ void nade_boom(
        }
   
        if(expef != "")
 --             pointparticles(particleeffectnum(expef), findbetterlocation(self.origin, 8), '0 0 0', 1);
 ++             Send_Effect(expef, findbetterlocation(self.origin, 8), '0 0 0', 1);
   
        sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
        sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
@@@@ -604,28 -608,28 -604,28 +604,28 @@@@ void nade_damage(entity inflictor, enti
        if(self.nade_type == NADE_TYPE_TRANSLOCATE.m_id || self.nade_type == NADE_TYPE_SPAWN.m_id)
                return;
   
- -     if(DEATH_ISWEAPON(deathtype, WEP_BLASTER))
+ +     if(DEATH_ISWEAPON(deathtype, WEP_BLASTER.m_id))
        {
                force *= 1.5;
                damage = 0;
        }
   
- -     if(DEATH_ISWEAPON(deathtype, WEP_VAPORIZER) && (deathtype & HITTYPE_SECONDARY))
+ +     if(DEATH_ISWEAPON(deathtype, WEP_VAPORIZER.m_id) && (deathtype & HITTYPE_SECONDARY))
        {
                force *= 0.5; // too much
                frag_damage = 0;
        }
   
- -     if(DEATH_ISWEAPON(deathtype, WEP_VORTEX) || DEATH_ISWEAPON(deathtype, WEP_VAPORIZER))
+ +     if(DEATH_ISWEAPON(deathtype, WEP_VORTEX.m_id) || DEATH_ISWEAPON(deathtype, WEP_VAPORIZER.m_id))
        {
                force *= 6;
                damage = self.max_health * 0.55;
        }
   
- -     if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN) || DEATH_ISWEAPON(deathtype, WEP_HMG))
+ +     if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN.m_id) || DEATH_ISWEAPON(deathtype, WEP_HMG.m_id))
                damage = self.max_health * 0.1;
   
- -     if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) // WEAPONTODO
+ +     if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE.m_id) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN.m_id)) // WEAPONTODO
        if(deathtype & HITTYPE_SECONDARY)
        {
                damage = self.max_health * 0.1;
@@@@ -799,7 -803,7 -799,7 +799,7 @@@@ void nade_prime(
        n.classname = "nade";
        fn.classname = "fake_nade";
   
 --     if(self.items & IT_STRENGTH && autocvar_g_nades_bonus_onstrength)
 ++     if(self.items & ITEM_Strength.m_itemid && autocvar_g_nades_bonus_onstrength)
                n.nade_type = self.nade_type;
        else if (self.bonus_nades >= 1)
        {
@@@@ -925,7 -929,7 -925,7 +925,7 @@@@ MUTATOR_HOOKFUNCTION(nades_PlayerPreThi
        float key_pressed = self.BUTTON_HOOK;
        float time_score;
   
- -     if(g_grappling_hook || client_hasweapon(self, WEP_HOOK, false, false) || (weaponsInMap & WEPSET_HOOK))
+ +     if(g_grappling_hook || client_hasweapon(self, WEP_HOOK.m_id, false, false) || (weaponsInMap & WEPSET_HOOK))
                key_pressed = self.button16; // if hook is enabled, use an alternate key
   
        if(self.nade)
@@@@ -1120,7 -1124,7 -1120,7 +1120,7 @@@@ MUTATOR_HOOKFUNCTION(nades_PlayerDamage
        {
                Unfreeze(frag_target);
                frag_target.health = autocvar_g_freezetag_revive_nade_health;
 --             pointparticles(particleeffectnum("iceorglass"), frag_target.origin, '0 0 0', 3);
 ++             Send_Effect("iceorglass", frag_target.origin, '0 0 0', 3);
                frag_damage = 0;
                frag_force = '0 0 0';
                Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_FREEZETAG_REVIVED_NADE, frag_target.netname);
@@@@ -24,7 -24,7 -24,7 +24,7 @@@@ float NIX_CanChooseWeapon(float wpn
        }
        else
        {
- -             if(wpn == WEP_BLASTER && g_nix_with_blaster) // WEAPONTODO: rename to g_nix_with_blaster
+ +             if(wpn == WEP_BLASTER.m_id && g_nix_with_blaster) // WEAPONTODO: rename to g_nix_with_blaster
                        return false;
                if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
                        return false;
@@@@ -180,19 -180,16 -180,16 +180,19 @@@@ MUTATOR_HOOKFUNCTION(nix_FilterItem
   {
        switch (self.items)
        {
 --             case IT_HEALTH:
 --             case IT_5HP:
 --             case IT_25HP:
 --             case IT_ARMOR:
 --             case IT_ARMOR_SHARD:
 ++             case ITEM_HealthSmall.m_itemid:
 ++             case ITEM_HealthMedium.m_itemid:
 ++             case ITEM_HealthLarge.m_itemid:
 ++             case ITEM_HealthMega.m_itemid:
 ++             case ITEM_ArmorSmall.m_itemid:
 ++             case ITEM_ArmorMedium.m_itemid:
 ++             case ITEM_ArmorLarge.m_itemid:
 ++             case ITEM_ArmorMega.m_itemid:
                        if (autocvar_g_nix_with_healtharmor)
                                return 0;
                        break;
 --             case IT_STRENGTH:
 --             case IT_INVINCIBLE:
 ++             case ITEM_Strength.m_itemid:
 ++             case ITEM_Shield.m_itemid:
                        if (autocvar_g_nix_with_powerups)
                                return 0;
                        break;
@@@@ -46,7 -46,7 -46,7 +46,7 @@@@ float ok_CheckWeaponCharge(entity ent, 
   MUTATOR_HOOKFUNCTION(ok_PlayerDamage_Calculate)
   {
        if(IS_PLAYER(frag_attacker) && IS_PLAYER(frag_target))
- -     if(DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER))
+ +     if(DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER.m_id))
        {
                frag_damage = 0;
   
@@@@ -75,7 -75,7 -75,7 +75,7 @@@@ MUTATOR_HOOKFUNCTION(ok_PlayerDies
        entity oldself = self;
        entity targ = ((frag_attacker) ? frag_attacker : frag_target);
   
 --     if(self.flags & FL_MONSTER)
 ++     if(IS_MONSTER(self))
        {
                remove(other); // remove default item
                other = world;
@@@@ -114,7 -114,7 -114,7 +114,7 @@@@ MUTATOR_HOOKFUNCTION(ok_PlayerRegen
                minf = autocvar_g_balance_fuel_regenstable;
                limitf = autocvar_g_balance_fuel_limit;
   
 --             self.ammo_fuel = CalcRotRegen(self.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, frametime * (time > self.pauseregen_finished) * ((self.items & IT_FUEL_REGEN) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > self.pauserotfuel_finished), limitf);
 ++             self.ammo_fuel = CalcRotRegen(self.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, frametime * (time > self.pauseregen_finished) * ((self.items & ITEM_JetpackRegen.m_itemid) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > self.pauserotfuel_finished), limitf);
        }
        return true; // return true anyway, as frozen uses no regen
   }
@@@@ -148,9 -148,9 -148,9 +148,9 @@@@ MUTATOR_HOOKFUNCTION(ok_PlayerPreThink
                makevectors(self.v_angle);
   
                int oldwep = self.weapon;
- -             self.weapon = WEP_BLASTER;
+ +             self.weapon = WEP_BLASTER.m_id;
                W_Blaster_Attack(
- -                     WEP_BLASTER | HITTYPE_SECONDARY,
+ +                     WEP_BLASTER.m_id | HITTYPE_SECONDARY,
                        WEP_CVAR_SEC(vaporizer, shotangle),
                        WEP_CVAR_SEC(vaporizer, damage),
                        WEP_CVAR_SEC(vaporizer, edgedamage),
@@@@ -256,8 -256,8 -256,8 +256,8 @@@@ MUTATOR_HOOKFUNCTION(ok_ItemRemove
   
        switch(self.items)
        {
 --             case IT_HEALTH: return !(autocvar_g_overkill_100h_anyway);
 --             case IT_ARMOR: return !(autocvar_g_overkill_100a_anyway);
 ++             case ITEM_HealthMega.m_itemid: return !(autocvar_g_overkill_100h_anyway);
 ++             case ITEM_ArmorMega.m_itemid: return !(autocvar_g_overkill_100a_anyway);
        }
   
        return true;
@@@@ -275,8 -275,8 -275,8 +275,8 @@@@ MUTATOR_HOOKFUNCTION(ok_StartItems
   {
        WepSet ok_start_items = (WEPSET_MACHINEGUN | WEPSET_VORTEX | WEPSET_SHOTGUN);
   
- -     if((get_weaponinfo(WEP_RPC)).weaponstart > 0) { ok_start_items |= WEPSET_RPC; }
- -     if((get_weaponinfo(WEP_HMG)).weaponstart > 0) { ok_start_items |= WEPSET_HMG; }
+ +     if(WEP_RPC.weaponstart > 0) { ok_start_items |= WEPSET_RPC; }
+ +     if(WEP_HMG.weaponstart > 0) { ok_start_items |= WEPSET_HMG; }
   
        start_items |= IT_UNLIMITED_WEAPON_AMMO;
        start_weapons = warmup_start_weapons = ok_start_items;
@@@@ -334,12 -334,12 -334,12 +334,12 @@@@ void ok_Initialize(
        addstat(STAT_OK_AMMO_CHARGE, AS_FLOAT, ok_use_ammocharge);
        addstat(STAT_OK_AMMO_CHARGEPOOL, AS_FLOAT, ok_ammo_charge);
   
- -     (get_weaponinfo(WEP_RPC)).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
- -     (get_weaponinfo(WEP_HMG)).spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
+ +     WEP_RPC.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
+ +     WEP_HMG.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
   
- -     (get_weaponinfo(WEP_SHOTGUN)).mdl = "ok_shotgun";
- -     (get_weaponinfo(WEP_MACHINEGUN)).mdl = "ok_mg";
- -     (get_weaponinfo(WEP_VORTEX)).mdl = "ok_sniper";
+ +     WEP_SHOTGUN.mdl = "ok_shotgun";
+ +     WEP_MACHINEGUN.mdl = "ok_mg";
+ +     WEP_VORTEX.mdl = "ok_sniper";
   }
   
   MUTATOR_DEFINITION(mutator_overkill)
   
        MUTATOR_ONREMOVE
        {
- -             (get_weaponinfo(WEP_RPC)).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
- -             (get_weaponinfo(WEP_HMG)).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
+ +             WEP_RPC.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
+ +             WEP_HMG.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
        }
   
        return false;
diff --combined qcsrc/server/progs.src
@@@@ -87,7 -87,6 -87,6 +87,7 @@@@ weapons/weaponsystem.q
   ../common/buffs.qc
   ../common/campaign_file.qc
   ../common/campaign_setup.qc
 ++../common/effects.qc
   ../common/mapinfo.qc
   ../common/monsters/all.qc
   ../common/monsters/spawn.qc
   ../warpzonelib/mathlib.qc
   ../warpzonelib/server.qc
   ../warpzonelib/util_server.qc
++ 
++ ../../mod/server/progs.inc
@@@@ -164,7 -164,7 -164,7 +164,7 @@@@ void targetdrone_damage(entity inflicto
        self.health -= damage;
        if(self.health <= 0)
        {
 --             pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);
 ++             Send_Effect("explosion_medium", self.origin, '0 0 0', 1);
   
                if(!self.cnt)
                        remove(self);
@@@@ -267,8 -267,8 -267,8 +267,8 @@@@ void vehicles_locktarget(float incr, fl
           if(trace_ent.deadflag != DEAD_NO)
               trace_ent = world;
           if(!(
 --            (trace_ent.vehicle_flags & VHF_ISVEHICLE) || 
 --            (trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET) || 
 ++            IS_VEHICLE(trace_ent) || 
 ++            IS_TURRET(trace_ent) || 
               (trace_ent.takedamage == DAMAGE_TARGETDRONE)
               )) { trace_ent = world; }
       }
@@@@ -434,7 -434,7 -434,7 +434,7 @@@@ entity vehicles_projectile(string _mzlf
           sound (self, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM);
   
       if(_mzlfx)
 --        pointparticles(particleeffectnum(_mzlfx), proj.origin, proj.velocity, 1);
 ++        Send_Effect(_mzlfx, proj.origin, proj.velocity, 1);
   
   
       setsize (proj, '-1 -1 -1' * _size, '1 1 1' * _size);
@@@@ -505,7 -505,7 -505,7 +505,7 @@@@ void vehicles_spawn(
       self.angles             = self.pos2;
       setorigin(self, self.pos1 + '0 0 0');
       // Show it
 --    pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
 ++    Send_Effect("teleport", self.origin + '0 0 64', '0 0 0', 1);
   
       if(self.vehicle_controller)
           self.team = self.vehicle_controller.team;
@@@@ -520,7 -520,7 -520,7 +520,7 @@@@ float vehicles_crushable(entity e
       if(IS_PLAYER(e))
           return true;
   
 --    if(e.flags & FL_MONSTER)
 ++    if(IS_MONSTER(e))
           return true;
   
       return false;
@@@@ -550,7 -550,7 -550,7 +550,7 @@@@ void vehicles_impact(float _minspeed, f
   
   void vehicles_touch()
   {
 -      if(MUTATOR_CALLHOOK(VehicleTouch))
 +      if(MUTATOR_CALLHOOK(VehicleTouch, self, other))
                return;
   
       // Vehicle currently in use
@@@@ -683,7 -683,11 -683,7 +683,7 @@@@ void vehicles_enter(
   
       CSQCVehicleSetup(self.owner, self.hud);
   
 -     vh_player = other;
 -     vh_vehicle = self;
 -     MUTATOR_CALLHOOK(VehicleEnter);
 -     other = vh_player;
 -     self = vh_vehicle;
 +     MUTATOR_CALLHOOK(VehicleEnter, other, self);
   
       self.vehicle_enter();
       antilag_clear(other);
@@@@ -819,7 -823,11 -819,7 +819,7 @@@@ void vehicles_exit(float eject
       if(!teamplay)
           _vehicle.team = 0;
   
 -     vh_player = _player;
 -     vh_vehicle = _vehicle;
 -     MUTATOR_CALLHOOK(VehicleExit);
 -     _player = vh_player;
 -     _vehicle = vh_vehicle;
 +     MUTATOR_CALLHOOK(VehicleExit, _player, _vehicle);
   
       _vehicle.team = _vehicle.tur_head.team;
   
@@@@ -877,7 -885,7 -877,7 +877,7 @@@@ void vehicles_painframe(
           float _ftmp;
           _ftmp = self.owner.vehicle_health / 50;
           self.pain_frame = time + 0.1 + (random() * 0.5 * _ftmp);
 --        pointparticles(particleeffectnum("smoke_small"), (self.origin + (randomvec() * 80)), '0 0 0', 1);
 ++        Send_Effect("smoke_small", (self.origin + (randomvec() * 80)), '0 0 0', 1);
   
           if(self.vehicle_flags & VHF_DMGSHAKE)
               self.velocity += randomvec() * 30;
@@@@ -896,19 -904,19 -896,19 +896,19 @@@@ void vehicles_damage(entity inflictor, 
       self.dmg_time = time;
   
        // WEAPONTODO
- -    if(DEATH_ISWEAPON(deathtype, WEP_VORTEX))
+ +    if(DEATH_ISWEAPON(deathtype, WEP_VORTEX.m_id))
           damage *= autocvar_g_vehicles_vortex_damagerate;
   
- -    if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN))
+ +    if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN.m_id))
           damage *= autocvar_g_vehicles_machinegun_damagerate;
   
- -    if(DEATH_ISWEAPON(deathtype, WEP_RIFLE))
+ +    if(DEATH_ISWEAPON(deathtype, WEP_RIFLE.m_id))
           damage *= autocvar_g_vehicles_rifle_damagerate;
   
- -    if(DEATH_ISWEAPON(deathtype, WEP_VAPORIZER))
+ +    if(DEATH_ISWEAPON(deathtype, WEP_VAPORIZER.m_id))
           damage *= autocvar_g_vehicles_vaporizer_damagerate;
   
- -    if(DEATH_ISWEAPON(deathtype, WEP_SEEKER))
+ +    if(DEATH_ISWEAPON(deathtype, WEP_SEEKER.m_id))
           damage *= autocvar_g_vehicles_tag_damagerate;
   
       self.enemy = attacker;
@@@@ -1003,7 -1011,7 -1003,7 +1003,7 @@@@ void vehicles_clearreturn(
   
   void vehicles_return()
   {
 --    pointparticles(particleeffectnum("teleport"), self.wp00.origin + '0 0 64', '0 0 0', 1);
 ++    Send_Effect("teleport", self.wp00.origin + '0 0 64', '0 0 0', 1);
   
       self.wp00.think     = vehicles_spawn;
       self.wp00.nextthink = time;
@@@@ -1359,7 -1367,7 -1359,7 +1359,7 @@@@ vector vehicle_aimturret(entity _vehic
   void vehicles_gib_explode()
   {
        sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
 --     pointparticles(particleeffectnum("explosion_small"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
 ++     Send_Effect("explosion_small", randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
        remove(self);
   }
   
   
   float W_WeaponRateFactor()
   {
 -      float t;
 -      t = 1.0 / g_weaponratefactor;
 +      float t = 1.0 / g_weaponratefactor;
   
 -      weapon_rate = t;
 -      MUTATOR_CALLHOOK(WeaponRateFactor);
 +      MUTATOR_CALLHOOK(WeaponRateFactor, t);
        t = weapon_rate;
   
        return t;
   
   float W_WeaponSpeedFactor()
   {
 -      float t;
 -      t = 1.0 * g_weaponspeedfactor;
 +      float t = 1.0 * g_weaponspeedfactor;
   
 -      ret_float = t;
 -      MUTATOR_CALLHOOK(WeaponSpeedFactor);
 +      MUTATOR_CALLHOOK(WeaponSpeedFactor, t);
        t = ret_float;
   
        return t;
@@@@ -472,11 -476,11 -472,11 +472,11 @@@@ float weapon_prepareattack_checkammo(fl
        {
                // always keep the Mine Layer if we placed mines, so that we can detonate them
                entity mine;
- -             if(self.weapon == WEP_MINE_LAYER)
+ +             if(self.weapon == WEP_MINE_LAYER.m_id)
                for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
                        return false;
   
- -             if(self.weapon == WEP_SHOTGUN)
+ +             if(self.weapon == WEP_SHOTGUN.m_id)
                if(!secondary && WEP_CVAR(shotgun, secondary) == 1)
                        return false; // no clicking, just allow
   
@@@@ -637,7 -641,7 -637,7 +637,7 @@@@ void weapon_thinkf(float fr, float t, v
   
        if((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
        {
- -             if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && fr == WFRAME_FIRE2)
+ +             if((self.weapon == WEP_SHOCKWAVE.m_id || self.weapon == WEP_SHOTGUN.m_id) && fr == WFRAME_FIRE2)
                        animdecide_setaction(self, ANIMACTION_MELEE, restartanim);
                else
                        animdecide_setaction(self, ANIMACTION_SHOOT, restartanim);