]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/showspecs
authorMario <mario.mario@y7mail.com>
Mon, 27 Jan 2014 06:14:00 +0000 (17:14 +1100)
committerMario <mario.mario@y7mail.com>
Mon, 27 Jan 2014 06:14:00 +0000 (17:14 +1100)
1  2 
defaultXonotic.cfg
qcsrc/client/Main.qc
qcsrc/client/autocvars.qh
qcsrc/client/hud.qc
qcsrc/common/constants.qh
qcsrc/server/autocvars.qh
qcsrc/server/cl_client.qc

diff --combined defaultXonotic.cfg
index 353d19c11c6faa29b2f8218e1d98b4442709fcc8,c6fa7642be5bb988be1c26272d43a86af5fb67e4..a83a2577b0bd568c9b019cbe906a3554628f5e97
@@@ -59,7 -59,7 +59,7 @@@ seta cl_reticle 1 "control for togglin
  seta cl_reticle_stretch 0 "whether to stretch reticles so they fit the screen (brakes image proportions)"
  seta cl_reticle_item_nex 1 "draw aiming reticle for the nex weapon's zoom, 0 disables and values between 0 and 1 change alpha"
  seta cl_reticle_item_normal 1 "draw reticle when zooming with the zoom button, 0 disables and values between 0 and 1 change alpha"
- fov 90
+ fov 100
  seta cl_velocityzoom 0        "velocity based zooming of fov, negative values zoom out"
  seta cl_velocityzoom_type 3 "how to factor in speed, 1 = all velocity in all directions, 2 = velocity only in forward direction (can be negative), 3 = velocity only in forward direction (limited to forward only)"
  seta cl_velocityzoom_speed 1000 "target speed for fov factoring"
@@@ -141,6 -141,9 +141,9 @@@ set rpn_linear_to_sRGB "dup 1.0 2.4 di
  // q3map_skylight 9.32523632 3
  alias skybox_nosRGB_to_sRGB "rpn $3 402.123 $4 div div $rpn_sRGB_to_linear 402.123 $4 div mul /new_skylight: $3 402.123 $4 div div $1 256 div $2 0.017453 mul sin mul add $rpn_sRGB_to_linear $3 402.123 $4 div div $rpn_sRGB_to_linear sub 256 mul $2 0.017453 mul sin div /new_sunlight:"
  
+ set cl_orthoview 0 "enable top-down view of the map- meant to be used for radar map images (note: orthoview sets cvars temporarily, requires restart to return them to normal)"
+ set cl_orthoview_nofog 1 "disable fog while in orthoview-- note, should not be enabled on ALL maps, i.e. oilrig works fine with this disabled"
  // these settings determine how much the view is affected by movement/damage
  cl_smoothviewheight 0.05 // time of the averaging to the viewheight value so that it creates a smooth transition for crouching and such. 0 for instant transition
  cl_deathfade 0 // fade screen to dark red when dead, value represents how fast the fade is (higher is faster)
@@@ -454,6 -457,10 +457,10 @@@ seta menu_sandbox_edit_material "
  
  bind f7 menu_showsandboxtools
  
+ seta menu_monsters_edit_spawn ""
+ seta menu_monsters_edit_skin 0
+ seta menu_monsters_edit_movetarget 1
  set g_playerclip_collisions 1 "0 = disable collision testing against playerclips, might be useful on some defrag maps"
  set g_botclip_collisions 1 "0 = disable collision testing against botclips, might be useful on some defrag maps"
  
@@@ -1072,6 -1079,8 +1079,8 @@@ sv_gameplayfix_delayprojectiles 
  sv_gameplayfix_q2airaccelerate 1
  sv_gameplayfix_stepmultipletimes 1
  
+ cl_gameplayfix_fixedcheckwatertransition 1
  // delay for "kill" to prevent abuse
  set g_balance_kill_delay 2
  set g_balance_kill_antispam 5
@@@ -1189,32 -1198,9 +1198,9 @@@ set g_showweaponspawns 1       "display sprit
  //   Quake-Joule:  1 qJ  = 1 qN * 1 qu
  //   Quake-Pascal: 1 qPa = 1 qN / 1 qu^2
  
- set g_ballistics_materialconstant 1414213562
- set g_ballistics_mindistance 16
+ set g_ballistics_mindistance 2 // enable ballistics starting from 2 qu
  set g_ballistics_density_player 0.50 // players are 2x as easy to pass as walls
  set g_ballistics_density_corpse 0.10 // corpses are 10x as easy to pass as walls
