]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/tturrets/system/system_main.qc
Move turrets death and gib to client (now zero network use for those events)
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / tturrets / system / system_main.qc
index 1b2fcd7723b8089c7fb5102dbb44f424eb4c7e66..fb79f5442fffd036ba08b56425209ffc9f57e6e8 100644 (file)
@@ -1,23 +1,42 @@
 #define cvar_base "g_turrets_unit_"
 
-/*
-float turret_customizeentityforclient()
-{
-}
-
-float Turret_SendEntity(entity to, float sf)
+float turret_send(entity to, float sf)
 {
-
-       WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET);
-       WriteCoord(MSG_ENTITY, self.tur_head.angles_x);
-       WriteCoord(MSG_ENTITY, self.tur_head.angles_y);
-    WriteByte(MSG_ENTITY, self.tur_head.frame);
-
-       //WriteCoord(MSG_ENTITY, self.tur_head.angles_z);
-
+       dprint("Sending update\n");
+       WriteByte(MSG_ENTITY, ENT_CLIENT_TURRET);    
+       WriteByte(MSG_ENTITY, sf);
+       if(sf & TNSF_SETUP)
+       {
+           WriteByte(MSG_ENTITY, self.turret_type);
+           
+           WriteCoord(MSG_ENTITY, self.origin_x);
+           WriteCoord(MSG_ENTITY, self.origin_y);
+           WriteCoord(MSG_ENTITY, self.origin_z);
+           
+           WriteAngle(MSG_ENTITY, self.angles_x);
+           WriteAngle(MSG_ENTITY, self.angles_y);
+    }
+    
+    if(sf & TNSF_ANG)
+    {
+        WriteShort(MSG_ENTITY, rint(self.tur_head.angles_x));
+        WriteShort(MSG_ENTITY, rint(self.tur_head.angles_y));
+    }
+    
+    if(sf & TNSF_AVEL)
+    {        
+        WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity_x));
+        WriteShort(MSG_ENTITY, rint(self.tur_head.avelocity_y));
+    }
+    
+    if(sf & TNSF_STATUS)
+    {        
+        WriteByte(MSG_ENTITY, self.team);
+        WriteByte(MSG_ENTITY, rint((self.health / self.tur_health) * 255)); // Send health as 0-255 insted of real value, where 255 = 100%
+    }
+    
        return TRUE;
 }
-*/
 
 void load_unit_settings(entity ent, string unitname, float is_reload)
 {
@@ -116,8 +135,6 @@ void turret_do_updates(entity t_turret)
             self.tur_dist_impact_to_aimpos = 0;
         else
             self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos);
-
-
     }
     else
         tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self);
@@ -199,12 +216,16 @@ vector turret_fovsearch_random()
 ** Handles head rotation according to
 ** the units .track_type and .track_flags
 **/
+.float turret_framecounter;
 void turret_stdproc_track()
 {
     vector target_angle; // This is where we want to aim
     vector move_angle;   // This is where we can aim
     float f_tmp;
-
+    vector v1, v2;
+    v1 = self.tur_head.angles;
+    v2 = self.tur_head.avelocity;
+    
     if (self.track_flags == TFL_TRACK_NO)
         return;
 
@@ -252,7 +273,10 @@ void turret_stdproc_track()
                 if(self.tur_head.angles_y  < -self.aim_maxrot)
                     self.tur_head.angles_y = self.aim_maxrot;
             }
-
+            
+            // CSQC
+            self.SendFlags  = TNSF_ANG;
+            
             return;
 
         case TFL_TRACKTYPE_FLUIDINERTIA:
@@ -278,12 +302,16 @@ void turret_stdproc_track()
         {
             self.tur_head.avelocity_x = 0;
             self.tur_head.angles_x = self.aim_maxpitch;
+            
+            self.SendFlags  |= TNSF_ANG;
         }
         
         if((self.tur_head.angles_x + self.tur_head.avelocity_x * self.ticrate) < -self.aim_maxpitch)
         {
             self.tur_head.avelocity_x = 0;
             self.tur_head.angles_x = -self.aim_maxpitch;
+                        
+            self.SendFlags  |= TNSF_ANG;
         }
     }
 
