Merge branch 'master' into TimePath/unified_weapons
authorTimePath <andrew.hardaker1995@gmail.com>
Sat, 3 Oct 2015 08:29:19 +0000 (18:29 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Sat, 3 Oct 2015 08:29:38 +0000 (18:29 +1000)
# Conflicts:
# qcsrc/common/turrets/turret/ewheel.qc
# qcsrc/common/turrets/turret/hk_weapon.qc
# qcsrc/common/turrets/turret/walker.qc
# qcsrc/common/turrets/unit/flac.qc
# qcsrc/common/turrets/unit/fusionreactor.qc
# qcsrc/common/turrets/unit/hellion.qc
# qcsrc/common/turrets/unit/machinegun.qc
# qcsrc/common/turrets/unit/mlrs.qc
# qcsrc/common/turrets/unit/phaser.qc
# qcsrc/common/turrets/unit/plasma.qc
# qcsrc/common/turrets/unit/plasma_dual.qc
# qcsrc/common/turrets/unit/tesla.qc
# qcsrc/common/vehicles/vehicle/bumblebee.qc
# qcsrc/common/weapons/weapon/hook.qc
# qcsrc/common/weapons/weapon/vortex.qc
# qcsrc/server/mutators/mutator_overkill.qc

60 files changed:
1  2 
qcsrc/client/progs.inc
qcsrc/common/monsters/monster/mage.qc
qcsrc/common/monsters/monster/shambler.qc
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/monsters/monster/wyvern.qc
qcsrc/common/monsters/monster/zombie.qc
qcsrc/common/monsters/sv_monsters.qc
qcsrc/common/mutators/mutator/itemstime.qc
qcsrc/common/turrets/turret/ewheel.qc
qcsrc/common/turrets/turret/flac.qc
qcsrc/common/turrets/turret/fusionreactor.qc
qcsrc/common/turrets/turret/hellion.qc
qcsrc/common/turrets/turret/hk.qc
qcsrc/common/turrets/turret/machinegun.qc
qcsrc/common/turrets/turret/mlrs.qc
qcsrc/common/turrets/turret/phaser.qc
qcsrc/common/turrets/turret/plasma.qc
qcsrc/common/turrets/turret/plasma_dual.qc
qcsrc/common/turrets/turret/tesla.qc
qcsrc/common/turrets/turret/walker.qc
qcsrc/common/vehicles/vehicle/bumblebee.qc
qcsrc/common/vehicles/vehicle/racer.qc
qcsrc/common/vehicles/vehicle/raptor.qc
qcsrc/common/vehicles/vehicle/spiderbot.qc
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/blaster.qc
qcsrc/common/weapons/weapon/crylink.qc
qcsrc/common/weapons/weapon/devastator.qc
qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/fireball.qc
qcsrc/common/weapons/weapon/hagar.qc
qcsrc/common/weapons/weapon/hlac.qc
qcsrc/common/weapons/weapon/hmg.qc
qcsrc/common/weapons/weapon/hook.qc
qcsrc/common/weapons/weapon/machinegun.qc
qcsrc/common/weapons/weapon/minelayer.qc
qcsrc/common/weapons/weapon/mortar.qc
qcsrc/common/weapons/weapon/porto.qc
qcsrc/common/weapons/weapon/rifle.qc
qcsrc/common/weapons/weapon/rpc.qc
qcsrc/common/weapons/weapon/seeker.qc
qcsrc/common/weapons/weapon/shockwave.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/common/weapons/weapon/tuba.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/common/weapons/weapon/vortex.qc
qcsrc/server/autocvars.qh
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/cl_client.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/mutators/gamemode_invasion.qc
qcsrc/server/mutators/gamemode_nexball.qc
qcsrc/server/mutators/mutator_instagib.qc
qcsrc/server/mutators/mutator_overkill.qc
qcsrc/server/progs.inc
qcsrc/server/t_items.qc

Simple merge
Simple merge
@@@ -222,11 -211,15 +222,11 @@@ float M_Shambler_Attack(float attack_ty
        return false;
  }
  
void spawnfunc_monster_shambler() { Monster_Spawn(MON_SHAMBLER.monsterid); }
spawnfunc(monster_shambler) { Monster_Spawn(MON_SHAMBLER.monsterid); }
  #endif // SVQC
  
 -bool M_Shambler(int req)
 -{SELFPARAM();
 -      switch(req)
 -      {
                #ifdef SVQC
 -              case MR_THINK:
 +              METHOD(Shambler, mr_think, bool(Shambler thismon))
                {
                        return true;
                }
@@@ -171,11 -124,15 +171,11 @@@ bool M_Spider_Attack(int attack_type, e
        return false;
  }
  
void spawnfunc_monster_spider() { Monster_Spawn(MON_SPIDER.monsterid); }
spawnfunc(monster_spider) { Monster_Spawn(MON_SPIDER.monsterid); }
  #endif // SVQC
  
 -bool M_Spider(int req)
 -{SELFPARAM();
 -      switch(req)
 -      {
                #ifdef SVQC
 -              case MR_THINK:
 +              METHOD(Spider, mr_think, bool(Spider thismon))
                {
                        return true;
                }
@@@ -136,11 -101,15 +136,11 @@@ float M_Wyvern_Attack(float attack_type
        return false;
  }
  
void spawnfunc_monster_wyvern() { Monster_Spawn(MON_WYVERN.monsterid); }
spawnfunc(monster_wyvern) { Monster_Spawn(MON_WYVERN.monsterid); }
  #endif // SVQC
  
 -bool M_Wyvern(int req)
 -{SELFPARAM();
 -      switch(req)
 -      {
                #ifdef SVQC
 -              case MR_THINK:
 +              METHOD(Wyvern, mr_think, bool(Wyvern thismon))
                {
                        return true;
                }
@@@ -149,13 -138,16 +149,13 @@@ float M_Zombie_Attack(float attack_type
        return false;
  }
  
void spawnfunc_monster_zombie() { Monster_Spawn(MON_ZOMBIE.monsterid); }
spawnfunc(monster_zombie) { Monster_Spawn(MON_ZOMBIE.monsterid); }
  #endif // SVQC
  
 -bool M_Zombie(int req)
 -{SELFPARAM();
 -      switch(req)
 -      {
                #ifdef SVQC
 -              case MR_THINK:
 +              METHOD(Zombie, mr_think, bool(Zombie thismon))
                {
 +                      SELFPARAM();
                        if(time >= self.spawn_time)
                                self.damageforcescale = autocvar_g_monster_zombie_damageforcescale;
                        return true;
Simple merge
index 6dab617,0000000..cdb9a60
mode 100644,000000..100644
--- /dev/null
@@@ -1,270 -1,0 +1,270 @@@
- void spawnfunc_turret_ewheel() { SELFPARAM(); if(!turret_initialize(TUR_EWHEEL)) remove(self); }
 +#ifndef TURRET_EWHEEL_H
 +#define TURRET_EWHEEL_H
 +
 +//#define EWHEEL_FANCYPATH
 +
 +#include "ewheel_weapon.qc"
 +
 +CLASS(EWheel, Turret)
 +/* spawnflags */ ATTRIB(EWheel, spawnflags, int, TUR_FLAG_PLAYER | TUR_FLAG_MOVE | TUR_FLAG_ROAM);
 +/* mins       */ ATTRIB(EWheel, mins, vector, '-32 -32 0');
 +/* maxs       */ ATTRIB(EWheel, maxs, vector, '32 32 48');
 +/* modelname  */ ATTRIB(EWheel, mdl, string, "ewheel-base2.md3");
 +/* model      */ ATTRIB(EWheel, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(EWheel, head_model, string, strzone(strcat("models/turrets/", "ewheel-gun1.md3")));
 +/* netname    */ ATTRIB(EWheel, netname, string, "ewheel");
 +/* fullname   */ ATTRIB(EWheel, turret_name, string, _("eWheel Turret"));
 +    ATTRIB(EWheel, m_weapon, Weapon, WEP_EWHEEL);
 +ENDCLASS(EWheel)
 +REGISTER_TURRET(EWHEEL, NEW(EWheel));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "ewheel_weapon.qc"
 +
 +#ifdef SVQC
 +
 +float autocvar_g_turrets_unit_ewheel_speed_fast;
 +float autocvar_g_turrets_unit_ewheel_speed_slow;
 +float autocvar_g_turrets_unit_ewheel_speed_slower;
 +float autocvar_g_turrets_unit_ewheel_speed_stop;
 +float autocvar_g_turrets_unit_ewheel_turnrate;
 +
 +const float ewheel_anim_stop = 0;
 +const float ewheel_anim_fwd_slow = 1;
 +const float ewheel_anim_fwd_fast = 2;
 +const float ewheel_anim_bck_slow = 3;
 +const float ewheel_anim_bck_fast = 4;
 +
 +void ewheel_move_path()
 +{SELFPARAM();
 +#ifdef EWHEEL_FANCYPATH
 +    // Are we close enougth to a path node to switch to the next?
 +    if (vlen(self.origin  - self.pathcurrent.origin) < 64)
 +        if (self.pathcurrent.path_next == world)
 +        {
 +            // Path endpoint reached
 +            pathlib_deletepath(self.pathcurrent.owner);
 +            self.pathcurrent = world;
 +
 +            if (self.pathgoal)
 +            {
 +                if (self.pathgoal.use)
 +                    self.pathgoal.use();
 +
 +                if (self.pathgoal.enemy)
 +                {
 +                    self.pathcurrent = pathlib_astar(self.pathgoal.origin,self.pathgoal.enemy.origin);
 +                    self.pathgoal = self.pathgoal.enemy;
 +                }
 +            }
 +            else
 +                self.pathgoal = world;
 +        }
 +        else
 +            self.pathcurrent = self.pathcurrent.path_next;
 +
 +#else
 +    if (vlen(self.origin - self.pathcurrent.origin) < 64)
 +        self.pathcurrent = self.pathcurrent.enemy;
 +#endif
 +
 +    if (self.pathcurrent)
 +    {
 +
 +        self.moveto = self.pathcurrent.origin;
 +        self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
 +
 +        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
 +    }
 +}
 +
 +void ewheel_move_enemy()
 +{SELFPARAM();
 +    float newframe;
 +
 +    self.steerto = steerlib_arrive(self.enemy.origin,self.target_range_optimal);
 +
 +    self.moveto  = self.origin + self.steerto * 128;
 +
 +    if (self.tur_dist_enemy > self.target_range_optimal)
 +    {
 +        if ( self.tur_head.spawnshieldtime < 1 )
 +        {
 +            newframe = ewheel_anim_fwd_fast;
 +            movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_fast), 0.4);
 +        }
 +        else if (self.tur_head.spawnshieldtime < 2)
 +        {
 +
 +            newframe = ewheel_anim_fwd_slow;
 +            movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
 +       }
 +        else
 +        {
 +            newframe = ewheel_anim_fwd_slow;
 +            movelib_move_simple(v_forward, (autocvar_g_turrets_unit_ewheel_speed_slower), 0.4);
 +        }
 +    }
 +    else if (self.tur_dist_enemy < self.target_range_optimal * 0.5)
 +    {
 +        newframe = ewheel_anim_bck_slow;
 +        movelib_move_simple(v_forward * -1, (autocvar_g_turrets_unit_ewheel_speed_slow), 0.4);
 +    }
 +    else
 +    {
 +        newframe = ewheel_anim_stop;
 +        movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
 +    }
 +
 +    turrets_setframe(newframe, false);
 +}
 +
 +void ewheel_move_idle()
 +{SELFPARAM();
 +    if(self.frame != 0)
 +    {
 +        self.SendFlags |= TNSF_ANIM;
 +        self.anim_start_time = time;
 +    }
 +
 +    self.frame = 0;
 +    if (vlen(self.velocity))
 +        movelib_beak_simple((autocvar_g_turrets_unit_ewheel_speed_stop));
 +}
 +
++spawnfunc(turret_ewheel) { if(!turret_initialize(TUR_EWHEEL)) remove(self); }
 +
 +        METHOD(EWheel, tr_think, void(EWheel thistur))
 +        {
 +            SELFPARAM();
 +            float vz;
 +            vector wish_angle, real_angle;
 +
 +            vz = self.velocity_z;
 +
 +            self.angles_x = anglemods(self.angles_x);
 +            self.angles_y = anglemods(self.angles_y);
 +
 +            fixedmakevectors(self.angles);
 +
 +            wish_angle = normalize(self.steerto);
 +            wish_angle = vectoangles(wish_angle);
 +            real_angle = wish_angle - self.angles;
 +            real_angle = shortangle_vxy(real_angle, self.tur_head.angles);
 +
 +            self.tur_head.spawnshieldtime = fabs(real_angle_y);
 +            real_angle_y  = bound(-self.tur_head.aim_speed, real_angle_y, self.tur_head.aim_speed);
 +            self.angles_y = (self.angles_y + real_angle_y);
 +
 +            if(self.enemy)
 +                ewheel_move_enemy();
 +            else if(self.pathcurrent)
 +                ewheel_move_path();
 +            else
 +                ewheel_move_idle();
 +
 +            self.velocity_z = vz;
 +
 +            if(vlen(self.velocity))
 +                self.SendFlags |= TNSF_MOVE;
 +        }
 +        METHOD(EWheel, tr_death, void(EWheel this, entity it))
 +        {
 +            it.velocity = '0 0 0';
 +
 +#ifdef EWHEEL_FANCYPATH
 +            if (self.pathcurrent)
 +                pathlib_deletepath(it.pathcurrent.owner);
 +#endif
 +            it.pathcurrent = NULL;
 +        }
 +        METHOD(EWheel, tr_setup, void(EWheel this, entity it))
 +        {
 +            entity e;
 +
 +            if(it.movetype == MOVETYPE_WALK)
 +            {
 +                it.velocity = '0 0 0';
 +                it.enemy = world;
 +
 +                setorigin(it, it.pos1);
 +
 +                if (it.target != "")
 +                {
 +                    e = find(world, targetname, it.target);
 +                    if (!e)
 +                    {
 +                        LOG_TRACE("Initital waypoint for ewheel does NOT exsist, fix your map!\n");
 +                        it.target = "";
 +                    }
 +
 +                    if (e.classname != "turret_checkpoint")
 +                        LOG_TRACE("Warning: not a turrret path\n");
 +                    else
 +                    {
 +
 +#ifdef EWHEEL_FANCYPATH
 +                        it.pathcurrent = WALKER_PATH(it.origin,e.origin);
 +                        it.pathgoal = e;
 +#else
 +                        it.pathcurrent  = e;
 +#endif
 +                    }
 +                }
 +            }
 +
 +            it.iscreature                             = true;
 +            it.teleportable                   = TELEPORT_NORMAL;
 +            it.damagedbycontents              = true;
 +            it.movetype                               = MOVETYPE_WALK;
 +            it.solid                                  = SOLID_SLIDEBOX;
 +            it.takedamage                             = DAMAGE_AIM;
 +            it.idle_aim                               = '0 0 0';
 +            it.pos1                                   = it.origin;
 +            it.target_select_flags    = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
 +            it.target_validate_flags  = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
 +            it.frame                                  = it.tur_head.frame = 1;
 +            it.ammo_flags                             = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
 +
 +            // Convert from dgr / sec to dgr / tic
 +            it.tur_head.aim_speed = (autocvar_g_turrets_unit_ewheel_turnrate);
 +            it.tur_head.aim_speed = it.tur_head.aim_speed / (1 / it.ticrate);
 +        }
 +
 +#endif // SVQC
 +#ifdef CSQC
 +
 +void ewheel_draw()
 +{SELFPARAM();
 +    float dt;
 +
 +    dt = time - self.move_time;
 +    self.move_time = time;
 +    if(dt <= 0)
 +        return;
 +
 +    fixedmakevectors(self.angles);
 +    setorigin(self, self.origin + self.velocity * dt);
 +    self.tur_head.angles += dt * self.tur_head.move_avelocity;
 +    self.angles_y = self.move_angles_y;
 +
 +    if (self.health < 127)
 +    if(random() < 0.05)
 +        te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
 +}
 +
 +        METHOD(EWheel, tr_setup, void(EWheel this, entity it))
 +        {
 +            it.gravity                = 1;
 +            it.movetype               = MOVETYPE_BOUNCE;
 +            it.move_movetype  = MOVETYPE_BOUNCE;
 +            it.move_origin    = it.origin;
 +            it.move_time              = time;
 +            it.draw                   = ewheel_draw;
 +        }
 +
 +#endif // CSQC
 +#endif
index a2de5ca,0000000..1c9122f
mode 100644,000000..100644
--- /dev/null
@@@ -1,39 -1,0 +1,39 @@@
- void spawnfunc_turret_flac() { SELFPARAM(); if (!turret_initialize(TUR_FLAC)) remove(self); }
 +#ifndef TURRET_FLAC_H
 +#define TURRET_FLAC_H
 +
 +#include "flac_weapon.qc"
 +
 +CLASS(Flac, Turret)
 +/* spawnflags */ ATTRIB(Flac, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_MISSILE);
 +/* mins       */ ATTRIB(Flac, mins, vector, '-32 -32 0');
 +/* maxs       */ ATTRIB(Flac, maxs, vector, '32 32 64');
 +/* modelname  */ ATTRIB(Flac, mdl, string, "base.md3");
 +/* model      */ ATTRIB(Flac, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(Flac, head_model, string, strzone(strcat("models/turrets/", "flac.md3")));
 +/* netname    */ ATTRIB(Flac, netname, string, "flac");
 +/* fullname   */ ATTRIB(Flac, turret_name, string, _("FLAC Cannon"));
 +    ATTRIB(Flac, m_weapon, Weapon, WEP_FLAC);
 +ENDCLASS(Flac)
 +REGISTER_TURRET(FLAC, NEW(Flac));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "flac_weapon.qc"
 +
 +#ifdef SVQC
 +
++spawnfunc(turret_flac) { if (!turret_initialize(TUR_FLAC)) remove(self); }
 +
 +METHOD(Flac, tr_setup, void(Flac this, entity it))
 +{
 +    it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
 +    it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
 +    it.damage_flags |= TFL_DMG_HEADSHAKE;
 +    it.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
 +}
 +
 +#endif
 +
 +#endif
index fcd6113,0000000..1077d5c
mode 100644,000000..100644
--- /dev/null
@@@ -1,77 -1,0 +1,77 @@@
- void spawnfunc_turret_fusionreactor() { SELFPARAM(); if (!turret_initialize(TUR_FUSIONREACTOR)) remove(self); }
 +#ifndef TURRET_FUSIONREACTOR_H
 +#define TURRET_FUSIONREACTOR_H
 +
 +CLASS(FusionReactor, Turret)
 +/* spawnflags */ ATTRIB(FusionReactor, spawnflags, int, TUR_FLAG_SUPPORT | TUR_FLAG_AMMOSOURCE);
 +/* mins       */ ATTRIB(FusionReactor, mins, vector, '-34 -34 0');
 +/* maxs       */ ATTRIB(FusionReactor, maxs, vector, '34 34 90');
 +/* modelname  */ ATTRIB(FusionReactor, mdl, string, "base.md3");
 +/* model      */ ATTRIB(FusionReactor, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(FusionReactor, head_model, string, strzone(strcat("models/turrets/", "reactor.md3")));
 +/* netname    */ ATTRIB(FusionReactor, netname, string, "fusionreactor");
 +/* fullname   */ ATTRIB(FusionReactor, turret_name, string, _("Fusion Reactor"));
 +ENDCLASS(FusionReactor)
 +REGISTER_TURRET(FUSIONREACTOR, NEW(FusionReactor));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +#ifdef SVQC
 +bool turret_fusionreactor_firecheck()
 +{SELFPARAM();
 +    if (self.attack_finished_single > time)
 +        return false;
 +
 +    if (self.enemy.deadflag != DEAD_NO)
 +        return false;
 +
 +    if (self.enemy == world)
 +        return false;
 +
 +    if (self.ammo < self.shot_dmg)
 +        return false;
 +
 +    if (self.enemy.ammo >= self.enemy.ammo_max)
 +        return false;
 +
 +    if (vlen(self.enemy.origin - self.origin) > self.target_range)
 +        return false;
 +
 +    if(self.team != self.enemy.team)
 +        return false;
 +
 +    if(!(self.enemy.ammo_flags & TFL_AMMO_ENERGY))
 +        return false;
 +
 +    return true;
 +}
 +
++spawnfunc(turret_fusionreactor) { if (!turret_initialize(TUR_FUSIONREACTOR)) remove(self); }
 +
 +METHOD(FusionReactor, tr_attack, void(FusionReactor this))
 +{
 +    self.enemy.ammo = min(self.enemy.ammo + self.shot_dmg,self.enemy.ammo_max);
 +    vector fl_org = 0.5 * (self.enemy.absmin + self.enemy.absmax);
 +    te_smallflash(fl_org);
 +}
 +METHOD(FusionReactor, tr_think, void(FusionReactor thistur))
 +{
 +    self.tur_head.avelocity = '0 250 0' * (self.ammo / self.ammo_max);
 +}
 +METHOD(FusionReactor, tr_setup, void(FusionReactor this, entity it))
 +{
 +    it.ammo_flags                             = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE;
 +    it.target_select_flags    = TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_OWNTEAM | TFL_TARGETSELECT_RANGELIMITS;
 +    it.firecheck_flags                = TFL_FIRECHECK_AMMO_OWN | TFL_FIRECHECK_AMMO_OTHER | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_DEAD;
 +    it.shoot_flags                    = TFL_SHOOT_HITALLVALID;
 +    it.aim_flags                              = TFL_AIM_NO;
 +    it.track_flags                    = TFL_TRACK_NO;
 +
 +    it.tur_head.scale = 0.75;
 +    it.tur_head.avelocity = '0 50 0';
 +
 +    it.turret_firecheckfunc = turret_fusionreactor_firecheck;
 +}
 +
 +#endif
 +#endif
index f2c6f7f,0000000..203be93
mode 100644,000000..100644
--- /dev/null
@@@ -1,46 -1,0 +1,46 @@@
- void spawnfunc_turret_hellion() { SELFPARAM(); if (!turret_initialize(TUR_HELLION)) remove(self); }
 +#ifndef TURRET_HELLION_H
 +#define TURRET_HELLION_H
 +
 +#include "hellion_weapon.qc"
 +
 +CLASS(Hellion, Turret)
 +/* spawnflags */ ATTRIB(Hellion, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_FASTPROJ | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE);
 +/* mins       */ ATTRIB(Hellion, mins, vector, '-32 -32 0');
 +/* maxs       */ ATTRIB(Hellion, maxs, vector, '32 32 64');
 +/* modelname  */ ATTRIB(Hellion, mdl, string, "base.md3");
 +/* model      */ ATTRIB(Hellion, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(Hellion, head_model, string, strzone(strcat("models/turrets/", "hellion.md3")));
 +/* netname    */ ATTRIB(Hellion, netname, string, "hellion");
 +/* fullname   */ ATTRIB(Hellion, turret_name, string, _("Hellion Missile Turret"));
 +    ATTRIB(Hellion, m_weapon, Weapon, WEP_HELLION);
 +ENDCLASS(Hellion)
 +REGISTER_TURRET(HELLION, NEW(Hellion));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "hellion_weapon.qc"
 +
 +#ifdef SVQC
 +
++spawnfunc(turret_hellion) { if (!turret_initialize(TUR_HELLION)) remove(self); }
 +
 +METHOD(Hellion, tr_think, void(Hellion thistur))
 +{
 +    if (self.tur_head.frame != 0)
 +        self.tur_head.frame += 1;
 +
 +    if (self.tur_head.frame >= 7)
 +        self.tur_head.frame = 0;
 +}
 +METHOD(Hellion, tr_setup, void(Hellion this, entity it))
 +{
 +    it.aim_flags = TFL_AIM_SIMPLE;
 +    it.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK ;
 +    it.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES | TFL_FIRECHECK_TEAMCHECK | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF | TFL_FIRECHECK_AMMO_OWN;
 +    it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
 +}
 +
 +#endif
 +#endif
index 0d7dc6d,0000000..61d8318
mode 100644,000000..100644
--- /dev/null
@@@ -1,72 -1,0 +1,72 @@@
- void spawnfunc_turret_hk() { SELFPARAM(); if(!turret_initialize(TUR_HK)) remove(self); }
 +#ifndef TURRET_HK_H
 +#define TURRET_HK_H
 +
 +//#define TURRET_DEBUG_HK
 +
 +#include "hk_weapon.qc"
 +
 +CLASS(HunterKiller, Turret)
 +/* spawnflags */ ATTRIB(HunterKiller, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER | TUR_FLAG_RECIEVETARGETS);
 +/* mins       */ ATTRIB(HunterKiller, mins, vector, '-32 -32 0');
 +/* maxs       */ ATTRIB(HunterKiller, maxs, vector, '32 32 64');
 +/* modelname  */ ATTRIB(HunterKiller, mdl, string, "base.md3");
 +/* model      */ ATTRIB(HunterKiller, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(HunterKiller, head_model, string, strzone(strcat("models/turrets/", "hk.md3")));
 +/* netname    */ ATTRIB(HunterKiller, netname, string, "hk");
 +/* fullname   */ ATTRIB(HunterKiller, turret_name, string, _("Hunter-Killer Turret"));
 +    ATTRIB(HunterKiller, m_weapon, Weapon, WEP_HK);
 +ENDCLASS(HunterKiller)
 +REGISTER_TURRET(HK, NEW(HunterKiller));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "hk_weapon.qc"
 +
 +#ifdef SVQC
 +
 +#ifdef TURRET_DEBUG_HK
 +.float atime;
 +#endif
 +
++spawnfunc(turret_hk) { if(!turret_initialize(TUR_HK)) remove(self); }
 +
 +METHOD(HunterKiller, tr_think, void(HunterKiller thistur))
 +{
 +    if (self.tur_head.frame != 0)
 +        self.tur_head.frame = self.tur_head.frame + 1;
 +
 +    if (self.tur_head.frame > 5)
 +        self.tur_head.frame = 0;
 +}
 +
 +float turret_hk_addtarget(entity e_target,entity e_sender);
 +METHOD(HunterKiller, tr_setup, void(HunterKiller this, entity it))
 +{
 +    it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
 +    it.aim_flags = TFL_AIM_SIMPLE;
 +    it.target_select_flags = TFL_TARGETSELECT_LOS | TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TRIGGERTARGET | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
 +    it.firecheck_flags = TFL_FIRECHECK_DEAD | TFL_FIRECHECK_TEAMCHECK  | TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AFF;
 +    it.shoot_flags = TFL_SHOOT_CLEARTARGET;
 +    it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
 +
 +    it.turret_addtarget = turret_hk_addtarget;
 +}
 +
 +float turret_hk_addtarget(entity e_target,entity e_sender)
 +{SELFPARAM();
 +    if (e_target)
 +    {
 +        if (turret_validate_target(self,e_target,self.target_validate_flags) > 0)
 +        {
 +            self.enemy = e_target;
 +            return 1;
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +#endif // SVQC
 +#endif
index 8fc1f42,0000000..9911b97
mode 100644,000000..100644
--- /dev/null
@@@ -1,39 -1,0 +1,39 @@@
- void spawnfunc_turret_machinegun() { SELFPARAM(); if (!turret_initialize(TUR_MACHINEGUN)) remove(self); }
 +#ifndef TURRET_MACHINEGUN_H
 +#define TURRET_MACHINEGUN_H
 +
 +#include "machinegun_weapon.qc"
 +
 +CLASS(MachineGunTurret, Turret)
 +/* spawnflags */ ATTRIB(MachineGunTurret, spawnflags, int, TUR_FLAG_PLAYER);
 +/* mins       */ ATTRIB(MachineGunTurret, mins, vector, '-32 -32 0');
 +/* maxs       */ ATTRIB(MachineGunTurret, maxs, vector, '32 32 64');
 +/* modelname  */ ATTRIB(MachineGunTurret, mdl, string, "base.md3");
 +/* model      */ ATTRIB(MachineGunTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(MachineGunTurret, head_model, string, strzone(strcat("models/turrets/", "machinegun.md3")));
 +/* netname    */ ATTRIB(MachineGunTurret, netname, string, "machinegun");
 +/* fullname   */ ATTRIB(MachineGunTurret, turret_name, string, _("Machinegun Turret"));
 +    ATTRIB(MachineGunTurret, m_weapon, Weapon, WEP_TUR_MACHINEGUN);
 +ENDCLASS(MachineGunTurret)
 +REGISTER_TURRET(MACHINEGUN, NEW(MachineGunTurret));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "machinegun_weapon.qc"
 +
 +#ifdef SVQC
 +
++spawnfunc(turret_machinegun) { if (!turret_initialize(TUR_MACHINEGUN)) remove(self); }
 +
 +METHOD(MachineGunTurret, tr_setup, void(MachineGunTurret this, entity it))
 +{
 +    it.damage_flags |= TFL_DMG_HEADSHAKE;
 +    it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
 +    it.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
 +    it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
 +    it.turret_flags |= TUR_FLAG_HITSCAN;
 +}
 +
 +#endif // SVQC
 +#endif
index 7920c1a,0000000..ae2d1d4
mode 100644,000000..100644
--- /dev/null
@@@ -1,50 -1,0 +1,50 @@@
- void spawnfunc_turret_mlrs() { SELFPARAM(); if (!turret_initialize(TUR_MLRS)) remove(self); }
 +#ifndef TURRET_MLRS_H
 +#define TURRET_MLRS_H
 +
 +#include "mlrs_weapon.qc"
 +
 +CLASS(MLRSTurret, Turret)
 +/* spawnflags */ ATTRIB(MLRSTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER);
 +/* mins       */ ATTRIB(MLRSTurret, mins, vector, '-32 -32 0');
 +/* maxs       */ ATTRIB(MLRSTurret, maxs, vector, '32 32 64');
 +/* modelname  */ ATTRIB(MLRSTurret, mdl, string, "base.md3");
 +/* model      */ ATTRIB(MLRSTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(MLRSTurret, head_model, string, strzone(strcat("models/turrets/", "mlrs.md3")));
 +/* netname    */ ATTRIB(MLRSTurret, netname, string, "mlrs");
 +/* fullname   */ ATTRIB(MLRSTurret, turret_name, string, _("MLRS Turret"));
 +    ATTRIB(MLRSTurret, m_weapon, Weapon, WEP_TUR_MLRS);
 +ENDCLASS(MLRSTurret)
 +REGISTER_TURRET(MLRS, NEW(MLRSTurret));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "mlrs_weapon.qc"
 +
 +#ifdef SVQC
 +
++spawnfunc(turret_mlrs) { if (!turret_initialize(TUR_MLRS)) remove(self); }
 +
 +METHOD(MLRSTurret, tr_think, void(MLRSTurret thistur))
 +{
 +    // 0 = full, 6 = empty
 +    self.tur_head.frame = bound(0, 6 - floor(0.1 + self.ammo / self.shot_dmg), 6);
 +    if(self.tur_head.frame < 0)
 +    {
 +        LOG_TRACE("ammo:",ftos(self.ammo),"\n");
 +        LOG_TRACE("shot_dmg:",ftos(self.shot_dmg),"\n");
 +    }
 +}
 +METHOD(MLRSTurret, tr_setup, void(MLRSTurret this, entity it))
 +{
 +    it.ammo_flags = TFL_AMMO_ROCKETS | TFL_AMMO_RECHARGE;
 +    it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
 +
 +    it.damage_flags |= TFL_DMG_HEADSHAKE;
 +    it.shoot_flags  |= TFL_SHOOT_VOLLYALWAYS;
 +    it.volly_counter = it.shot_volly;
 +}
 +
 +#endif // SVQC
 +#endif
index 7fcb013,0000000..24d4d30
mode 100644,000000..100644
--- /dev/null
@@@ -1,67 -1,0 +1,67 @@@
- void spawnfunc_turret_phaser() { SELFPARAM(); if (!turret_initialize(TUR_PHASER)) remove(self); }
 +#ifndef TURRET_PHASER_H
 +#define TURRET_PHASER_H
 +
 +#include "phaser_weapon.qc"
 +
 +CLASS(PhaserTurret, Turret)
 +/* spawnflags */ ATTRIB(PhaserTurret, spawnflags, int, TUR_FLAG_SNIPER | TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER);
 +/* mins       */ ATTRIB(PhaserTurret, mins, vector, '-32 -32 0');
 +/* maxs       */ ATTRIB(PhaserTurret, maxs, vector, '32 32 64');
 +/* modelname  */ ATTRIB(PhaserTurret, mdl, string, "base.md3");
 +/* model      */ ATTRIB(PhaserTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(PhaserTurret, head_model, string, strzone(strcat("models/turrets/", "phaser.md3")));
 +/* netname    */ ATTRIB(PhaserTurret, netname, string, "phaser");
 +/* fullname   */ ATTRIB(PhaserTurret, turret_name, string, _("Phaser Cannon"));
 +    ATTRIB(PhaserTurret, m_weapon, Weapon, WEP_PHASER);
 +ENDCLASS(PhaserTurret)
 +REGISTER_TURRET(PHASER, NEW(PhaserTurret));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "phaser_weapon.qc"
 +
 +#ifdef SVQC
 +
++spawnfunc(turret_phaser) { if (!turret_initialize(TUR_PHASER)) remove(self); }
 +
 +METHOD(PhaserTurret, tr_think, void(PhaserTurret thistur))
 +{
 +    if (self.tur_head.frame != 0)
 +    {
 +        if (self.fireflag == 1)
 +        {
 +            if (self.tur_head.frame == 10)
 +                self.tur_head.frame = 1;
 +            else
 +                self.tur_head.frame = self.tur_head.frame +1;
 +        }
 +        else if (self.fireflag == 2 )
 +        {
 +            self.tur_head.frame = self.tur_head.frame +1;
 +            if (self.tur_head.frame == 15)
 +            {
 +                self.tur_head.frame = 0;
 +                self.fireflag = 0;
 +            }
 +        }
 +    }
 +}
 +float turret_phaser_firecheck();
 +METHOD(PhaserTurret, tr_setup, void(PhaserTurret this, entity it))
 +{
 +    it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
 +    it.aim_flags = TFL_AIM_LEAD;
 +
 +    it.turret_firecheckfunc = turret_phaser_firecheck;
 +}
 +float turret_phaser_firecheck()
 +{
 +    SELFPARAM();
 +    if (self.fireflag != 0) return 0;
 +    return turret_firecheck();
 +}
 +
 +#endif
 +#endif
index 04f81cb,0000000..7c40299
mode 100644,000000..100644
--- /dev/null
@@@ -1,68 -1,0 +1,68 @@@
- void spawnfunc_turret_plasma() { SELFPARAM(); if (!turret_initialize(TUR_PLASMA)) remove(self); }
 +#ifndef TURRET_PLASMA_H
 +#define TURRET_PLASMA_H
 +
 +#include "plasma_weapon.qc"
 +
 +CLASS(PlasmaTurret, Turret)
 +/* spawnflags */ ATTRIB(PlasmaTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER);
 +/* mins       */ ATTRIB(PlasmaTurret, mins, vector, '-32 -32 0');
 +/* maxs       */ ATTRIB(PlasmaTurret, maxs, vector, '32 32 64');
 +/* modelname  */ ATTRIB(PlasmaTurret, mdl, string, "base.md3");
 +/* model      */ ATTRIB(PlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(PlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasma.md3")));
 +/* netname    */ ATTRIB(PlasmaTurret, netname, string, "plasma");
 +/* fullname   */ ATTRIB(PlasmaTurret, turret_name, string, _("Plasma Cannon"));
 +    ATTRIB(PlasmaTurret, m_weapon, Weapon, WEP_PLASMA);
 +ENDCLASS(PlasmaTurret)
 +REGISTER_TURRET(PLASMA, NEW(PlasmaTurret));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "plasma_weapon.qc"
 +
 +#ifdef SVQC
 +
++spawnfunc(turret_plasma) { if (!turret_initialize(TUR_PLASMA)) remove(self); }
 +
 +METHOD(PlasmaTurret, tr_attack, void(PlasmaTurret this))
 +{
 +    if(g_instagib)
 +    {
 +        FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
 +                           800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
 +
 +        Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
 +
 +        // teamcolor / hit beam effect
 +        vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
 +        WarpZone_TrailParticles(world, particleeffectnum(EFFECT_VAPORIZER(self.team)), self.tur_shotorg, v);
 +    }
 +    else
 +    {
 +        super.tr_attack(this);
 +    }
 +    if (self.tur_head.frame == 0)
 +        self.tur_head.frame = 1;
 +}
 +METHOD(PlasmaTurret, tr_think, void(PlasmaTurret thistur))
 +{
 +    if (self.tur_head.frame != 0)
 +        self.tur_head.frame = self.tur_head.frame + 1;
 +
 +    if (self.tur_head.frame > 5)
 +        self.tur_head.frame = 0;
 +}
 +METHOD(PlasmaTurret, tr_setup, void(PlasmaTurret this, entity it))
 +{
 +    it.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
 +    it.damage_flags |= TFL_DMG_HEADSHAKE;
 +    it.firecheck_flags |= TFL_FIRECHECK_AFF;
 +    it.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE | TFL_AIM_SPLASH;
 +
 +    turret_do_updates(it);
 +}
 +
 +#endif
 +#endif
index faac00d,0000000..e1143bc
mode 100644,000000..100644
--- /dev/null
@@@ -1,58 -1,0 +1,58 @@@
- void spawnfunc_turret_plasma_dual() { SELFPARAM(); if (!turret_initialize(TUR_PLASMA_DUAL)) remove(self); }
 +#ifndef TURRET_PLASMA_DUAL_H
 +#define TURRET_PLASMA_DUAL_H
 +
 +CLASS(PlasmaDualAttack, PlasmaAttack)
 +/* refname   */ ATTRIB(PlasmaDualAttack, netname, string, "turret_plasma_dual");
 +/* wepname   */ ATTRIB(PlasmaDualAttack, message, string, _("Dual plasma"));
 +ENDCLASS(PlasmaDualAttack)
 +REGISTER_WEAPON(PLASMA_DUAL, NEW(PlasmaDualAttack));
 +
 +CLASS(DualPlasmaTurret, PlasmaTurret)
 +/* spawnflags */ ATTRIB(DualPlasmaTurret, spawnflags, int, TUR_FLAG_SPLASH | TUR_FLAG_MEDPROJ | TUR_FLAG_PLAYER);
 +/* mins       */ ATTRIB(DualPlasmaTurret, mins, vector, '-32 -32 0');
 +/* maxs       */ ATTRIB(DualPlasmaTurret, maxs, vector, '32 32 64');
 +/* modelname  */ ATTRIB(DualPlasmaTurret, mdl, string, "base.md3");
 +/* model      */ ATTRIB(DualPlasmaTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(DualPlasmaTurret, head_model, string, strzone(strcat("models/turrets/", "plasmad.md3")));
 +/* netname    */ ATTRIB(DualPlasmaTurret, netname, string, "plasma_dual");
 +/* fullname   */ ATTRIB(DualPlasmaTurret, turret_name, string, _("Dual Plasma Cannon"));
 +    ATTRIB(DualPlasmaTurret, m_weapon, Weapon, WEP_PLASMA_DUAL);
 +ENDCLASS(DualPlasmaTurret)
 +REGISTER_TURRET(PLASMA_DUAL, NEW(DualPlasmaTurret));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#ifdef SVQC
 +
++spawnfunc(turret_plasma_dual) { if (!turret_initialize(TUR_PLASMA_DUAL)) remove(self); }
 +
 +METHOD(DualPlasmaTurret, tr_attack, void(DualPlasmaTurret this))
 +{
 +    if (g_instagib) {
 +        FireRailgunBullet (self.tur_shotorg, self.tur_shotorg + self.tur_shotdir_updated * MAX_SHOT_DISTANCE, 10000000000,
 +                           800, 0, 0, 0, 0, DEATH_TURRET_PLASMA);
 +
 +
 +        Send_Effect(EFFECT_VORTEX_MUZZLEFLASH, self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
 +
 +        // teamcolor / hit beam effect
 +        vector v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
 +        WarpZone_TrailParticles(world, particleeffectnum(EFFECT_VAPORIZER(self.team)), self.tur_shotorg, v);
 +    } else {
 +        super.vtblbase.tr_attack(this);
 +    }
 +    self.tur_head.frame += 1;
 +}
 +METHOD(DualPlasmaTurret, tr_think, void(DualPlasmaTurret thistur))
 +{
 +    if ((self.tur_head.frame != 0) && (self.tur_head.frame != 3))
 +        self.tur_head.frame = self.tur_head.frame + 1;
 +
 +    if (self.tur_head.frame > 6)
 +        self.tur_head.frame = 0;
 +}
 +
 +#endif
 +#endif
index 65733a8,0000000..3ae039c
mode 100644,000000..100644
--- /dev/null
@@@ -1,111 -1,0 +1,111 @@@
- void spawnfunc_turret_tesla() { SELFPARAM(); if (!turret_initialize(TUR_TESLA)) remove(self); }
 +#ifndef TURRET_TESLA_H
 +#define TURRET_TESLA_H
 +
 +#include "tesla_weapon.qc"
 +
 +CLASS(TeslaCoil, Turret)
 +/* spawnflags */ ATTRIB(TeslaCoil, spawnflags, int, TUR_FLAG_HITSCAN | TUR_FLAG_PLAYER | TUR_FLAG_MISSILE);
 +/* mins       */ ATTRIB(TeslaCoil, mins, vector, '-60 -60 0');
 +/* maxs       */ ATTRIB(TeslaCoil, maxs, vector, '60 60 128');
 +/* modelname  */ ATTRIB(TeslaCoil, mdl, string, "tesla_base.md3");
 +/* model      */ ATTRIB(TeslaCoil, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(TeslaCoil, head_model, string, strzone(strcat("models/turrets/", "tesla_head.md3")));
 +/* netname    */ ATTRIB(TeslaCoil, netname, string, "tesla");
 +/* fullname   */ ATTRIB(TeslaCoil, turret_name, string, _("Tesla Coil"));
 +    ATTRIB(TeslaCoil, m_weapon, Weapon, WEP_TESLA);
 +ENDCLASS(TeslaCoil)
 +REGISTER_TURRET(TESLA, NEW(TeslaCoil));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "tesla_weapon.qc"
 +
 +#ifdef SVQC
 +
++spawnfunc(turret_tesla) { if (!turret_initialize(TUR_TESLA)) remove(self); }
 +
 +METHOD(TeslaCoil, tr_think, void(TeslaCoil thistur))
 +{
 +    if(!self.active)
 +    {
 +        self.tur_head.avelocity = '0 0 0';
 +        return;
 +    }
 +
 +    if(self.ammo < self.shot_dmg)
 +    {
 +        self.tur_head.avelocity = '0 45 0' * (self.ammo / self.shot_dmg);
 +    }
 +    else
 +    {
 +        self.tur_head.avelocity = '0 180 0' * (self.ammo / self.shot_dmg);
 +
 +        if(self.attack_finished_single > time)
 +            return;
 +
 +        float f;
 +        f = (self.ammo / self.ammo_max);
 +        f = f * f;
 +        if(f > random())
 +            if(random() < 0.1)
 +                te_csqc_lightningarc(self.tur_shotorg,self.tur_shotorg + (randomvec() * 350));
 +    }
 +}
 +
 +float turret_tesla_firecheck();
 +METHOD(TeslaCoil, tr_setup, void(TeslaCoil this, entity it))
 +{
 +    it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
 +                         TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
 +
 +    it.turret_firecheckfunc = turret_tesla_firecheck;
 +    it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
 +                       TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK;
 +
 +    it.firecheck_flags        = TFL_FIRECHECK_REFIRE | TFL_FIRECHECK_AMMO_OWN;
 +    it.shoot_flags            = TFL_SHOOT_CUSTOM;
 +    it.ammo_flags                     = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
 +    it.aim_flags                      = TFL_AIM_NO;
 +    it.track_flags            = TFL_TRACK_NO;
 +}
 +
 +float turret_tesla_firecheck()
 +{SELFPARAM();
 +    // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
 +    float do_target_scan = 0;
 +
 +    if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
 +        do_target_scan = 1;
 +
 +    // Old target (if any) invalid?
 +    if(self.target_validate_time < time)
 +    if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
 +    {
 +        self.enemy = world;
 +        self.target_validate_time = time + 0.5;
 +        do_target_scan = 1;
 +    }
 +
 +    // But never more often then g_turrets_targetscan_mindelay!
 +    if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
 +        do_target_scan = 0;
 +
 +    if(do_target_scan)
 +    {
 +        self.enemy = turret_select_target();
 +        self.target_select_time = time;
 +    }
 +
 +    if(!turret_firecheck())
 +        return 0;
 +
 +    if(self.enemy)
 +        return 1;
 +
 +    return 0;
 +}
 +
 +#endif
 +#endif
index 49e93c0,0000000..1feace4
mode 100644,000000..100644
--- /dev/null
@@@ -1,667 -1,0 +1,667 @@@
- void spawnfunc_turret_walker() { SELFPARAM(); if(!turret_initialize(TUR_WALKER)) remove(self); }
 +#ifndef TURRET_WALKER_H
 +#define TURRET_WALKER_H
 +
 +//#define WALKER_FANCYPATHING
 +
 +#include "walker_weapon.qc"
 +
 +CLASS(WalkerTurret, Turret)
 +/* spawnflags */ ATTRIB(WalkerTurret, spawnflags, int, TUR_FLAG_PLAYER | TUR_FLAG_MOVE);
 +/* mins       */ ATTRIB(WalkerTurret, mins, vector, '-70 -70 0');
 +/* maxs       */ ATTRIB(WalkerTurret, maxs, vector, '70 70 95');
 +/* modelname  */ ATTRIB(WalkerTurret, mdl, string, "walker_body.md3");
 +/* model      */ ATTRIB(WalkerTurret, model, string, strzone(strcat("models/turrets/", this.mdl)));
 +/* head_model */ ATTRIB(WalkerTurret, head_model, string, strzone(strcat("models/turrets/", "walker_head_minigun.md3")));
 +/* netname    */ ATTRIB(WalkerTurret, netname, string, "walker");
 +/* fullname   */ ATTRIB(WalkerTurret, turret_name, string, _("Walker Turret"));
 +    ATTRIB(WalkerTurret, m_weapon, Weapon, WEP_WALKER);
 +ENDCLASS(WalkerTurret)
 +REGISTER_TURRET(WALKER, NEW(WalkerTurret));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "walker_weapon.qc"
 +
 +#ifdef SVQC
 +
 +float autocvar_g_turrets_unit_walker_melee_damage;
 +float autocvar_g_turrets_unit_walker_melee_force;
 +float autocvar_g_turrets_unit_walker_melee_range;
 +float autocvar_g_turrets_unit_walker_rocket_damage;
 +float autocvar_g_turrets_unit_walker_rocket_radius;
 +float autocvar_g_turrets_unit_walker_rocket_force;
 +float autocvar_g_turrets_unit_walker_rocket_speed;
 +float autocvar_g_turrets_unit_walker_rocket_range;
 +float autocvar_g_turrets_unit_walker_rocket_range_min;
 +float autocvar_g_turrets_unit_walker_rocket_refire;
 +float autocvar_g_turrets_unit_walker_rocket_turnrate;
 +float autocvar_g_turrets_unit_walker_speed_stop;
 +float autocvar_g_turrets_unit_walker_speed_walk;
 +float autocvar_g_turrets_unit_walker_speed_run;
 +float autocvar_g_turrets_unit_walker_speed_jump;
 +float autocvar_g_turrets_unit_walker_speed_swim;
 +float autocvar_g_turrets_unit_walker_speed_roam;
 +float autocvar_g_turrets_unit_walker_turn;
 +float autocvar_g_turrets_unit_walker_turn_walk;
 +float autocvar_g_turrets_unit_walker_turn_strafe;
 +float autocvar_g_turrets_unit_walker_turn_swim;
 +float autocvar_g_turrets_unit_walker_turn_run;
 +
 +const int ANIM_NO         = 0;
 +const int ANIM_TURN       = 1;
 +const int ANIM_WALK       = 2;
 +const int ANIM_RUN        = 3;
 +const int ANIM_STRAFE_L   = 4;
 +const int ANIM_STRAFE_R   = 5;
 +const int ANIM_JUMP       = 6;
 +const int ANIM_LAND       = 7;
 +const int ANIM_PAIN       = 8;
 +const int ANIM_MELEE      = 9;
 +const int ANIM_SWIM       = 10;
 +const int ANIM_ROAM       = 11;
 +
 +.float animflag;
 +.float idletime;
 +
 +#define WALKER_PATH(s,e) pathlib_astar(s,e)
 +
 +float walker_firecheck()
 +{SELFPARAM();
 +    if (self.animflag == ANIM_MELEE)
 +        return 0;
 +
 +    return turret_firecheck();
 +}
 +
 +void walker_melee_do_dmg()
 +{SELFPARAM();
 +    vector where;
 +    entity e;
 +
 +    makevectors(self.angles);
 +    where = self.origin + v_forward * 128;
 +
 +    e = findradius(where,32);
 +    while (e)
 +    {
 +        if (turret_validate_target(self, e, self.target_validate_flags))
 +            if (e != self && e.owner != self)
 +                Damage(e, self, self, (autocvar_g_turrets_unit_walker_melee_damage), DEATH_TURRET_WALK_MELEE, '0 0 0', v_forward * (autocvar_g_turrets_unit_walker_melee_force));
 +
 +        e = e.chain;
 +    }
 +}
 +
 +void walker_setnoanim()
 +{SELFPARAM();
 +    turrets_setframe(ANIM_NO, false);
 +    self.animflag = self.frame;
 +}
 +void walker_rocket_explode()
 +{SELFPARAM();
 +    RadiusDamage (self, self.owner, (autocvar_g_turrets_unit_walker_rocket_damage), 0, (autocvar_g_turrets_unit_walker_rocket_radius), self, world, (autocvar_g_turrets_unit_walker_rocket_force), DEATH_TURRET_WALK_ROCKET, world);
 +    remove (self);
 +}
 +
 +void walker_rocket_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
 +{SELFPARAM();
 +    self.health = self.health - damage;
 +    self.velocity = self.velocity + vforce;
 +
 +    if (self.health <= 0)
 +        W_PrepareExplosionByDamage(self.owner, walker_rocket_explode);
 +}
 +
 +#define WALKER_ROCKET_MOVE movelib_move_simple(newdir, (autocvar_g_turrets_unit_walker_rocket_speed), (autocvar_g_turrets_unit_walker_rocket_turnrate)); UpdateCSQCProjectile(self)
 +void walker_rocket_loop();
 +void walker_rocket_think()
 +{SELFPARAM();
 +    vector newdir;
 +    float edist;
 +    float itime;
 +    float m_speed;
 +
 +    self.nextthink = time;
 +
 +    edist = vlen(self.enemy.origin - self.origin);
 +
 +    // Simulate crude guidance
 +    if (self.cnt < time)
 +    {
 +        if (edist < 1000)
 +            self.tur_shotorg = randomvec() * min(edist, 64);
 +        else
 +            self.tur_shotorg = randomvec() * min(edist, 256);
 +
 +        self.cnt = time + 0.5;
 +    }
 +
 +    if (edist < 128)
 +        self.tur_shotorg = '0 0 0';
 +
 +    if (self.max_health < time)
 +    {
 +        self.think      = walker_rocket_explode;
 +        self.nextthink  = time;
 +        return;
 +    }
 +
 +    if (self.shot_dmg != 1337 && random() < 0.01)
 +    {
 +        walker_rocket_loop();
 +        return;
 +    }
 +
 +    m_speed = vlen(self.velocity);
 +
 +    // Enemy dead? just keep on the current heading then.
 +    if (self.enemy == world || self.enemy.deadflag != DEAD_NO)
 +        self.enemy = world;
 +
 +    if (self.enemy)
 +    {
 +        itime = max(edist / m_speed, 1);
 +        newdir = steerlib_pull(self.enemy.origin + self.tur_shotorg);
 +    }
 +    else
 +        newdir  = normalize(self.velocity);
 +
 +    WALKER_ROCKET_MOVE;
 +}
 +
 +void walker_rocket_loop3()
 +{SELFPARAM();
 +    vector newdir;
 +    self.nextthink = time;
 +
 +    if (self.max_health < time)
 +    {
 +        self.think = walker_rocket_explode;
 +        return;
 +    }
 +
 +    if (vlen(self.origin - self.tur_shotorg) < 100 )
 +    {
 +        self.think = walker_rocket_think;
 +        return;
 +    }
 +
 +    newdir = steerlib_pull(self.tur_shotorg);
 +    WALKER_ROCKET_MOVE;
 +
 +    self.angles = vectoangles(self.velocity);
 +}
 +
 +void walker_rocket_loop2()
 +{SELFPARAM();
 +    vector newdir;
 +
 +    self.nextthink = time;
 +
 +    if (self.max_health < time)
 +    {
 +        self.think = walker_rocket_explode;
 +        return;
 +    }
 +
 +    if (vlen(self.origin - self.tur_shotorg) < 100 )
 +    {
 +        self.tur_shotorg = self.origin - '0 0 200';
 +        self.think = walker_rocket_loop3;
 +        return;
 +    }
 +
 +    newdir = steerlib_pull(self.tur_shotorg);
 +    WALKER_ROCKET_MOVE;
 +}
 +
 +void walker_rocket_loop()
 +{SELFPARAM();
 +    self.nextthink = time;
 +    self.tur_shotorg = self.origin + '0 0 300';
 +    self.think = walker_rocket_loop2;
 +    self.shot_dmg = 1337;
 +}
 +
 +void walker_fire_rocket(vector org)
 +{SELFPARAM();
 +    entity rocket;
 +
 +    fixedmakevectors(self.angles);
 +
 +    te_explosion (org);
 +
 +    rocket = spawn ();
 +    setorigin(rocket, org);
 +
 +    sound (self, CH_WEAPON_A, SND_HAGAR_FIRE, VOL_BASE, ATTEN_NORM);
 +    setsize (rocket, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
 +
 +    rocket.classname            = "walker_rocket";
 +    rocket.owner                        = self;
 +    rocket.bot_dodge            = true;
 +    rocket.bot_dodgerating    = 50;
 +    rocket.takedamage          = DAMAGE_YES;
 +    rocket.damageforcescale   = 2;
 +    rocket.health                      = 25;
 +    rocket.tur_shotorg                = randomvec() * 512;
 +    rocket.cnt                                = time + 1;
 +    rocket.enemy                        = self.enemy;
 +
 +    if (random() < 0.01)
 +        rocket.think            = walker_rocket_loop;
 +    else
 +        rocket.think            = walker_rocket_think;
 +
 +    rocket.event_damage          = walker_rocket_damage;
 +
 +    rocket.nextthink            = time;
 +    rocket.movetype              = MOVETYPE_FLY;
 +    rocket.velocity              = normalize((v_forward + v_up * 0.5) + (randomvec() * 0.2)) * (autocvar_g_turrets_unit_walker_rocket_speed);
 +    rocket.angles                      = vectoangles(rocket.velocity);
 +    rocket.touch                        = walker_rocket_explode;
 +    rocket.flags                        = FL_PROJECTILE;
 +    rocket.solid                        = SOLID_BBOX;
 +    rocket.max_health          = time + 9;
 +    rocket.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_HEAT;
 +
 +    CSQCProjectile(rocket, false, PROJECTILE_ROCKET, false); // no culling, has fly sound
 +}
 +
 +.vector enemy_last_loc;
 +.float enemy_last_time;
 +void walker_move_to(vector _target, float _dist)
 +{SELFPARAM();
 +    switch (self.waterlevel)
 +    {
 +        case WATERLEVEL_NONE:
 +            if (_dist > 500)
 +                self.animflag = ANIM_RUN;
 +            else
 +                self.animflag = ANIM_WALK;
 +        case WATERLEVEL_WETFEET:
 +        case WATERLEVEL_SWIMMING:
 +            if (self.animflag != ANIM_SWIM)
 +                self.animflag = ANIM_WALK;
 +            else
 +                self.animflag = ANIM_SWIM;
 +            break;
 +        case WATERLEVEL_SUBMERGED:
 +            self.animflag = ANIM_SWIM;
 +    }
 +
 +    self.moveto = _target;
 +    self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
 +
 +    if(self.enemy)
 +    {
 +        self.enemy_last_loc = _target;
 +        self.enemy_last_time = time;
 +    }
 +}
 +
 +void walker_move_path()
 +{SELFPARAM();
 +#ifdef WALKER_FANCYPATHING
 +    // Are we close enougth to a path node to switch to the next?
 +    if (vlen(self.origin  - self.pathcurrent.origin) < 64)
 +        if (self.pathcurrent.path_next == world)
 +        {
 +            // Path endpoint reached
 +            pathlib_deletepath(self.pathcurrent.owner);
 +            self.pathcurrent = world;
 +
 +            if (self.pathgoal)
 +            {
 +                if (self.pathgoal.use)
 +                    self.pathgoal.use();
 +
 +                if (self.pathgoal.enemy)
 +                {
 +                    self.pathcurrent = WALKER_PATH(self.pathgoal.origin,self.pathgoal.enemy.origin);
 +                    self.pathgoal = self.pathgoal.enemy;
 +                }
 +            }
 +            else
 +                self.pathgoal = world;
 +        }
 +        else
 +            self.pathcurrent = self.pathcurrent.path_next;
 +
 +    self.moveto = self.pathcurrent.origin;
 +    self.steerto = steerlib_attract2(self.moveto,0.5,500,0.95);
 +    walker_move_to(self.moveto, 0);
 +
 +#else
 +    if (vlen(self.origin - self.pathcurrent.origin) < 64)
 +        self.pathcurrent = self.pathcurrent.enemy;
 +
 +    if(!self.pathcurrent)
 +        return;
 +
 +    self.moveto = self.pathcurrent.origin;
 +    self.steerto = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
 +    walker_move_to(self.moveto, 0);
 +#endif
 +}
 +
++spawnfunc(turret_walker) { if(!turret_initialize(TUR_WALKER)) remove(self); }
 +
 +        METHOD(WalkerTurret, tr_think, void(WalkerTurret thistur))
 +        {
 +            fixedmakevectors(self.angles);
 +
 +            if (self.spawnflags & TSF_NO_PATHBREAK && self.pathcurrent)
 +                walker_move_path();
 +            else if (self.enemy == world)
 +            {
 +                if(self.pathcurrent)
 +                    walker_move_path();
 +                else
 +                {
 +                    if(self.enemy_last_time != 0)
 +                    {
 +                        if(vlen(self.origin - self.enemy_last_loc) < 128 || time - self.enemy_last_time > 10)
 +                            self.enemy_last_time = 0;
 +                        else
 +                            walker_move_to(self.enemy_last_loc, 0);
 +                    }
 +                    else
 +                    {
 +                        if(self.animflag != ANIM_NO)
 +                        {
 +                            traceline(self.origin + '0 0 64', self.origin + '0 0 64' + v_forward * 128, MOVE_NORMAL, self);
 +
 +                            if(trace_fraction != 1.0)
 +                                self.tur_head.idletime = -1337;
 +                            else
 +                            {
 +                                traceline(trace_endpos, trace_endpos - '0 0 256', MOVE_NORMAL, self);
 +                                if(trace_fraction == 1.0)
 +                                    self.tur_head.idletime = -1337;
 +                            }
 +
 +                            if(self.tur_head.idletime == -1337)
 +                            {
 +                                self.moveto = self.origin + randomvec() * 256;
 +                                self.tur_head.idletime = 0;
 +                            }
 +
 +                            self.moveto = self.moveto * 0.9 + ((self.origin + v_forward * 500) + randomvec() * 400) * 0.1;
 +                            self.moveto_z = self.origin_z + 64;
 +                            walker_move_to(self.moveto, 0);
 +                        }
 +
 +                        if(self.idletime < time)
 +                        {
 +                            if(random() < 0.5 || !(self.spawnflags & TSL_ROAM))
 +                            {
 +                                self.idletime = time + 1 + random() * 5;
 +                                self.moveto = self.origin;
 +                                self.animflag = ANIM_NO;
 +                            }
 +                            else
 +                            {
 +                                self.animflag = ANIM_WALK;
 +                                self.idletime = time + 4 + random() * 2;
 +                                self.moveto = self.origin + randomvec() * 256;
 +                                self.tur_head.moveto = self.moveto;
 +                                self.tur_head.idletime = 0;
 +                            }
 +                        }
 +                    }
 +                }
 +            }
 +            else
 +            {
 +                if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_melee_range) && self.animflag != ANIM_MELEE)
 +                {
 +                    vector wish_angle;
 +
 +                    wish_angle = angleofs(self, self.enemy);
 +                    if (self.animflag != ANIM_SWIM)
 +                    if (fabs(wish_angle_y) < 15)
 +                    {
 +                        self.moveto   = self.enemy.origin;
 +                        self.steerto  = steerlib_attract2(self.moveto, 0.5, 500, 0.95);
 +                        self.animflag = ANIM_MELEE;
 +                    }
 +                }
 +                else if (self.tur_head.attack_finished_single < time)
 +                {
 +                    if(self.tur_head.shot_volly)
 +                    {
 +                        self.animflag = ANIM_NO;
 +
 +                        self.tur_head.shot_volly = self.tur_head.shot_volly -1;
 +                        if(self.tur_head.shot_volly == 0)
 +                            self.tur_head.attack_finished_single = time + (autocvar_g_turrets_unit_walker_rocket_refire);
 +                        else
 +                            self.tur_head.attack_finished_single = time + 0.2;
 +
 +                        if(self.tur_head.shot_volly > 1)
 +                            walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket01")));
 +                        else
 +                            walker_fire_rocket(gettaginfo(self, gettagindex(self, "tag_rocket02")));
 +                    }
 +                    else
 +                    {
 +                        if (self.tur_dist_enemy > (autocvar_g_turrets_unit_walker_rocket_range_min))
 +                        if (self.tur_dist_enemy < (autocvar_g_turrets_unit_walker_rocket_range))
 +                            self.tur_head.shot_volly = 4;
 +                    }
 +                }
 +                else
 +                {
 +                    if (self.animflag != ANIM_MELEE)
 +                        walker_move_to(self.enemy.origin, self.tur_dist_enemy);
 +                }
 +            }
 +
 +            {
 +                vector real_angle;
 +                float turny = 0, turnx = 0;
 +                float vz;
 +
 +                real_angle = vectoangles(self.steerto) - self.angles;
 +                vz = self.velocity_z;
 +
 +                switch (self.animflag)
 +                {
 +                    case ANIM_NO:
 +                        movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
 +                        break;
 +
 +                    case ANIM_TURN:
 +                        turny = (autocvar_g_turrets_unit_walker_turn);
 +                        movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
 +                        break;
 +
 +                    case ANIM_WALK:
 +                        turny = (autocvar_g_turrets_unit_walker_turn_walk);
 +                        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_walk), 0.6);
 +                        break;
 +
 +                    case ANIM_RUN:
 +                        turny = (autocvar_g_turrets_unit_walker_turn_run);
 +                        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_run), 0.6);
 +                        break;
 +
 +                    case ANIM_STRAFE_L:
 +                        turny = (autocvar_g_turrets_unit_walker_turn_strafe);
 +                        movelib_move_simple(v_right * -1, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
 +                        break;
 +
 +                    case ANIM_STRAFE_R:
 +                        turny = (autocvar_g_turrets_unit_walker_turn_strafe);
 +                        movelib_move_simple(v_right, (autocvar_g_turrets_unit_walker_speed_walk), 0.8);
 +                        break;
 +
 +                    case ANIM_JUMP:
 +                        self.velocity += '0 0 1' * (autocvar_g_turrets_unit_walker_speed_jump);
 +                        break;
 +
 +                    case ANIM_LAND:
 +                        break;
 +
 +                    case ANIM_PAIN:
 +                        if(self.frame != ANIM_PAIN)
 +                            defer(0.25, walker_setnoanim);
 +
 +                        break;
 +
 +                    case ANIM_MELEE:
 +                        if(self.frame != ANIM_MELEE)
 +                        {
 +                            defer(0.41, walker_setnoanim);
 +                            defer(0.21, walker_melee_do_dmg);
 +                        }
 +
 +                        movelib_beak_simple((autocvar_g_turrets_unit_walker_speed_stop));
 +                        break;
 +
 +                    case ANIM_SWIM:
 +                        turny = (autocvar_g_turrets_unit_walker_turn_swim);
 +                        turnx = (autocvar_g_turrets_unit_walker_turn_swim);
 +
 +                        self.angles_x += bound(-10, shortangle_f(real_angle_x, self.angles_x), 10);
 +                        movelib_move_simple(v_forward, (autocvar_g_turrets_unit_walker_speed_swim), 0.3);
 +                        vz = self.velocity_z + sin(time * 4) * 8;
 +                        break;
 +
 +                    case ANIM_ROAM:
 +                        turny = (autocvar_g_turrets_unit_walker_turn_walk);
 +                        movelib_move_simple(v_forward ,(autocvar_g_turrets_unit_walker_speed_roam), 0.5);
 +                        break;
 +                }
 +
 +                if(turny)
 +                {
 +                    turny = bound( turny * -1, shortangle_f(real_angle_y, self.angles_y), turny );
 +                    self.angles_y += turny;
 +                }
 +
 +                if(turnx)
 +                {
 +                    turnx = bound( turnx * -1, shortangle_f(real_angle_x, self.angles_x), turnx );
 +                    self.angles_x += turnx;
 +                }
 +
 +                self.velocity_z = vz;
 +            }
 +
 +
 +            if(self.origin != self.oldorigin)
 +                self.SendFlags |= TNSF_MOVE;
 +
 +            self.oldorigin = self.origin;
 +            turrets_setframe(self.animflag, false);
 +        }
 +        METHOD(WalkerTurret, tr_death, void(WalkerTurret this, entity it))
 +        {
 +#ifdef WALKER_FANCYPATHING
 +            if (it.pathcurrent)
 +                pathlib_deletepath(it.pathcurrent.owner);
 +#endif
 +            it.pathcurrent = NULL;
 +        }
 +        METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
 +        {
 +            it.ticrate = 0.05;
 +
 +            entity e;
 +
 +            // Respawn is called & first spawn to, to set team. need to make sure we do not move the initial spawn.
 +            if(it.movetype == MOVETYPE_WALK)
 +            {
 +                if(it.pos1)
 +                    setorigin(it, it.pos1);
 +                if(it.pos2)
 +                    it.angles = it.pos2;
 +            }
 +
 +            it.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIEVE;
 +            it.aim_flags = TFL_AIM_LEAD;
 +            it.turret_flags |= TUR_FLAG_HITSCAN;
 +
 +            it.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
 +            it.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMITS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
 +            it.iscreature = true;
 +            it.teleportable = TELEPORT_NORMAL;
 +            it.damagedbycontents = true;
 +            it.solid = SOLID_SLIDEBOX;
 +            it.takedamage = DAMAGE_AIM;
 +            if(it.movetype != MOVETYPE_WALK)
 +            {
 +                setorigin(it, it.origin);
 +                tracebox(it.origin + '0 0 128', it.mins, it.maxs, it.origin - '0 0 10000', MOVE_NORMAL, it);
 +                setorigin(it, trace_endpos + '0 0 4');
 +                it.pos1 = it.origin;
 +                it.pos2 = it.angles;
 +            }
 +            it.movetype = MOVETYPE_WALK;
 +            it.idle_aim = '0 0 0';
 +            it.turret_firecheckfunc = walker_firecheck;
 +
 +            if (it.target != "")
 +            {
 +                e = find(world, targetname, it.target);
 +                if (!e)
 +                {
 +                    LOG_TRACE("Initital waypoint for walker does NOT exsist, fix your map!\n");
 +                    it.target = "";
 +                }
 +
 +                if (e.classname != "turret_checkpoint")
 +                    LOG_TRACE("Warning: not a turrret path\n");
 +                else
 +                {
 +#ifdef WALKER_FANCYPATHING
 +                    it.pathcurrent = WALKER_PATH(it.origin, e.origin);
 +                    it.pathgoal = e;
 +#else
 +                    it.pathcurrent = e;
 +#endif
 +                }
 +            }
 +        }
 +
 +#endif // SVQC
 +#ifdef CSQC
 +
 +#include "../../../client/movelib.qh"
 +
 +void walker_draw()
 +{SELFPARAM();
 +    float dt;
 +
 +    dt = time - self.move_time;
 +    self.move_time = time;
 +    if(dt <= 0)
 +        return;
 +
 +    fixedmakevectors(self.angles);
 +    movelib_groundalign4point(300, 100, 0.25, 45);
 +    setorigin(self, self.origin + self.velocity * dt);
 +    self.tur_head.angles += dt * self.tur_head.move_avelocity;
 +    self.angles_y = self.move_angles_y;
 +
 +    if (self.health < 127)
 +    if(random() < 0.15)
 +        te_spark(self.origin + '0 0 40', randomvec() * 256 + '0 0 256', 16);
 +}
 +
 +        METHOD(WalkerTurret, tr_setup, void(WalkerTurret this, entity it))
 +        {
 +            it.gravity                = 1;
 +            it.movetype               = MOVETYPE_BOUNCE;
 +            it.move_movetype  = MOVETYPE_BOUNCE;
 +            it.move_origin    = it.origin;
 +            it.move_time              = time;
 +            it.draw                   = walker_draw;
 +        }
 +
 +#endif // CSQC
 +#endif
index ee276f2,0000000..011fdf1
mode 100644,000000..100644
--- /dev/null
@@@ -1,975 -1,0 +1,975 @@@
- void spawnfunc_vehicle_bumblebee()
- {SELFPARAM();
 +#ifndef VEHICLE_BUMBLEBEE
 +#define VEHICLE_BUMBLEBEE
 +#include "bumblebee.qh"
 +
 +#include "bumblebee_weapons.qc"
 +
 +CLASS(Bumblebee, Vehicle)
 +/* spawnflags */ ATTRIB(Bumblebee, spawnflags, int, VHF_DMGSHAKE);
 +/* mins       */ ATTRIB(Bumblebee, mins, vector, '-245 -130 -130');
 +/* maxs       */ ATTRIB(Bumblebee, maxs, vector, '230 130 130');
 +/* model        */ ATTRIB(Bumblebee, mdl, string, "models/vehicles/bumblebee_body.dpm");
 +/* model        */ ATTRIB(Bumblebee, model, string, "models/vehicles/bumblebee_body.dpm");
 +/* head_model */ ATTRIB(Bumblebee, head_model, string, "");
 +/* hud_model  */ ATTRIB(Bumblebee, hud_model, string, "models/vehicles/spiderbot_cockpit.dpm");
 +/* tags       */ ATTRIB(Bumblebee, tag_head, string, "");
 +/* tags       */ ATTRIB(Bumblebee, tag_hud, string, "");
 +/* tags       */ ATTRIB(Bumblebee, tag_view, string, "tag_viewport");
 +/* netname    */ ATTRIB(Bumblebee, netname, string, "bumblebee");
 +/* fullname   */ ATTRIB(Bumblebee, vehicle_name, string, _("Bumblebee"));
 +/* icon       */ ATTRIB(Bumblebee, m_icon, string, "vehicle_bumble");
 +ENDCLASS(Bumblebee)
 +REGISTER_VEHICLE(BUMBLEBEE, NEW(Bumblebee));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +const float BRG_SETUP = 2;
 +const float BRG_START = 4;
 +const float BRG_END = 8;
 +
 +#include "bumblebee_weapons.qc"
 +
 +#ifdef SVQC
 +float autocvar_g_vehicle_bumblebee_speed_forward;
 +float autocvar_g_vehicle_bumblebee_speed_strafe;
 +float autocvar_g_vehicle_bumblebee_speed_up;
 +float autocvar_g_vehicle_bumblebee_speed_down;
 +float autocvar_g_vehicle_bumblebee_turnspeed;
 +float autocvar_g_vehicle_bumblebee_pitchspeed;
 +float autocvar_g_vehicle_bumblebee_pitchlimit;
 +float autocvar_g_vehicle_bumblebee_friction;
 +
 +float autocvar_g_vehicle_bumblebee_energy;
 +float autocvar_g_vehicle_bumblebee_energy_regen;
 +float autocvar_g_vehicle_bumblebee_energy_regen_pause;
 +
 +float autocvar_g_vehicle_bumblebee_health;
 +float autocvar_g_vehicle_bumblebee_health_regen;
 +float autocvar_g_vehicle_bumblebee_health_regen_pause;
 +
 +float autocvar_g_vehicle_bumblebee_shield;
 +float autocvar_g_vehicle_bumblebee_shield_regen;
 +float autocvar_g_vehicle_bumblebee_shield_regen_pause;
 +
 +float autocvar_g_vehicle_bumblebee_cannon_ammo;
 +float autocvar_g_vehicle_bumblebee_cannon_ammo_regen;
 +float autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause;
 +
 +float autocvar_g_vehicle_bumblebee_cannon_lock = 0;
 +
 +float autocvar_g_vehicle_bumblebee_cannon_turnspeed;
 +float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down;
 +float autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up;
 +float autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
 +float autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
 +
 +
 +float autocvar_g_vehicle_bumblebee_raygun_turnspeed;
 +float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down;
 +float autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up;
 +float autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides;
 +
 +float autocvar_g_vehicle_bumblebee_raygun_range;
 +float autocvar_g_vehicle_bumblebee_raygun_dps;
 +float autocvar_g_vehicle_bumblebee_raygun_aps;
 +float autocvar_g_vehicle_bumblebee_raygun_fps;
 +
 +float autocvar_g_vehicle_bumblebee_raygun;
 +float autocvar_g_vehicle_bumblebee_healgun_hps;
 +float autocvar_g_vehicle_bumblebee_healgun_hmax;
 +float autocvar_g_vehicle_bumblebee_healgun_aps;
 +float autocvar_g_vehicle_bumblebee_healgun_amax;
 +float autocvar_g_vehicle_bumblebee_healgun_sps;
 +float autocvar_g_vehicle_bumblebee_healgun_locktime;
 +
 +float autocvar_g_vehicle_bumblebee_respawntime;
 +
 +float autocvar_g_vehicle_bumblebee_blowup_radius;
 +float autocvar_g_vehicle_bumblebee_blowup_coredamage;
 +float autocvar_g_vehicle_bumblebee_blowup_edgedamage;
 +float autocvar_g_vehicle_bumblebee_blowup_forceintensity;
 +vector autocvar_g_vehicle_bumblebee_bouncepain;
 +
 +bool autocvar_g_vehicle_bumblebee = 0;
 +
 +float bumblebee_gunner_frame()
 +{SELFPARAM();
 +      entity vehic    = self.vehicle.owner;
 +      entity gun      = self.vehicle;
 +      entity gunner   = self;
 +      setself(vehic);
 +
 +      vehic.solid = SOLID_NOT;
 +      //setorigin(gunner, vehic.origin);
 +      gunner.velocity = vehic.velocity;
 +
 +      float _in, _out;
 +      vehic.angles_x *= -1;
 +      makevectors(vehic.angles);
 +      vehic.angles_x *= -1;
 +      if(gun == vehic.gun1)
 +      {
 +              _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
 +              _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
 +              setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * 128);
 +      }
 +      else
 +      {
 +              _in = autocvar_g_vehicle_bumblebee_cannon_turnlimit_out;
 +              _out = autocvar_g_vehicle_bumblebee_cannon_turnlimit_in;
 +              setorigin(gunner, vehic.origin + v_up * -16 + v_forward * -16 + v_right * -128);
 +      }
 +
 +      crosshair_trace(gunner);
 +      vector _ct = trace_endpos;
 +      vector ad;
 +
 +      if(autocvar_g_vehicle_bumblebee_cannon_lock)
 +      {
 +              if(gun.lock_time < time)
 +                      gun.enemy = world;
 +
 +              if(trace_ent)
 +                      if(trace_ent.movetype)
 +                              if(trace_ent.takedamage)
 +                                      if(!trace_ent.deadflag)
 +                                      {
 +                                              if(DIFF_TEAM(trace_ent, gunner))
 +                                              {
 +                                                      gun.enemy = trace_ent;
 +                                                      gun.lock_time = time + 5;
 +                                              }
 +                                      }
 +      }
 +
 +      if(gun.enemy)
 +      {
 +              float distance, impact_time;
 +
 +              vector vf = real_origin(gun.enemy);
 +              vector _vel = gun.enemy.velocity;
 +              if(gun.enemy.movetype == MOVETYPE_WALK)
 +                      _vel.z *= 0.1;
 +
 +
 +              ad = vf;
 +              distance = vlen(ad - gunner.origin);
 +              impact_time = distance / autocvar_g_vehicle_bumblebee_cannon_speed;
 +              ad = vf + _vel * impact_time;
 +              trace_endpos = ad;
 +
 +
 +              UpdateAuxiliaryXhair(gunner, ad, '1 0 1', 1);
 +              vehicle_aimturret(vehic, trace_endpos, gun, "fire",
 +                                                autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
 +                                                _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
 +
 +      }
 +      else
 +              vehicle_aimturret(vehic, _ct, gun, "fire",
 +                                                autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up,
 +                                                _out * -1,  _in,  autocvar_g_vehicle_bumblebee_cannon_turnspeed);
 +
 +      if(!forbidWeaponUse(gunner))
 +      if(gunner.BUTTON_ATCK)
 +              if(time > gun.attack_finished_single)
 +                      if(gun.vehicle_energy >= autocvar_g_vehicle_bumblebee_cannon_cost)
 +                      {
 +                              gun.vehicle_energy -= autocvar_g_vehicle_bumblebee_cannon_cost;
 +                              bumblebee_fire_cannon(gun, "fire", gunner);
 +                              gun.delay = time;
 +                              gun.attack_finished_single = time + autocvar_g_vehicle_bumblebee_cannon_refire;
 +                      }
 +
 +      VEHICLE_UPDATE_PLAYER(gunner, health, bumblebee);
 +
 +      if(vehic.vehicle_flags & VHF_HASSHIELD)
 +              VEHICLE_UPDATE_PLAYER(gunner, shield, bumblebee);
 +
 +      ad = gettaginfo(gun, gettagindex(gun, "fire"));
 +      traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, gun);
 +
 +      UpdateAuxiliaryXhair(gunner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), 0);
 +
 +      if(vehic.owner)
 +              UpdateAuxiliaryXhair(vehic.owner, trace_endpos, ('1 0 0' * gunner.vehicle_reload1) + ('0 1 0' *(1 - gunner.vehicle_reload1)), ((gunner == vehic.gunner1) ? 1 : 2));
 +
 +      vehic.solid = SOLID_BBOX;
 +      gunner.BUTTON_ATCK = gunner.BUTTON_ATCK2 = gunner.BUTTON_CROUCH = 0;
 +      gunner.vehicle_energy = (gun.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
 +
 +      setself(gunner);
 +      return 1;
 +}
 +
 +vector bumblebee_gunner_findgoodexit(vector prefer_spot, entity gunner, entity player)
 +{
 +      //vector exitspot;
 +      float mysize;
 +
 +      tracebox(gunner.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, player);
 +      if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
 +              return prefer_spot;
 +
 +      mysize = 1.5 * vlen(PL_MAX - PL_MIN); // can't use gunner's size, as they don't have a size
 +      float i;
 +      vector v, v2;
 +      v2 = 0.5 * (gunner.absmin + gunner.absmax);
 +      for(i = 0; i < 100; ++i)
 +      {
 +              v = randomvec();
 +              v_z = 0;
 +              v = v2 + normalize(v) * mysize;
 +              tracebox(v2, PL_MIN, PL_MAX, v, MOVE_NORMAL, player);
 +              if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
 +                      return v;
 +      }
 +
 +      return prefer_spot; // this should be considered a fallback?!
 +}
 +
 +void bumblebee_gunner_exit(int _exitflag)
 +{SELFPARAM();
 +      entity player = self;
 +      entity gunner = player.vehicle;
 +      entity vehic = gunner.owner;
 +
 +      if(IS_REAL_CLIENT(player))
 +      {
 +              msg_entity = player;
 +              WriteByte(MSG_ONE, SVC_SETVIEWPORT);
 +              WriteEntity(MSG_ONE, player);
 +
 +              WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
 +              WriteAngle(MSG_ONE, 0);
 +              WriteAngle(MSG_ONE, vehic.angles.y);
 +              WriteAngle(MSG_ONE, 0);
 +      }
 +
 +      CSQCVehicleSetup(player, HUD_NORMAL);
 +      setsize(player, PL_MIN, PL_MAX);
 +
 +      player.takedamage     = DAMAGE_AIM;
 +      player.solid          = SOLID_SLIDEBOX;
 +      player.movetype       = MOVETYPE_WALK;
 +      player.effects       &= ~EF_NODRAW;
 +      player.alpha          = 1;
 +      player.PlayerPhysplug = func_null;
 +      player.view_ofs       = PL_VIEW_OFS;
 +      player.event_damage   = PlayerDamage;
 +      player.hud            = HUD_NORMAL;
 +      player.teleportable       = TELEPORT_NORMAL;
 +      player.switchweapon   = gunner.switchweapon;
 +      player.vehicle_enter_delay = time + 2;
 +
 +      fixedmakevectors(vehic.angles);
 +
 +      if(player == vehic.gunner1) { vehic.gunner1 = world; }
 +      if(player == vehic.gunner2) { vehic.gunner2 = world; v_right *= -1; }
 +
 +      vector spot = real_origin(gunner);
 +      spot = spot + v_up * 128 + v_forward * 300 + v_right * 150;
 +      spot = bumblebee_gunner_findgoodexit(spot, gunner, player);
 +
 +      // TODO: figure a way to move player out of the gunner
 +
 +      player.velocity = 0.75 * vehic.velocity + normalize(spot - vehic.origin) * 200;
 +      player.velocity_z += 10;
 +
 +      gunner.phase = time + 5;
 +      gunner.vehicle_hudmodel.viewmodelforclient = gunner;
 +
 +      MUTATOR_CALLHOOK(VehicleExit, player, gunner);
 +
 +      player.vehicle = world;
 +}
 +
 +bool bumblebee_gunner_enter()
 +{SELFPARAM();
 +      entity vehic = self;
 +      entity player = other;
 +      entity gunner = world;
 +
 +      if(!vehic.gunner1 && !vehic.gunner2 && ((time >= vehic.gun1.phase) + (time >= vehic.gun2.phase)) == 2)
 +      {
 +              // we can have some fun
 +              if(vlen(real_origin(vehic.gun2) - player.origin) < vlen(real_origin(vehic.gun1) - player.origin))
 +              {
 +                      gunner = vehic.gun2;
 +                      vehic.gunner2 = player;
 +              }
 +              else
 +              {
 +                      gunner = vehic.gun1;
 +                      vehic.gunner1 = player;
 +              }
 +      }
 +      else if(!vehic.gunner1 && time >= vehic.gun1.phase)     { gunner = vehic.gun1; vehic.gunner1 = player; }
 +      else if(!vehic.gunner2 && time >= vehic.gun2.phase)             { gunner = vehic.gun2; vehic.gunner2 = player; }
 +      else { LOG_TRACE("Vehicle is full, fail\n"); return false; }
 +
 +      player.vehicle                  = gunner;
 +      player.angles                   = vehic.angles;
 +      player.takedamage               = DAMAGE_NO;
 +      player.solid                    = SOLID_NOT;
 +      player.alpha                    = -1;
 +      player.movetype                 = MOVETYPE_NOCLIP;
 +      player.event_damage     = func_null;
 +      player.view_ofs                 = '0 0 0';
 +      player.hud                              = gunner.hud;
 +      player.teleportable     = false;
 +      player.PlayerPhysplug   = gunner.PlayerPhysplug;
 +      player.vehicle_ammo1    = vehic.vehicle_ammo1;
 +      player.vehicle_ammo2    = vehic.vehicle_ammo2;
 +      player.vehicle_reload1  = vehic.vehicle_reload1;
 +      player.vehicle_reload2  = vehic.vehicle_reload2;
 +      player.vehicle_energy   = vehic.vehicle_energy;
 +      player.flags               &= ~FL_ONGROUND;
 +
 +      RemoveGrapplingHook(player);
 +
 +      gunner.switchweapon = player.switchweapon;
 +      gunner.vehicle_exit = bumblebee_gunner_exit;
 +      gunner.vehicle_hudmodel.viewmodelforclient = player;
 +
 +      if(IS_REAL_CLIENT(player))
 +      {
 +              msg_entity = player;
 +              WriteByte(MSG_ONE,              SVC_SETVIEWPORT);
 +              WriteEntity(MSG_ONE,    gunner.vehicle_viewport);
 +
 +              WriteByte(MSG_ONE,              SVC_SETVIEWANGLES);
 +              WriteAngle(MSG_ONE,     gunner.angles_x + vehic.angles_x); // tilt
 +              WriteAngle(MSG_ONE,     gunner.angles_y + vehic.angles_y); // yaw
 +              WriteAngle(MSG_ONE,     0); // roll
 +      }
 +
 +      CSQCVehicleSetup(player, player.hud);
 +
 +      MUTATOR_CALLHOOK(VehicleEnter, player, gunner);
 +
 +      return true;
 +}
 +
 +bool vehicles_valid_pilot()
 +{SELFPARAM();
 +      if(IS_BOT_CLIENT(other) && !autocvar_g_vehicles_allow_bots)
 +              return false;
 +
 +      if((!IS_PLAYER(other))
 +      || (other.deadflag != DEAD_NO)
 +      || (other.vehicle)
 +      || (DIFF_TEAM(other, self))
 +      ) { return false; }
 +
 +      return true;
 +}
 +
 +void bumblebee_touch()
 +{SELFPARAM();
 +      if(autocvar_g_vehicles_enter) { return; }
 +
 +      if(self.gunner1 != world && self.gunner2 != world)
 +      {
 +              vehicles_touch();
 +              return;
 +      }
 +
 +      if(vehicles_valid_pilot())
 +      {
 +              float phase_time = (time >= self.gun1.phase) + (time >= self.gun2.phase);
 +
 +              if(time >= other.vehicle_enter_delay && phase_time)
 +              if(bumblebee_gunner_enter())
 +                      return;
 +      }
 +
 +      vehicles_touch();
 +}
 +
 +void bumblebee_regen()
 +{SELFPARAM();
 +      if(self.gun1.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
 +              self.gun1.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
 +                                                                         self.gun1.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
 +
 +      if(self.gun2.delay + autocvar_g_vehicle_bumblebee_cannon_ammo_regen_pause < time)
 +              self.gun2.vehicle_energy = min(autocvar_g_vehicle_bumblebee_cannon_ammo,
 +                                                                         self.gun2.vehicle_energy + autocvar_g_vehicle_bumblebee_cannon_ammo_regen * frametime);
 +
 +      if(self.vehicle_flags  & VHF_SHIELDREGEN)
 +              vehicles_regen(self.dmg_time, vehicle_shield, autocvar_g_vehicle_bumblebee_shield, autocvar_g_vehicle_bumblebee_shield_regen_pause, autocvar_g_vehicle_bumblebee_shield_regen, frametime, true);
 +
 +      if(self.vehicle_flags  & VHF_HEALTHREGEN)
 +              vehicles_regen(self.dmg_time, vehicle_health, autocvar_g_vehicle_bumblebee_health, autocvar_g_vehicle_bumblebee_health_regen_pause, autocvar_g_vehicle_bumblebee_health_regen, frametime, false);
 +
 +      if(self.vehicle_flags  & VHF_ENERGYREGEN)
 +              vehicles_regen(self.wait, vehicle_energy, autocvar_g_vehicle_bumblebee_energy, autocvar_g_vehicle_bumblebee_energy_regen_pause, autocvar_g_vehicle_bumblebee_energy_regen, frametime, false);
 +
 +}
 +
 +float bumblebee_pilot_frame()
 +{SELFPARAM();
 +      entity pilot, vehic;
 +      vector newvel;
 +
 +      if(intermission_running)
 +      {
 +              self.vehicle.velocity = '0 0 0';
 +              self.vehicle.avelocity = '0 0 0';
 +              return 1;
 +      }
 +
 +      pilot = self;
 +      vehic = self.vehicle;
 +      setself(vehic);
 +
 +      if(vehic.deadflag != DEAD_NO)
 +      {
 +              setself(pilot);
 +              pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = 0;
 +              return 1;
 +      }
 +
 +      bumblebee_regen();
 +
 +      crosshair_trace(pilot);
 +
 +      vector vang;
 +      float ftmp;
 +
 +      vang = vehic.angles;
 +      newvel = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
 +      vang.x *= -1;
 +      newvel.x *= -1;
 +      if(newvel.x > 180)  newvel.x -= 360;
 +      if(newvel.x < -180) newvel.x += 360;
 +      if(newvel.y > 180)  newvel.y -= 360;
 +      if(newvel.y < -180) newvel.y += 360;
 +
 +      ftmp = shortangle_f(pilot.v_angle.y - vang.y, vang.y);
 +      if(ftmp > 180)  ftmp -= 360;
 +      if(ftmp < -180) ftmp += 360;
 +      vehic.avelocity_y = bound(-autocvar_g_vehicle_bumblebee_turnspeed, ftmp + vehic.avelocity.y * 0.9, autocvar_g_vehicle_bumblebee_turnspeed);
 +
 +      // Pitch
 +      ftmp = 0;
 +      if(pilot.movement.x > 0 && vang.x < autocvar_g_vehicle_bumblebee_pitchlimit)
 +              ftmp = 4;
 +      else if(pilot.movement.x < 0 && vang.x > -autocvar_g_vehicle_bumblebee_pitchlimit)
 +              ftmp = -8;
 +
 +      newvel.x = bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x , autocvar_g_vehicle_bumblebee_pitchlimit);
 +      ftmp = vang.x - bound(-autocvar_g_vehicle_bumblebee_pitchlimit, newvel.x + ftmp, autocvar_g_vehicle_bumblebee_pitchlimit);
 +      vehic.avelocity_x = bound(-autocvar_g_vehicle_bumblebee_pitchspeed, ftmp + vehic.avelocity.x * 0.9, autocvar_g_vehicle_bumblebee_pitchspeed);
 +
 +      vehic.angles_x = anglemods(vehic.angles.x);
 +      vehic.angles_y = anglemods(vehic.angles.y);
 +      vehic.angles_z = anglemods(vehic.angles.z);
 +
 +      makevectors('0 1 0' * vehic.angles.y);
 +      newvel = vehic.velocity * -autocvar_g_vehicle_bumblebee_friction;
 +
 +      if(pilot.movement.x != 0)
 +      {
 +              if(pilot.movement.x > 0)
 +                      newvel += v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
 +              else if(pilot.movement.x < 0)
 +                      newvel -= v_forward  * autocvar_g_vehicle_bumblebee_speed_forward;
 +      }
 +
 +      if(pilot.movement.y != 0)
 +      {
 +              if(pilot.movement.y < 0)
 +                      newvel -= v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
 +              else if(pilot.movement.y > 0)
 +                      newvel += v_right * autocvar_g_vehicle_bumblebee_speed_strafe;
 +              ftmp = newvel * v_right;
 +              ftmp *= frametime * 0.1;
 +              vehic.angles_z = bound(-15, vehic.angles.z + ftmp, 15);
 +      }
 +      else
 +      {
 +              vehic.angles_z *= 0.95;
 +              if(vehic.angles.z >= -1 && vehic.angles.z <= -1)
 +                      vehic.angles_z = 0;
 +      }
 +
 +      if(pilot.BUTTON_CROUCH)
 +              newvel -=   v_up * autocvar_g_vehicle_bumblebee_speed_down;
 +      else if(pilot.BUTTON_JUMP)
 +              newvel +=  v_up * autocvar_g_vehicle_bumblebee_speed_up;
 +
 +      vehic.velocity  += newvel * frametime;
 +      pilot.velocity = pilot.movement  = vehic.velocity;
 +
 +
 +      if(autocvar_g_vehicle_bumblebee_healgun_locktime)
 +      {
 +              if(vehic.tur_head.lock_time < time || vehic.tur_head.enemy.deadflag)
 +                      vehic.tur_head.enemy = world;
 +
 +              if(trace_ent)
 +              if(trace_ent.movetype)
 +              if(trace_ent.takedamage)
 +              if(!trace_ent.deadflag)
 +              {
 +                      if(teamplay)
 +                      {
 +                              if(trace_ent.team == pilot.team)
 +                              {
 +                                      vehic.tur_head.enemy = trace_ent;
 +                                      vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
 +                              }
 +                      }
 +                      else
 +                      {
 +                              vehic.tur_head.enemy = trace_ent;
 +                              vehic.tur_head.lock_time = time + autocvar_g_vehicle_bumblebee_healgun_locktime;
 +                      }
 +              }
 +
 +              if(vehic.tur_head.enemy)
 +              {
 +                      trace_endpos = real_origin(vehic.tur_head.enemy);
 +                      UpdateAuxiliaryXhair(pilot, trace_endpos, '0 0.75 0', 0);
 +              }
 +      }
 +
 +      vang = vehicle_aimturret(vehic, trace_endpos, self.gun3, "fire",
 +                                        autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1,  autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up,
 +                                        autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1,  autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides,  autocvar_g_vehicle_bumblebee_raygun_turnspeed);
 +
 +      if(!forbidWeaponUse(pilot))
 +      if((pilot.BUTTON_ATCK || pilot.BUTTON_ATCK2) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime || autocvar_g_vehicle_bumblebee_raygun == 0))
 +      {
 +              vehic.gun3.enemy.realowner = pilot;
 +              vehic.gun3.enemy.effects &= ~EF_NODRAW;
 +
 +              vehic.gun3.enemy.hook_start = gettaginfo(vehic.gun3, gettagindex(vehic.gun3, "fire"));
 +              vehic.gun3.enemy.SendFlags |= BRG_START;
 +
 +              traceline(vehic.gun3.enemy.hook_start, vehic.gun3.enemy.hook_start + v_forward * autocvar_g_vehicle_bumblebee_raygun_range, MOVE_NORMAL, vehic);
 +
 +              if(trace_ent)
 +              {
 +                      if(autocvar_g_vehicle_bumblebee_raygun)
 +                      {
 +                              Damage(trace_ent, vehic, pilot, autocvar_g_vehicle_bumblebee_raygun_dps * sys_frametime, DEATH_GENERIC, trace_endpos, v_forward * autocvar_g_vehicle_bumblebee_raygun_fps * sys_frametime);
 +                              vehic.vehicle_energy -= autocvar_g_vehicle_bumblebee_raygun_aps * sys_frametime;
 +                      }
 +                      else
 +                      {
 +                              if(trace_ent.deadflag == DEAD_NO)
 +                                      if((teamplay && trace_ent.team == pilot.team) || !teamplay)
 +                                      {
 +
 +                                              if(trace_ent.vehicle_flags & VHF_ISVEHICLE)
 +                                              {
 +                                                      if(autocvar_g_vehicle_bumblebee_healgun_sps && trace_ent.vehicle_health <= trace_ent.max_health)
 +                                                              trace_ent.vehicle_shield = min(trace_ent.vehicle_shield + autocvar_g_vehicle_bumblebee_healgun_sps * frametime, trace_ent.tur_head.max_health);
 +
 +                                                      if(autocvar_g_vehicle_bumblebee_healgun_hps)
 +                                                              trace_ent.vehicle_health = min(trace_ent.vehicle_health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health);
 +                                              }
 +                                              else if(IS_CLIENT(trace_ent))
 +                                              {
 +                                                      if(trace_ent.health <= autocvar_g_vehicle_bumblebee_healgun_hmax && autocvar_g_vehicle_bumblebee_healgun_hps)
 +                                                              trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
 +
 +                                                      if(trace_ent.armorvalue <= autocvar_g_vehicle_bumblebee_healgun_amax && autocvar_g_vehicle_bumblebee_healgun_aps)
 +                                                              trace_ent.armorvalue = min(trace_ent.armorvalue + autocvar_g_vehicle_bumblebee_healgun_aps * frametime, autocvar_g_vehicle_bumblebee_healgun_amax);
 +
 +                                                      trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, autocvar_g_vehicle_bumblebee_healgun_hmax);
 +                                              }
 +                                              else if(IS_TURRET(trace_ent))
 +                                              {
 +                                                      if(trace_ent.health  <= trace_ent.max_health && autocvar_g_vehicle_bumblebee_healgun_hps)
 +                                                              trace_ent.health = min(trace_ent.health + autocvar_g_vehicle_bumblebee_healgun_hps * frametime, trace_ent.max_health);
 +                                                      //else ..hmmm what? ammo?
 +
 +                                                      trace_ent.SendFlags |= TNSF_STATUS;
 +                                              }
 +                                      }
 +                      }
 +              }
 +
 +              vehic.gun3.enemy.hook_end = trace_endpos;
 +              setorigin(vehic.gun3.enemy, trace_endpos);
 +              vehic.gun3.enemy.SendFlags |= BRG_END;
 +
 +              vehic.wait = time + 1;
 +      }
 +      else
 +              vehic.gun3.enemy.effects |= EF_NODRAW;
 +      /*{
 +              if(vehic.gun3.enemy)
 +                      remove(vehic.gun3.enemy);
 +
 +              vehic.gun3.enemy = world;
 +      }
 +      */
 +
 +      VEHICLE_UPDATE_PLAYER(pilot, health, bumblebee);
 +      VEHICLE_UPDATE_PLAYER(pilot, energy, bumblebee);
 +
 +      pilot.vehicle_ammo1 = (vehic.gun1.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
 +      pilot.vehicle_ammo2 = (vehic.gun2.vehicle_energy / autocvar_g_vehicle_bumblebee_cannon_ammo) * 100;
 +
 +      if(vehic.vehicle_flags & VHF_HASSHIELD)
 +              VEHICLE_UPDATE_PLAYER(pilot, shield, bumblebee);
 +
 +      vehic.angles_x *= -1;
 +      makevectors(vehic.angles);
 +      vehic.angles_x *= -1;
 +      setorigin(pilot, vehic.origin + v_up * 48 + v_forward * 160);
 +
 +      pilot.BUTTON_ATCK = pilot.BUTTON_ATCK2 = pilot.BUTTON_CROUCH = 0;
 +      setself(pilot);
 +
 +      return 1;
 +}
 +
 +void bumblebee_land()
 +{SELFPARAM();
 +      float hgt;
 +
 +      hgt = raptor_altitude(512);
 +      self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
 +      self.angles_x *= 0.95;
 +      self.angles_z *= 0.95;
 +
 +      if(hgt < 16)
 +              self.think      = vehicles_think;
 +
 +      self.nextthink = time;
 +
 +      CSQCMODEL_AUTOUPDATE(self);
 +}
 +
 +void bumblebee_exit(float eject)
 +{SELFPARAM();
 +      if(self.owner.vehicleid == VEH_BUMBLEBEE.vehicleid)
 +      {
 +              bumblebee_gunner_exit(eject);
 +              return;
 +      }
 +
 +      self.touch = vehicles_touch;
 +
 +      if(self.deadflag == DEAD_NO)
 +      {
 +              self.think = bumblebee_land;
 +              self.nextthink  = time;
 +      }
 +
 +      self.movetype = MOVETYPE_TOSS;
 +
 +      if(!self.owner)
 +              return;
 +
 +      fixedmakevectors(self.angles);
 +      vector spot;
 +      if(vlen(self.velocity) > autocvar_g_vehicle_bumblebee_speed_forward * 0.5)
 +              spot = self.origin + v_up * 128 + v_forward * 300;
 +      else
 +              spot = self.origin + v_up * 128 - v_forward * 300;
 +
 +      spot = vehicles_findgoodexit(spot);
 +
 +      // Hide beam
 +      if(self.gun3.enemy || !wasfreed(self.gun3.enemy)) {
 +              self.gun3.enemy.effects |= EF_NODRAW;
 +      }
 +
 +      self.owner.velocity = 0.75 * self.vehicle.velocity + normalize(spot - self.vehicle.origin) * 200;
 +      self.owner.velocity_z += 10;
 +      setorigin(self.owner, spot);
 +
 +      antilag_clear(self.owner);
 +      self.owner = world;
 +}
 +
 +void bumblebee_blowup()
 +{SELFPARAM();
 +      RadiusDamage(self, self.enemy, autocvar_g_vehicle_bumblebee_blowup_coredamage,
 +                               autocvar_g_vehicle_bumblebee_blowup_edgedamage,
 +                               autocvar_g_vehicle_bumblebee_blowup_radius, self, world,
 +                               autocvar_g_vehicle_bumblebee_blowup_forceintensity,
 +                               DEATH_VH_BUMB_DEATH, world);
 +
 +      sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 +      Send_Effect(EFFECT_EXPLOSION_BIG, (self.origin + '0 0 100') + (randomvec() * 80), '0 0 0', 1);
 +
 +      if(self.owner.deadflag == DEAD_DYING)
 +              self.owner.deadflag = DEAD_DEAD;
 +
 +      remove(self);
 +}
 +
 +void bumblebee_diethink()
 +{SELFPARAM();
 +      if(time >= self.wait)
 +              self.think = bumblebee_blowup;
 +
 +      if(random() < 0.1)
 +      {
 +              sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 +              Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
 +      }
 +
 +      self.nextthink = time + 0.1;
 +}
 +
++spawnfunc(vehicle_bumblebee)
++{
 +      if(!autocvar_g_vehicle_bumblebee) { remove(self); return; }
 +      if(!vehicle_initialize(VEH_BUMBLEBEE, false)) { remove(self); return; }
 +}
 +
 +              METHOD(Bumblebee, vr_impact, void(Bumblebee thisveh))
 +              {
 +                      if(autocvar_g_vehicle_bumblebee_bouncepain)
 +                              vehicles_impact(autocvar_g_vehicle_bumblebee_bouncepain_x, autocvar_g_vehicle_bumblebee_bouncepain_y, autocvar_g_vehicle_bumblebee_bouncepain_z);
 +              }
 +              METHOD(Bumblebee, vr_enter, void(Bumblebee thisveh))
 +              {
 +                      SELFPARAM();
 +                      self.touch = bumblebee_touch;
 +                      self.nextthink = 0;
 +                      self.movetype = MOVETYPE_BOUNCEMISSILE;
 +              }
 +              METHOD(Bumblebee, vr_think, void(Bumblebee thisveh))
 +              {
 +                      SELFPARAM();
 +                      self.angles_z *= 0.8;
 +                      self.angles_x *= 0.8;
 +
 +                      self.nextthink = time;
 +
 +                      if(!self.owner)
 +                      {
 +                              entity oldself = self;
 +                              if(self.gunner1)
 +                              {
 +                                      setself(self.gunner1);
 +                                      oldself.gun1.vehicle_exit(VHEF_EJECT);
 +                                      entity oldother = other;
 +                                      other = self;
 +                                      setself(oldself);
 +                                      self.phase = 0;
 +                                      self.touch();
 +                                      other = oldother;
 +                                      return;
 +                              }
 +
 +                              if(self.gunner2)
 +                              {
 +                                      setself(self.gunner2);
 +                                      oldself.gun2.vehicle_exit(VHEF_EJECT);
 +                                      entity oldother = other;
 +                                      other = self;
 +                                      setself(oldself);
 +                                      self.phase = 0;
 +                                      self.touch();
 +                                      other = oldother;
 +                                      return;
 +                              }
 +                      }
 +              }
 +              METHOD(Bumblebee, vr_death, void(Bumblebee thisveh))
 +              {
 +                      SELFPARAM();
 +                      entity oldself = self;
 +
 +                      CSQCModel_UnlinkEntity();
 +
 +                      // Hide beam
 +                      if(self.gun3.enemy || !wasfreed(self.gun3.enemy))
 +                              self.gun3.enemy.effects |= EF_NODRAW;
 +
 +                      if(self.gunner1)
 +                      {
 +                              setself(self.gunner1);
 +                              oldself.gun1.vehicle_exit(VHEF_EJECT);
 +                              setself(oldself);
 +                      }
 +
 +                      if(self.gunner2)
 +                      {
 +                              setself(self.gunner2);
 +                              oldself.gun2.vehicle_exit(VHEF_EJECT);
 +                              setself(oldself);
 +                      }
 +
 +                      self.vehicle_exit(VHEF_EJECT);
 +
 +                      fixedmakevectors(self.angles);
 +                      vehicle_tossgib(self.gun1, self.velocity + v_right * 300 + v_up * 100 + randomvec() * 200, "cannon_right", rint(random()), rint(random()), 6, randomvec() * 200);
 +                      vehicle_tossgib(self.gun2, self.velocity + v_right * -300 + v_up * 100 + randomvec() * 200, "cannon_left", rint(random()), rint(random()), 6, randomvec() * 200);
 +                      vehicle_tossgib(self.gun3, self.velocity + v_forward * 300 + v_up * -100 + randomvec() * 200, "raygun", rint(random()), rint(random()), 6, randomvec() * 300);
 +
 +                      entity _body = vehicle_tossgib(self, self.velocity + randomvec() * 200, "", rint(random()), rint(random()), 6, randomvec() * 100);
 +
 +                      if(random() > 0.5)
 +                              _body.touch = bumblebee_blowup;
 +                      else
 +                              _body.touch = func_null;
 +
 +                      _body.think = bumblebee_diethink;
 +                      _body.nextthink = time;
 +                      _body.wait = time + 2 + (random() * 8);
 +                      _body.owner = self;
 +                      _body.enemy = self.enemy;
 +                      _body.scale = 1.5;
 +                      _body.angles = self.angles;
 +
 +                      Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation(self.origin, 16), '0 0 0', 1);
 +
 +                      self.health                     = 0;
 +                      self.event_damage       = func_null;
 +                      self.solid                      = SOLID_NOT;
 +                      self.takedamage         = DAMAGE_NO;
 +                      self.deadflag           = DEAD_DYING;
 +                      self.movetype           = MOVETYPE_NONE;
 +                      self.effects            = EF_NODRAW;
 +                      self.colormod           = '0 0 0';
 +                      self.avelocity          = '0 0 0';
 +                      self.velocity           = '0 0 0';
 +                      self.touch                      = func_null;
 +                      self.nextthink          = 0;
 +
 +                      setorigin(self, self.pos1);
 +              }
 +              METHOD(Bumblebee, vr_spawn, void(Bumblebee thisveh))
 +              {
 +                      SELFPARAM();
 +                      if(!self.gun1)
 +                      {
 +                              // for some reason, autosizing of the shield entity refuses to work for this one so set it up in advance.
 +                              self.vehicle_shieldent = spawn();
 +                              self.vehicle_shieldent.effects = EF_LOWPRECISION;
 +                              setmodel(self.vehicle_shieldent, MDL_VEH_BUMBLEBEE_SHIELD);
 +                              setattachment(self.vehicle_shieldent, self, "");
 +                              setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
 +                              self.vehicle_shieldent.scale       = 512 / vlen(self.maxs - self.mins);
 +                              self.vehicle_shieldent.think       = shieldhit_think;
 +                              self.vehicle_shieldent.alpha = -1;
 +                              self.vehicle_shieldent.effects = EF_LOWPRECISION | EF_NODRAW;
 +
 +                              self.gun1 = spawn();
 +                              self.gun2 = spawn();
 +                              self.gun3 = spawn();
 +
 +                              self.vehicle_flags |= VHF_MULTISLOT;
 +
 +                              self.gun1.owner = self;
 +                              self.gun2.owner = self;
 +                              self.gun3.owner = self;
 +
 +                              self.gun1.classname = self.gun2.classname = "vehicle_playerslot";
 +
 +                              setmodel(self.gun1, MDL_VEH_BUMBLEBEE_CANNON_RIGHT);
 +                              setmodel(self.gun2, MDL_VEH_BUMBLEBEE_CANNON_LEFT);
 +                              setmodel(self.gun3, MDL_VEH_BUMBLEBEE_CANNON_CENTER);
 +
 +                              setattachment(self.gun1, self, "cannon_right");
 +                              setattachment(self.gun2, self, "cannon_left");
 +
 +                              // Angled bones are no fun, messes up gun-aim; so work arround it.
 +                              self.gun3.pos1 = self.angles;
 +                              self.angles = '0 0 0';
 +                              vector ofs = gettaginfo(self, gettagindex(self, "raygun"));
 +                              ofs -= self.origin;
 +                              setattachment(self.gun3, self, "");
 +                              setorigin(self.gun3, ofs);
 +                              self.angles = self.gun3.pos1;
 +
 +                              vehicle_addplayerslot(self, self.gun1, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
 +                              vehicle_addplayerslot(self, self.gun2, HUD_BUMBLEBEE_GUN, "models/vehicles/wakizashi_cockpit.dpm", bumblebee_gunner_frame, bumblebee_gunner_exit, bumblebee_gunner_enter);
 +
 +                              setorigin(self.vehicle_hudmodel, '50 0 -5');    // Move cockpit forward - down.
 +                              setorigin(self.vehicle_viewport, '5 0 2');    // Move camera forward up
 +
 +                              //fixme-model-bones
 +                              setorigin(self.gun1.vehicle_hudmodel, '90 -27 -23');
 +                              setorigin(self.gun1.vehicle_viewport, '-85 0 50');
 +                              //fixme-model-bones
 +                              setorigin(self.gun2.vehicle_hudmodel, '90 27 -23');
 +                              setorigin(self.gun2.vehicle_viewport, '-85 0 50');
 +
 +                              self.scale = 1.5;
 +
 +                              // Raygun beam
 +                              if(self.gun3.enemy == world)
 +                              {
 +                                      self.gun3.enemy = spawn();
 +                                      Net_LinkEntity(self.gun3.enemy, true, 0, bumble_raygun_send);
 +                                      self.gun3.enemy.SendFlags = BRG_SETUP;
 +                                      self.gun3.enemy.cnt = autocvar_g_vehicle_bumblebee_raygun;
 +                                      self.gun3.enemy.effects = EF_NODRAW | EF_LOWPRECISION;
 +                              }
 +                      }
 +
 +                      self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
 +                      self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
 +                      self.solid = SOLID_BBOX;
 +                      self.movetype = MOVETYPE_TOSS;
 +                      self.damageforcescale = 0.025;
 +
 +                      self.PlayerPhysplug = bumblebee_pilot_frame;
 +
 +                      setorigin(self, self.origin + '0 0 25');
 +              }
 +              METHOD(Bumblebee, vr_setup, void(Bumblebee thisveh))
 +              {
 +                      SELFPARAM();
 +                      if(autocvar_g_vehicle_bumblebee_energy)
 +                      if(autocvar_g_vehicle_bumblebee_energy_regen)
 +                              self.vehicle_flags |= VHF_ENERGYREGEN;
 +
 +                      if(autocvar_g_vehicle_bumblebee_shield)
 +                              self.vehicle_flags |= VHF_HASSHIELD;
 +
 +                      if(autocvar_g_vehicle_bumblebee_shield_regen)
 +                              self.vehicle_flags |= VHF_SHIELDREGEN;
 +
 +                      if(autocvar_g_vehicle_bumblebee_health_regen)
 +                              self.vehicle_flags |= VHF_HEALTHREGEN;
 +
 +                      self.vehicle_exit = bumblebee_exit;
 +                      self.respawntime = autocvar_g_vehicle_bumblebee_respawntime;
 +                      self.vehicle_health = autocvar_g_vehicle_bumblebee_health;
 +                      self.max_health = self.vehicle_health;
 +                      self.vehicle_shield = autocvar_g_vehicle_bumblebee_shield;
 +              }
 +
 +#endif // SVQC
 +#ifdef CSQC
 +
 +void CSQC_BUMBLE_GUN_HUD()
 +{
 +      Vehicles_drawHUD("vehicle_gunner", "vehicle_gunner_weapon1", string_null,
 +                                       "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
 +                                       string_null, '0 0 0',
 +                                       string_null);
 +}
 +
 +              METHOD(Bumblebee, vr_hud, void(Bumblebee thisveh))
 +              {
 +                      Vehicles_drawHUD(VEH_BUMBLEBEE.m_icon, "vehicle_bumble_weapon1", "vehicle_bumble_weapon2",
 +                                                       "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
 +                                                       "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
 +                                                       vCROSS_HEAL);
 +              }
 +              METHOD(Bumblebee, vr_setup, void(Bumblebee thisveh))
 +              {
 +                      AuxiliaryXhair[0].axh_image = vCROSS_LOCK;  // Raygun-locked
 +                      AuxiliaryXhair[1].axh_image = vCROSS_BURST; // Gunner1
 +                      AuxiliaryXhair[2].axh_image = vCROSS_BURST; // Gunner2
 +              }
 +
 +#endif
 +#endif
index e9211d5,0000000..b550180
mode 100644,000000..100644
--- /dev/null
@@@ -1,693 -1,0 +1,693 @@@
- void spawnfunc_vehicle_racer()
- {SELFPARAM();
 +#ifndef VEHICLE_RACER
 +#define VEHICLE_RACER
 +
 +#include "racer_weapon.qc"
 +
 +CLASS(Racer, Vehicle)
 +/* spawnflags */ ATTRIB(Racer, spawnflags, int, VHF_DMGSHAKE | VHF_DMGROLL);
 +/* mins       */ ATTRIB(Racer, mins, vector, '-120 -120 -40' * 0.5);
 +/* maxs       */ ATTRIB(Racer, maxs, vector, '120 120 40' * 0.5);
 +/* model        */ ATTRIB(Racer, mdl, string, "models/vehicles/wakizashi.dpm");
 +/* model        */ ATTRIB(Racer, model, string, "models/vehicles/wakizashi.dpm");
 +/* head_model */ ATTRIB(Racer, head_model, string, "null");
 +/* hud_model  */ ATTRIB(Racer, hud_model, string, "models/vehicles/wakizashi_cockpit.dpm");
 +/* tags       */ ATTRIB(Racer, tag_head, string, "");
 +/* tags       */ ATTRIB(Racer, tag_hud, string, "");
 +/* tags       */ ATTRIB(Racer, tag_view, string, "tag_viewport");
 +/* netname    */ ATTRIB(Racer, netname, string, "racer");
 +/* fullname   */ ATTRIB(Racer, vehicle_name, string, _("Racer"));
 +/* icon       */ ATTRIB(Racer, m_icon, string, "vehicle_racer");
 +ENDCLASS(Racer)
 +REGISTER_VEHICLE(RACER, NEW(Racer));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "racer_weapon.qc"
 +
 +#ifdef SVQC
 +#include "../../effects/effects.qh"
 +#include "../../triggers/trigger/impulse.qh"
 +
 +bool autocvar_g_vehicle_racer;
 +
 +float autocvar_g_vehicle_racer_speed_afterburn;
 +float autocvar_g_vehicle_racer_afterburn_cost;
 +
 +float autocvar_g_vehicle_racer_waterburn_cost;
 +float autocvar_g_vehicle_racer_waterburn_speed;
 +
 +float autocvar_g_vehicle_racer_water_speed_forward;
 +float autocvar_g_vehicle_racer_water_speed_strafe;
 +
 +float autocvar_g_vehicle_racer_pitchlimit = 30;
 +
 +float autocvar_g_vehicle_racer_water_downforce = 0.03;
 +float autocvar_g_vehicle_racer_water_upforcedamper = 15;
 +
 +float autocvar_g_vehicle_racer_anglestabilizer;
 +float autocvar_g_vehicle_racer_downforce;
 +
 +float autocvar_g_vehicle_racer_speed_forward;
 +float autocvar_g_vehicle_racer_speed_strafe;
 +float autocvar_g_vehicle_racer_springlength;
 +float autocvar_g_vehicle_racer_upforcedamper;
 +float autocvar_g_vehicle_racer_friction;
 +
 +float autocvar_g_vehicle_racer_water_time = 5;
 +
 +float autocvar_g_vehicle_racer_hovertype;
 +float autocvar_g_vehicle_racer_hoverpower;
 +
 +float autocvar_g_vehicle_racer_turnroll;
 +float autocvar_g_vehicle_racer_turnspeed;
 +float autocvar_g_vehicle_racer_pitchspeed;
 +
 +float autocvar_g_vehicle_racer_energy;
 +float autocvar_g_vehicle_racer_energy_regen;
 +float autocvar_g_vehicle_racer_energy_regen_pause;
 +
 +float autocvar_g_vehicle_racer_health;
 +float autocvar_g_vehicle_racer_health_regen;
 +float autocvar_g_vehicle_racer_health_regen_pause;
 +
 +float autocvar_g_vehicle_racer_shield;
 +float autocvar_g_vehicle_racer_shield_regen;
 +float autocvar_g_vehicle_racer_shield_regen_pause;
 +
 +float autocvar_g_vehicle_racer_rocket_locktarget;
 +float autocvar_g_vehicle_racer_rocket_locking_time;
 +float autocvar_g_vehicle_racer_rocket_locking_releasetime;
 +float autocvar_g_vehicle_racer_rocket_locked_time;
 +
 +float autocvar_g_vehicle_racer_respawntime;
 +
 +float autocvar_g_vehicle_racer_blowup_radius;
 +float autocvar_g_vehicle_racer_blowup_coredamage;
 +float autocvar_g_vehicle_racer_blowup_edgedamage;
 +float autocvar_g_vehicle_racer_blowup_forceintensity;
 +
 +float autocvar_g_vehicle_racer_bouncefactor;
 +float autocvar_g_vehicle_racer_bouncestop;
 +vector autocvar_g_vehicle_racer_bouncepain;
 +
 +.float racer_watertime;
 +
 +var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
 +
 +void racer_align4point(float _delta)
 +{SELFPARAM();
 +      vector push_vector;
 +      float fl_push, fr_push, bl_push, br_push;
 +
 +      push_vector  = racer_force_from_tag("tag_engine_fr", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
 +      fr_push   = force_fromtag_normpower;
 +      //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
 +
 +      push_vector += racer_force_from_tag("tag_engine_fl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
 +      fl_push   = force_fromtag_normpower;
 +      //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
 +
 +      push_vector += racer_force_from_tag("tag_engine_br", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
 +      br_push   = force_fromtag_normpower;
 +      //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
 +
 +      push_vector += racer_force_from_tag("tag_engine_bl", autocvar_g_vehicle_racer_springlength, autocvar_g_vehicle_racer_hoverpower);
 +      bl_push   = force_fromtag_normpower;
 +      //vehicles_sweap_collision(force_fromtag_origin, self.velocity, _delta, v_add, autocvar_g_vehicle_racer_collision_multiplier);
 +
 +      self.velocity += push_vector * _delta;
 +
 +      float uforce = autocvar_g_vehicle_racer_upforcedamper;
 +
 +      int cont = pointcontents(self.origin - '0 0 64');
 +      if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
 +      {
 +              uforce = autocvar_g_vehicle_racer_water_upforcedamper;
 +
 +              if(self.owner.BUTTON_CROUCH && time < self.air_finished)
 +                      self.velocity_z += 30;
 +              else
 +                      self.velocity_z += 200;
 +      }
 +
 +
 +      // Anti ocilation
 +      if(self.velocity_z > 0)
 +              self.velocity_z *= 1 - uforce * _delta;
 +
 +      push_vector_x =  (fl_push - bl_push);
 +      push_vector_x += (fr_push - br_push);
 +      push_vector_x *= 360;
 +
 +      push_vector_z = (fr_push - fl_push);
 +      push_vector_z += (br_push - bl_push);
 +      push_vector_z *= 360;
 +
 +      // Apply angle diffrance
 +      self.angles_z += push_vector_z * _delta;
 +      self.angles_x += push_vector_x * _delta;
 +
 +      // Apply stabilizer
 +      self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
 +      self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * _delta);
 +}
 +
 +void racer_fire_rocket_aim(string tagname, entity trg)
 +{
 +      SELFPARAM();
 +      vector v = gettaginfo(self, gettagindex(self, tagname));
 +      racer_fire_rocket(v, v_forward, trg);
 +}
 +
 +float racer_frame()
 +{SELFPARAM();
 +      entity player, racer;
 +      vector df;
 +      float ftmp;
 +
 +      if(intermission_running)
 +      {
 +              self.vehicle.velocity = '0 0 0';
 +              self.vehicle.avelocity = '0 0 0';
 +              return 1;
 +      }
 +
 +      player  = self;
 +      racer   = self.vehicle;
 +      setself(racer);
 +
 +      vehicles_painframe();
 +
 +      if(pointcontents(racer.origin) != CONTENT_WATER)
 +              racer.air_finished = time + autocvar_g_vehicle_racer_water_time;
 +
 +      if(racer.deadflag != DEAD_NO)
 +      {
 +              setself(player);
 +              player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
 +              return 1;
 +      }
 +
 +      racer_align4point(PHYS_INPUT_TIMELENGTH);
 +
 +      player.BUTTON_ZOOM = player.BUTTON_CROUCH = 0;
 +
 +      crosshair_trace(player);
 +
 +      racer.angles_x *= -1;
 +
 +      // Yaw
 +      ftmp = autocvar_g_vehicle_racer_turnspeed * PHYS_INPUT_TIMELENGTH;
 +      ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
 +      racer.angles_y = anglemods(racer.angles_y + ftmp);
 +
 +      // Roll
 +      racer.angles_z += -ftmp * autocvar_g_vehicle_racer_turnroll * PHYS_INPUT_TIMELENGTH;
 +
 +      // Pitch
 +      ftmp = autocvar_g_vehicle_racer_pitchspeed  * PHYS_INPUT_TIMELENGTH;
 +      ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - racer.angles_x, racer.angles_x), ftmp);
 +      racer.angles_x = bound(-autocvar_g_vehicle_racer_pitchlimit, anglemods(racer.angles_x + ftmp), autocvar_g_vehicle_racer_pitchlimit);
 +
 +      makevectors(racer.angles);
 +      racer.angles_x *= -1;
 +
 +      //ftmp = racer.velocity_z;
 +      df = racer.velocity * -autocvar_g_vehicle_racer_friction;
 +      //racer.velocity_z = ftmp;
 +
 +      int cont = pointcontents(racer.origin);
 +      if(vlen(player.movement) != 0)
 +      {
 +              if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
 +              {
 +                      if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_water_speed_forward : -autocvar_g_vehicle_racer_water_speed_forward); }
 +                      if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_water_speed_strafe : -autocvar_g_vehicle_racer_water_speed_strafe); }
 +              }
 +              else
 +              {
 +                      if(player.movement_x) { df += v_forward * ((player.movement_x > 0) ? autocvar_g_vehicle_racer_speed_forward : -autocvar_g_vehicle_racer_speed_forward); }
 +                      if(player.movement_y) { df += v_right * ((player.movement_y > 0) ? autocvar_g_vehicle_racer_speed_strafe : -autocvar_g_vehicle_racer_speed_strafe); }
 +              }
 +
 +#ifdef SVQC
 +              if(self.sound_nexttime < time || self.sounds != 1)
 +              {
 +                      self.sounds = 1;
 +                      self.sound_nexttime = time + 10.922667; //soundlength("vehicles/racer_move.wav");
 +                      sound (self, CH_TRIGGER_SINGLE, SND_VEH_RACER_MOVE, VOL_VEHICLEENGINE, ATTEN_NORM);
 +              }
 +#endif
 +      }
 +#ifdef SVQC
 +      else
 +      {
 +              if(self.sound_nexttime < time || self.sounds != 0)
 +              {
 +                      self.sounds = 0;
 +                      self.sound_nexttime = time + 11.888604; //soundlength("vehicles/racer_idle.wav");
 +                      sound (self, CH_TRIGGER_SINGLE, SND_VEH_RACER_IDLE, VOL_VEHICLEENGINE, ATTEN_NORM);
 +              }
 +      }
 +#endif
 +
 +      // Afterburn
 +      if (PHYS_INPUT_BUTTON_JUMP(player) && racer.vehicle_energy >= (autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH))
 +      {
 +#ifdef SVQC
 +              if(time - racer.wait > 0.2)
 +                      pointparticles(particleeffectnum(EFFECT_RACER_BOOSTER), self.origin - v_forward * 32, v_forward  * vlen(self.velocity), 1);
 +#endif
 +
 +              racer.wait = time;
 +
 +              if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
 +              {
 +                      racer.vehicle_energy -= autocvar_g_vehicle_racer_waterburn_cost * PHYS_INPUT_TIMELENGTH;
 +                      df += (v_forward * autocvar_g_vehicle_racer_waterburn_speed);
 +              }
 +              else
 +              {
 +                      racer.vehicle_energy -= autocvar_g_vehicle_racer_afterburn_cost * PHYS_INPUT_TIMELENGTH;
 +                      df += (v_forward * autocvar_g_vehicle_racer_speed_afterburn);
 +              }
 +
 +#ifdef SVQC
 +              if(racer.invincible_finished < time)
 +              {
 +                      traceline(racer.origin, racer.origin - '0 0 256', MOVE_NORMAL, self);
 +                      if(trace_fraction != 1.0)
 +                              pointparticles(particleeffectnum(EFFECT_SMOKE_SMALL), trace_endpos, '0 0 0', 1);
 +
 +                      racer.invincible_finished = time + 0.1 + (random() * 0.1);
 +              }
 +
 +              if(racer.strength_finished < time)
 +              {
 +                      racer.strength_finished = time + 10.922667; //soundlength("vehicles/racer_boost.wav");
 +                      sound (racer.tur_head, CH_TRIGGER_SINGLE, SND_VEH_RACER_BOOST, VOL_VEHICLEENGINE, ATTEN_NORM);
 +              }
 +#endif
 +      }
 +      else
 +      {
 +              racer.strength_finished = 0;
 +              sound (racer.tur_head, CH_TRIGGER_SINGLE, SND_Null, VOL_VEHICLEENGINE, ATTEN_NORM);
 +      }
 +
 +      if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
 +              racer.racer_watertime = time;
 +
 +      float dforce = autocvar_g_vehicle_racer_downforce;
 +      if(time - racer.racer_watertime <= 3)
 +              dforce = autocvar_g_vehicle_racer_water_downforce;
 +
 +      df -= v_up * (vlen(racer.velocity) * dforce);
 +      player.movement = racer.velocity += df * PHYS_INPUT_TIMELENGTH;
 +
 +#ifdef SVQC
 +      Weapon wep1 = WEP_RACER;
 +      if (!forbidWeaponUse(player))
 +      if (player.BUTTON_ATCK)
 +      if (wep1.wr_checkammo1(wep1))
 +      {
 +              string tagname = (racer.cnt)
 +                  ? (racer.cnt = 0, "tag_fire1")
 +                  : (racer.cnt = 1, "tag_fire2");
 +              vector org = gettaginfo(self, gettagindex(self, tagname));
 +              w_shotorg = org;
 +              w_shotdir = v_forward;
 +              // Fix z-aim (for chase mode)
 +              crosshair_trace(player);
 +              w_shotdir.z = normalize(trace_endpos - org).z * 0.5;
 +              wep1.wr_think(wep1, self, true, false);
 +      }
 +
 +      if(autocvar_g_vehicle_racer_rocket_locktarget)
 +      {
 +              vehicles_locktarget((1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime,
 +                                               (1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime,
 +                                               autocvar_g_vehicle_racer_rocket_locked_time);
 +
 +              if(self.lock_target)
 +              {
 +                      if(racer.lock_strength == 1)
 +                              UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '1 0 0', 0);
 +                      else if(self.lock_strength > 0.5)
 +                              UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 1 0', 0);
 +                      else if(self.lock_strength < 0.5)
 +                              UpdateAuxiliaryXhair(player, real_origin(self.lock_target), '0 0 1', 0);
 +              }
 +      }
 +
 +      if(!forbidWeaponUse(player))
 +      if(time > racer.delay)
 +      if(player.BUTTON_ATCK2)
 +      {
 +              racer.misc_bulletcounter += 1;
 +              racer.delay = time + 0.3;
 +
 +              if(racer.misc_bulletcounter == 1)
 +              {
 +                      racer_fire_rocket_aim("tag_rocket_r", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
 +                      player.vehicle_ammo2 = 50;
 +              }
 +              else if(racer.misc_bulletcounter == 2)
 +              {
 +                      racer_fire_rocket_aim("tag_rocket_l", (racer.lock_strength == 1 && racer.lock_target) ? racer.lock_target : world);
 +                      racer.lock_strength  = 0;
 +                      racer.lock_target       = world;
 +                      racer.misc_bulletcounter = 0;
 +                      racer.delay = time + autocvar_g_vehicle_racer_rocket_refire;
 +                      racer.lip = time;
 +                      player.vehicle_ammo2 = 0;
 +              }
 +      }
 +      else if(racer.misc_bulletcounter == 0)
 +              player.vehicle_ammo2 = 100;
 +
 +      player.vehicle_reload2 = bound(0, 100 * ((time - racer.lip) / (racer.delay - racer.lip)), 100);
 +
 +      if(racer.vehicle_flags  & VHF_SHIELDREGEN)
 +              vehicles_regen(racer.dmg_time, vehicle_shield, autocvar_g_vehicle_racer_shield, autocvar_g_vehicle_racer_shield_regen_pause, autocvar_g_vehicle_racer_shield_regen, frametime, true);
 +
 +      if(racer.vehicle_flags  & VHF_HEALTHREGEN)
 +              vehicles_regen(racer.dmg_time, vehicle_health, autocvar_g_vehicle_racer_health, autocvar_g_vehicle_racer_health_regen_pause, autocvar_g_vehicle_racer_health_regen, frametime, false);
 +
 +      if(racer.vehicle_flags  & VHF_ENERGYREGEN)
 +              vehicles_regen(racer.wait, vehicle_energy, autocvar_g_vehicle_racer_energy, autocvar_g_vehicle_racer_energy_regen_pause, autocvar_g_vehicle_racer_energy_regen, frametime, false);
 +
 +
 +      VEHICLE_UPDATE_PLAYER(player, health, racer);
 +      VEHICLE_UPDATE_PLAYER(player, energy, racer);
 +
 +      if(racer.vehicle_flags & VHF_HASSHIELD)
 +              VEHICLE_UPDATE_PLAYER(player, shield, racer);
 +
 +      player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
 +#endif
 +
 +      setorigin(player,racer.origin + '0 0 32');
 +      player.velocity = racer.velocity;
 +
 +      setself(player);
 +      return 1;
 +}
 +
 +void racer_think()
 +{SELFPARAM();
 +      self.nextthink = time;
 +
 +      float pushdeltatime = time - self.lastpushtime;
 +      if (pushdeltatime > 0.15) pushdeltatime = 0;
 +      self.lastpushtime = time;
 +      if(!pushdeltatime) return;
 +
 +      tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NOMONSTERS, self);
 +
 +      vector df = self.velocity * -autocvar_g_vehicle_racer_friction;
 +      df_z += (1 - trace_fraction) * autocvar_g_vehicle_racer_hoverpower + sin(time * 2) * (autocvar_g_vehicle_racer_springlength * 2);
 +
 +      float forced = autocvar_g_vehicle_racer_upforcedamper;
 +
 +      int cont = pointcontents(self.origin - '0 0 64');
 +      if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
 +      {
 +              forced = autocvar_g_vehicle_racer_water_upforcedamper;
 +              self.velocity_z += 200;
 +      }
 +
 +      self.velocity += df * pushdeltatime;
 +      if(self.velocity_z > 0)
 +              self.velocity_z *= 1 - forced * pushdeltatime;
 +
 +      self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
 +      self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
 +
 +      CSQCMODEL_AUTOUPDATE(self);
 +}
 +
 +void racer_exit(float eject)
 +{SELFPARAM();
 +      vector spot;
 +
 +      self.think        = racer_think;
 +      self.nextthink  = time;
 +      self.movetype   = MOVETYPE_BOUNCE;
 +      sound (self.tur_head, CH_TRIGGER_SINGLE, SND_Null, VOL_VEHICLEENGINE, ATTEN_NORM);
 +
 +      if(!self.owner)
 +              return;
 +
 +      makevectors(self.angles);
 +      if(eject)
 +      {
 +              spot = self.origin + v_forward * 100 + '0 0 64';
 +              spot = vehicles_findgoodexit(spot);
 +              setorigin(self.owner , spot);
 +              self.owner.velocity = (v_up + v_forward * 0.25) * 750;
 +              self.owner.oldvelocity = self.owner.velocity;
 +      }
 +      else
 +      {
 +              if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
 +              {
 +                      self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
 +                      self.owner.velocity_z += 200;
 +                      spot = self.origin + v_forward * 32 + '0 0 32';
 +                      spot = vehicles_findgoodexit(spot);
 +              }
 +              else
 +              {
 +                      self.owner.velocity = self.velocity * 0.5;
 +                      self.owner.velocity_z += 10;
 +                      spot = self.origin - v_forward * 200 + '0 0 32';
 +                      spot = vehicles_findgoodexit(spot);
 +              }
 +              self.owner.oldvelocity = self.owner.velocity;
 +              setorigin(self.owner , spot);
 +      }
 +      antilag_clear(self.owner);
 +      self.owner = world;
 +}
 +
 +void racer_blowup()
 +{SELFPARAM();
 +      self.deadflag   = DEAD_DEAD;
 +      self.vehicle_exit(VHEF_NORMAL);
 +
 +      RadiusDamage (self, self.enemy, autocvar_g_vehicle_racer_blowup_coredamage,
 +                                      autocvar_g_vehicle_racer_blowup_edgedamage,
 +                                      autocvar_g_vehicle_racer_blowup_radius, world, world,
 +                                      autocvar_g_vehicle_racer_blowup_forceintensity,
 +                                      DEATH_VH_WAKI_DEATH, world);
 +
 +      self.nextthink  = time + autocvar_g_vehicle_racer_respawntime;
 +      self.think        = vehicles_spawn;
 +      self.movetype   = MOVETYPE_NONE;
 +      self.effects    = EF_NODRAW;
 +
 +      self.colormod  = '0 0 0';
 +      self.avelocity = '0 0 0';
 +      self.velocity  = '0 0 0';
 +
 +      setorigin(self, self.pos1);
 +}
 +
 +void racer_blowup_think()
 +{SELFPARAM();
 +      self.nextthink = time;
 +
 +      if(time >= self.delay)
 +              racer_blowup();
 +
 +      CSQCMODEL_AUTOUPDATE(self);
 +}
 +
 +void racer_deadtouch()
 +{SELFPARAM();
 +      self.avelocity_x *= 0.7;
 +      self.cnt -= 1;
 +      if(self.cnt <= 0)
 +              racer_blowup();
 +}
 +
++spawnfunc(vehicle_racer)
++{
 +      if(!autocvar_g_vehicle_racer) { remove(self); return; }
 +      if(!vehicle_initialize(VEH_RACER, false)) { remove(self); return; }
 +}
 +
 +#endif // SVQC
 +
 +#ifdef CSQC
 +#if 0
 +void racer_draw()
 +{SELFPARAM();
 +      float pushdeltatime = time - self.lastpushtime;
 +      if (pushdeltatime > 0.15) pushdeltatime = 0;
 +      self.lastpushtime = time;
 +      if(!pushdeltatime) return;
 +
 +      tracebox(self.move_origin, self.mins, self.maxs, self.move_origin - ('0 0 1' * getstatf(STAT_VEH_RACER_SPRINGLENGTH)), MOVE_NOMONSTERS, self);
 +
 +      vector df = self.move_velocity * -getstatf(STAT_VEH_RACER_FRICTION);
 +      df_z += (1 - trace_fraction) * getstatf(STAT_VEH_RACER_HOVERPOWER) + sin(time * 2) * (getstatf(STAT_VEH_RACER_SPRINGLENGTH) * 2);
 +
 +      float forced = getstatf(STAT_VEH_RACER_UPFORCEDAMPER);
 +
 +      int cont = pointcontents(self.move_origin - '0 0 64');
 +      if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
 +      {
 +              forced = getstatf(STAT_VEH_RACER_WATER_UPFORCEDAMPER);
 +              self.move_velocity_z += 200;
 +      }
 +
 +      self.move_velocity += df * pushdeltatime;
 +      if(self.move_velocity_z > 0)
 +              self.move_velocity_z *= 1 - forced * pushdeltatime;
 +
 +      self.move_angles_x *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
 +      self.move_angles_z *= 1 - (getstatf(STAT_VEH_RACER_ANGLESTABILIZER) * pushdeltatime);
 +
 +      Movetype_Physics_MatchServer(false);
 +}
 +#endif
 +#endif
 +
 +              METHOD(Racer, vr_impact, void(Racer thisveh))
 +              {
 +              #ifdef SVQC
 +                      if(autocvar_g_vehicle_racer_bouncepain)
 +                              vehicles_impact(autocvar_g_vehicle_racer_bouncepain_x, autocvar_g_vehicle_racer_bouncepain_y, autocvar_g_vehicle_racer_bouncepain_z);
 +              #endif
 +              }
 +
 +              METHOD(Racer, vr_enter, void(Racer thisveh))
 +              {
 +              #ifdef SVQC
 +                      self.movetype = MOVETYPE_BOUNCE;
 +                      self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_racer_health)  * 100;
 +                      self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_racer_shield)  * 100;
 +
 +                      if(self.owner.flagcarried)
 +                         setorigin(self.owner.flagcarried, '-190 0 96');
 +              #elif defined(CSQC)
 +
 +                      self.move_movetype = MOVETYPE_BOUNCE;
 +              #endif
 +              }
 +
 +              METHOD(Racer, vr_spawn, void(Racer thisveh))
 +              {
 +              #ifdef SVQC
 +                      if(self.scale != 0.5)
 +                      {
 +                              if(autocvar_g_vehicle_racer_hovertype != 0)
 +                                      racer_force_from_tag = vehicles_force_fromtag_maglev;
 +                              else
 +                                      racer_force_from_tag = vehicles_force_fromtag_hover;
 +
 +                              // FIXME: this be hakkz, fix the models insted (scale body, add tag_viewport to the hudmodel).
 +                              self.scale = 0.5;
 +                              setattachment(self.vehicle_hudmodel, self, "");
 +                              setattachment(self.vehicle_viewport, self, "tag_viewport");
 +
 +                              self.mass                          = 900;
 +                      }
 +
 +                      self.think                = racer_think;
 +                      self.nextthink    = time;
 +                      self.vehicle_health = autocvar_g_vehicle_racer_health;
 +                      self.vehicle_shield = autocvar_g_vehicle_racer_shield;
 +
 +                      self.movetype     = MOVETYPE_TOSS;
 +                      self.solid                = SOLID_SLIDEBOX;
 +                      self.delay                = time;
 +                      self.scale                = 0.5;
 +
 +                      self.PlayerPhysplug = racer_frame;
 +
 +                      self.bouncefactor = autocvar_g_vehicle_racer_bouncefactor;
 +                      self.bouncestop = autocvar_g_vehicle_racer_bouncestop;
 +                      self.damageforcescale = 0.5;
 +                      self.vehicle_health = autocvar_g_vehicle_racer_health;
 +                      self.vehicle_shield = autocvar_g_vehicle_racer_shield;
 +              #endif
 +              }
 +
 +              METHOD(Racer, vr_death, void(Racer thisveh))
 +              {
 +              #ifdef SVQC
 +                      self.SendEntity         = func_null; // stop networking this racer (for now)
 +                      self.health                     = 0;
 +                      self.event_damage       = func_null;
 +                      self.solid                      = SOLID_CORPSE;
 +                      self.takedamage         = DAMAGE_NO;
 +                      self.deadflag           = DEAD_DYING;
 +                      self.movetype           = MOVETYPE_BOUNCE;
 +                      self.wait                       = time;
 +                      self.delay                      = 2 + time + random() * 3;
 +                      self.cnt                        = 1 + random() * 2;
 +                      self.touch                      = racer_deadtouch;
 +
 +                      Send_Effect(EFFECT_EXPLOSION_MEDIUM, self.origin, '0 0 0', 1);
 +
 +                      if(random() < 0.5)
 +                              self.avelocity_z = 32;
 +                      else
 +                              self.avelocity_z = -32;
 +
 +                      self.avelocity_x = -vlen(self.velocity) * 0.2;
 +                      self.velocity += '0 0 700';
 +                      self.colormod = '-0.5 -0.5 -0.5';
 +
 +                      self.think = racer_blowup_think;
 +                      self.nextthink = time;
 +              #endif
 +              }
 +
 +#ifdef CSQC
 +              METHOD(Racer, vr_hud, void(Racer thisveh))
 +              {
 +                      Vehicles_drawHUD(VEH_RACER.m_icon, "vehicle_racer_weapon1", "vehicle_racer_weapon2",
 +                                                       "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
 +                                                       "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
 +                                                       vCROSS_GUIDE);
 +              }
 +#endif
 +              METHOD(Racer, vr_setup, void(Racer thisveh))
 +              {
 +              #ifdef SVQC
 +                      self.vehicle_exit = racer_exit;
 +              #endif
 +
 +              #ifdef SVQC
 +                      // we have no need to network energy
 +                      if(autocvar_g_vehicle_racer_energy)
 +                      if(autocvar_g_vehicle_racer_energy_regen)
 +                              self.vehicle_flags |= VHF_ENERGYREGEN;
 +
 +                      if(autocvar_g_vehicle_racer_shield)
 +                              self.vehicle_flags |= VHF_HASSHIELD;
 +
 +                      if(autocvar_g_vehicle_racer_shield_regen)
 +                              self.vehicle_flags |= VHF_SHIELDREGEN;
 +
 +                      if(autocvar_g_vehicle_racer_health_regen)
 +                              self.vehicle_flags |= VHF_HEALTHREGEN;
 +
 +                      self.respawntime = autocvar_g_vehicle_racer_respawntime;
 +                      self.vehicle_health = autocvar_g_vehicle_racer_health;
 +                      self.vehicle_shield = autocvar_g_vehicle_racer_shield;
 +                      self.max_health = self.vehicle_health;
 +              #endif
 +
 +              #ifdef CSQC
 +                      AuxiliaryXhair[0].axh_image = vCROSS_LOCK; // Rocket
 +              #endif
 +              }
 +
 +#endif
index db3d880,0000000..1f62337
mode 100644,000000..100644
--- /dev/null
@@@ -1,797 -1,0 +1,797 @@@
- void spawnfunc_vehicle_raptor()
- {SELFPARAM();
 +#ifndef VEHICLE_RAPTOR
 +#define VEHICLE_RAPTOR
 +#include "raptor.qh"
 +
 +#include "raptor_weapons.qc"
 +
 +CLASS(Raptor, Vehicle)
 +/* spawnflags */ ATTRIB(Raptor, spawnflags, int, VHF_DMGSHAKE | VHF_DMGROLL);
 +/* mins       */ ATTRIB(Raptor, mins, vector, '-80 -80 0');
 +/* maxs       */ ATTRIB(Raptor, maxs, vector, '80 80 70');
 +/* model        */ ATTRIB(Raptor, mdl, string, "models/vehicles/raptor.dpm");
 +/* model        */ ATTRIB(Raptor, model, string, "models/vehicles/raptor.dpm");
 +/* head_model */ ATTRIB(Raptor, head_model, string, "");
 +/* hud_model  */ ATTRIB(Raptor, hud_model, string, "models/vehicles/raptor_cockpit.dpm");
 +/* tags       */ ATTRIB(Raptor, tag_head, string, "");
 +/* tags       */ ATTRIB(Raptor, tag_hud, string, "tag_hud");
 +/* tags       */ ATTRIB(Raptor, tag_view, string, "tag_camera");
 +/* netname    */ ATTRIB(Raptor, netname, string, "raptor");
 +/* fullname   */ ATTRIB(Raptor, vehicle_name, string, _("Raptor"));
 +/* icon       */ ATTRIB(Raptor, m_icon, string, "vehicle_raptor");
 +ENDCLASS(Raptor)
 +REGISTER_VEHICLE(RAPTOR, NEW(Raptor));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +#include "raptor_weapons.qc"
 +
 +#ifdef SVQC
 +
 +bool autocvar_g_vehicle_raptor;
 +
 +float autocvar_g_vehicle_raptor_respawntime;
 +float autocvar_g_vehicle_raptor_takeofftime;
 +
 +float autocvar_g_vehicle_raptor_movestyle;
 +float autocvar_g_vehicle_raptor_turnspeed;
 +float autocvar_g_vehicle_raptor_pitchspeed;
 +float autocvar_g_vehicle_raptor_pitchlimit;
 +
 +float autocvar_g_vehicle_raptor_speed_forward;
 +float autocvar_g_vehicle_raptor_speed_strafe;
 +float autocvar_g_vehicle_raptor_speed_up;
 +float autocvar_g_vehicle_raptor_speed_down;
 +float autocvar_g_vehicle_raptor_friction;
 +
 +float autocvar_g_vehicle_raptor_cannon_turnspeed;
 +float autocvar_g_vehicle_raptor_cannon_turnlimit;
 +float autocvar_g_vehicle_raptor_cannon_pitchlimit_up;
 +float autocvar_g_vehicle_raptor_cannon_pitchlimit_down;
 +
 +float autocvar_g_vehicle_raptor_cannon_locktarget;
 +float autocvar_g_vehicle_raptor_cannon_locking_time;
 +float autocvar_g_vehicle_raptor_cannon_locking_releasetime;
 +float autocvar_g_vehicle_raptor_cannon_locked_time;
 +float autocvar_g_vehicle_raptor_cannon_predicttarget;
 +
 +float autocvar_g_vehicle_raptor_energy;
 +float autocvar_g_vehicle_raptor_energy_regen;
 +float autocvar_g_vehicle_raptor_energy_regen_pause;
 +
 +float autocvar_g_vehicle_raptor_health;
 +float autocvar_g_vehicle_raptor_health_regen;
 +float autocvar_g_vehicle_raptor_health_regen_pause;
 +
 +float autocvar_g_vehicle_raptor_shield;
 +float autocvar_g_vehicle_raptor_shield_regen;
 +float autocvar_g_vehicle_raptor_shield_regen_pause;
 +
 +float autocvar_g_vehicle_raptor_bouncefactor;
 +float autocvar_g_vehicle_raptor_bouncestop;
 +vector autocvar_g_vehicle_raptor_bouncepain;
 +
 +.entity bomb1;
 +.entity bomb2;
 +
 +float raptor_altitude(float amax)
 +{SELFPARAM();
 +      tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * amax), MOVE_WORLDONLY, self);
 +      return vlen(self.origin - trace_endpos);
 +}
 +
 +void raptor_land()
 +{SELFPARAM();
 +      float hgt;
 +
 +      hgt = raptor_altitude(512);
 +      self.velocity = (self.velocity * 0.9) + ('0 0 -1800' * (hgt / 256) * sys_frametime);
 +      self.angles_x *= 0.95;
 +      self.angles_z *= 0.95;
 +
 +      if(hgt < 128)
 +      if(hgt > 0)
 +              self.frame = (hgt / 128) * 25;
 +
 +      self.bomb1.gun1.avelocity_y = 90 + ((self.frame / 25) * 2000);
 +      self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
 +
 +      if(hgt < 16)
 +      {
 +              self.movetype = MOVETYPE_TOSS;
 +              self.think      = vehicles_think;
 +              self.frame      = 0;
 +      }
 +
 +      self.nextthink  = time;
 +
 +      CSQCMODEL_AUTOUPDATE(self);
 +}
 +
 +void raptor_exit(float eject)
 +{SELFPARAM();
 +      vector spot;
 +      self.tur_head.exteriormodeltoclient = world;
 +
 +      if(self.deadflag == DEAD_NO)
 +      {
 +              self.think        = raptor_land;
 +              self.nextthink  = time;
 +      }
 +
 +      if(!self.owner)
 +              return;
 +
 +      makevectors(self.angles);
 +      if(eject)
 +      {
 +              spot = self.origin + v_forward * 100 + '0 0 64';
 +              spot = vehicles_findgoodexit(spot);
 +              setorigin(self.owner , spot);
 +              self.owner.velocity = (v_up + v_forward * 0.25) * 750;
 +              self.owner.oldvelocity = self.owner.velocity;
 +      }
 +      else
 +      {
 +              if(vlen(self.velocity) > 2 * autocvar_sv_maxairspeed)
 +              {
 +                      self.owner.velocity = normalize(self.velocity) * autocvar_sv_maxairspeed * 2;
 +                      self.owner.velocity_z += 200;
 +                      spot = self.origin + v_forward * 32 + '0 0 64';
 +                      spot = vehicles_findgoodexit(spot);
 +              }
 +              else
 +              {
 +                      self.owner.velocity = self.velocity * 0.5;
 +                      self.owner.velocity_z += 10;
 +                      spot = self.origin - v_forward * 200 + '0 0 64';
 +                      spot = vehicles_findgoodexit(spot);
 +              }
 +              self.owner.oldvelocity = self.owner.velocity;
 +              setorigin(self.owner , spot);
 +      }
 +
 +      antilag_clear(self.owner);
 +      self.owner = world;
 +}
 +
 +float raptor_frame()
 +{SELFPARAM();
 +      entity player, raptor;
 +      float ftmp = 0;
 +      vector df;
 +
 +      if(intermission_running)
 +      {
 +              self.vehicle.velocity = '0 0 0';
 +              self.vehicle.avelocity = '0 0 0';
 +              return 1;
 +      }
 +
 +      player = self;
 +      raptor = self.vehicle;
 +      setself(raptor);
 +
 +      vehicles_painframe();
 +      /*
 +      ftmp = vlen(self.velocity);
 +      if(ftmp > autocvar_g_vehicle_raptor_speed_forward)
 +              ftmp = 1;
 +      else
 +              ftmp = ftmp / autocvar_g_vehicle_raptor_speed_forward;
 +      */
 +
 +      if(self.sound_nexttime < time)
 +      {
 +              self.sound_nexttime = time + 7.955812;
 +              //sound (self.tur_head, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_FLY, 1 - ftmp,   ATTEN_NORM );
 +              sound (self, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_SPEED, 1, ATTEN_NORM);
 +              self.wait = ftmp;
 +      }
 +      /*
 +      else if(fabs(ftmp - self.wait) > 0.2)
 +      {
 +              sound (self.tur_head, CH_TRIGGER_SINGLE, SND_Null, 1 - ftmp,   ATTEN_NORM );
 +              sound (self, CH_TRIGGER_SINGLE, SND_Null, ftmp, ATTEN_NORM);
 +              self.wait = ftmp;
 +      }
 +      */
 +
 +      if(raptor.deadflag != DEAD_NO)
 +      {
 +              setself(player);
 +              player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
 +              return 1;
 +      }
 +      crosshair_trace(player);
 +
 +      //if(time - self.lastteleporttime < 1)
 +      //{
 +              if(raptor.angles_z > 50 || raptor.angles_z < -50)
 +              {
 +                      if(player.BUTTON_JUMP)
 +                      {
 +                              player.BUTTON_CROUCH = true;
 +                              player.BUTTON_JUMP = false;
 +                      }
 +              }
 +      //}
 +
 +      vector vang;
 +      vang = raptor.angles;
 +      df = vectoangles(normalize(trace_endpos - self.origin + '0 0 32'));
 +      vang_x *= -1;
 +      df_x *= -1;
 +      if(df_x > 180)  df_x -= 360;
 +      if(df_x < -180) df_x += 360;
 +      if(df_y > 180)  df_y -= 360;
 +      if(df_y < -180) df_y += 360;
 +
 +      ftmp = shortangle_f(player.v_angle_y - vang_y, vang_y);
 +      if(ftmp > 180)  ftmp -= 360; if(ftmp < -180) ftmp += 360;
 +      raptor.avelocity_y = bound(-autocvar_g_vehicle_raptor_turnspeed, ftmp + raptor.avelocity_y * 0.9, autocvar_g_vehicle_raptor_turnspeed);
 +
 +      // Pitch
 +      ftmp = 0;
 +      if(player.movement_x > 0 && vang_x < autocvar_g_vehicle_raptor_pitchlimit) ftmp = 5;
 +      else if(player.movement_x < 0 && vang_x > -autocvar_g_vehicle_raptor_pitchlimit) ftmp = -20;
 +
 +      df_x = bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x , autocvar_g_vehicle_raptor_pitchlimit);
 +      ftmp = vang_x - bound(-autocvar_g_vehicle_raptor_pitchlimit, df_x + ftmp, autocvar_g_vehicle_raptor_pitchlimit);
 +      raptor.avelocity_x = bound(-autocvar_g_vehicle_raptor_pitchspeed, ftmp + raptor.avelocity_x * 0.9, autocvar_g_vehicle_raptor_pitchspeed);
 +
 +      raptor.angles_x = anglemods(raptor.angles_x);
 +      raptor.angles_y = anglemods(raptor.angles_y);
 +      raptor.angles_z = anglemods(raptor.angles_z);
 +
 +      if(autocvar_g_vehicle_raptor_movestyle == 1)
 +              makevectors('0 1 0' * raptor.angles_y);
 +      else
 +              makevectors(player.v_angle);
 +
 +      df = raptor.velocity * -autocvar_g_vehicle_raptor_friction;
 +
 +      if(player.movement_x != 0)
 +      {
 +              if(player.movement_x > 0)
 +                      df += v_forward  * autocvar_g_vehicle_raptor_speed_forward;
 +              else if(player.movement_x < 0)
 +                      df -= v_forward  * autocvar_g_vehicle_raptor_speed_forward;
 +      }
 +
 +      if(player.movement_y != 0)
 +      {
 +              if(player.movement_y < 0)
 +                      df -= v_right * autocvar_g_vehicle_raptor_speed_strafe;
 +              else if(player.movement_y > 0)
 +                      df += v_right * autocvar_g_vehicle_raptor_speed_strafe;
 +
 +              raptor.angles_z = bound(-30,raptor.angles_z + (player.movement_y / autocvar_g_vehicle_raptor_speed_strafe),30);
 +      }
 +      else
 +      {
 +              raptor.angles_z *= 0.95;
 +              if(raptor.angles_z >= -1 && raptor.angles_z <= -1)
 +                      raptor.angles_z = 0;
 +      }
 +
 +      if(player.BUTTON_CROUCH)
 +              df -=   v_up * autocvar_g_vehicle_raptor_speed_down;
 +      else if (player.BUTTON_JUMP)
 +              df +=  v_up * autocvar_g_vehicle_raptor_speed_up;
 +
 +      raptor.velocity  += df * frametime;
 +      player.velocity = player.movement  = raptor.velocity;
 +      setorigin(player, raptor.origin + '0 0 32');
 +
 +      player.vehicle_weapon2mode = raptor.vehicle_weapon2mode;
 +
 +      vector vf, ad;
 +      // Target lock & predict
 +      if(autocvar_g_vehicle_raptor_cannon_locktarget == 2)
 +      {
 +              if(raptor.gun1.lock_time < time || raptor.gun1.enemy.deadflag)
 +                      raptor.gun1.enemy = world;
 +
 +              if(trace_ent)
 +              if(trace_ent.movetype)
 +              if(trace_ent.takedamage)
 +              if(!trace_ent.deadflag)
 +              {
 +                      if(teamplay)
 +                      {
 +                              if(trace_ent.team != player.team)
 +                              {
 +                                      raptor.gun1.enemy = trace_ent;
 +                                      raptor.gun1.lock_time = time + 5;
 +                              }
 +                      }
 +                      else
 +                      {
 +                              raptor.gun1.enemy = trace_ent;
 +                              raptor.gun1.lock_time = time + 0.5;
 +                      }
 +              }
 +
 +              if(raptor.gun1.enemy)
 +              {
 +                      float distance, impact_time;
 +
 +                      vf = real_origin(raptor.gun1.enemy);
 +                      UpdateAuxiliaryXhair(player, vf, '1 0 0', 1);
 +                      vector _vel = raptor.gun1.enemy.velocity;
 +                      if(raptor.gun1.enemy.movetype == MOVETYPE_WALK)
 +                              _vel_z *= 0.1;
 +
 +                      if(autocvar_g_vehicle_raptor_cannon_predicttarget)
 +                      {
 +                              ad = vf;
 +                              distance = vlen(ad - player.origin);
 +                              impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
 +                              ad = vf + _vel * impact_time;
 +                              trace_endpos = ad;
 +                      }
 +                      else
 +                              trace_endpos = vf;
 +              }
 +      }
 +      else if(autocvar_g_vehicle_raptor_cannon_locktarget == 1)
 +      {
 +
 +              vehicles_locktarget((1 / autocvar_g_vehicle_raptor_cannon_locking_time) * frametime,
 +                                                       (1 / autocvar_g_vehicle_raptor_cannon_locking_releasetime) * frametime,
 +                                                       autocvar_g_vehicle_raptor_cannon_locked_time);
 +
 +              if(self.lock_target != world)
 +              if(autocvar_g_vehicle_raptor_cannon_predicttarget)
 +              if(self.lock_strength == 1)
 +              {
 +                      float i, distance, impact_time;
 +
 +                      vf = real_origin(raptor.lock_target);
 +                      ad = vf;
 +                      for(i = 0; i < 4; ++i)
 +                      {
 +                              distance = vlen(ad - raptor.origin);
 +                              impact_time = distance / autocvar_g_vehicle_raptor_cannon_speed;
 +                              ad = vf + raptor.lock_target.velocity * impact_time;
 +                      }
 +                      trace_endpos = ad;
 +              }
 +
 +              if(self.lock_target)
 +              {
 +                      if(raptor.lock_strength == 1)
 +                              UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '1 0 0', 1);
 +                      else if(self.lock_strength > 0.5)
 +                              UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 1 0', 1);
 +                      else if(self.lock_strength < 0.5)
 +                              UpdateAuxiliaryXhair(player, real_origin(raptor.lock_target), '0 0 1', 1);
 +              }
 +      }
 +
 +
 +      vehicle_aimturret(raptor, trace_endpos, raptor.gun1, "fire1",
 +                                                autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1,  autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
 +                                                autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed);
 +
 +      vehicle_aimturret(raptor, trace_endpos, raptor.gun2, "fire1",
 +                                                autocvar_g_vehicle_raptor_cannon_pitchlimit_down * -1,  autocvar_g_vehicle_raptor_cannon_pitchlimit_up,
 +                                                autocvar_g_vehicle_raptor_cannon_turnlimit * -1,  autocvar_g_vehicle_raptor_cannon_turnlimit,  autocvar_g_vehicle_raptor_cannon_turnspeed);
 +
 +      /*
 +      ad = ad * 0.5;
 +      v_forward = vf * 0.5;
 +      traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, raptor);
 +      UpdateAuxiliaryXhair(player, trace_endpos, '0 1 0', 0);
 +      */
 +
 +      Weapon wep1 = WEP_RAPTOR;
 +      if(!forbidWeaponUse(player))
 +      if(player.BUTTON_ATCK)
 +      if (wep1.wr_checkammo1(wep1))
 +      {
 +              wep1.wr_think(wep1, self, true, false);
 +      }
 +
 +      if(self.vehicle_flags  & VHF_SHIELDREGEN)
 +              vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
 +
 +      if(self.vehicle_flags  & VHF_HEALTHREGEN)
 +              vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
 +
 +      if(self.vehicle_flags  & VHF_ENERGYREGEN)
 +              vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
 +
 +      Weapon wep2a = WEP_RAPTOR_BOMB;
 +      if(!forbidWeaponUse(player))
 +      if(raptor.vehicle_weapon2mode == RSM_BOMB)
 +      {
 +              if(time > raptor.lip + autocvar_g_vehicle_raptor_bombs_refire)
 +              if(player.BUTTON_ATCK2)
 +              {
 +                      wep2a.wr_think(wep2a, self, false, true);
 +                      raptor.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
 +                      raptor.lip   = time;
 +              }
 +      }
 +      else
 +      {
 +              Weapon wep2b = WEP_RAPTOR_FLARE;
 +              if(time > raptor.lip + autocvar_g_vehicle_raptor_flare_refire)
 +              if(player.BUTTON_ATCK2)
 +              {
 +                      wep2b.wr_think(wep2b, self, false, true);
 +                      raptor.delay = time + autocvar_g_vehicle_raptor_flare_refire;
 +                      raptor.lip   = time;
 +              }
 +      }
 +
 +      raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
 +      player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
 +      player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0;
 +
 +      if(self.bomb1.cnt < time)
 +      {
 +              entity _missile = findchainentity(enemy, raptor);
 +              float _incomming = 0;
 +              while(_missile)
 +              {
 +                      if(_missile.flags & FL_PROJECTILE)
 +                      if(MISSILE_IS_TRACKING(_missile))
 +                      if(vlen(self.origin - _missile.origin) < 2 * autocvar_g_vehicle_raptor_flare_range)
 +                              ++_incomming;
 +
 +                      _missile = _missile.chain;
 +              }
 +
 +              if(_incomming)
 +                      sound(self, CH_PAIN_SINGLE, SND_VEH_MISSILE_ALARM, VOL_BASE, ATTEN_NONE);
 +
 +              self.bomb1.cnt = time + 1;
 +      }
 +
 +
 +      VEHICLE_UPDATE_PLAYER(player, health, raptor);
 +      VEHICLE_UPDATE_PLAYER(player, energy, raptor);
 +      if(self.vehicle_flags & VHF_HASSHIELD)
 +              VEHICLE_UPDATE_PLAYER(player, shield, raptor);
 +
 +      player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
 +
 +      setself(player);
 +      return 1;
 +}
 +
 +float raptor_takeoff()
 +{SELFPARAM();
 +      entity player, raptor;
 +
 +      player = self;
 +      raptor = self.vehicle;
 +      setself(raptor);
 +
 +      self.nextthink = time;
 +      CSQCMODEL_AUTOUPDATE(self);
 +      self.nextthink = 0; // will this work?
 +
 +      if(self.sound_nexttime < time)
 +      {
 +              self.sound_nexttime = time + 7.955812; //soundlength("vehicles/raptor_fly.wav");
 +              sound (self, CH_TRIGGER_SINGLE, SND_VEH_RAPTOR_SPEED, VOL_VEHICLEENGINE, ATTEN_NORM);
 +      }
 +
 +      // Takeoff sequense
 +      if(raptor.frame < 25)
 +      {
 +              raptor.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / sys_frametime);
 +              raptor.velocity_z = min(raptor.velocity_z * 1.5, 256);
 +              self.bomb1.gun1.avelocity_y = 90 + ((raptor.frame / 25) * 25000);
 +              self.bomb1.gun2.avelocity_y = -self.bomb1.gun1.avelocity_y;
 +              player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
 +
 +              setorigin(player, raptor.origin + '0 0 32');
 +      }
 +      else
 +              player.PlayerPhysplug = raptor_frame;
 +
 +      if(self.vehicle_flags  & VHF_SHIELDREGEN)
 +              vehicles_regen(raptor.dmg_time, vehicle_shield, autocvar_g_vehicle_raptor_shield, autocvar_g_vehicle_raptor_shield_regen_pause, autocvar_g_vehicle_raptor_shield_regen, frametime, true);
 +
 +      if(self.vehicle_flags  & VHF_HEALTHREGEN)
 +              vehicles_regen(raptor.dmg_time, vehicle_health, autocvar_g_vehicle_raptor_health, autocvar_g_vehicle_raptor_health_regen_pause, autocvar_g_vehicle_raptor_health_regen, frametime, false);
 +
 +      if(self.vehicle_flags  & VHF_ENERGYREGEN)
 +              vehicles_regen(raptor.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, frametime, false);
 +
 +
 +      raptor.bomb1.alpha = raptor.bomb2.alpha = (time - raptor.lip) / (raptor.delay - raptor.lip);
 +      player.vehicle_reload2 = bound(0, raptor.bomb1.alpha * 100, 100);
 +      player.vehicle_ammo2 = (player.vehicle_reload2 == 100) ? 100 : 0;
 +
 +      VEHICLE_UPDATE_PLAYER(player, health, raptor);
 +      VEHICLE_UPDATE_PLAYER(player, energy, raptor);
 +      if(self.vehicle_flags & VHF_HASSHIELD)
 +              VEHICLE_UPDATE_PLAYER(player, shield, raptor);
 +
 +      player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
 +      setself(player);
 +      return 1;
 +}
 +
 +void raptor_blowup()
 +{SELFPARAM();
 +      self.deadflag   = DEAD_DEAD;
 +      self.vehicle_exit(VHEF_NORMAL);
 +      RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_RAPT_DEATH, world);
 +
 +      self.alpha                = -1;
 +      self.movetype      = MOVETYPE_NONE;
 +      self.effects            = EF_NODRAW;
 +      self.colormod      = '0 0 0';
 +      self.avelocity    = '0 0 0';
 +      self.velocity      = '0 0 0';
 +
 +      setorigin(self, self.pos1);
 +      self.touch = func_null;
 +      self.nextthink = 0;
 +}
 +
 +void raptor_diethink()
 +{SELFPARAM();
 +      if(time >= self.wait)
 +              self.think = raptor_blowup;
 +
 +      if(random() < 0.05)
 +      {
 +              sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 +              Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
 +      }
 +      self.nextthink = time;
 +
 +      CSQCMODEL_AUTOUPDATE(self);
 +}
 +
 +// If we dont do this ever now and then, the raptors rotors
 +// stop working, presumably due to angle overflow. cute.
 +void raptor_rotor_anglefix()
 +{SELFPARAM();
 +      self.gun1.angles_y = anglemods(self.gun1.angles_y);
 +      self.gun2.angles_y = anglemods(self.gun2.angles_y);
 +      self.nextthink = time + 15;
 +}
 +
 +float raptor_impulse(float _imp)
 +{SELFPARAM();
 +      switch(_imp)
 +      {
 +              case 1:
 +                      self.vehicle.vehicle_weapon2mode = RSM_BOMB;
 +                      CSQCVehicleSetup(self, 0);
 +                      return true;
 +              case 2:
 +                      self.vehicle.vehicle_weapon2mode = RSM_FLARE;
 +                      CSQCVehicleSetup(self, 0);
 +                      return true;
 +
 +              case 10:
 +              case 15:
 +              case 18:
 +                      self.vehicle.vehicle_weapon2mode += 1;
 +                      if(self.vehicle.vehicle_weapon2mode > RSM_LAST)
 +                              self.vehicle.vehicle_weapon2mode = RSM_FIRST;
 +
 +                      CSQCVehicleSetup(self, 0);
 +                      return true;
 +              case 11:
 +              case 12:
 +              case 16:
 +              case 19:
 +                      self.vehicle.vehicle_weapon2mode -= 1;
 +                      if(self.vehicle.vehicle_weapon2mode < RSM_FIRST)
 +                              self.vehicle.vehicle_weapon2mode = RSM_LAST;
 +
 +                      CSQCVehicleSetup(self, 0);
 +                      return true;
 +
 +              /*
 +              case 17: // toss gun, could be used to exit?
 +                      break;
 +              case 20: // Manual minigun reload?
 +                      break;
 +              */
 +      }
 +      return false;
 +}
 +
++spawnfunc(vehicle_raptor)
++{
 +      if(!autocvar_g_vehicle_raptor) { remove(self); return; }
 +      if(!vehicle_initialize(VEH_RAPTOR, false)) { remove(self); return; }
 +}
 +
 +              METHOD(Raptor, vr_impact, void(Raptor thisveh))
 +              {
 +                      if(autocvar_g_vehicle_raptor_bouncepain)
 +                              vehicles_impact(autocvar_g_vehicle_raptor_bouncepain_x, autocvar_g_vehicle_raptor_bouncepain_y, autocvar_g_vehicle_raptor_bouncepain_z);
 +              }
 +              METHOD(Raptor, vr_enter, void(Raptor thisveh))
 +              {
 +                      self.vehicle_weapon2mode = RSM_BOMB;
 +                      self.owner.PlayerPhysplug = raptor_takeoff;
 +                      self.movetype      = MOVETYPE_BOUNCEMISSILE;
 +                      self.solid                = SOLID_SLIDEBOX;
 +                      self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_raptor_health) * 100;
 +                      self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_raptor_shield) * 100;
 +                      self.velocity_z = 1; // Nudge upwards to takeoff sequense can work.
 +                      self.tur_head.exteriormodeltoclient = self.owner;
 +
 +                      self.delay = time + autocvar_g_vehicle_raptor_bombs_refire;
 +                      self.lip   = time;
 +
 +                      if(self.owner.flagcarried)
 +                         setorigin(self.owner.flagcarried, '-20 0 96');
 +
 +                      CSQCVehicleSetup(self.owner, 0);
 +              }
 +              METHOD(Raptor, vr_death, void(Raptor thisveh))
 +              {
 +                      self.health                             = 0;
 +                      self.event_damage               = func_null;
 +                      self.solid                              = SOLID_CORPSE;
 +                      self.takedamage                 = DAMAGE_NO;
 +                      self.deadflag                   = DEAD_DYING;
 +                      self.movetype                   = MOVETYPE_BOUNCE;
 +                      self.think                              = raptor_diethink;
 +                      self.nextthink                  = time;
 +                      self.wait                               = time + 5 + (random() * 5);
 +
 +                      Send_Effect(EFFECT_EXPLOSION_MEDIUM, findbetterlocation (self.origin, 16), '0 0 0', 1);
 +
 +                      self.velocity_z += 600;
 +
 +                      self.avelocity = '0 0.5 1' * (random() * 400);
 +                      self.avelocity -= '0 0.5 1' * (random() * 400);
 +
 +                      self.colormod = '-0.5 -0.5 -0.5';
 +                      self.touch = raptor_blowup;
 +              }
 +              METHOD(Raptor, vr_spawn, void(Raptor thisveh))
 +              {
 +                      if(!self.gun1)
 +                      {
 +                              entity spinner;
 +                              vector ofs;
 +
 +                              //FIXME: Camera is in a bad place in HUD model.
 +                              //setorigin(self.vehicle_viewport, '25 0 5');
 +
 +                              self.vehicles_impulse   = raptor_impulse;
 +
 +                              self.frame = 0;
 +
 +                              self.bomb1 = spawn();
 +                              self.bomb2 = spawn();
 +                              self.gun1  = spawn();
 +                              self.gun2  = spawn();
 +
 +                              setmodel(self.bomb1, MDL_VEH_RAPTOR_CB_FOLDED);
 +                              setmodel(self.bomb2, MDL_VEH_RAPTOR_CB_FOLDED);
 +                              setmodel(self.gun1, MDL_VEH_RAPTOR_GUN);
 +                              setmodel(self.gun2, MDL_VEH_RAPTOR_GUN);
 +                              setmodel(self.tur_head, MDL_VEH_RAPTOR_TAIL);
 +
 +                              setattachment(self.bomb1, self, "bombmount_left");
 +                              setattachment(self.bomb2, self, "bombmount_right");
 +                              setattachment(self.tur_head, self,"root");
 +
 +                              // FIXMODEL Guns mounts to angled bones
 +                              self.bomb1.angles = self.angles;
 +                              self.angles = '0 0 0';
 +                              // This messes up gun-aim, so work arround it.
 +                              //setattachment(self.gun1, self, "gunmount_left");
 +                              ofs = gettaginfo(self, gettagindex(self, "gunmount_left"));
 +                              ofs -= self.origin;
 +                              setattachment(self.gun1, self, "");
 +                              setorigin(self.gun1, ofs);
 +
 +                              //setattachment(self.gun2, self, "gunmount_right");
 +                              ofs = gettaginfo(self, gettagindex(self, "gunmount_right"));
 +                              ofs -= self.origin;
 +                              setattachment(self.gun2, self, "");
 +                              setorigin(self.gun2, ofs);
 +
 +                              self.angles = self.bomb1.angles;
 +                              self.bomb1.angles = '0 0 0';
 +
 +                              spinner = spawn();
 +                              spinner.owner = self;
 +                              setmodel(spinner, MDL_VEH_RAPTOR_PROP);
 +                              setattachment(spinner, self, "engine_left");
 +                              spinner.movetype = MOVETYPE_NOCLIP;
 +                              spinner.avelocity = '0 90 0';
 +                              self.bomb1.gun1 = spinner;
 +
 +                              spinner = spawn();
 +                              spinner.owner = self;
 +                              setmodel(spinner, MDL_VEH_RAPTOR_PROP);
 +                              setattachment(spinner, self, "engine_right");
 +                              spinner.movetype = MOVETYPE_NOCLIP;
 +                              spinner.avelocity = '0 -90 0';
 +                              self.bomb1.gun2 = spinner;
 +
 +                              // Sigh.
 +                              self.bomb1.think = raptor_rotor_anglefix;
 +                              self.bomb1.nextthink = time;
 +
 +                              self.mass                          = 1 ;
 +                      }
 +
 +                      self.frame                = 0;
 +                      self.vehicle_health = autocvar_g_vehicle_raptor_health;
 +                      self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
 +                      self.movetype      = MOVETYPE_TOSS;
 +                      self.solid                = SOLID_SLIDEBOX;
 +                      self.vehicle_energy = 1;
 +
 +                      self.PlayerPhysplug = raptor_frame;
 +
 +                      self.bomb1.gun1.avelocity_y = 90;
 +                      self.bomb1.gun2.avelocity_y = -90;
 +
 +                      self.delay = time;
 +
 +                      self.bouncefactor = autocvar_g_vehicle_raptor_bouncefactor;
 +                      self.bouncestop = autocvar_g_vehicle_raptor_bouncestop;
 +                      self.damageforcescale = 0.25;
 +                      self.vehicle_health = autocvar_g_vehicle_raptor_health;
 +                      self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
 +              }
 +              METHOD(Raptor, vr_setup, void(Raptor thisveh))
 +              {
 +                      if(autocvar_g_vehicle_raptor_shield)
 +                              self.vehicle_flags |= VHF_HASSHIELD;
 +
 +                      if(autocvar_g_vehicle_raptor_shield_regen)
 +                              self.vehicle_flags |= VHF_SHIELDREGEN;
 +
 +                      if(autocvar_g_vehicle_raptor_health_regen)
 +                              self.vehicle_flags |= VHF_HEALTHREGEN;
 +
 +                      if(autocvar_g_vehicle_raptor_energy_regen)
 +                              self.vehicle_flags |= VHF_ENERGYREGEN;
 +
 +                      self.vehicle_exit = raptor_exit;
 +                      self.respawntime = autocvar_g_vehicle_raptor_respawntime;
 +                      self.vehicle_health = autocvar_g_vehicle_raptor_health;
 +                      self.vehicle_shield = autocvar_g_vehicle_raptor_shield;
 +                      self.max_health = self.vehicle_health;
 +              }
 +
 +#endif
 +#ifdef CSQC
 +
 +              METHOD(Raptor, vr_hud, void(Raptor thisveh))
 +              {
 +                      string crosshair;
 +
 +                      switch(weapon2mode)
 +                      {
 +                              case RSM_FLARE: crosshair = vCROSS_RAIN;  break;
 +                              case RSM_BOMB:  crosshair = vCROSS_BURST; break;
 +                              default:        crosshair = vCROSS_BURST;
 +                      }
 +
 +                      Vehicles_drawHUD(VEH_RAPTOR.m_icon, "vehicle_raptor_weapon1", "vehicle_raptor_weapon2",
 +                                                       "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
 +                                                       "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
 +                                                       crosshair);
 +              }
 +              METHOD(Raptor, vr_setup, void(Raptor thisveh))
 +              {
 +                      AuxiliaryXhair[1].axh_image = vCROSS_LOCK;
 +              }
 +
 +#endif
 +#endif
index ede09c5,0000000..9d524ef
mode 100644,000000..100644
--- /dev/null
@@@ -1,671 -1,0 +1,671 @@@
- void spawnfunc_vehicle_spiderbot()
- {SELFPARAM();
 +#ifndef VEHICLE_SPIDERBOT
 +#define VEHICLE_SPIDERBOT
 +
 +#include "spiderbot_weapons.qc"
 +
 +CLASS(Spiderbot, Vehicle)
 +/* spawnflags */ ATTRIB(Spiderbot, spawnflags, int, VHF_DMGSHAKE);
 +/* mins       */ ATTRIB(Spiderbot, mins, vector, '-75 -75 10');
 +/* maxs       */ ATTRIB(Spiderbot, maxs, vector, '75 75 125');
 +/* model        */ ATTRIB(Spiderbot, mdl, string, "models/vehicles/spiderbot.dpm");
 +/* model        */ ATTRIB(Spiderbot, model, string, "models/vehicles/spiderbot.dpm");
 +/* head_model */ ATTRIB(Spiderbot, head_model, string, "models/vehicles/spiderbot_top.dpm");
 +/* hud_model  */ ATTRIB(Spiderbot, hud_model, string, "models/vehicles/spiderbot_cockpit.dpm");
 +/* tags       */ ATTRIB(Spiderbot, tag_head, string, "tag_head");
 +/* tags       */ ATTRIB(Spiderbot, tag_hud, string, "tag_hud");
 +/* tags       */ ATTRIB(Spiderbot, tag_view, string, "");
 +/* netname    */ ATTRIB(Spiderbot, netname, string, "spiderbot");
 +/* fullname   */ ATTRIB(Spiderbot, vehicle_name, string, _("Spiderbot"));
 +/* icon       */ ATTRIB(Spiderbot, m_icon, string, "vehicle_spider");
 +ENDCLASS(Spiderbot)
 +
 +REGISTER_VEHICLE(SPIDERBOT, NEW(Spiderbot));
 +
 +#endif
 +
 +#ifdef IMPLEMENTATION
 +
 +const int SBRM_FIRST = 1;
 +const int SBRM_VOLLY = 1;
 +const int SBRM_GUIDE = 2;
 +const int SBRM_ARTILLERY = 3;
 +const int SBRM_LAST = 3;
 +
 +#include "spiderbot_weapons.qc"
 +
 +#ifdef SVQC
 +bool autocvar_g_vehicle_spiderbot;
 +
 +float autocvar_g_vehicle_spiderbot_respawntime;
 +
 +float autocvar_g_vehicle_spiderbot_speed_stop;
 +float autocvar_g_vehicle_spiderbot_speed_strafe;
 +float autocvar_g_vehicle_spiderbot_speed_walk;
 +float autocvar_g_vehicle_spiderbot_speed_run = 700;
 +float autocvar_g_vehicle_spiderbot_turnspeed;
 +float autocvar_g_vehicle_spiderbot_turnspeed_strafe;
 +float autocvar_g_vehicle_spiderbot_movement_inertia;
 +
 +float autocvar_g_vehicle_spiderbot_springlength;
 +float autocvar_g_vehicle_spiderbot_springup;
 +float autocvar_g_vehicle_spiderbot_springblend;
 +float autocvar_g_vehicle_spiderbot_tiltlimit;
 +
 +float autocvar_g_vehicle_spiderbot_head_pitchlimit_down;
 +float autocvar_g_vehicle_spiderbot_head_pitchlimit_up;
 +float autocvar_g_vehicle_spiderbot_head_turnlimit;
 +float autocvar_g_vehicle_spiderbot_head_turnspeed;
 +
 +int autocvar_g_vehicle_spiderbot_health;
 +float autocvar_g_vehicle_spiderbot_health_regen;
 +float autocvar_g_vehicle_spiderbot_health_regen_pause;
 +
 +int autocvar_g_vehicle_spiderbot_shield;
 +float autocvar_g_vehicle_spiderbot_shield_regen;
 +float autocvar_g_vehicle_spiderbot_shield_regen_pause;
 +
 +vector autocvar_g_vehicle_spiderbot_bouncepain;
 +
 +.float jump_delay;
 +float spiderbot_frame()
 +{SELFPARAM();
 +      vector ad, vf;
 +      entity player, spider;
 +      float ftmp;
 +
 +      if(intermission_running)
 +      {
 +              self.vehicle.velocity = '0 0 0';
 +              self.vehicle.avelocity = '0 0 0';
 +              return 1;
 +      }
 +
 +      player = self;
 +      spider = self.vehicle;
 +      setself(spider);
 +
 +      vehicles_painframe();
 +
 +      player.BUTTON_ZOOM        = 0;
 +      player.BUTTON_CROUCH    = 0;
 +      player.switchweapon      = 0;
 +      player.vehicle_weapon2mode = spider.vehicle_weapon2mode;
 +
 +
 +#if 1 // 0 to enable per-gun impact aux crosshairs
 +      // Avarage gun impact point's -> aux cross
 +      ad = gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint01"));
 +      vf = v_forward;
 +      ad += gettaginfo(spider.tur_head, gettagindex(spider.tur_head, "tag_hardpoint02"));
 +      vf += v_forward;
 +      ad = ad * 0.5;
 +      v_forward = vf * 0.5;
 +      traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
 +      UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
 +#else
 +      ad = gettaginfo(spider.gun1, gettagindex(spider.gun1, "barrels"));
 +      traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
 +      UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 0);
 +      vf = ad;
 +      ad = gettaginfo(spider.gun2, gettagindex(spider.gun2, "barrels"));
 +      traceline(ad, ad + v_forward * MAX_SHOT_DISTANCE, MOVE_NORMAL, spider);
 +      UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload1) + ('0 1 0' * (1 - player.vehicle_reload1)), 1);
 +      ad = 0.5 * (ad + vf);
 +#endif
 +
 +      crosshair_trace(player);
 +      ad = vectoangles(normalize(trace_endpos - ad));
 +      ad = AnglesTransform_ToAngles(AnglesTransform_LeftDivide(AnglesTransform_FromAngles(spider.angles), AnglesTransform_FromAngles(ad))) - spider.tur_head.angles;
 +      ad = AnglesTransform_Normalize(ad, true);
 +      //UpdateAuxiliaryXhair(player, trace_endpos, ('1 0 0' * player.vehicle_reload2) + ('0 1 0' * (1 - player.vehicle_reload2)), 2);
 +
 +      // Rotate head
 +      ftmp = autocvar_g_vehicle_spiderbot_head_turnspeed * sys_frametime;
 +      ad_y = bound(-ftmp, ad_y, ftmp);
 +      spider.tur_head.angles_y = bound(autocvar_g_vehicle_spiderbot_head_turnlimit * -1, spider.tur_head.angles_y + ad_y, autocvar_g_vehicle_spiderbot_head_turnlimit);
 +
 +      // Pitch head
 +      ad_x = bound(ftmp * -1, ad_x, ftmp);
 +      spider.tur_head.angles_x = bound(autocvar_g_vehicle_spiderbot_head_pitchlimit_down, spider.tur_head.angles_x + ad_x, autocvar_g_vehicle_spiderbot_head_pitchlimit_up);
 +
 +
 +      //fixedmakevectors(spider.angles);
 +      makevectors(spider.angles + '-2 0 0' * spider.angles_x);
 +
 +      movelib_groundalign4point(autocvar_g_vehicle_spiderbot_springlength, autocvar_g_vehicle_spiderbot_springup, autocvar_g_vehicle_spiderbot_springblend, autocvar_g_vehicle_spiderbot_tiltlimit);
 +
 +      if(spider.flags & FL_ONGROUND)
 +              spider.jump_delay = time; // reset now so movement can begin
 +
 +      //if(spider.flags & FL_ONGROUND)
 +      {
 +              if(spider.flags & FL_ONGROUND)
 +              if(spider.frame == 4 && self.tur_head.wait != 0)
 +              {
 +                      sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_LAND, VOL_VEHICLEENGINE, ATTEN_NORM);
 +                      spider.frame = 5;
 +              }
 +
 +              if(!player.BUTTON_JUMP)
 +                      spider.BUTTON_JUMP = 0;
 +
 +              if((spider.flags & FL_ONGROUND) && player.BUTTON_JUMP && !spider.BUTTON_JUMP && self.tur_head.wait < time)
 +              {
 +                      sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_JUMP, VOL_VEHICLEENGINE, ATTEN_NORM);
 +                      //dprint("spiderbot_jump:", ftos(soundlength("vehicles/spiderbot_jump.wav")), "\n");
 +                      self.delay = 0;
 +
 +                      self.tur_head.wait = time + 2;
 +                      spider.jump_delay = time + 2;
 +                      spider.BUTTON_JUMP = 1; // set spider's jump
 +                      //player.BUTTON_JUMP = 0;
 +
 +                      vector movefix = '0 0 0';
 +                      if(player.movement_x > 0) movefix_x = 1;
 +                      if(player.movement_x < 0) movefix_x = -1;
 +                      if(player.movement_y > 0) movefix_y = 1;
 +                      if(player.movement_y < 0) movefix_y = -1;
 +
 +                      vector rt = movefix_y * v_right;
 +                      vector sd = movefix_x * v_forward;
 +                      if(movefix_y == 0 && movefix_x == 0)
 +                              sd = v_forward; // always do forward
 +
 +                      spider.flags &= ~FL_ONGROUND;
 +
 +                      spider.velocity = sd * 700 + rt * 600 + v_up * 600;
 +                      spider.frame = 4;
 +              }
 +              else if(time >= spider.jump_delay)
 +              {
 +                      if(vlen(player.movement) == 0)
 +                      {
 +                              if(spider.flags & FL_ONGROUND)
 +                              {
 +                                      if(self.sound_nexttime < time || self.delay != 3)
 +                                      {
 +                                              self.delay = 3;
 +                                              self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_idle.wav");
 +                                              //dprint("spiderbot_idle:", ftos(soundlength("vehicles/spiderbot_idle.wav")), "\n");
 +                                              sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_IDLE, VOL_VEHICLEENGINE, ATTEN_NORM);
 +                                      }
 +                                      movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
 +                                      spider.frame = 5;
 +                              }
 +                      }
 +                      else
 +                      {
 +                              // Turn Body
 +                              if(player.movement_x == 0 && player.movement_y != 0)
 +                                      ftmp = autocvar_g_vehicle_spiderbot_turnspeed_strafe * sys_frametime;
 +                              else
 +                                      ftmp = autocvar_g_vehicle_spiderbot_turnspeed * sys_frametime;
 +
 +                              ftmp = bound(-ftmp, spider.tur_head.angles_y, ftmp);
 +                              spider.angles_y = anglemods(spider.angles_y + ftmp);
 +                              spider.tur_head.angles_y -= ftmp;
 +
 +                              if(player.movement_x != 0)
 +                              {
 +                                      if(player.movement_x > 0)
 +                                      {
 +                                              player.movement_x = 1;
 +                                              if(spider.flags & FL_ONGROUND)
 +                                                      spider.frame = 0;
 +                                      }
 +                                      else if(player.movement_x < 0)
 +                                      {
 +                                              player.movement_x = -1;
 +                                              if(spider.flags & FL_ONGROUND)
 +                                                      spider.frame = 1;
 +                                      }
 +                                      player.movement_y = 0;
 +                                      float oldvelz = spider.velocity_z;
 +                                      movelib_move_simple(normalize(v_forward * player.movement_x),((player.BUTTON_JUMP) ? autocvar_g_vehicle_spiderbot_speed_run : autocvar_g_vehicle_spiderbot_speed_walk),autocvar_g_vehicle_spiderbot_movement_inertia);
 +                                      spider.velocity_z = oldvelz;
 +                                      float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
 +                                      if(spider.velocity_z <= 20) // not while jumping
 +                                              spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
 +                                      if(spider.flags & FL_ONGROUND)
 +                                      if(self.sound_nexttime < time || self.delay != 1)
 +                                      {
 +                                              self.delay = 1;
 +                                              self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_walk.wav");
 +                                              sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_WALK, VOL_VEHICLEENGINE, ATTEN_NORM);
 +                                              //dprint("spiderbot_walk:", ftos(soundlength("vehicles/spiderbot_walk.wav")), "\n");
 +                                      }
 +                              }
 +                              else if(player.movement_y != 0)
 +                              {
 +                                      if(player.movement_y < 0)
 +                                      {
 +                                              player.movement_y = -1;
 +                                              if(spider.flags & FL_ONGROUND)
 +                                                      spider.frame = 2;
 +                                      }
 +                                      else if(player.movement_y > 0)
 +                                      {
 +                                              player.movement_y = 1;
 +                                              if(spider.flags & FL_ONGROUND)
 +                                                      spider.frame = 3;
 +                                      }
 +
 +                                      float oldvelz = spider.velocity_z;
 +                                      movelib_move_simple(normalize(v_right * player.movement_y),autocvar_g_vehicle_spiderbot_speed_strafe,autocvar_g_vehicle_spiderbot_movement_inertia);
 +                                      spider.velocity_z = oldvelz;
 +                                      float g = ((autocvar_sv_gameplayfix_gravityunaffectedbyticrate) ? 0.5 : 1);
 +                                      if(spider.velocity_z <= 20) // not while jumping
 +                                              spider.velocity_z -= g * sys_frametime * autocvar_sv_gravity;
 +                                      if(spider.flags & FL_ONGROUND)
 +                                      if(self.sound_nexttime < time || self.delay != 2)
 +                                      {
 +                                              self.delay = 2;
 +                                              self.sound_nexttime = time + 6.486500; //soundlength("vehicles/spiderbot_strafe.wav");
 +                                              sound (self, CH_TRIGGER_SINGLE, SND_VEH_SPIDERBOT_STRAFE, VOL_VEHICLEENGINE, ATTEN_NORM);
 +                                              //dprint("spiderbot_strafe:", ftos(soundlength("vehicles/spiderbot_strafe.wav")), "\n");
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
 +
 +      self.angles_x = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_x, autocvar_g_vehicle_spiderbot_tiltlimit);
 +      self.angles_z = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, self.angles_z, autocvar_g_vehicle_spiderbot_tiltlimit);
 +
 +      if(!forbidWeaponUse(player))
 +      if(player.BUTTON_ATCK)
 +      {
 +              spider.cnt = time;
 +              if(spider.vehicle_ammo1 >= autocvar_g_vehicle_spiderbot_minigun_ammo_cost && spider.tur_head.attack_finished_single <= time)
 +              {
 +                      entity gun;
 +                      vector v;
 +                      spider.misc_bulletcounter += 1;
 +
 +                      setself(player);
 +
 +                      gun = (spider.misc_bulletcounter % 2) ? spider.gun1 : spider.gun2;
 +
 +                      v = gettaginfo(gun, gettagindex(gun, "barrels"));
 +                      v_forward = normalize(v_forward);
 +                      v += v_forward * 50;
 +
 +                      fireBullet(v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_solidpenetration,
 +                                autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN, 0);
 +
 +                      sound (gun, CH_WEAPON_A, SND_UZI_FIRE, VOL_BASE, ATTEN_NORM);
 +                      //trailparticles(self, _particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos);
 +                      pointparticles(particleeffectnum(EFFECT_SPIDERBOT_MINIGUN_MUZZLEFLASH), v, v_forward * 2500, 1);
 +
 +                      setself(spider);
 +
 +                      spider.vehicle_ammo1 -= autocvar_g_vehicle_spiderbot_minigun_ammo_cost;
 +                      spider.tur_head.attack_finished_single = time + autocvar_g_vehicle_spiderbot_minigun_refire;
 +                      player.vehicle_ammo1 = (spider.vehicle_ammo1 / autocvar_g_vehicle_spiderbot_minigun_ammo_max) * 100;
 +                      spider.gun1.angles_z += 45;
 +                      spider.gun2.angles_z -= 45;
 +                      if(spider.gun1.angles_z >= 360)
 +                      {
 +                              spider.gun1.angles_z = 0;
 +                              spider.gun2.angles_z = 0;
 +                      }
 +              }
 +      }
 +      else
 +              vehicles_regen(spider.cnt, vehicle_ammo1, autocvar_g_vehicle_spiderbot_minigun_ammo_max,
 +                                                                                 autocvar_g_vehicle_spiderbot_minigun_ammo_regen_pause,
 +                                                                                 autocvar_g_vehicle_spiderbot_minigun_ammo_regen, frametime, false);
 +
 +
 +      spiderbot_rocket_do();
 +
 +      if(self.vehicle_flags  & VHF_SHIELDREGEN)
 +              vehicles_regen(spider.dmg_time, vehicle_shield, autocvar_g_vehicle_spiderbot_shield, autocvar_g_vehicle_spiderbot_shield_regen_pause, autocvar_g_vehicle_spiderbot_shield_regen, frametime, true);
 +
 +      if(self.vehicle_flags  & VHF_HEALTHREGEN)
 +              vehicles_regen(spider.dmg_time, vehicle_health, autocvar_g_vehicle_spiderbot_health, autocvar_g_vehicle_spiderbot_health_regen_pause, autocvar_g_vehicle_spiderbot_health_regen, frametime, false);
 +
 +      player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
 +      //player.vehicle_ammo2 = spider.tur_head.frame;
 +      player.vehicle_ammo2 = (9 - spider.tur_head.frame) / 8 * 100; // Percentage, like ammo1
 +
 +      if(spider.gun2.cnt <= time)
 +              player.vehicle_reload2 = 100;
 +      else
 +              player.vehicle_reload2 = 100 - ((spider.gun2.cnt - time) / spider.attack_finished_single) * 100;
 +
 +      setorigin(player, spider.origin + '0 0 1' * spider.maxs_z);
 +      player.velocity = spider.velocity;
 +
 +      VEHICLE_UPDATE_PLAYER(player, health, spiderbot);
 +
 +      if(self.vehicle_flags & VHF_HASSHIELD)
 +              VEHICLE_UPDATE_PLAYER(player, shield, spiderbot);
 +
 +      setself(player);
 +      return 1;
 +}
 +
 +void spiderbot_exit(float eject)
 +{SELFPARAM();
 +      entity e;
 +      vector spot;
 +
 +      e = findchain(classname,"spiderbot_rocket");
 +      while(e)
 +      {
 +              if(e.owner == self.owner)
 +              {
 +                      e.realowner = self.owner;
 +                      e.owner = world;
 +              }
 +              e = e.chain;
 +      }
 +
 +      self.think = vehicles_think;
 +      self.nextthink = time;
 +      self.frame = 5;
 +      self.movetype = MOVETYPE_WALK;
 +
 +      if(!self.owner)
 +              return;
 +
 +      makevectors(self.angles);
 +      if(eject)
 +      {
 +              spot = self.origin + v_forward * 100 + '0 0 64';
 +              spot = vehicles_findgoodexit(spot);
 +              setorigin(self.owner , spot);
 +              self.owner.velocity = (v_up + v_forward * 0.25) * 750;
 +              self.owner.oldvelocity = self.owner.velocity;
 +      }
 +      else
 +      {
 +              if(vlen(self.velocity) > autocvar_g_vehicle_spiderbot_speed_strafe)
 +              {
 +                      self.owner.velocity = normalize(self.velocity) * vlen(self.velocity);
 +                      self.owner.velocity_z += 200;
 +                      spot = self.origin + v_forward * 128 + '0 0 64';
 +                      spot = vehicles_findgoodexit(spot);
 +              }
 +              else
 +              {
 +                      self.owner.velocity = self.velocity * 0.5;
 +                      self.owner.velocity_z += 10;
 +                      spot = self.origin + v_forward * 256 + '0 0 64';
 +                      spot = vehicles_findgoodexit(spot);
 +              }
 +              self.owner.oldvelocity = self.owner.velocity;
 +              setorigin(self.owner , spot);
 +      }
 +
 +      antilag_clear(self.owner);
 +      self.owner = world;
 +}
 +
 +void spiderbot_headfade()
 +{SELFPARAM();
 +      self.think = spiderbot_headfade;
 +      self.nextthink = self.fade_time;
 +      self.alpha = 1 - (time - self.fade_time) * self.fade_rate;
 +
 +      if(self.cnt < time || self.alpha < 0.1)
 +      {
 +              if(self.alpha > 0.1)
 +              {
 +                      sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 +                      Send_Effect(EFFECT_EXPLOSION_BIG, self.origin + '0 0 100', '0 0 0', 1);
 +              }
 +              remove(self);
 +      }
 +}
 +
 +void spiderbot_blowup()
 +{SELFPARAM();
 +      if(self.cnt > time)
 +      {
 +              if(random() < 0.1)
 +              {
 +                      sound (self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
 +                      Send_Effect(EFFECT_EXPLOSION_SMALL, randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
 +              }
 +              self.nextthink = time + 0.1;
 +              return;
 +      }
 +
 +      entity h, g1, g2, b;
 +      b = spawn();
 +      h = spawn();
 +      g1 = spawn();
 +      g2 = spawn();
 +
 +      setmodel(b, MDL_VEH_SPIDERBOT_BODY);
 +      setmodel(h, MDL_VEH_SPIDERBOT_TOP);
 +      setmodel(g1, MDL_VEH_SPIDERBOT_GUN);
 +      setmodel(g2, MDL_VEH_SPIDERBOT_GUN);
 +
 +      setorigin(b, self.origin);
 +      b.frame = 11;
 +      b.angles = self.angles;
 +      setsize(b, self.mins, self.maxs);
 +
 +      setorigin(h, gettaginfo(self, gettagindex(self, "tag_head")));
 +      h.movetype = MOVETYPE_BOUNCE;
 +      h.solid = SOLID_BBOX;
 +      h.velocity = v_up * (500 + random() * 500) + randomvec() * 128;
 +      h.modelflags = MF_ROCKET;
 +      h.effects = EF_FLAME | EF_LOWPRECISION;
 +      h.avelocity = randomvec() * 360;
 +
 +      h.alpha = 1;
 +      h.cnt = time + (3.5 * random());
 +      h.fade_rate = 1 / min(self.respawntime, 10);
 +      h.fade_time = time;
 +      h.think = spiderbot_headfade;
 +      h.nextthink = time;
 +
 +      setorigin(g1, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint01")));
 +      g1.movetype = MOVETYPE_TOSS;
 +      g1.solid = SOLID_CORPSE;
 +      g1.velocity = v_forward * 700 + (randomvec() * 32);
 +      g1.avelocity = randomvec() * 180;
 +
 +      setorigin(g2, gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_hardpoint02")));
 +      g2.movetype = MOVETYPE_TOSS;
 +      g2.solid = SOLID_CORPSE;
 +      g2.velocity = v_forward * 700 + (randomvec() * 32);
 +      g2.avelocity = randomvec() * 180;
 +
 +      h.colormod = b.colormod = g1.colormod = g2.colormod = '-2 -2 -2';
 +
 +      SUB_SetFade(b,  time + 5, min(self.respawntime, 1));
 +      //SUB_SetFade(h,  time, min(self.respawntime, 10));
 +      SUB_SetFade(g1, time, min(self.respawntime, 10));
 +      SUB_SetFade(g2, time, min(self.respawntime, 10));
 +
 +      RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_SPID_DEATH, world);
 +
 +      self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
 +      self.movetype = MOVETYPE_NONE;
 +      self.deadflag = DEAD_DEAD;
 +      self.solid = SOLID_NOT;
 +      self.tur_head.effects &= ~EF_FLAME;
 +      self.vehicle_hudmodel.viewmodelforclient = self;
 +}
 +
 +bool spiderbot_impulse(int _imp)
 +{SELFPARAM();
 +      switch(_imp)
 +      {
 +              case 1:
 +                      self.vehicle.vehicle_weapon2mode = SBRM_VOLLY;
 +                      CSQCVehicleSetup(self, 0);
 +                      return true;
 +              case 2:
 +                      self.vehicle.vehicle_weapon2mode = SBRM_GUIDE;
 +                      CSQCVehicleSetup(self, 0);
 +                      return true;
 +              case 3:
 +                      self.vehicle.vehicle_weapon2mode = SBRM_ARTILLERY;
 +                      CSQCVehicleSetup(self, 0);
 +                      return true;
 +
 +              case 10:
 +              case 15:
 +              case 18:
 +                      self.vehicle.vehicle_weapon2mode += 1;
 +                      if(self.vehicle.vehicle_weapon2mode > SBRM_LAST)
 +                              self.vehicle.vehicle_weapon2mode = SBRM_FIRST;
 +
 +                      //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
 +                      CSQCVehicleSetup(self, 0);
 +                      return true;
 +              case 11:
 +              case 12:
 +              case 16:
 +              case 19:
 +                      self.vehicle.vehicle_weapon2mode -= 1;
 +                      if(self.vehicle.vehicle_weapon2mode < SBRM_FIRST)
 +                              self.vehicle.vehicle_weapon2mode = SBRM_LAST;
 +
 +                      //centerprint(self, strcat("Rocket mode is ", ftos(self.vehicle.vehicle_weapon2mode)));
 +                      CSQCVehicleSetup(self, 0);
 +                      return true;
 +
 +              /*
 +              case 17: // toss gun, could be used to exit?
 +                      break;
 +              case 20: // Manual minigun reload?
 +                      break;
 +              */
 +      }
 +      return false;
 +}
 +
++spawnfunc(vehicle_spiderbot)
++{
 +      if(!autocvar_g_vehicle_spiderbot) { remove(self); return; }
 +      if(!vehicle_initialize(VEH_SPIDERBOT, false)) { remove(self); return; }
 +}
 +
 +              METHOD(Spiderbot, vr_impact, void(Spiderbot thisveh))
 +              {
 +                      if(autocvar_g_vehicle_spiderbot_bouncepain)
 +                              vehicles_impact(autocvar_g_vehicle_spiderbot_bouncepain_x, autocvar_g_vehicle_spiderbot_bouncepain_y, autocvar_g_vehicle_spiderbot_bouncepain_z);
 +              }
 +              METHOD(Spiderbot, vr_enter, void(Spiderbot thisveh))
 +              {
 +                      self.vehicle_weapon2mode = SBRM_GUIDE;
 +                      self.movetype = MOVETYPE_WALK;
 +                      CSQCVehicleSetup(self.owner, 0);
 +                      self.owner.vehicle_health = (self.vehicle_health / autocvar_g_vehicle_spiderbot_health) * 100;
 +                      self.owner.vehicle_shield = (self.vehicle_shield / autocvar_g_vehicle_spiderbot_shield) * 100;
 +
 +                      if(self.owner.flagcarried)
 +                      {
 +                              setattachment(self.owner.flagcarried, self.tur_head, "");
 +                              setorigin(self.owner.flagcarried, '-20 0 120');
 +                      }
 +              }
 +              METHOD(Spiderbot, vr_think, void(Spiderbot thisveh))
 +              {
 +                      if(self.flags & FL_ONGROUND)
 +                              movelib_beak_simple(autocvar_g_vehicle_spiderbot_speed_stop);
 +              }
 +              METHOD(Spiderbot, vr_death, void(Spiderbot thisveh))
 +              {
 +                      self.health                             = 0;
 +                      self.event_damage               = func_null;
 +                      self.takedamage                 = DAMAGE_NO;
 +                      self.touch                              = func_null;
 +                      self.cnt                                = 3.4 + time + random() * 2;
 +                      self.think                              = spiderbot_blowup;
 +                      self.nextthink                  = time;
 +                      self.deadflag                   = DEAD_DYING;
 +                      self.frame                              = 5;
 +                      self.tur_head.effects  |= EF_FLAME;
 +                      self.colormod                   = self.tur_head.colormod = '-1 -1 -1';
 +                      self.frame                              = 10;
 +                      self.movetype                   = MOVETYPE_TOSS;
 +
 +                      CSQCModel_UnlinkEntity(); // networking the death scene would be a nightmare
 +              }
 +              METHOD(Spiderbot, vr_spawn, void(Spiderbot thisveh))
 +              {
 +                      if(!self.gun1)
 +                      {
 +                              self.vehicles_impulse = spiderbot_impulse;
 +                              self.gun1 = spawn();
 +                              self.gun2 = spawn();
 +                              setmodel(self.gun1, MDL_VEH_SPIDERBOT_GUN);
 +                              setmodel(self.gun2, MDL_VEH_SPIDERBOT_GUN);
 +                              setattachment(self.gun1, self.tur_head, "tag_hardpoint01");
 +                              setattachment(self.gun2, self.tur_head, "tag_hardpoint02");
 +                              self.gravity = 2;
 +                              self.mass = 5000;
 +                      }
 +
 +                      self.frame = 5;
 +                      self.tur_head.frame = 1;
 +                      self.movetype = MOVETYPE_WALK;
 +                      self.solid = SOLID_SLIDEBOX;
 +                      self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = 1;
 +                      self.tur_head.angles = '0 0 0';
 +                      self.vehicle_exit = spiderbot_exit;
 +
 +                      setorigin(self, self.pos1 + '0 0 128');
 +                      self.angles = self.pos2;
 +                      self.damageforcescale = 0.03;
 +                      self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
 +                      self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
 +
 +                      self.PlayerPhysplug = spiderbot_frame;
 +              }
 +              METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh))
 +              {
 +                      if(autocvar_g_vehicle_spiderbot_shield)
 +                              self.vehicle_flags |= VHF_HASSHIELD;
 +
 +                      if(autocvar_g_vehicle_spiderbot_shield_regen)
 +                              self.vehicle_flags |= VHF_SHIELDREGEN;
 +
 +                      if(autocvar_g_vehicle_spiderbot_health_regen)
 +                              self.vehicle_flags |= VHF_HEALTHREGEN;
 +
 +                      self.respawntime = autocvar_g_vehicle_spiderbot_respawntime;
 +                      self.vehicle_health = autocvar_g_vehicle_spiderbot_health;
 +                      self.vehicle_shield = autocvar_g_vehicle_spiderbot_shield;
 +                      self.max_health = self.vehicle_health;
 +                      self.pushable = true; // spiderbot can use jumppads
 +              }
 +
 +#endif // SVQC
 +#ifdef CSQC
 +float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
 +float autocvar_cl_vehicle_spiderbot_cross_size = 1;
 +
 +              METHOD(Spiderbot, vr_hud, void(Spiderbot thisveh))
 +              {
 +                      string crosshair;
 +
 +                      switch(weapon2mode)
 +                      {
 +                              case SBRM_VOLLY:     crosshair = vCROSS_BURST; break;
 +                              case SBRM_GUIDE:     crosshair = vCROSS_GUIDE; break;
 +                              case SBRM_ARTILLERY: crosshair = vCROSS_RAIN;  break;
 +                              default:             crosshair = vCROSS_BURST;
 +                      }
 +
 +                      Vehicles_drawHUD(VEH_SPIDERBOT.m_icon, "vehicle_spider_weapon1", "vehicle_spider_weapon2",
 +                                                       "vehicle_icon_ammo1", autocvar_hud_progressbar_vehicles_ammo1_color,
 +                                                       "vehicle_icon_ammo2", autocvar_hud_progressbar_vehicles_ammo2_color,
 +                                                       crosshair);
 +              }
 +              METHOD(Spiderbot, vr_setup, void(Spiderbot thisveh))
 +              {
 +                      AuxiliaryXhair[0].axh_image = vCROSS_HINT; // Minigun1
 +                      AuxiliaryXhair[1].axh_image = vCROSS_HINT; // Minigun2
 +              }
 +
 +#endif
 +#endif
Simple merge
Simple merge
Simple merge
@@@ -43,13 -41,13 +43,13 @@@ HMG_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP
  #ifdef IMPLEMENTATION
  #ifdef SVQC
  
void spawnfunc_weapon_hmg() { weapon_defaultspawnfunc(WEP_HMG.m_id); }
spawnfunc(weapon_hmg) { weapon_defaultspawnfunc(WEP_HMG.m_id); }
  
 -void W_HeavyMachineGun_Attack_Auto()
 -{SELFPARAM();
 -      if (!self.BUTTON_ATCK)
 +void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, bool fire1, bool fire2)
 +{
 +      if (!actor.BUTTON_ATCK)
        {
 -              w_ready();
 +              w_ready(thiswep, actor, fire1, fire2);
                return;
        }
  
@@@ -70,7 -59,16 +70,7 @@@ HOOK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PRO
  #ifdef IMPLEMENTATION
  #ifdef SVQC
  
- void spawnfunc_weapon_hook() { weapon_defaultspawnfunc(WEP_HOOK.m_id); }
 -spawnfunc(weapon_hook)
 -{
 -      if(g_grappling_hook) // offhand hook
 -      {
 -              startitem_failed = true;
 -              remove(self);
 -              return;
 -      }
 -      weapon_defaultspawnfunc(WEP_HOOK.m_id);
 -}
++spawnfunc(weapon_hook) { weapon_defaultspawnfunc(WEP_HOOK.m_id); }
  
  void W_Hook_ExplodeThink(void)
  {SELFPARAM();
Simple merge
Simple merge
@@@ -49,11 -47,11 +49,11 @@@ RIFLE_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PR
  #endif
  #ifdef IMPLEMENTATION
  #ifdef SVQC
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(); }
spawnfunc(weapon_rifle) { weapon_defaultspawnfunc(WEP_RIFLE.m_id); }
spawnfunc(weapon_campingrifle) { spawnfunc_weapon_rifle(this); }
spawnfunc(weapon_sniperrifle) { spawnfunc_weapon_rifle(this); }
  
 -void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, string pSound)
 +void W_Rifle_FireBullet(Weapon thiswep, float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, int deathtype, float pTracer, float pShots, string pSound)
  {SELFPARAM();
        float i;
  
Simple merge
Simple merge
@@@ -54,9 -52,9 +54,9 @@@ SHOTGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_
  #endif
  #ifdef IMPLEMENTATION
  #ifdef SVQC
void spawnfunc_weapon_shotgun(void) { weapon_defaultspawnfunc(WEP_SHOTGUN.m_id); }
spawnfunc(weapon_shotgun) { weapon_defaultspawnfunc(WEP_SHOTGUN.m_id); }
  
 -void W_Shotgun_Attack(float isprimary)
 +void W_Shotgun_Attack(Weapon thiswep, float isprimary)
  {SELFPARAM();
        float   sc;
        entity flash;
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -3,9 -3,9 +3,9 @@@
  
  #include "mutator.qh"
  
 -void W_Blaster_Attack(float, float, float, float, float, float, float, float, float, float);
 +void W_Blaster_Attack(entity, float, float, float, float, float, float, float, float, float, float);
void spawnfunc_weapon_hmg();
void spawnfunc_weapon_rpc();
spawnfunc(weapon_hmg);
spawnfunc(weapon_rpc);
  
  void ok_DecreaseCharge(entity ent, int wep)
  {
Simple merge
Simple merge