- // unit: qJ / qu^3 (energy needed per volume unit of solid to push/burn away
- // parameter: bullet constant: mass / area in g/qu^2
- // = mass / (pi/4 * caliber^2)
- // with caliber in inches, mass in grams:
- // = 1.273239544735163 * mass / caliber^2
- // with caliber in inches, mass in grains:
- // = 0.082633246453312 * mass / caliber^2
- // bullet max travel distance inside solid:
- //   0.5 * v^2 * bulletconstant / g_ballistics_materialconstant
- // some bullet constants:
- //   http://hypertextbook.com/facts/2000/ShantayArmstrong.shtml
- //     second bullet: caliber .45, mass 16.2g, bullet constant 101.859163578813
- //     third bullet: caliber .338, mass 16.2g, bullet constant 180.5476053421592
- //     fourth bullet: caliber .25, mass 2.3g, bullet constant 46.85521524625399
- //   http://en.wikipedia.org/wiki/.50_BMG
- //     caliber .5, 360 grains, bullet constant 118.9918748927693
- //   AK-47:
- //     caliber .3, 62 grains, bullet constant 56.92512533450383
- //   .3 winchester magnum:
- //     caliber .3, 150 grains, bullet constant 137.7220774221867
  
  set cl_stripcolorcodes 0      "experimental feature (notes: strips ALL color codes from messages!)"
  
@@@ -1562,6 -1548,7 +1548,7 @@@ exec crosshairs.cf
  exec gamemodes.cfg
  exec mutators.cfg
  exec notifications.cfg
+ exec monsters.cfg
  
  // load console command aliases and settings
  exec commands.cfg
@@@ -1594,6 -1581,3 +1581,6 @@@ set cl_simpleitems_postfix "_simple" "p
  set cl_fullbright_items 0 "enable fullbright items (if server allows, controled by g_fullbrightitems)"
  set cl_weapon_stay_color "2 0.5 0.5" "Color of picked up weapons when g_weapon_stay > 0"
  set cl_weapon_stay_alpha 0.75 "Alpha of picked up weapons when g_weapon_stay > 0"
 +
 +set sv_showspectators 0
 +set cl_showspectators 1