@@ -296,14 +324,28 @@ void turret_stdproc_track()
         {
             self.tur_head.avelocity_y = 0;
             self.tur_head.angles_y = self.aim_maxrot;
+            
+            self.SendFlags  |= TNSF_ANG;
         }
 
         if((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate) < -self.aim_maxrot)
         {
             self.tur_head.avelocity_y = 0;
             self.tur_head.angles_y = -self.aim_maxrot;
+            
+            self.SendFlags  |= TNSF_ANG;
         }
     }
+        
+    self.SendFlags  |= TNSF_AVEL;
+    
+    // Force a angle update every 10'th frame
+    self.turret_framecounter += 1;
+    if(self.turret_framecounter >= 10)
+    {        
+        self.SendFlags |= TNSF_ANG;
+        self.turret_framecounter = 0;
+    }            
 }
 
 
@@ -340,8 +382,9 @@ float turret_stdproc_firecheck()
 
     // Special case: volly fire turret that has to fire a full volly if a shot was fired.
     if (self.shoot_flags & TFL_SHOOT_VOLLYALWAYS)
-        if not (self.volly_counter == self.shot_volly)
-            return 1;
+        if (self.volly_counter != self.shot_volly)
+                       if(self.ammo >= self.shot_dmg)
+                               return 1;               
 
     // Lack of zombies makes shooting dead things unnecessary :P
     if (self.firecheck_flags & TFL_FIRECHECK_DEAD)
@@ -606,7 +649,8 @@ void turret_think()
     entity e;
 
     self.nextthink = time + self.ticrate;
-
+    //self.SendFlags = TNSF_UPDATE | TNSF_STATUS | TNSF_ANG | TNSF_AVEL;
+    
     // ONS uses somewhat backwards linking.
     if (teamplay)
     {
@@ -635,7 +679,7 @@ void turret_think()
     if not (self.spawnflags & TSF_NO_AMMO_REGEN)
     if (self.ammo < self.ammo_max)
         self.ammo = min(self.ammo + self.ammo_recharge, self.ammo_max);
-
+                       
     // Inactive turrets needs to run the think loop,
     // So they can handle animation and wake up if need be.
     if not (self.tur_active)
@@ -717,7 +761,7 @@ void turret_think()
 
         // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
         float do_target_scan;
-        if((self.target_select_time + cvar("g_turrets_targetscan_maxdelay")) < time)
+        if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
             do_target_scan = 1;
 
         // Old target (if any) invalid?
@@ -728,7 +772,7 @@ void turret_think()
         }
 
         // But never more often then g_turrets_targetscan_mindelay!
-        if (self.target_select_time + cvar("g_turrets_targetscan_mindelay") > time)
+        if (self.target_select_time + autocvar_g_turrets_targetscan_mindelay > time)
             do_target_scan = 0;
 
         if(do_target_scan)
@@ -752,7 +796,7 @@ void turret_think()
             return;
         }
         else
-            self.lip = time + cvar("g_turrets_aimidle_delay"); // Keep track of the last time we had a target.
+            self.lip = time + autocvar_g_turrets_aimidle_delay; // Keep track of the last time we had a target.
 
         // Predict?
         if not(self.aim_flags & TFL_AIM_NO)
