]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/vehicles/vehicles.qc
unwops the projetile damage fix
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / vehicles / vehicles.qc
index ace756ddb40145b77ccbd95f0960b227fbc02948..69c0f87e51f23528c0fd5caeffb32f3844dc2f29 100644 (file)
@@ -1,8 +1,21 @@
+float autocvar_g_vehicles_crush_dmg;
+float autocvar_g_vehicles_crush_force;
+float autocvar_g_vehicles_delayspawn;
+float autocvar_g_vehicles_delayspawn_jitter;
+
 void vehicles_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force);
 void vehicles_return();
+void vehicles_enter();
+void vehicles_touch();
+void vehicles_reset_colors();
 void vehicles_clearrturn();
+void vehicles_setreturn();
+
 
-#define MAX_AXH 4
+/** AuxiliaryXhair*
+    Send additional points of interest to be drawn, to vehicle owner
+**/
+float MAX_AXH = 4;
 .entity AuxiliaryXhair[MAX_AXH];
 
 float SendAuxiliaryXhair(entity to, float sf)
@@ -47,6 +60,7 @@ void UpdateAuxiliaryXhair(entity own, vector loc, vector clr, float axh_id)
 
 /*
 // SVC_TEMPENTITY based, horrible with even 50 ping. hm.
+// WriteByte(MSG_ONE, SVC_TEMPENTITY) uses reliable messagess, never use for thinsg that need continous updates.
 void SendAuxiliaryXhair2(entity own, vector loc, vector clr, float axh_id)
 {
        msg_entity = own;
@@ -66,7 +80,14 @@ void SendAuxiliaryXhair2(entity own, vector loc, vector clr, float axh_id)
 
 }
 */
-
+// End AuxiliaryXhair
+
+/**
+    Notifies the client that he enterd a vehicle, and sends 
+    realavent data.
+    
+    only sends vehicle_id atm (wich is a HUD_* constant, ex. HUD_SPIDERBOT)
+**/
 void CSQCVehicleSetup(entity own, float vehicle_id)
 {
        msg_entity = own;
@@ -76,63 +97,74 @@ void CSQCVehicleSetup(entity own, float vehicle_id)
        WriteByte(MSG_ONE, vehicle_id);
 }
 
+/** vehicles_locktarget
+
+    Generic target locking.
+
+    Figure out if what target is "locked" (if any), for missile tracking as such.
+
+    after calling, "if(self.lock_target != world && self.lock_strength == 1)" mean
+    you have a locked in target.
+
+    Exspects a crosshair_trace() or equivalent to be
+    dont before calling.
+
+**/
 .entity lock_target;
 .float  lock_strength;
 .float  lock_time;