diff --combined qcsrc/client/Main.qc
index 1e320048886f730986b0207da806939cd3bf7277,2ba4130db2a126bfdcf81120ba136957fbbb29b2..545ba592ed864678de5707c0a93cc40c3d2bdc93
@@@ -53,7 -53,7 +53,7 @@@ void CSQC_Init(void
        check_unacceptable_compiler_bugs();
  
  #ifdef WATERMARK
-       print(sprintf(_("^4CSQC Build information: ^1%s\n"), WATERMARK));
+       printf(_("^4CSQC Build information: ^1%s\n"), WATERMARK);
  #endif
  
        float i;
  
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
+       CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
@@@ -213,7 -214,7 +214,7 @@@ float SetTeam(entity o, float Team
                        default:
                                if(GetTeam(Team, false) == world)
                                {
-                                       print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
+                                       printf(_("trying to switch to unsupported team %d\n"), Team);
                                        Team = NUM_SPECTATOR;
                                }
                                break;
                        default:
                                if(GetTeam(Team, false) == world)
                                {
-                                       print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
+                                       printf(_("trying to switch to unsupported team %d\n"), Team);
                                        Team = NUM_SPECTATOR;
                                }
                                break;
@@@ -424,7 -425,7 +425,7 @@@ void Ent_ReadPlayerScore(
        if(!isNew && n != self.sv_entnum)
        {
                //print("A CSQC entity changed its owner!\n");
-               print(sprintf("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname));
+               printf("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname);
                isNew = true;
                Ent_Remove();
                self.enttype = ENT_CLIENT_SCORES;
@@@ -687,7 -688,7 +688,7 @@@ void Ent_ReadSpawnPoint(float is_new) /
                }
        }
  
-       //print(sprintf("Ent_ReadSpawnPoint(is_new = %d); origin = %s, team = %d, effect = %d\n", is_new, vtos(self.origin), teamnum, self.cnt));
+       //printf("Ent_ReadSpawnPoint(is_new = %d); origin = %s, team = %d, effect = %d\n", is_new, vtos(self.origin), teamnum, self.cnt);
  }
  
  void Ent_ReadSpawnEvent(float is_new)
                }
        }
  
-       //print(sprintf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum));
+       //printf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum);
  }
  
  // CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
@@@ -753,7 -754,7 +754,7 @@@ void CSQC_Ent_Update(float bIsNewEntity
        t = ReadByte();
  
        if(autocvar_developer_csqcentities)
-               print(sprintf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t));
+               printf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t);
  
        // set up the "time" global for received entities to be correct for interpolation purposes
        savetime = time;
                if(t != self.enttype || bIsNewEntity)
                {
                        //print("A CSQC entity changed its type!\n");
-                       print(sprintf("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t));
+                       printf("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t);
                        Ent_Remove();
                        clearentity(self);
                        bIsNewEntity = 1;
        {
                if(!bIsNewEntity)
                {
-                       print(sprintf("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t));
+                       printf("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t);
                        bIsNewEntity = 1;
                }
        }
@@@ -868,7 -869,7 +869,7 @@@ void Ent_Remove(
  void CSQC_Ent_Remove()
  {
        if(autocvar_developer_csqcentities)
-               print(sprintf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype));
+               printf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype);
  
        if(wasfreed(self))
        {
@@@ -893,7 -894,7 +894,7 @@@ void Gamemode_Init(
  void CSQC_Parse_StuffCmd(string strMessage)
  {
        if(autocvar_developer_csqcentities)
-               print(sprintf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage));
+               printf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage);
  
        localcmd(strMessage);
  }
  void CSQC_Parse_Print(string strMessage)
  {
        if(autocvar_developer_csqcentities)
-               print(sprintf("CSQC_Parse_Print(\"%s\")\n", strMessage));
+               printf("CSQC_Parse_Print(\"%s\")\n", strMessage);
  
        print(ColorTranslateRGB(strMessage));
  }
  void CSQC_Parse_CenterPrint(string strMessage)
  {
        if(autocvar_developer_csqcentities)
-               print(sprintf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage));
+               printf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage);
  
        centerprint_hud(strMessage);
  }
@@@ -921,8 -922,10 +922,10 @@@ void Fog_Force(
  {
        // TODO somehow thwart prvm_globalset client ...
  
-       if(forcefog != "")
-               localcmd(strcat(notranslate_fogcmd1, forcefog, notranslate_fogcmd2));
+       if(autocvar_cl_orthoview && autocvar_cl_orthoview_nofog)
+               { localcmd("\nr_drawfog 0\n"); }
+       else if(forcefog != "")
+               { localcmd(strcat(notranslate_fogcmd1, forcefog, notranslate_fogcmd2)); }
  }
  
  void Gamemode_Init();
@@@ -1187,19 -1190,6 +1190,19 @@@ void Net_WeaponComplain(
        }
  }
  
 +void Net_ReadSpecInfo()
 +{
 +      float i;
 +      
 +      num_spectators = ReadByte();
 +      for(i = 0; i < num_spectators; ++i)
 +      {
 +              local float slot = ReadByte();
 +              if(i < MAX_SPECTATORS)
 +                      spectatorlist[i] = slot - 1;
 +      }
 +}
 +
  // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
  // You must ALWAYS first acquire the temporary ID, which is sent as a byte.
  // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
@@@ -1212,7 -1202,7 +1215,7 @@@ float CSQC_Parse_TempEntity(
                nTEID = ReadByte();
  
        if(autocvar_developer_csqcentities)
-               print(sprintf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID));
+               printf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
  
                // NOTE: Could just do return instead of break...
        switch(nTEID)
                        Net_ReadRace();
                        bHandled = true;
                        break;
-               case TE_CSQC_ZCURVEPARTICLES:
-                       Net_ReadZCurveParticles();
-                       bHandled = true;
-                       break;
                case TE_CSQC_NEXGUNBEAMPARTICLE:
                        Net_ReadNexgunBeamParticle();
                        bHandled = true;
                        cl_notice_read();
                        bHandled = true;
                        break;
 +              case TE_CSQC_SPECINFO:
 +                      Net_ReadSpecInfo();
 +                      bHandled = true;
 +                      break;
                default:
                        // No special logic for this temporary entity; return 0 so the engine can handle it
                        bHandled = false;
index 2169d10051afc36c04c5d6cb205a49e338eebbd3,43aab6ae44c73f3c2b0c598bbe4ae3d72014248e..64ef41ff54a11fc377d4e36e03f3d2702e2d2442
@@@ -54,6 -54,8 +54,8 @@@ float autocvar_cl_gunalign
  float autocvar_cl_hidewaypoints;
  float autocvar_cl_lockview;
  float autocvar_cl_nogibs;
+ float autocvar_cl_orthoview;
+ float autocvar_cl_orthoview_nofog;
  float autocvar_cl_particlegibs;
  float autocvar_cl_particles_oldnexbeam;
  float autocvar_cl_particles_quality;
@@@ -427,4 -429,3 +429,4 @@@ string autocvar__cl_playermodel
  float autocvar_cl_deathglow;
  float autocvar_developer_csqcentities;
  float autocvar_g_jetpack_attenuation;
 +float autocvar_cl_showspectators;
diff --combined qcsrc/client/hud.qc
index f24df1e2050ea49ceac401a163ffec32e6f09700,252142506f88731b28e21e679c0bd5d84b7d52b2..08dcd6d382ea212259e0654d21fb8b18348e97bf
@@@ -3734,22 -3734,6 +3734,22 @@@ void HUD_InfoMessages(void
                        s = _("^2Currently in ^1warmup^2 stage!");
                        drawInfoMessage(s)
                }
 +              
 +              if(autocvar_cl_showspectators)
 +              if(num_spectators)
 +              if not(spectatee_status)
 +              {
 +                      s = _("^1Spectating you:");
 +                      drawInfoMessage(s)
 +                      float limit = min(num_spectators, MAX_SPECTATORS);
 +                      float i;
 +                      for(i = 0; i < limit; ++i)
 +                      {
 +                              float slot = spectatorlist[i];
 +                              s = strcat("^3", GetPlayerName(slot));
 +                              drawInfoMessage(s)
 +                      }
 +              }
  
                string blinkcolor;
                if(mod(time, 1) >= 0.5)
@@@ -4111,7 -4095,7 +4111,7 @@@ float centerprint_showing
  
  void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num)
  {
-       //print(sprintf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num));
+       //printf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num);
        float i, j;
  
        if(strMessage == "" && new_id == 0)
@@@ -4277,8 -4261,7 +4277,7 @@@ void HUD_CenterPrint (void
        float a, sz, align, current_msg_pos_y = 0, msg_size;
        vector pos;
        string ts;
-       n = -1; // if no msg will be displayed, n stays -1
+       float all_messages_expired = TRUE;
  
        pos = panel_pos;
        if (autocvar_hud_panel_centerprint_flip)
                                continue;
                }
  
+               all_messages_expired = FALSE;
  
                // fade the centerprint_hud in/out
-               if(centerprint_time[j] < 0)
-                       a = bound(0, (time - centerprint_expire_time[j]) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
-               else if(centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time)
-                       a = bound(0, (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
-               else if(centerprint_expire_time[j] > time)
+               if(centerprint_time[j] < 0)  // Expired but forced. Expire time is the fade-in time.
+                       a = (time - centerprint_expire_time[j]) / max(0.0001, autocvar_hud_panel_centerprint_fade_in);
+               else if(centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time)  // Regularily printed. Not fading out yet.
+                       a = (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in);
+               else // Expiring soon, so fade it out.
                        a = (centerprint_expire_time[j] - time) / max(0.0001, autocvar_hud_panel_centerprint_fade_out);
-               else
-                       a = 0;
+               if (a <= 0.5/255.0)  // Guaranteed invisible - don't show.
+                       continue;
+               if (a > 1)
+                       a = 1;
  
                // set the size from fading in/out before subsequent fading
                sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
                        a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha, (1 - (g / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passone))), 1); // pass one: all messages after the first have half theAlpha
                        a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha, (1 - (g / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passtwo))), 1); // pass two: after that, gradually lower theAlpha even more for each message
                }
+               a *= panel_fg_alpha;
  
                // finally set the size based on the new theAlpha from subsequent fading
                sz = sz * (autocvar_hud_panel_centerprint_fade_subsequent_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_subsequent_minfontsize));
                                {
                                        if (align)
                                                pos_x = panel_pos_x + (panel_size_x - stringwidth(ts, TRUE, fontsize)) * align;
-                                       drawcolorcodedstring(pos + eY * 0.5 * (1 - sz) * fontsize_y, ts, fontsize, a * panel_fg_alpha, DRAWFLAG_NORMAL);
+                                       if (a > 0.5/255.0)  // Otherwise guaranteed invisible - don't show. This is checked a second time after some multiplications with other factors were done so temporary changes of these cannot cause flicker.
+                                               drawcolorcodedstring(pos + eY * 0.5 * (1 - sz) * fontsize_y, ts, fontsize, a, DRAWFLAG_NORMAL);
                                        pos_y += fontsize_y;
                                }
                                else
                }
        }
        drawfontscale = '1 1 0';