@@ -776,7 +820,7 @@ void turret_think()
 
 void turret_fire()
 {
-    if (cvar("g_turrets_nofire") != 0)
+    if (autocvar_g_turrets_nofire != 0)
         return;
 
     self.turret_firefunc();
@@ -825,9 +869,10 @@ void turret_stdproc_use()
 
 void turret_link()
 {
-    //Net_LinkEntity(self, FALSE, 0, Turret_SendEntity);
+    Net_LinkEntity(self, TRUE, 0, turret_send);
     self.think      = turret_think;
     self.nextthink  = time;
+    self.tur_head.effects = EF_NODRAW;
 }
 
 void turrets_manager_think()
@@ -835,7 +880,7 @@ void turrets_manager_think()
     self.nextthink = time + 1;
 
     entity e;
-    if (cvar("g_turrets_reloadcvars") == 1)
+    if (autocvar_g_turrets_reloadcvars == 1)
     {
         e = nextent(world);
         while (e)
@@ -858,20 +903,27 @@ void turrets_manager_think()
 * (unless you have a very good reason not to)
 * if the return value is 0, the turret should be removed.
 */
-float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base, string head)
+float turret_stdproc_init (string cvar_base_name, string base, string head, float _turret_type)
 {
        entity e, ee;
 
     // Are turrets allowed?
-    if (cvar("g_turrets") == 0)
+    if (autocvar_g_turrets == 0)
         return 0;
-
-
+    
+    if(_turret_type < 1 || _turret_type > TID_LAST)
+    {
+        dprint("Invalid / Unkown turret type\"", ftos(_turret_type), "\", aborting!\n");
+        return 0;
+    }    
+    self.turret_type = _turret_type;
+    
     e = find(world, classname, "turret_manager");
     if not (e)
     {
         e = spawn();
 
+        /*
         setorigin(e,'0 0 0');
         setmodel(e,"models/turrets/plasma.md3");
         vector v;
@@ -882,23 +934,27 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base
             //crash();
         }
         setmodel(e,"");
+        */
 
         e.classname = "turret_manager";
         e.think = turrets_manager_think;
         e.nextthink = time + 2;
     }
 
+    /*
     if(csqc_shared)
     {
         dprint("WARNING: turret requested csqc_shared but this is not implemented. Expect strange things to happen.\n");
         csqc_shared = 0;
     }
-
+    */
+    
     if not (self.spawnflags & TSF_SUSPENDED)
         droptofloor_builtin();
 
     // Terrainbase spawnflag. This puts a enlongated model
     // under the turret, so it looks ok on uneaven surfaces.
+    /*  TODO: Handle this with CSQC
     if (self.spawnflags & TSF_TERRAINBASE)
     {
         entity tb;
@@ -907,12 +963,13 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base
         setorigin(tb,self.origin);
         tb.solid = SOLID_BBOX;
     }
+    */
 
     self.cvar_basename = cvar_base_name;
-    load_unit_settings(self,self.cvar_basename, 0);
+    load_unit_settings(self, self.cvar_basename, 0);
 
     // Handle turret teams.
-    if (cvar("g_assault") != 0)
+    if (autocvar_g_assault != 0)
     {
         if not (self.team)
             self.team = 14; // Assume turrets are on the defending side if not explicitly set otehrwize
@@ -1100,7 +1157,6 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base
 
     self.target_validate_flags = self.target_select_flags;
 
-
 // Ammo stuff
     if not (self.ammo_max)
         self.ammo_max = self.shot_dmg * 10;
@@ -1127,6 +1183,13 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base
 
 // Offsets & origins
     if (!self.tur_shotorg)   self.tur_shotorg = '50 0 50';
+    
+    if (!self.health)
+        self.health = 150;
+
+// Game hooks
+       if(MUTATOR_CALLHOOK(TurretSpawn))
+               return 0;
 
 // End of default & sanety checks, start building the turret.
 
@@ -1145,9 +1208,6 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base
     setorigin(self.tur_head, '0 0 0');
     setattachment(self.tur_head, self, "tag_head");
 
-    if (!self.health)
-        self.health = 150;
-
     self.tur_health          = self.health;
     self.solid               = SOLID_BBOX;
     self.tur_head.solid      = SOLID_NOT;
@@ -1174,35 +1234,19 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base
     else
         self.idle_aim  = '0 0 0';
 
-    // Team color
-    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';
-
     // Attach stdprocs. override when and what needed
+    self.turret_firecheckfunc   = turret_stdproc_firecheck;
+    self.turret_firefunc        = turret_stdproc_fire;
+    self.event_damage           = turret_stdproc_damage;
+    
     if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT)
-    {
         self.turret_score_target    = turret_stdproc_targetscore_support;
-        self.turret_firecheckfunc   = turret_stdproc_firecheck;
-        self.turret_firefunc        = turret_stdproc_fire;
-        self.event_damage           = turret_stdproc_damage;
-    }
     else
-    {
         self.turret_score_target    = turret_stdproc_targetscore_generic;
-        self.turret_firecheckfunc   = turret_stdproc_firecheck;
-        self.turret_firefunc        = turret_stdproc_fire;
-        self.event_damage           = turret_stdproc_damage;
-    }
 
     self.use = turret_stdproc_use;
     self.bot_attack = TRUE;
 
-    // Initiate the main AI loop
-    if(csqc_shared)
-        self.think     = turret_link;
-    else
-        self.think     = turret_think;
-
     ++turret_count;
     self.nextthink = time + 1;
     self.nextthink +=  turret_count * sys_frametime;
@@ -1233,7 +1277,12 @@ float turret_stdproc_init (string cvar_base_name, float csqc_shared, string base
         activator = ee;
         self.use();
     }
-
+    
+       turret_stdproc_respawn();
+           
+    if (!turret_tag_fire_update())
+        dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+    
     return 1;
 }