-void vehicles_locktarget(float deltatime)
+.float  lock_soundtime;
+void vehicles_locktarget(float incr, float decr, float _lock_time)
 {
-    // no target hit by trace
-    if(trace_ent == world)
+    if(self.lock_target && self.lock_target.deadflag != DEAD_NO)
     {
-        self.lock_strength = max(self.lock_strength - deltatime, 0);
-        if(self.lock_strength == 0)
-            self.lock_target = world;
-
-        return;
+        self.lock_target    = world;
+        self.lock_strength  = 0;
+        self.lock_time      = 0;
     }
 
-    // Current have no target
-    if(self.lock_target == world)
+    if(self.lock_time > time)
     {
-        // aquire
-        if(trace_ent != world)
+        if(self.lock_target)
+        if(self.lock_soundtime < time)
         {
-            self.lock_target = trace_ent;
-            self.lock_strength = deltatime;
+            self.lock_soundtime = time + 0.5;
+            play2(self.owner, "vehicles/locked.wav");
         }
+        
         return;
     }
 
-    // Have a locking target
-    // Trace hit current target
-    if(trace_ent == self.lock_target)
-    {
-        self.lock_strength = min(self.lock_strength + deltatime, 1);
-    }
-    else
+    if(trace_ent != world)
     {
-        self.lock_strength = max(self.lock_strength - deltatime, 0);
-        if(self.lock_strength == 0)
-            self.lock_target = world;
-    }
-}
-
-
-void vehicles_locktarget2(float incr, float decr, float _lock_time)
-{
-    if(self.lock_time > time)
-        return;
-
+        if(teams_matter && trace_ent.team == self.team)
+            trace_ent = world;
 
+        if(trace_ent.deadflag != DEAD_NO)
+            trace_ent = world;
 
-    if not (trace_ent.vehicle_flags & VHF_ISVEHICLE || trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
-        self.lock_strength = min(self.lock_strength - decr, 1);
-    else if(trace_ent.deadflag != DEAD_NO)
-        self.lock_strength = min(self.lock_strength - decr, 1);
+        if not (trace_ent.vehicle_flags & VHF_ISVEHICLE || trace_ent.turrcaps_flags & TFL_TURRCAPS_ISTURRET)
+            trace_ent = world;
+    }
 
     if(self.lock_target == world && trace_ent != world)
         self.lock_target = trace_ent;
-
+    
+    if(self.lock_target && trace_ent == self.lock_target) 
+    {            
+        if(self.lock_strength != 1 && self.lock_strength + incr >= 1)
+        {
+            play2(self.owner, "vehicles/lock.wav");
+            self.lock_soundtime = time + 0.8;
+        }        
+        else if (self.lock_strength != 1 && self.lock_soundtime < time)
+        {            
+            play2(self.owner, "vehicles/locking.wav");
+            self.lock_soundtime = time + 0.3;
+        }
+        
+    }    
+        
     // Have a locking target
     // Trace hit current target
     if(trace_ent == self.lock_target && trace_ent != world)
@@ -143,22 +175,25 @@ void vehicles_locktarget2(float incr, float decr, float _lock_time)
     }
     else
     {
-        self.lock_strength = max(self.lock_strength - decr, 0);
+        if(trace_ent)
+            self.lock_strength = max(self.lock_strength - decr * 2, 0);
+        else
+            self.lock_strength = max(self.lock_strength - decr, 0);
 
         if(self.lock_strength == 0)
             self.lock_target = world;
     }
 }
 
-
 #define VEHICLE_UPDATE_PLAYER(fld,vhname) \
-self.owner.vehicle_##fld = self.vehicle_##fld / autocvar_g_vehicle_##vhname##_##fld
+self.owner.vehicle_##fld = (self.vehicle_##fld / autocvar_g_vehicle_##vhname##_##fld) * 100
 
 #define vehicles_sweap_collision(orig,vel,dt,acm,mult) \
 traceline(orig, orig + vel * dt, MOVE_NORMAL, self); \
 if(trace_fraction != 1) \
     acm += normalize(self.origin - trace_endpos) * (vlen(vel) * mult)
 
+// Hover movement support
 float  force_fromtag_power;
 float  force_fromtag_normpower;
 vector force_fromtag_origin;
@@ -174,6 +209,8 @@ vector vehicles_force_fromtag_hover(string tag_name, float spring_length, float
     return v_forward  * force_fromtag_power;
 }
 