-       if (n == -1)
+       if (all_messages_expired)
        {
                centerprint_showing = FALSE;
                reset_centerprint_messages();
index 58d2c19a7c3e349f020addf2219432aa7df2adf7,e02fad45f06090b6b3d8e24bfed12f7ade651548..58612bd76d9ee7bb8ceb3b13a77573107f18b7a3
@@@ -30,7 -30,6 +30,6 @@@ const float AS_FLOAT = 8
  
  const float TE_CSQC_PICTURE = 100;
  const float TE_CSQC_RACE = 101;
- const float TE_CSQC_ZCURVEPARTICLES = 102;
  const float TE_CSQC_NEXGUNBEAMPARTICLE = 103;
  const float TE_CSQC_LIGHTNINGARC = 104;
  const float TE_CSQC_TEAMNAGGER = 105;
@@@ -42,7 -41,6 +41,7 @@@ const float TE_CSQC_MINELAYER_MAXMINES 
  const float TE_CSQC_HAGAR_MAXROCKETS = 111;
  const float TE_CSQC_VEHICLESETUP = 112;
  const float TE_CSQC_SVNOTICE = 113;
 +const float TE_CSQC_SPECINFO = 114;
  
  const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
  const float RACE_NET_CHECKPOINT_CLEAR = 1;
@@@ -184,6 -182,9 +183,9 @@@ const float STAT_ROUNDSTARTTIME = 73
  const float STAT_WEAPONS2 = 74;
  const float STAT_WEAPONS3 = 75;
  
+ const float STAT_MONSTERS_TOTAL = 76;
+ const float STAT_MONSTERS_KILLED = 77;
  // mod stats (1xx)
  const float STAT_REDALIVE = 100;
  const float STAT_BLUEALIVE = 101;
@@@ -356,6 -357,9 +358,9 @@@ const float PROJECTILE_WAKICANNON = 29
  const float PROJECTILE_BUMBLE_GUN = 30;
  const float PROJECTILE_BUMBLE_BEAM = 31;
  
+ const float PROJECTILE_MAGE_SPIKE = 32;
+ const float PROJECTILE_SHAMBLER_LIGHTNING = 33;
  const float PROJECTILE_NADE_RED = 50;
  const float PROJECTILE_NADE_RED_BURN = 51;
  const float PROJECTILE_NADE_BLUE = 52;
index 349bf90dd223e627a34271e7bf7aedfea44b1ca1,fc9181d56c473061faf366bf2b1c697f3bd969de..0f5e1635642d55ff9bcdfdf2ee368b4d89f70dc0
@@@ -83,30 -83,26 +83,26 @@@ float autocvar_g_balance_armor_start
  float autocvar_g_balance_rifle_bursttime;
  float autocvar_g_balance_rifle_primary_ammo;
  float autocvar_g_balance_rifle_primary_animtime;
- float autocvar_g_balance_rifle_primary_bulletconstant;
  float autocvar_g_balance_rifle_primary_bullethail;
  float autocvar_g_balance_rifle_primary_burstcost;
  float autocvar_g_balance_rifle_primary_damage;
  float autocvar_g_balance_rifle_primary_force;
- float autocvar_g_balance_rifle_primary_lifetime;
  float autocvar_g_balance_rifle_primary_refire;
  float autocvar_g_balance_rifle_primary_shots;
- float autocvar_g_balance_rifle_primary_speed;
+ float autocvar_g_balance_rifle_primary_solidpenetration;
  float autocvar_g_balance_rifle_primary_spread;
  float autocvar_g_balance_rifle_primary_tracer;
  float autocvar_g_balance_rifle_secondary;
  float autocvar_g_balance_rifle_secondary_ammo;
  float autocvar_g_balance_rifle_secondary_animtime;
- float autocvar_g_balance_rifle_secondary_bulletconstant;
  float autocvar_g_balance_rifle_secondary_bullethail;
  float autocvar_g_balance_rifle_secondary_burstcost;
  float autocvar_g_balance_rifle_secondary_damage;
  float autocvar_g_balance_rifle_secondary_force;
- float autocvar_g_balance_rifle_secondary_lifetime;
  float autocvar_g_balance_rifle_secondary_reload;
  float autocvar_g_balance_rifle_secondary_refire;
  float autocvar_g_balance_rifle_secondary_shots;
- float autocvar_g_balance_rifle_secondary_speed;
+ float autocvar_g_balance_rifle_secondary_solidpenetration;
  float autocvar_g_balance_rifle_secondary_spread;
  float autocvar_g_balance_rifle_secondary_tracer;
  float autocvar_g_balance_rifle_reload_ammo;
@@@ -340,7 -336,6 +336,6 @@@ float autocvar_g_balance_health_regenst
  float autocvar_g_balance_health_rot;
  float autocvar_g_balance_health_rotlinear;
  float autocvar_g_balance_health_rotstable;
- float autocvar_g_balance_health_start;
  float autocvar_g_balance_hlac_primary_ammo;
  float autocvar_g_balance_hlac_primary_animtime;
  float autocvar_g_balance_hlac_primary_damage;
@@@ -621,12 -616,11 +616,11 @@@ float autocvar_g_balance_seeker_reload_
  float autocvar_g_balance_selfdamagepercent;
  float autocvar_g_balance_shotgun_primary_ammo;
  float autocvar_g_balance_shotgun_primary_animtime;
- float autocvar_g_balance_shotgun_primary_bulletconstant;
  float autocvar_g_balance_shotgun_primary_bullets;
  float autocvar_g_balance_shotgun_primary_damage;
  float autocvar_g_balance_shotgun_primary_force;
  float autocvar_g_balance_shotgun_primary_refire;
- float autocvar_g_balance_shotgun_primary_speed;
+ float autocvar_g_balance_shotgun_primary_solidpenetration;
  float autocvar_g_balance_shotgun_primary_spread;
  float autocvar_g_balance_shotgun_secondary;
  float autocvar_g_balance_shotgun_secondary_animtime;
@@@ -654,7 -648,6 +648,6 @@@ float autocvar_g_balance_tuba_edgedamag
  float autocvar_g_balance_tuba_force;
  float autocvar_g_balance_tuba_radius;
  float autocvar_g_balance_tuba_refire;
- float autocvar_g_balance_uzi_bulletconstant;
  float autocvar_g_balance_uzi_burst;
  float autocvar_g_balance_uzi_burst_ammo;
  float autocvar_g_balance_uzi_burst_animtime;
@@@ -668,7 -661,7 +661,7 @@@ float autocvar_g_balance_uzi_first_forc
  float autocvar_g_balance_uzi_first_refire;
  float autocvar_g_balance_uzi_first_spread;
  float autocvar_g_balance_uzi_mode;
- float autocvar_g_balance_uzi_speed;
+ float autocvar_g_balance_uzi_solidpenetration;
  float autocvar_g_balance_uzi_spread_add;
  float autocvar_g_balance_uzi_spread_max;
  float autocvar_g_balance_uzi_spread_min;
@@@ -681,7 -674,6 +674,6 @@@ float autocvar_g_balance_uzi_reload_amm
  float autocvar_g_balance_uzi_reload_time;
  float autocvar_g_ballistics_density_corpse;
  float autocvar_g_ballistics_density_player;
- float autocvar_g_ballistics_materialconstant;
  float autocvar_g_ballistics_mindistance;
  float autocvar_g_ban_default_bantime;
  float autocvar_g_ban_default_masksize;
@@@ -702,6 -694,7 +694,7 @@@ float autocvar_g_ca_round_timelimit
  float autocvar_g_ca_spectate_enemies;
  float autocvar_g_ca_teams;
  float autocvar_g_ca_teams_override;
+ float autocvar_g_ca_team_spawns;
  float autocvar_g_ca_warmup;
  float autocvar_g_campaign;
  #define autocvar_g_campaign_forceteam cvar("g_campaign_forceteam")
@@@ -723,6 -716,7 +716,7 @@@ float autocvar_g_chat_teamcolors
  float autocvar_g_chat_tellprivacy;
  float autocvar_g_ctf_allow_vehicle_carry;
  float autocvar_g_ctf_allow_vehicle_touch;
+ float autocvar_g_ctf_allow_monster_touch;
  float autocvar_g_ctf_throw;
  float autocvar_g_ctf_throw_angle_max;
  float autocvar_g_ctf_throw_angle_min;
@@@ -819,6 -813,7 +813,7 @@@ float autocvar_g_freezetag_revive_clear
  float autocvar_g_freezetag_round_timelimit;
  float autocvar_g_freezetag_teams;
  float autocvar_g_freezetag_teams_override;
+ float autocvar_g_freezetag_team_spawns;
  float autocvar_g_freezetag_warmup;
  #define autocvar_g_friendlyfire cvar("g_friendlyfire")
  #define autocvar_g_friendlyfire_virtual cvar("g_friendlyfire_virtual")
@@@ -1221,10 -1216,36 +1216,36 @@@ float autocvar_physics_ode
  float autocvar_g_physical_items;
  float autocvar_g_physical_items_damageforcescale;
  float autocvar_g_physical_items_reset;
+ float autocvar_g_monsters;
+ float autocvar_g_monsters_edit;
+ float autocvar_g_monsters_think_delay;
+ float autocvar_g_monsters_max;
+ float autocvar_g_monsters_max_perplayer;
+ float autocvar_g_monsters_target_range;
+ float autocvar_g_monsters_target_infront;
+ float autocvar_g_monsters_attack_range;
+ float autocvar_g_monsters_score_kill;
+ float autocvar_g_monsters_score_spawned;
+ float autocvar_g_monsters_typefrag;
+ float autocvar_g_monsters_owners;
+ float autocvar_g_monsters_miniboss_chance;
+ float autocvar_g_monsters_miniboss_healthboost;
+ float autocvar_g_monsters_drop_time;
+ float autocvar_g_monsters_spawnshieldtime;
+ float autocvar_g_monsters_teams;
+ float autocvar_g_monsters_respawn_delay;
+ float autocvar_g_monsters_respawn;
+ float autocvar_g_monsters_armor_blockpercent;
  float autocvar_g_touchexplode_radius;
  float autocvar_g_touchexplode_damage;
  float autocvar_g_touchexplode_edgedamage;
  float autocvar_g_touchexplode_force;
+ float autocvar_g_invasion_round_timelimit;
+ #define autocvar_g_invasion_round_limit cvar("g_invasion_round_limit")
+ float autocvar_g_invasion_warmup;
+ float autocvar_g_invasion_monster_count;
+ float autocvar_g_invasion_zombies_only;
+ float autocvar_g_invasion_spawn_delay;
  #define autocvar_g_bloodloss cvar("g_bloodloss")
  float autocvar_g_random_gravity_negative_chance;
  float autocvar_g_random_gravity_min;
@@@ -1248,4 -1269,3 +1269,4 @@@ float autocvar_g_campcheck_damage
  float autocvar_g_campcheck_distance;
  float autocvar_g_campcheck_interval;
  float autocvar_g_jump_grunt;
 +float autocvar_sv_showspectators;
index b7ca56b84aaaf1a88d7606264cc4fc30c8b3a477,691c4930e995978bc50135e3185260b659fd6979..8bc0e458950b09b8de619e07d445eda3133fbb5f
@@@ -136,7 -136,6 +136,7 @@@ putting a client as observer in the ser
  =============
  */
  void FixPlayermodel();
 +void UpdateSpectators(entity is_spec, entity is_player);
  void PutObserverInServer (void)
  {
        entity  spot;
                WriteByte(MSG_ONE, SVC_SETVIEW);
                WriteEntity(MSG_ONE, self);
        }
 +      
 +      UpdateSpectators(self, self); // don't update spectators or spectatees
  
        if((g_race && g_race_qualifying) || g_cts)
        {
        if(self.killcount != -666)
        {
                Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_SPECTATE, self.netname);
+               if(autocvar_g_chat_nospectators == 1 || (cvar("g_warmup") && !(warmup_stage || gameover) && autocvar_g_chat_nospectators == 2))
+                       Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_CHAT_NOSPECTATORS);
  
                if(self.just_joined == FALSE) {
                        LogTeamchange(self.playerid, -1, 4);
@@@ -403,6 -402,9 +405,9 @@@ void PutClientInServer (void
  
                RemoveGrapplingHook(self); // Wazat's Grappling Hook
  
+               if(self.vehicle)
+                       vehicles_exit(VHEF_RELESE);
                self.classname = "player";
                self.wasplayer = TRUE;
                self.iscreature = TRUE;
                self.event_damage = PlayerDamage;
  
                self.bot_attack = TRUE;
+               self.monster_attack = TRUE;
+               
+               self.spider_slowness = 0;
  
                self.statdraintime = time + 5;
                self.BUTTON_ATCK = self.BUTTON_JUMP = self.BUTTON_ATCK2 = 0;
        {
                PutObserverInServer ();
        }
 +      
 +      UpdateSpectators(((IS_PLAYER(self)) ? world : self), ((IS_SPEC(self) || IS_OBSERVER(self)) ? self : world));
  }
  
  .float ebouncefactor, ebouncestop; // electro's values
@@@ -1251,8 -1254,6 +1259,8 @@@ Called when a client disconnects from t
  void ReadyCount();
  void ClientDisconnect (void)
  {
 +      UpdateSpectators(self, world);
 +
        if(self.vehicle)
            vehicles_exit(VHEF_RELESE);
  
@@@ -1584,44 -1585,42 +1592,42 @@@ float CalcRotRegen(float current, floa
  
  void player_regen (void)
  {
-       float minh, mina, minf, maxh, maxa, maxf, limith, limita, limitf, max_mod, regen_mod, rot_mod, limit_mod;
-       maxh = autocvar_g_balance_health_rotstable;
-       maxa = autocvar_g_balance_armor_rotstable;
-       maxf = autocvar_g_balance_fuel_rotstable;
-       minh = autocvar_g_balance_health_regenstable;
-       mina = autocvar_g_balance_armor_regenstable;
-       minf = autocvar_g_balance_fuel_regenstable;
-       limith = autocvar_g_balance_health_limit;
-       limita = autocvar_g_balance_armor_limit;
-       limitf = autocvar_g_balance_fuel_limit;
-       max_mod = regen_mod = rot_mod = limit_mod = 1;
-       maxh = maxh * max_mod;
-       //maxa = maxa * max_mod;
-       //maxf = maxf * max_mod;
-       minh = minh * max_mod;
-       //mina = mina * max_mod;
-       //minf = minf * max_mod;
-       limith = limith * limit_mod;
-       limita = limita * limit_mod;
-       //limitf = limitf * limit_mod;
-       if(g_ca)
-               rot_mod = 0;
-       if (!g_minstagib && !g_ca && (!g_lms || autocvar_g_lms_regenerate))
+       if(!MUTATOR_CALLHOOK(PlayerRegen))
        {
+               float minh, mina, maxh, maxa, limith, limita, max_mod, regen_mod, rot_mod, limit_mod;
+               maxh = autocvar_g_balance_health_rotstable;
+               maxa = autocvar_g_balance_armor_rotstable;
+               minh = autocvar_g_balance_health_regenstable;
+               mina = autocvar_g_balance_armor_regenstable;
+               limith = autocvar_g_balance_health_limit;
+               limita = autocvar_g_balance_armor_limit;
+               max_mod = regen_mod = rot_mod = limit_mod = 1;
+               maxh = maxh * max_mod;
+               minh = minh * max_mod;
+               limith = limith * limit_mod;
+               limita = limita * limit_mod;
                self.armorvalue = CalcRotRegen(self.armorvalue, mina, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear, regen_mod * frametime * (time > self.pauseregen_finished), maxa, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear, rot_mod * frametime * (time > self.pauserotarmor_finished), limita);
                self.health = CalcRotRegen(self.health, minh, autocvar_g_balance_health_regen, autocvar_g_balance_health_regenlinear, regen_mod * frametime * (time > self.pauseregen_finished), maxh, autocvar_g_balance_health_rot, autocvar_g_balance_health_rotlinear, rot_mod * frametime * (time > self.pauserothealth_finished), limith);
-               // if player rotted to death...  die!
-               if(self.health < 1)
-                       self.event_damage(self, self, 1, DEATH_ROT, self.origin, '0 0 0');
        }
  
+       // if player rotted to death...  die!
+       // check this outside above checks, as player may still be able to rot to death
+       if(self.health < 1)
+               self.event_damage(self, self, 1, DEATH_ROT, self.origin, '0 0 0');
        if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-               self.ammo_fuel = CalcRotRegen(self.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, regen_mod * frametime * (time > self.pauseregen_finished) * ((self.items & IT_FUEL_REGEN) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, rot_mod * frametime * (time > self.pauserotfuel_finished), limitf);
+       {
+               float minf, maxf, limitf;
+               maxf = autocvar_g_balance_fuel_rotstable;
+               minf = autocvar_g_balance_fuel_regenstable;
+               limitf = autocvar_g_balance_fuel_limit;
+               self.ammo_fuel = CalcRotRegen(self.ammo_fuel, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, frametime * (time > self.pauseregen_finished) * ((self.items & IT_FUEL_REGEN) != 0), maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > self.pauserotfuel_finished), limitf);
+       }
  }
  
  float zoomstate_set;
@@@ -1774,42 -1773,13 +1780,42 @@@ float SpectateUpdate() 
                return 0;
  
        if (!IS_PLAYER(self.enemy))
 +      {
 +              self.enemy = world;
                return 0;
 +      }
  
        SpectateCopy(self.enemy);
  
        return 1;
  }
  
 +void UpdateSpectators(entity is_spec, entity is_player)
 +{
 +      entity head, spec;
 +      float specs = 0;
 +      FOR_EACH_REALCLIENT(head)
 +      {
 +              msg_entity = head;
 +              WriteByte(MSG_ONE, SVC_TEMPENTITY);
 +              WriteByte(MSG_ONE, TE_CSQC_SPECINFO);
 +              
 +              specs = 0;
 +              
 +              FOR_EACH_SPEC(spec) if(spec.enemy == head && is_player != spec && spec != is_player)
 +                      ++specs;
 +      
 +              if(IS_SPEC(head) || IS_OBSERVER(head) || head == is_spec || !autocvar_sv_showspectators)
 +              {
 +                      WriteByte(MSG_ONE, 0);
 +                      continue;
 +              }
 +              
 +              WriteByte(MSG_ONE, specs);
 +              FOR_EACH_SPEC(spec) if(spec.enemy == head && is_player != spec)
 +                      WriteByte(MSG_ONE, num_for_edict(spec));
 +      }
 +}
  
  float SpectateSet()
  {
@@@ -1888,10 -1858,7 +1894,10 @@@ float SpectateNext(
        }
  
        if (other)
 +      {
                self.enemy = other;
 +              UpdateSpectators(world, world);
 +      }
  
        return SpectateSet();
  }
@@@ -1931,7 -1898,6 +1937,7 @@@ float SpectatePrev(
                        other = first;
        }
        self.enemy = other;
 +      UpdateSpectators(world, world);
        return SpectateSet();
  }
  
@@@ -2459,6 -2425,9 +2465,9 @@@ void PlayerPreThink (void
                // secret status
                secrets_setstatus();
  
+               // monsters status
+               monsters_setstatus();
                self.dmg_team = max(0, self.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
  
                //self.angles_y=self.v_angle_y + 90;   // temp
@@@ -2660,7 -2629,7 +2669,7 @@@ void PlayerPostThink (void
  
        /*
        if(g_race)
-               dprint(sprintf("%f %.6f\n", time, race_GetFractionalLapCount(self)));
+               dprintf("%f %.6f\n", time, race_GetFractionalLapCount(self));
        */
  
        CSQCMODEL_AUTOUPDATE();