+// Experimental hovermode wich uses attraction/repulstion from surface insted of gravity/repulsion
+// Can possibly be use to move abt any surface (inclusing walls/celings)
 vector vehicles_force_fromtag_maglev(string tag_name, float spring_length, float max_power)
 {
 
@@ -181,6 +218,7 @@ vector vehicles_force_fromtag_maglev(string tag_name, float spring_length, float
     v_forward  = normalize(v_forward) * -1;
     traceline(force_fromtag_origin, force_fromtag_origin - (v_forward  * spring_length), MOVE_NORMAL, self);
 
+    // TODO - this may NOT be compatible with wall/celing movement, unhardcode 0.25 (engine count multiplier)
     if(trace_fraction == 1.0)
     {
         force_fromtag_normpower = -0.25;
@@ -193,9 +231,174 @@ vector vehicles_force_fromtag_maglev(string tag_name, float spring_length, float
     return v_forward  * force_fromtag_power;
 }
 
+// Generic vehile projectile system
+void vehicles_projectile_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+    // Ignore damage from oterh projectiles from my owner (dont mess up volly's)
+    if(inflictor.owner == self.owner)
+        return; 
+    
+    self.health -= damage;
+    self.velocity += force;
+    if(self.health < 1)
+    {
+        self.takedamage = DAMAGE_NO;
+        self.event_damage = SUB_Null;
+        self.think = self.use;
+        self.nextthink = time;
+    }
+
+}
+
+void vehicles_projectile_explode()
+{
+    if(self.owner && other != world)
+    {
+        if(other == self.owner.vehicle)
+            return;
+
+        if(other == self.owner.vehicle.tur_head)
+            return;
+    }
+
+       PROJECTILE_TOUCH;
+
+       self.event_damage = SUB_Null;
+    RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, self.shot_force, self.totalfrags, other);
+
+    remove (self);
+}
+
+entity vehicles_projectile(string _mzlfx, string _mzlsound,
+                           vector _org, vector _vel,
+                           float _dmg, float _radi, float _force,  float _size,
+                           float _deahtype, float _projtype, float _health,
+                           float _cull, float _clianim)
+{
+    entity proj;
+
+    proj = spawn();
+
+    PROJECTILE_MAKETRIGGER(proj);
+    setorigin(proj, _org);
+
+    proj.shot_dmg         = _dmg;
+    proj.shot_radius      = _radi;
+    proj.shot_force       = _force;
+    proj.totalfrags       = _deahtype;
+    proj.solid            = SOLID_BBOX;
+    proj.movetype         = MOVETYPE_FLYMISSILE;
+    proj.flags            = FL_PROJECTILE;
+    proj.bot_dodge        = TRUE;
+    proj.bot_dodgerating  = _dmg;
+    proj.velocity         = _vel;
+    proj.touch            = vehicles_projectile_explode;
+    proj.use              = vehicles_projectile_explode;
+    proj.owner            = self;
+    proj.realowner        = self.owner;
+    proj.think            = SUB_Remove;
+    proj.nextthink        = time + 30;
+
+    if(_health)
+    {
+        proj.takedamage       = DAMAGE_AIM;
+        proj.event_damage     = vehicles_projectile_damage;
+        proj.health           = _health;
+    }
+    else
+        proj.flags           = FL_PROJECTILE | FL_NOTARGET;
+
+    if(_mzlsound)
+        sound (self, CHAN_WEAPON, _mzlsound, VOL_BASE, ATTN_NORM);
+
+    if(_mzlfx)
+        pointparticles(particleeffectnum(_mzlfx), proj.origin, proj.velocity, 1);
+
+
+    setsize (proj, '-1 -1 -1' * _size, '1 1 1' * _size);
+
+    CSQCProjectile(proj, _clianim, _projtype, _cull);
+
+    return proj;
+}
+// End generic vehile projectile system
+
+/** vehicles_spawn
+    Exetuted for all vehicles on (re)spawn.
+    Sets defaults for newly spawned units.
+**/
+void vehicles_spawn()
+{
+    dprint("Spawning vehicle: ", self.netname, "\n");
+
+    // De-own & reset
+    self.vehicle_hudmodel.viewmodelforclient = self;
+
+    self.owner              = world;
+    self.touch              = vehicles_touch;
+    self.event_damage       = vehicles_damage;
+    self.iscreature         = TRUE;
+    self.movetype           = MOVETYPE_WALK;
+    self.solid              = SOLID_SLIDEBOX;
+    self.takedamage         = DAMAGE_AIM;
+       self.deadflag           = DEAD_NO;
+    self.bot_attack         = TRUE;
+    self.flags              = FL_NOTARGET;
+    self.avelocity          = '0 0 0';
+    self.velocity           = '0 0 0';
+
+    // Reset locking
+    self.lock_strength      = 0;
+    self.lock_target        = world;
+    self.misc_bulletcounter = 0;
+
+    // Return to spawn
+    self.angles             = self.pos2;
+    setorigin(self, self.pos1 + '0 0 128');
+    // Show it
+    pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
+
+    vehicles_reset_colors();
+    self.vehicle_spawn();
+}
+
+// Better way of determening whats crushable needed! (fl_crushable?)
+float vehicles_crushable(entity e)
+{
+    if(e.classname == "player")
+        return TRUE;
+
+    if(e.classname == "monster_zombie")
+        return TRUE;
+
+    return FALSE;
+}
 
 void vehicles_touch()
 {
+    // Vehicle currently in use
+    if(self.owner)
+    {
+        // Colided with world?
+        if(other == world)
+        {
+            // Apply velocity based self damage here
+        }
+        else
+        {
+            if(other.vehicle_flags & VHF_ISVEHICLE)
+            {
+                //other.velocity += self.velocity * (self.mass / other.mass);
+            }
+            else if(vehicles_crushable(other))
+            {
+                if(vlen(self.velocity) != 0)
+                    Damage(other, self, self.owner, autocvar_g_vehicles_crush_dmg, DEATH_VHCRUSH, '0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicles_crush_force);
+            }
+        }
+        return;
+    }
+
     if(other.classname != "player")
         return;
 
@@ -209,7 +412,7 @@ void vehicles_touch()
     if (clienttype(other) != CLIENTTYPE_REAL)
         return;
 
-    self.vehicle_enter();
+    vehicles_enter();
 }
 
 void vehicles_enter()
@@ -218,17 +421,28 @@ void vehicles_enter()
     if (clienttype(other) != CLIENTTYPE_REAL)
         return;
 
-    self.colormod = self.tur_head.colormod = '0 0 0';
+    if(self.phase > time)
+        return;
 
     if(teams_matter)
     if(self.team)
     if(self.team != other.team)
         return;
 
+    self.vehicle_ammo1   = 0;
+    self.vehicle_ammo2   = 0;
+    self.vehicle_reload1 = 0;
+    self.vehicle_reload2 = 0;
+    self.vehicle_energy  = 0;
+
     self.owner          = other;
     self.switchweapon   = other.switchweapon;
 
+    // .viewmodelforclient works better.
+    //self.vehicle_hudmodel.drawonlytoclient = self.owner;
+
     self.vehicle_hudmodel.viewmodelforclient = self.owner;
+
     self.event_damage         = vehicles_damage;
     self.nextthink            = 0;
     self.owner.angles         = self.angles;
@@ -251,6 +465,10 @@ void vehicles_enter()
     self.owner.vehicle_reload1  = self.vehicle_reload1;
     self.owner.vehicle_reload2  = self.vehicle_reload2;
 
+    // Cant do this, hides attached objects too.
+    //self.exteriormodeltoclient = self.owner;
+    //self.tur_head.exteriormodeltoclient = self.owner;
+
     other.flags &~= FL_ONGROUND;
     self.flags  &~= FL_ONGROUND;
 
@@ -261,46 +479,87 @@ void vehicles_enter()
     WriteByte (MSG_ONE, SVC_SETVIEWPORT);
     WriteEntity(MSG_ONE, self.vehicle_viewport);
 
-    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);  // 10 = SVC_SETVIEWANGLES
+    WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
     if(self.tur_head)
     {
-        WriteAngle(MSG_ONE, self.tur_head.angles_x + self.angles_x);    // tilt
-        WriteAngle(MSG_ONE, self.tur_head.angles_y + self.angles_y);    // yaw
-        WriteAngle(MSG_ONE, 0);    // roll
+        WriteAngle(MSG_ONE, self.tur_head.angles_x + self.angles_x); // tilt
+        WriteAngle(MSG_ONE, self.tur_head.angles_y + self.angles_y); // yaw
+        WriteAngle(MSG_ONE, 0);                                      // roll
     }
     else
     {
-        WriteByte (MSG_ONE, SVC_SETVIEWANGLES); // 10 = SVC_SETVIEWANGLES
-        WriteAngle(MSG_ONE,  self.angles_x * -1);    // tilt
-        WriteAngle(MSG_ONE,  self.angles_y);    // yaw
-        WriteAngle(MSG_ONE,  0);                // roll
+        WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+        WriteAngle(MSG_ONE,  self.angles_x * -1); // tilt
+        WriteAngle(MSG_ONE,  self.angles_y);      // yaw
+        WriteAngle(MSG_ONE,  0);                  // roll
     }
 
     vehicles_clearrturn();
 
     CSQCVehicleSetup(self.owner, self.hud);
 
-    if(self.vehicle_enter)
-        self.vehicle_enter();
+    self.vehicle_enter();
 }
 
-void vehicles_exit(float eject)
+/** vehicles_findgoodexit
+    Locates a valid location for the player to exit the vehicle.
+    Will first try prefer_spot, then up 100 random spots arround the vehicle
+    wich are in direct line of sight and empty enougth to hold a players bbox
+**/
+vector vehicles_findgoodexit(vector prefer_spot)
 {
-       self.colormap   = 1024;
-       self.tur_head.colormap   = 1024;
-
-    if (teams_matter)
-    {
-        if (self.team == COLOR_TEAM1)
-            self.colormod = '1.4 0.8 0.8';
-
-        if (self.team == COLOR_TEAM2)
-            self.colormod = '0.8 0.8 1.4';
-
-        self.tur_head.colormod = self.colormod;
+    vector exitspot;
+    float mysize;
+    
+    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, prefer_spot, MOVE_NORMAL, self.owner);
+    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+        return prefer_spot;
+    
+    mysize = vlen(self.maxs - self.mins);
+    float i;
+    vector v, v2;
+    v2 = 0.5 * (self.absmin + self.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, self.owner);
+        if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+            return v;
     }
+    
+    /*
+    exitspot = (self.origin + '0 0 48') + v_forward * mysize;
+    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
+    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+        return exitspot;
+    
+    exitspot = (self.origin + '0 0 48') - v_forward * mysize;
+    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
+    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+        return exitspot;
+
+    exitspot = (self.origin + '0 0 48') + v_right * mysize;
+    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
+    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+        return exitspot;
+    
+    exitspot = (self.origin + '0 0 48') - v_right * mysize;
+    tracebox(self.origin + '0 0 32', PL_MIN, PL_MAX, exitspot, MOVE_NORMAL, self.owner);
+    if(trace_fraction == 1.0 && !trace_startsolid && !trace_allsolid)
+        return exitspot;
+    */
+    
+    return self.origin;
+}
 
-
+/** vehicles_exit
+    Standarrd vehicle release fucntion.
+    custom code goes in self.vehicle_exit
+**/
+void vehicles_exit(float eject)
+{      
        self.flags |= FL_NOTARGET;
 
     if (self.owner)
@@ -309,12 +568,12 @@ void vehicles_exit(float eject)
         WriteByte (MSG_ONE, SVC_SETVIEWPORT);
         WriteEntity( MSG_ONE, self.owner);
 
-        WriteByte (MSG_ONE, SVC_SETVIEWANGLES);    // 10 = SVC_SETVIEWANGLES
-        WriteAngle(MSG_ONE,  0);                   // tilt
-        WriteAngle(MSG_ONE,  self.angles_y);        // yaw
-        WriteAngle(MSG_ONE,  0);                   // roll
+        WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
+        WriteAngle(MSG_ONE, 0);                 // pich
+        WriteAngle(MSG_ONE, self.angles_y);     // yaw
+        WriteAngle(MSG_ONE, 0);                 // roll
 
-        setsize(self.owner,PL_MIN,PL_MAX);
+        setsize(self.owner, PL_MIN,PL_MAX);
 
         self.owner.takedamage     = DAMAGE_AIM;
         self.owner.solid          = SOLID_SLIDEBOX;
@@ -327,14 +586,22 @@ void vehicles_exit(float eject)
         self.owner.event_damage   = PlayerDamage;
         self.owner.hud            = HUD_NORMAL;
         self.owner.switchweapon   = self.switchweapon;
+        self.owner.BUTTON_USE     = 0;
     }
 
+    if(self.deadflag == DEAD_NO)
+        self.avelocity          = '0 0 0';
+
     self.vehicle_hudmodel.viewmodelforclient = self;
-       self.tur_head.nodrawtoclient             = self;
+       self.tur_head.nodrawtoclient             = world;
+    vehicles_setreturn();
+
+    self.phase = time + 1;
 
-    if(self.vehicle_exit)
-        self.vehicle_exit(eject);
+    if(!teams_matter)
+        self.team = 0;
 
+    self.vehicle_exit(eject);
     self.owner = world;
 }
 
@@ -347,7 +614,7 @@ void vehicles_regen(.float timer, .float regen_field, float field_max, float rpa
         self.regen_field = min(self.regen_field + regen * delta_time, field_max);
 
         if(self.owner)
-            self.owner.regen_field = self.regen_field / field_max;
+            self.owner.regen_field = (self.regen_field / field_max) * 100;
     }
 }
 
@@ -356,7 +623,7 @@ void shieldhit_think()
     self.alpha -= 0.1;
     if (self.alpha <= 0)
     {
-        setmodel(self, "");
+        //setmodel(self, "");
         self.alpha = -1;
     }
     else
@@ -367,41 +634,43 @@ void shieldhit_think()
 
 void vehicles_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 {
-    float ddmg_take;
-
     self.dmg_time = time;
 
     if((self.vehicle_flags & VHF_HASSHIELD) && (self.vehicle_shield > 0))
     {
-        if (wasfreed(self.tur_head.enemy) || self.tur_head.enemy == world)
+        if (wasfreed(self.vehicle_shieldent) || self.vehicle_shieldent == world)
         {
-            self.tur_head.enemy = spawn();
-            self.tur_head.enemy.effects = EF_LOWPRECISION;
+            self.vehicle_shieldent = spawn();
+            self.vehicle_shieldent.effects = EF_LOWPRECISION;
+
+            setmodel(self.vehicle_shieldent, "models/vhshield.md3");
+            setattachment(self.vehicle_shieldent, self, "");
+            setorigin(self.vehicle_shieldent, real_origin(self) - self.origin);
+            self.vehicle_shieldent.scale       = 256 / vlen(self.maxs - self.mins);
+            self.vehicle_shieldent.think       = shieldhit_think;
         }
 
-        setmodel(self.tur_head.enemy, "models/vhshield.md3");
-        setattachment(self.tur_head.enemy, self, "");
 
-        self.tur_head.enemy.colormod    = '1 1 1';
-        self.tur_head.enemy.alpha       = 0.45;
-        self.tur_head.enemy.scale       = (256 / vlen(self.maxs - self.mins));
-        self.tur_head.enemy.angles      = vectoangles(normalize(hitloc - self.origin)) - self.angles;
-        self.tur_head.enemy.think       = shieldhit_think;
-        self.tur_head.enemy.nextthink   = time;
+        self.vehicle_shieldent.colormod    = '1 1 1';
+        self.vehicle_shieldent.alpha       = 0.45;
+        self.vehicle_shieldent.angles      = vectoangles(normalize(hitloc - (self.origin + self.vehicle_shieldent.origin))) - self.angles;
+        self.vehicle_shieldent.nextthink   = time;
 
         self.vehicle_shield -= damage;
+
         if(self.vehicle_shield < 0)
         {
-            self.tur_head.enemy.colormod = '10 0 -1';
-            ddmg_take = fabs(self.vehicle_shield);
-            self.vehicle_shield         = 0;
-            self.tur_head.enemy.alpha   = 0.75;
-            self.vehicle_health         -= ddmg_take;
+            self.vehicle_shieldent.colormod = '2 0 0';
+            self.vehicle_shield             = 0;
+            self.vehicle_shieldent.alpha    = 0.75;
+            self.vehicle_health            -= fabs(self.vehicle_shield);
         }
     }
     else
         self.vehicle_health -= damage;
 
+    self.velocity += force; // * (vlen(force) / self.mass);
+
     if(self.vehicle_health <= 0)
     {
         if(self.owner)
@@ -411,14 +680,17 @@ void vehicles_damage(entity inflictor, entity attacker, float damage, float deat
                 vehicles_exit(VHEF_RELESE);
 
         self.vehicle_die();
+        vehicles_setreturn();
     }
 }
 
 void vehicles_return()
 {
     pointparticles(particleeffectnum("teleport"), self.enemy.origin + '0 0 64', '0 0 0', 1);
-    self.enemy.think = self.use;
+
+    self.enemy.think     = vehicles_spawn;
     self.enemy.nextthink = time;
+
     remove(self);
 }
 
@@ -431,46 +703,35 @@ void vehicles_clearrturn()
     {
         if(ret.enemy == self)
         {
-            ret.think = SUB_Remove;
-            ret.nextthink = time + 0.1;
+            ret.classname   = "";
+            ret.think       = SUB_Remove;
+            ret.nextthink   = time + 0.1;
             return;
         }
         ret = ret.chain;
     }
 }
 
-void vehicles_setreturn(float retime, void() respawn_proc)
+void vehicles_setreturn()
 {
-    vehicles_clearrturn();
-
-    if (self.deadflag == DEAD_NO)
-    {
-        entity ret;
-
-        ret = spawn();
-        ret.classname = "vehicle_return";
-        ret.enemy = self;
-        ret.think = vehicles_return;
-        ret.nextthink = time + retime;
-        ret.use = respawn_proc;
-    }
-}
+    entity ret;
 
-float vehicles_customizeentityforclient()
-{
-    if(self.deadflag == DEAD_DEAD)
-        return FALSE;
+    vehicles_clearrturn();
 
-    return TRUE;
-}
+    ret = spawn();
+    ret.classname   = "vehicle_return";
+    ret.enemy       = self;
+    ret.think       = vehicles_return;
+    ret.nextthink   = time + self.vehicle_respawntime;
+} 
 
-void vehicles_configcheck(string  configname, float   check_cvar)
+void vehicles_configcheck(string  configname, float check_cvar)
 {
     if(check_cvar == 0)
         localcmd(strcat("exec ", configname, "\n"));
 }
 
-void vehicles_common_spawn()
+void vehicles_reset_colors()
 {
     entity e;
     float _effects, _colormap;
@@ -480,30 +741,39 @@ void vehicles_common_spawn()
         _effects = EF_NODEPTHTEST;
 
     if(autocvar_g_fullbrightplayers)
-        _colormap |= EF_FULLBRIGHT;
+        _effects |= EF_FULLBRIGHT;
 
     if(self.team)
         _colormap = 1024 + (self.team - 1) * 17;
     else
         _colormap = 1024;
 
-    _glowmod = '0 0 0';
+    _glowmod  = '0 0 0';
     _colormod = '0 0 0';
 
+    // Find all ents attacked to main model and setup effects, colormod etc.
     e = findchainentity(tag_entity, self);
     while(e)
     {
-        e.colormap = _colormap;
-        e.effects = _effects;
-        e.colormod = _colormod;
-        e.colormap = _colormap;
+        if(e != self.vehicle_shieldent)
+        {
+            e.effects   = _effects  | EF_LOWPRECISION;
+            e.colormod  = _colormod;
+            e.colormap  = _colormap;
+            e.alpha     = 1;
+        }
         e = e.chain;
     }
 
-    self.effects  = _effects;
-    self.colormap = _colormap;
-    self.colormod = _colormod;
-    self.colormap = _colormap;
+    self.vehicle_hudmodel.effects  = self.effects  = _effects | EF_LOWPRECISION;
+    self.vehicle_hudmodel.colormod = self.colormod = _colormod;
+    self.vehicle_hudmodel.colormap = self.colormap = _colormap;
+    self.vehicle_viewport.effects = (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT);
+
+    self.alpha     = 1;
+    self.avelocity = '0 0 0';
+    self.velocity  = '0 0 0';
+    self.effects   = _effects;
 }
 
 float vehicle_initialize(string  net_name,
@@ -514,27 +784,28 @@ float vehicle_initialize(string  net_name,
                          string  hudtag,
                          string  viewtag,
                          float   vhud,
-                         vector min_s,
-                         vector max_s,
-                         float  nodrop,
+                         vector  min_s,
+                         vector  max_s,
+                         float   nodrop,
                          void()  spawnproc,
+                         float   _respawntime,
                          float() physproc,
                          void()  enterproc,
                          void(float extflag) exitfunc,
                          void() dieproc,
-                         void() thinkproc )
+                         void() thinkproc,
+                         float  use_csqc)
 {
     addstat(STAT_HUD, AS_INT,  hud);
-       addstat(STAT_VEHICLESTAT_HEALTH,  AS_FLOAT, vehicle_health);
-       addstat(STAT_VEHICLESTAT_SHIELD,  AS_FLOAT, vehicle_shield);
-       addstat(STAT_VEHICLESTAT_ENERGY,  AS_FLOAT, vehicle_energy);
+       addstat(STAT_VEHICLESTAT_HEALTH,  AS_INT, vehicle_health);
+       addstat(STAT_VEHICLESTAT_SHIELD,  AS_INT, vehicle_shield);
+       addstat(STAT_VEHICLESTAT_ENERGY,  AS_INT, vehicle_energy);
 
        addstat(STAT_VEHICLESTAT_AMMO1,   AS_INT,   vehicle_ammo1);
-       addstat(STAT_VEHICLESTAT_RELOAD1, AS_FLOAT, vehicle_reload1);
+       addstat(STAT_VEHICLESTAT_RELOAD1, AS_INT, vehicle_reload1);
 
        addstat(STAT_VEHICLESTAT_AMMO2,   AS_INT,   vehicle_ammo2);
-       addstat(STAT_VEHICLESTAT_RELOAD2, AS_FLOAT, vehicle_reload2);
-
+       addstat(STAT_VEHICLESTAT_RELOAD2, AS_INT, vehicle_reload2);
 
     if(bodymodel == "")
         error("vehicles: missing bodymodel!");
@@ -563,15 +834,16 @@ float vehicle_initialize(string  net_name,
     self.iscreature         = TRUE;
     self.hud                = vhud;
 
-    self.customizeentityforclient = vehicles_customizeentityforclient;
-    self.vehicle_die        = dieproc;
-    self.vehicle_exit       = exitfunc;
-    self.vehicle_enter      = enterproc;
-    self.PlayerPhysplug     = physproc;
-    self.event_damage       = vehicles_damage;
-    self.touch              = vehicles_touch;
-    self.think              = spawnproc;
-    self.nextthink          = time;
+    self.vehicle_die         = dieproc;
+    self.vehicle_exit        = exitfunc;
+    self.vehicle_enter       = enterproc;
+    self.PlayerPhysplug      = physproc;
+    self.event_damage        = vehicles_damage;
+    self.touch               = vehicles_touch;
+    self.think               = vehicles_spawn;    
+    self.nextthink           = time;        
+    self.vehicle_respawntime = _respawntime;
+    self.vehicle_spawn       = spawnproc;
 
     if(autocvar_g_nodepthtestplayers)
         self.effects = self.effects | EF_NODEPTHTEST;
@@ -582,6 +854,7 @@ float vehicle_initialize(string  net_name,
     setmodel(self.vehicle_hudmodel, hudmodel);
     setmodel(self.vehicle_viewport, "null");
 
+
     if(topmodel != "")
     {
         setmodel(self.tur_head, topmodel);
@@ -616,5 +889,5 @@ void bugmenot()
     self.vehicle_enter      = self.vehicle_exit;
     self.vehicle_die        = self.vehicle_exit;
     self.vehicle_spawn      = self.vehicle_exit;
-    //self.vehicle_message    = self.vehicle_exit;
+    self.AuxiliaryXhair     = self.AuxiliaryXhair;
 }