]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into terencehill/itemstime
authorterencehill <piuntn@gmail.com>
Sun, 18 Dec 2011 15:27:37 +0000 (16:27 +0100)
committerterencehill <piuntn@gmail.com>
Sun, 18 Dec 2011 15:27:37 +0000 (16:27 +0100)
1  2 
defaultXonotic.cfg
qcsrc/client/autocvars.qh
qcsrc/common/constants.qh
qcsrc/common/util.qh
qcsrc/server/cl_client.qc
qcsrc/server/defs.qh
qcsrc/server/g_world.qc
qcsrc/server/t_items.qc

diff --combined defaultXonotic.cfg
index a2f732f5b9fff53a2fef89a8e22a3f787e7c021d,6fc54b53aa730f9154f7c4d2db219bd4a0592f1f..d5fc82aa243304d88ba5419c2d94684ebfec2065
@@@ -498,14 -498,11 +498,11 @@@ set g_shootfromeye 0 "shots are fired f
  set g_shootfromcenter 0 "weapon gets moved to the center, shots still come from the barrel of your weapon; visual gun position can still be influenced by cl_gunalign 1 and 2"
  set g_shootfromfixedorigin "" "if set to a string like 0 y z, the gun is moved to the given y and z coordinates. If set to a string like x y z, the whole shot origin is used"
  set g_pinata 0 "if set to 1 you will not only drop your current weapon when you are killed, but you will drop all weapons that you possessed"
- set g_weapon_stay 0 "if set to 1 or 2, weapons stay after they were picked up (1: weapons you don't have yet give you ammo of their type and they can not be dropped, 2: weapons don't give ammo, but instead players start with one pickup-load of ammo by default, 3: weapons give ammo, weapons only stay as ammo-less ghosts)"
+ set g_weapon_stay 0 "1: ghost weapons can be picked up too but give no ammo, 2: ghost weapons refill ammo to one pickup size, thrown guns have no ammo"
  set g_weapon_throwable 1 "if set to 1, weapons can be dropped"
- set g_powerup_superhealth 1 "if set to 0 the mega health powerup will not spawn on the map"
- set g_powerup_strength 1 "if set to 0 the strength powerup will not spawn on the map"
- set g_powerup_shield 1 "if set to 0 the shield (invincibility) powerup will not spawn on the map"
- set g_balance_powerup_timer 1 "if set to 0 the powerups dont wear off"
+ set g_powerups -1 "if set to 0 the strength and shield (invincibility) will not spawn on the map, if 1 they will spawn in all game modes, -1 is game mode default"
  set g_use_ammunition 1 "if set to 0 all weapons have unlimited ammunition"
- set g_pickup_items 1 "if set to 0 all items (health, armor, ammo, weapons...) are removed from the map"
+ set g_pickup_items -1 "if set to 0 all items (health, armor, ammo, weapons...) are removed from the map, if 1 they are forced to spawn"
  set g_minstagib 0     "enable minstagib"
  set g_minstagib_extralives 2  "how many extra lives you will get per powerup"
  set g_minstagib_ammo_start 10 "starting ammo"
@@@ -689,7 -686,7 +686,7 @@@ set g_cts_respawn_waves 
  set g_cts_respawn_delay 0
  set g_cts_selfdamage 1 "0 = disable all selfdamage and falldamage in cts"
  set g_cts_finish_kill_delay 10 "prevent cheating by running back to the start line, and starting out with more speed than otherwise possible"
- set g_cts_weapon_stay 1
+ set g_cts_weapon_stay 2
  set g_freezetag_respawn_waves 0
  set g_freezetag_respawn_delay 0
  set g_freezetag_weapon_stay 0
@@@ -838,7 -835,6 +835,6 @@@ set g_arena 0 "Arena: many one-on-one r
  set g_arena_maxspawned 2      "maximum number of players to spawn at once (the rest is spectating, waiting for their turn)"
  set g_arena_roundbased 1      "if disabled, the next player will spawn as soon as someone dies"
  set g_arena_warmup 5  "time, newly spawned players have to prepare themselves in round based matches"
- set g_arena_powerups 0        "enables powerups (superhealth, strength and shield), which are removed by default"
  
  // ca
  set g_ca 0 "Clan Arena: Played in rounds, once you're dead you're out! The team with survivors wins the round."
@@@ -1308,7 -1304,6 +1304,7 @@@ seta g_waypointsprite_crosshairfadedist
  seta g_waypointsprite_distancefadealpha 1 "alpha multiplier near distance"
  seta g_waypointsprite_distancefadescale 0.7 "scale multiplier near the distance"
  seta g_waypointsprite_distancefadedistancemultiplier 0.5 "distance in map sizes from distance where to stop fading"
 +seta g_waypointsprite_items_for_spectators 1 "show waypoints when spectating to indicate that some important items (mega health, large armor) are about to respawn"
  set g_waypointsprite_spam 0 "Debugging feature. Set to 10 and load courtfun in race mode to test."
  alias "g_waypointsprite_personal"     "impulse 30"
  alias "g_waypointsprite_personal_p"   "impulse 31"
@@@ -1806,11 -1801,6 +1802,6 @@@ set menu_updatecheck 
  set bot_navigation_ignoreplayers 0 // FIXME remove this once the issue is solved
  set bot_sound_monopoly 0 "when enabled, only bots can make any noise"
  
- // broken, sorry (cannot handle weapon attachment properly)
- //seta cl_forceplayermodels 0 "force all players to look like you; WARNING: animations can look very bad with this"
- //seta cl_forceplayermodelsfromxonotic 0 "force models coming from xonotic; WARNING: animations can look very bad with this"
- //set sv_clforceplayermodels 1 "allow clients to use cl_forcemodels"
  set sv_loddistance1 1024
  set sv_loddistance2 4096
  seta cl_playerdetailreduction 0       "the higher, the less detailed player models are displayed (LOD)"
@@@ -1920,6 -1910,9 +1911,9 @@@ set developer_shtest 0 "experimental sp
  set waypoint_benchmark 0 "quit after waypoint loading to benchmark bot navigation code"
  set g_debug_bot_commands 0 "print scripted bot commands before executing"
  set g_debug_defaultsounds 0 "always use default sounds"
+ set sv_use_csqc_players 1 "set to 0 to disable CSQC players for better Xonotic 0.5 compat"
+ set cl_forceplayermodels 0 "set to 1 to make everyone look like yourself (requires server to have sv_use_csqc_players 1)"
+ set cl_precacheplayermodels 0 "TODO please check if this needs to be 1 or if precaching a model the server already requested is fast enough to do it at runtime"
  
  // debug cvars for keyhunt attaching
  set _angles "0 0 0"
index 28f37d6f035af738432a3ecf043de9d40842e43c,d829904631ab0cf20e04d1fe5ffdea4b7b541ad4..af8f96d99f5efeb530a449f84b4fb62ee450e055
@@@ -145,7 -145,6 +145,7 @@@ float autocvar_g_waypointsprite_edgeoff
  float autocvar_g_waypointsprite_edgeoffset_right;
  float autocvar_g_waypointsprite_edgeoffset_top;
  float autocvar_g_waypointsprite_fontsize;
 +float autocvar_g_waypointsprite_items_for_spectators;
  float autocvar_g_waypointsprite_minalpha;
  float autocvar_g_waypointsprite_minscale;
  float autocvar_g_waypointsprite_normdistance;
@@@ -242,13 -241,6 +242,13 @@@ float autocvar_hud_panel_healtharmor_pr
  float autocvar_hud_panel_healtharmor_text;
  float autocvar_hud_panel_infomessages;
  float autocvar_hud_panel_infomessages_flip;
 +float autocvar_hud_panel_itemstime;
 +float autocvar_hud_panel_itemstime_iconalign;
 +float autocvar_hud_panel_itemstime_maxitemstime;
 +float autocvar_hud_panel_itemstime_progressbar;
 +string autocvar_hud_panel_itemstime_progressbar_name;
 +float autocvar_hud_panel_itemstime_progressbar_xoffset;
 +float autocvar_hud_panel_itemstime_text;
  float autocvar_hud_panel_modicons;
  float autocvar_hud_panel_modicons_dom_layout;
  float autocvar_hud_panel_notify;
@@@ -381,3 -373,10 +381,10 @@@ var float autocvar_cl_eventchase_distan
  var float autocvar_cl_eventchase_speed = 1.3;
  float autocvar_cl_lerpexcess;
  string autocvar__togglezoom;
+ float autocvar_cl_playerdetailreduction;
+ float autocvar_cl_loddistance1 = 1024;
+ float autocvar_cl_loddistance2 = 4096;
+ float autocvar_cl_forceplayermodels;
+ float autocvar__cl_playerskin;
+ string autocvar__cl_playermodel;
+ float autocvar_cl_precacheplayermodels;
index c0637fbe14c18b461ad30ae1871886d31fde3059,55834f1a6d36bd5f84f20475a908f737c8a6a0a4..f7d97c5aa58f79a9b477c4cab1043799db2f3f93
@@@ -114,6 -114,7 +114,7 @@@ const float ENT_CLIENT_GAUNTLET = 29
  const float ENT_CLIENT_ACCURACY = 30;
  const float ENT_CLIENT_SHOWNAMES = 31;
  const float ENT_CLIENT_WARPZONE_TELEPORTED = 32;
+ const float ENT_CLIENT_MODEL = 33;
  
  const float ENT_CLIENT_TURRET = 40;
  const float ENT_CLIENT_AUXILIARYXHAIR = 50;
@@@ -121,7 -122,6 +122,7 @@@ const float ENT_CLIENT_VEHICLE = 60
  
  const float SPRITERULE_DEFAULT = 0;
  const float SPRITERULE_TEAMPLAY = 1;
 +const float SPRITERULE_SPECTATOR = 2;
  
  const float RADARICON_NONE = 0;
  const float RADARICON_FLAG = 1;
@@@ -214,16 -214,6 +215,16 @@@ const float STAT_VEHICLESTAT_RELOAD2 = 
  const float STAT_SECRETS_TOTAL = 70;
  const float STAT_SECRETS_FOUND = 71;
  
 +const float STAT_ARMOR_LARGE_TIME = 80;
 +const float STAT_HEALTH_MEGA_TIME = 81;
 +const float STAT_STRENGTH_TIME = 82;
 +const float STAT_INVISIBLE_TIME = 83;
 +const float STAT_EXTRALIFE_TIME = 84;
 +const float STAT_SPEED_TIME = 85;
 +const float STAT_SHIELD_TIME = 86;
 +const float STAT_FUELREGEN_TIME = 87;
 +const float STAT_JETPACK_TIME = 88;
 +
  // mod stats (1xx)
  const float STAT_REDALIVE = 100;
  const float STAT_BLUEALIVE = 101;
@@@ -560,8 -550,7 +561,8 @@@ float HUD_PANEL_ENGINEINFO = 13
  float HUD_PANEL_INFOMESSAGES  = 14;
  float HUD_PANEL_PHYSICS       = 15;
  float HUD_PANEL_CENTERPRINT   = 16;
 -float HUD_PANEL_NUM           = 17; // always last panel id + 1, please increment when adding a new panel
 +float HUD_PANEL_ITEMSTIME             = 17;
 +float HUD_PANEL_NUM                           = 18; // always last panel id + 1, please increment when adding a new panel
  
  string HUD_PANELNAME_WEAPONS          = "weapons";
  string HUD_PANELNAME_AMMO             = "ammo";
@@@ -580,7 -569,6 +581,7 @@@ string HUD_PANELNAME_ENGINEINFO            = "en
  string HUD_PANELNAME_INFOMESSAGES     = "infomessages";
  string HUD_PANELNAME_PHYSICS  = "physics";
  string HUD_PANELNAME_CENTERPRINT      = "centerprint";
 +string HUD_PANELNAME_ITEMSTIME                = "itemstime";
  
  float HUD_MENU_ENABLE         = 0;
  
  #define SERVERFLAG_TEAMPLAY 2
  #define SERVERFLAG_PLAYERSTATS 4
  
+ var vector autocvar_sv_player_maxs = '16 16 45';
+ var vector autocvar_sv_player_mins = '-16 -16 -24';
+ var vector autocvar_sv_player_viewoffset = '0 0 20';
+ var vector autocvar_sv_player_crouch_maxs = '16 16 25';
+ var vector autocvar_sv_player_crouch_mins = '-16 -16 -24';
+ var vector autocvar_sv_player_crouch_viewoffset = '0 0 20';
+ noref var vector autocvar_sv_player_headsize = '24 24 12';
+ #define PL_VIEW_OFS autocvar_sv_player_viewoffset
+ #define PL_MIN autocvar_sv_player_mins
+ #define PL_MAX autocvar_sv_player_maxs
+ #define PL_CROUCH_VIEW_OFS autocvar_sv_player_crouch_viewoffset
+ #define PL_CROUCH_MIN autocvar_sv_player_crouch_mins
+ #define PL_CROUCH_MAX autocvar_sv_player_crouch_maxs
+ #define PL_HEAD autocvar_sv_player_headsize
+ // helpers
+ #define PL_VIEW_OFS_z autocvar_sv_player_viewoffset_z
+ #define PL_MIN_z autocvar_sv_player_mins_z
+ #define PL_MAX_z autocvar_sv_player_maxs_z
+ #define PL_CROUCH_VIEW_OFS_z autocvar_sv_player_crouch_viewoffset_z
+ #define PL_CROUCH_MIN_z autocvar_sv_player_mins_z
+ #define PL_HEAD_x autocvar_sv_player_headsize_x
+ #define PL_HEAD_y autocvar_sv_player_headsize_y
+ #define PL_HEAD_z autocvar_sv_player_headsize_z
  // spawnpoint prios
  #define SPAWN_PRIO_NEAR_TEAMMATE_FOUND    200
  #define SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM 100
diff --combined qcsrc/common/util.qh
index 461cfd9b23876195f8731210e432a14d51d376b2,e2dfcb3b86b1257c7b440837e7714fc78a1e48ff..c4dabf296c5583079b2b7e9202b71ee771bbe767
@@@ -223,7 -223,6 +223,7 @@@ switch(id) {
        case HUD_PANEL_INFOMESSAGES: panel_name = HUD_PANELNAME_INFOMESSAGES; break; \
        case HUD_PANEL_PHYSICS: panel_name = HUD_PANELNAME_PHYSICS; break; \
        case HUD_PANEL_CENTERPRINT: panel_name = HUD_PANELNAME_CENTERPRINT; break; \
 +      case HUD_PANEL_ITEMSTIME: panel_name = HUD_PANELNAME_ITEMSTIME; break; \
  } ENDS_WITH_CURLY_BRACE
  
  // Get name of specified panel id
@@@ -271,3 -270,7 +271,7 @@@ float xdecode(string s)
  #ifndef COMPAT_XON010_CHANNELS
  #define sound(e,c,s,v,a) sound7(e,c,s,v,a,0,0)
  #endif
+ #ifdef CSQC
+ entity ReadCSQCEntity()
+ #endif
index a29742a335e4e7047b7dcdeded0366acbb4fc7b8,d34a0c28756c05e966a1ff986dd41dc54b43addc..bcba20cc1b023e01ed1089a43872cbdc17ede50e
@@@ -341,160 -341,36 +341,36 @@@ string CheckPlayerModel(string plyermod
                // to change a cvar default, we'll have a small leak here.
                FallbackPlayerModel = strzone(cvar_defstring("_cl_playermodel"));
        }
-       if(strlen(plyermodel) < 4)
-               return FallbackPlayerModel;
+       // only in right path
        if( substring(plyermodel,0,14) != "models/player/")
                return FallbackPlayerModel;
-       else if(autocvar_sv_servermodelsonly)
+       // only good file extensions
+       if(substring(plyermodel,-4,4) != ".zym")
+       if(substring(plyermodel,-4,4) != ".dpm")
+       if(substring(plyermodel,-4,4) != ".iqm")
+       if(substring(plyermodel,-4,4) != ".md3")
+       if(substring(plyermodel,-4,4) != ".psk")
+               return FallbackPlayerModel;
+       // forbid the LOD models
+       if(substring(plyermodel, -9,5) == "_lod1")
+               return FallbackPlayerModel;
+       if(substring(plyermodel, -9,5) == "_lod2")
+               return FallbackPlayerModel;
+       if(plyermodel != strtolower(plyermodel))
+               return FallbackPlayerModel;
+       // also, restrict to server models
+       if(autocvar_sv_servermodelsonly)
        {
-               if(substring(plyermodel,-4,4) != ".zym")
-               if(substring(plyermodel,-4,4) != ".dpm")
-               if(substring(plyermodel,-4,4) != ".iqm")
-               if(substring(plyermodel,-4,4) != ".md3")
-               if(substring(plyermodel,-4,4) != ".psk")
-                       return FallbackPlayerModel;
-               // forbid the LOD models
-               if(substring(plyermodel, -9,5) == "_lod1")
-                       return FallbackPlayerModel;
-               if(substring(plyermodel, -9,5) == "_lod2")
-                       return FallbackPlayerModel;
-               if(plyermodel != strtolower(plyermodel))
-                       return FallbackPlayerModel;
                if(!fexists(plyermodel))
                        return FallbackPlayerModel;
        }
        return plyermodel;
  }
  
- /*
- =============
- Client_customizeentityforclient
- LOD reduction
- =============
- */
- void Client_uncustomizeentityforclient()
- {
-       if(self.modelindex == 0) // no need to uncustomize then
-               return;
-       self.modelindex = self.modelindex_lod0;
-       self.skin = self.skinindex;
- }
- float Client_customizeentityforclient()
- {
-       entity modelsource;
-       if(self.modelindex == 0)
-               return TRUE;
-       // forcemodel stuff
- #ifdef PROFILING
-       float t0;
-       t0 = gettime(GETTIME_HIRES); // reference
- #endif
-       modelsource = self;
- #ifdef ALLOW_FORCEMODELS
-       if(other.cvar_cl_forceplayermodelsfromxonotic)
-               if not(self.modelindex_lod0_from_xonotic)
-                       modelsource = other;
-       if(other.cvar_cl_forceplayermodels && sv_clforceplayermodels)
-               modelsource = other;
- #endif
-       self.skin = modelsource.skinindex;
- #if 0
-       if(modelsource == self)
-               self.skin = modelsource.skinindex;
-       else
-               self.skin = mod(modelsource.skinindex, 3); // forbid the fbskins as forced skins
- #endif
-       // self: me
-       // other: the player viewing me
-       float distance;
-       float f;
-       if(other.cvar_cl_playerdetailreduction <= 0)
-       {
-               if(other.cvar_cl_playerdetailreduction <= -2)
-                       self.modelindex = modelsource.modelindex_lod2;
-               else if(other.cvar_cl_playerdetailreduction <= -1)
-                       self.modelindex = modelsource.modelindex_lod1;
-               else
-                       self.modelindex = modelsource.modelindex_lod0;
-       }
-       else
-       {
-               distance = vlen(self.origin - other.origin);
-               f = (distance + 100.0) * other.cvar_cl_playerdetailreduction;
-               if(f > sv_loddistance2)
-                       self.modelindex = modelsource.modelindex_lod2;
-               else if(f > sv_loddistance1)
-                       self.modelindex = modelsource.modelindex_lod1;
-               else
-                       self.modelindex = modelsource.modelindex_lod0;
-       }
- #ifdef PROFILING
-       float t1;
-       t1 = gettime(GETTIME_HIRES); // reference
-       client_cefc_accumulator += (t1 - t0);
- #endif
-       return TRUE;
- }
- void setmodel_lod(entity e, string modelname)
+ void setplayermodel(entity e, string modelname)
  {
-       string s;
-       if(sv_loddistance1)
-       {
-               // FIXME: this only supports 3-letter extensions
-               s = strcat(substring(modelname, 0, strlen(modelname)-4), "_lod1", substring(modelname, -4, 4));
-               if(fexists(s))
-               {
-                       setmodel(e, s); // players have high precision
-                       self.modelindex_lod1 = self.modelindex;
-               }
-               else
-                       self.modelindex_lod1 = -1;
-               s = strcat(substring(modelname, 0, strlen(modelname)-4), "_lod2", substring(modelname, -4, 4));
-               if(fexists(s))
-               {
-                       setmodel(e, s); // players have high precision
-                       self.modelindex_lod2 = self.modelindex;
-               }
-               else
-                       self.modelindex_lod2 = -1;
-               precache_model(modelname);
-               setmodel(e, modelname); // players have high precision
-               self.modelindex_lod0 = self.modelindex;
-               if(self.modelindex_lod1 < 0)
-                       self.modelindex_lod1 = self.modelindex;
-               if(self.modelindex_lod2 < 0)
-                       self.modelindex_lod2 = self.modelindex;
-       }
-       else
-       {
-               precache_model(modelname);
-               setmodel(e, modelname); // players have high precision
-               self.modelindex_lod0 = self.modelindex;
-                       // save it for possible player model forcing
-       }
-       s = whichpack(self.model);
-       self.modelindex_lod0_from_xonotic = ((s == "") || (substring(s, 0, 4) == "data"));
+       precache_model(modelname);
+       setmodel(e, modelname);
        player_setupanimsformodel();
        UpdatePlayerSounds();
  }
@@@ -520,7 -396,6 +396,7 @@@ void PutObserverInServer (void
  
        if(clienttype(self) == CLIENTTYPE_REAL)
        {
 +              Item_GetItemsTime(self);
                msg_entity = self;
                WriteByte(MSG_ONE, SVC_SETVIEW);
                WriteEntity(MSG_ONE, self);
        self.fixangle = TRUE;
        self.crouch = FALSE;
  
-       self.view_ofs = '0 0 0'; // so that your view doesn't go into the ceiling with MOVETYPE_FLY_WORLDONLY, previously "PL_VIEW_OFS"
        setorigin (self, spot.origin);
-       setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX); // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY
        self.prevorigin = self.origin;
        self.items = 0;
        self.weapons = 0;
        self.model = "";
        FixPlayermodel();
-       self.model = "";
-       self.modelindex = 0;
+       setmodel(self, "null");
+       self.drawonlytoclient = self;
+       setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX); // give the spectator some space between walls for MOVETYPE_FLY_WORLDONLY
+       self.view_ofs = '0 0 0'; // so that your view doesn't go into the ceiling with MOVETYPE_FLY_WORLDONLY, previously "PL_VIEW_OFS"
        self.weapon = 0;
        self.weaponname = "";
        self.switchingweapon = 0;
        self.oldvelocity = self.velocity;
        self.fire_endtime = -1;
  
-       if(sv_loddistance1)
-               SetCustomizer(self, Client_customizeentityforclient, Client_uncustomizeentityforclient);
        if(g_arena)
        {
                if(self.version_mismatch)
@@@ -723,29 -597,29 +598,29 @@@ void FixPlayermodel(
                {
                        m1 = self.mins;
                        m2 = self.maxs;
-                       setmodel_lod (self, defaultmodel);
+                       setplayermodel (self, defaultmodel);
                        setsize (self, m1, m2);
                        chmdl = TRUE;
                }
  
-               oldskin = self.skinindex;
-               self.skinindex = defaultskin;
+               oldskin = self.skin;
+               self.skin = defaultskin;
        } else {
                if (self.playermodel != self.model || self.playermodel == "")
                {
                        self.playermodel = CheckPlayerModel(self.playermodel); // this is never "", so no endless loop
                        m1 = self.mins;
                        m2 = self.maxs;
-                       setmodel_lod (self, self.playermodel);
+                       setplayermodel (self, self.playermodel);
                        setsize (self, m1, m2);
                        chmdl = TRUE;
                }
  
-               oldskin = self.skinindex;
-               self.skinindex = stof(self.playerskin);
+               oldskin = self.skin;
+               self.skin = stof(self.playerskin);
        }
  
-       if(chmdl || oldskin != self.skinindex)
+       if(chmdl || oldskin != self.skin)
                self.species = player_getspecies(); // model or skin has changed
  
        if(!teamplay)
@@@ -826,8 -700,6 +701,8 @@@ void PutClientInServer (void
                        return; // spawn failed
                }
  
 +              Item_ClearItemsTime();
 +
                RemoveGrapplingHook(self); // Wazat's Grappling Hook
  
                self.classname = "player";
                        self.effects = EF_FULLBRIGHT;
                else
                        self.effects = 0;
+               self.effects |= EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
                self.air_finished = time + 12;
                self.dmg = 2;
                if(autocvar_g_balance_nex_charge)
                        WriteByte(MSG_ONE, TE_CSQC_SPAWN);
                });
  
-               if(sv_loddistance1)
-                       SetCustomizer(self, Client_customizeentityforclient, Client_uncustomizeentityforclient);
                self.model = "";
                FixPlayermodel();
+               self.drawonlytoclient = world;
  
                self.crouch = FALSE;
                self.view_ofs = PL_VIEW_OFS;
@@@ -1318,7 -1189,7 +1192,7 @@@ void ClientKill_TeamChange (float targe
                        self.clientkill_nexttime = time + killtime + autocvar_g_balance_kill_antispam;
                }
  
-               if(killtime <= 0 || !self.modelindex || self.deadflag != DEAD_NO)
+               if(killtime <= 0 || self.classname != "player" || self.deadflag != DEAD_NO)
                {
                        ClientKill_Now();
                }
@@@ -1726,6 -1597,8 +1600,8 @@@ void ClientConnect (void
        if(!autocvar_g_campaign)
                Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), autocvar_welcome_message_time, 0);
  
+       CSQCMODEL_AUTOINIT();
        self.model_randomizer = random();
  }
  
@@@ -1979,7 -1852,7 +1855,7 @@@ void player_powerups (void
                if (self.items & IT_INVINCIBLE)
                {
                        play_countdown(self.invincible_finished, "misc/poweroff.wav");
-                       if (time > self.invincible_finished && autocvar_g_balance_powerup_timer)
+                       if (time > self.invincible_finished)
                        {
                                self.items = self.items - (self.items & IT_INVINCIBLE);
                                sprint(self, "^3Speed has worn off\n");
                {
                        play_countdown(self.strength_finished, "misc/poweroff.wav");
                        self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
-                       if (time > self.strength_finished && autocvar_g_balance_powerup_timer)
+                       if (time > self.strength_finished)
                        {
                                self.items = self.items - (self.items & IT_STRENGTH);
                                sprint(self, "^3Strength has worn off\n");
                {
                        play_countdown(self.invincible_finished, "misc/poweroff.wav");
                        self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
-                       if (time > self.invincible_finished && autocvar_g_balance_powerup_timer)
+                       if (time > self.invincible_finished)
                        {
                                self.items = self.items - (self.items & IT_INVINCIBLE);
                                sprint(self, "^3Shield has worn off\n");
@@@ -2746,42 -2619,26 +2622,26 @@@ void PlayerPreThink (void
  
                if(frametime)
                {
-                       if(self.health <= 0 && autocvar_g_deathglow)
-                       {
-                               if(self.glowmod_x > 0)
-                                       self.glowmod_x -= autocvar_g_deathglow * frametime;
-                               else
-                                       self.glowmod_x = -1;
-                               if(self.glowmod_y > 0)
-                                       self.glowmod_y -= autocvar_g_deathglow * frametime;
-                               else
-                                       self.glowmod_y = -1;
-                               if(self.glowmod_z > 0)
-                                       self.glowmod_z -= autocvar_g_deathglow * frametime;
-                               else
-                                       self.glowmod_z = -1;
-                       }
-                       else
+ #ifndef NO_LEGACY_NETWORKING
+                       self.glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2;
+ #endif
+                       if(self.weapon == WEP_NEX && autocvar_g_balance_nex_charge)
                        {
-                               // set weapon and player glowmod
-                               self.glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2;
+                               self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
+                               self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
+                               self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
  
-                               if(self.weapon == WEP_NEX && autocvar_g_balance_nex_charge)
+                               if(self.nex_charge > autocvar_g_balance_nex_charge_animlimit)
                                {
-                                       self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
-                                       self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
-                                       self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
-                                       if(self.nex_charge > autocvar_g_balance_nex_charge_animlimit)
-                                       {
-                                               self.weaponentity_glowmod_x = self.weaponentity_glowmod_x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
-                                               self.weaponentity_glowmod_y = self.weaponentity_glowmod_y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
-                                               self.weaponentity_glowmod_z = self.weaponentity_glowmod_z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
-                                       }
+                                       self.weaponentity_glowmod_x = self.weaponentity_glowmod_x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
+                                       self.weaponentity_glowmod_y = self.weaponentity_glowmod_y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
+                                       self.weaponentity_glowmod_z = self.weaponentity_glowmod_z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
                                }
-                               else
-                                       self.weaponentity_glowmod = self.glowmod;
                        }
+                       else
+                               self.weaponentity_glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2;
                        player_powerups();
                }
  
@@@ -3194,4 -3051,6 +3054,6 @@@ void PlayerPostThink (void
        if(g_race)
                dprint(sprintf("%f %.6f\n", time, race_GetFractionalLapCount(self)));
        */
+       CSQCMODEL_AUTOUPDATE();
  }
diff --combined qcsrc/server/defs.qh
index be30ca3bec48057280980083f2fad82602e1ddbb,0c06958af30d6de3baf411d5ba5308495894227f..d70dd193777bb5a004b0269274acc0efb28b494a
@@@ -174,7 -174,6 +174,7 @@@ void setanim(entity e, vector anim, flo
  
  .float species;
  
 +.float        scheduledrespawntime;
  .float        respawntime;
  .float        respawntimejitter;
  //.float      chasecam;
@@@ -328,7 -327,6 +328,6 @@@ float default_weapon_alpha
  
  .float() customizeentityforclient;
  .float cvar_cl_handicap;
- .float cvar_cl_playerdetailreduction;
  .float cvar_cl_clippedspectating;
  .float cvar_cl_autoscreenshot;
  .float cvar_cl_movement_track_canjump;
  .float cvar_cl_forceplayermodelsfromxonotic;
  float sv_clforceplayermodels;
  #endif
- float sv_loddistance1;
- float sv_loddistance2;
  .float cvar_cl_gunalign;
  .float cvar_cl_noantilag;
  
@@@ -358,12 -354,6 +355,6 @@@ void AnnounceTo(entity e, string snd)
  
  .float version_nagtime;
  
- .float modelindex_lod0;
- .float modelindex_lod0_from_xonotic;
- .float skinindex;
- .float modelindex_lod1;
- .float modelindex_lod2;
  #define NUM_JUMPPADSUSED 3
  .float jumppadcount;
  .entity jumppadsused[NUM_JUMPPADSUSED];
@@@ -661,16 -651,6 +652,16 @@@ string deathmessage
  .float (float act_state) setactive;
  .entity realowner;
  
 +.float item_armor_large_time;
 +.float item_health_mega_time;
 +.float item_strength_time;
 +.float item_invisible_time;
 +.float item_extralife_time;
 +.float item_speed_time;
 +.float item_shield_time;
 +.float item_fuelregen_time;
 +.float item_jetpack_time;
 +
  .float nex_charge;
  .float nex_charge_rottime;
  .float nex_chargepool_ammo;
diff --combined qcsrc/server/g_world.qc
index 3d3cd582cc9476a220482dfc87ab8e2861cef3d2,1c0f9306e4fe34263a1e6ff7b2d9868b71fd646e..d65a74e4a1a4229aa7891741c4c48d343aa73928
@@@ -402,6 -402,9 +402,9 @@@ void cvar_changes_init(
                BADCVAR("gameversion");
                BADPREFIX("gameversion_");
                BADCVAR("sv_namechangetimer");
+ #ifndef NO_LEGACY_NETWORKING
+               BADCVAR("sv_use_csqc_players"); // transition
+ #endif
  
                // allowed changes to server admins (please sync this to server.cfg)
                // vi commands:
                //   :%s,//\([^ ]*\).*,BADCVAR("\1");,
                //   :%!sort
                // yes, this does contain some redundant stuff, don't really care
+               BADCVAR("bot_config_file");
                BADCVAR("bot_number");
                BADCVAR("bot_prefix");
                BADCVAR("bot_suffix");
-               BADCVAR("bot_config_file");
                BADCVAR("capturelimit_override");
                BADCVAR("fraglimit_override");
                BADCVAR("gametype");
                BADCVAR("g_minstagib");
                BADCVAR("g_mirrordamage");
                BADCVAR("g_nexball_goallimit");
+               BADCVAR("g_powerups");
                BADCVAR("g_runematch_point_limit");
                BADCVAR("g_start_delay");
                BADCVAR("g_warmup");
                BADCVAR("skill");
                BADCVAR("sv_adminnick");
                BADCVAR("sv_autoscreenshot");
+               BADCVAR("sv_autotaunt");
                BADCVAR("sv_curl_defaulturl");
                BADCVAR("sv_defaultcharacter");
                BADCVAR("sv_defaultplayercolors");
                BADCVAR("sv_public");
                BADCVAR("sv_ready_restart");
                BADCVAR("sv_status_privacy");
+               BADCVAR("sv_taunt");
                BADCVAR("sv_vote_call");
                BADCVAR("sv_vote_commands");
                BADCVAR("sv_vote_majority_factor");
                BADCVAR("teamplay_mode");
                BADCVAR("timelimit_override");
                BADPREFIX("g_warmup_");
+               BADPREFIX("sv_ready_restart_");
  
                if(autocvar_g_minstagib)
                {
@@@ -743,8 -750,10 +750,10 @@@ void spawnfunc_worldspawn (void
                        s = strcat(s, ":no_use_ammunition");
  
                // initialiation stuff, not good in the mutator system
-               if(!autocvar_g_pickup_items)
+               if(autocvar_g_pickup_items == 0)
                        s = strcat(s, ":no_pickup_items");
+               if(autocvar_g_pickup_items > 0)
+                       s = strcat(s, ":pickup_items");
  
                // initialiation stuff, not good in the mutator system
                if(autocvar_g_weaponarena != "0")
                if(autocvar_g_minstagib)
                        s = strcat(s, ":minstagib");
  
+               // TODO to mutator system
+               if(autocvar_g_powerups == 0)
+                       s = strcat(s, ":no_powerups");
+               if(autocvar_g_powerups > 0)
+                       s = strcat(s, ":powerups");
                GameLogEcho(s);
                GameLogEcho(":gameinfo:end");
        }
  
        addstat(STAT_HAGAR_LOAD, AS_INT, hagar_load);
  
 +      addstat(STAT_ARMOR_LARGE_TIME, AS_FLOAT, item_armor_large_time);
 +      addstat(STAT_HEALTH_MEGA_TIME, AS_FLOAT, item_health_mega_time);
 +      addstat(STAT_STRENGTH_TIME, AS_FLOAT, item_strength_time);
 +      addstat(STAT_INVISIBLE_TIME, AS_FLOAT, item_invisible_time);
 +      addstat(STAT_EXTRALIFE_TIME, AS_FLOAT, item_extralife_time);
 +      addstat(STAT_SPEED_TIME, AS_FLOAT, item_speed_time);
 +      addstat(STAT_SHIELD_TIME, AS_FLOAT, item_shield_time);
 +      addstat(STAT_FUELREGEN_TIME, AS_FLOAT, item_fuelregen_time);
 +      addstat(STAT_JETPACK_TIME, AS_FLOAT, item_jetpack_time);
 +
        if(g_ca || g_freezetag)
        {
                addstat(STAT_REDALIVE, AS_INT, redalive_stat);
                s = "";
                n = tokenize_console(cvar_string("sv_curl_serverpackages"));
                for(i = 0; i < n; ++i)
-                       if(substring(argv(i), -14, -1) != ".serverpackage")
+                       if(substring(argv(i), -14, -1) != "-serverpackage.txt")
+                       if(substring(argv(i), -14, -1) != ".serverpackage") // OLD legacy
                                s = strcat(s, " ", argv(i));
+               fd = search_begin("*-serverpackage.txt", TRUE, FALSE);
+               if(fd >= 0)
+               {
+                       j = search_getsize(fd);
+                       for(i = 0; i < j; ++i)
+                               s = strcat(s, " ", search_getfilename(fd, i));
+                       search_end(fd);
+               }
                fd = search_begin("*.serverpackage", TRUE, FALSE);
                if(fd >= 0)
                {
diff --combined qcsrc/server/t_items.qc
index c74c8b5722c5112a32c4f7b14aea01be7de24b34,a43be3ff7dd63ee4d7b4a6e8fa66c1fb5da7d1df..3846af4bca478403d51bb226f2f0e3f8ab56b4a2
@@@ -1,3 -1,40 +1,40 @@@
+ float have_pickup_item(void)
+ {
+       // minstagib: only allow filtered items
+       if(g_minstagib)
+               if(self.classname != "minstagib")
+                       return FALSE;
+       if(self.items == IT_STRENGTH || self.items == IT_INVINCIBLE)
+       {
+               if(autocvar_g_powerups > 0)
+                       return TRUE;
+               if(autocvar_g_powerups == 0)
+                       return FALSE;
+               if(g_lms)
+                       return FALSE;
+               if(g_ca)
+                       return FALSE;
+               if(g_arena)
+                       return FALSE;
+       }
+       else
+       {
+               if(autocvar_g_pickup_items > 0)
+                       return TRUE;
+               if(autocvar_g_pickup_items == 0)
+                       return FALSE;
+               if(g_lms)
+                       return FALSE;
+               if(g_ca)
+                       return FALSE;
+               if(g_weaponarena)
+                       if((self.weapons & WEPBIT_ALL) || (self.items & IT_AMMO))
+                               return FALSE;
+       }
+       return TRUE;
+ }
  #define ITEM_RESPAWN_TICKS 10
  
  #define ITEM_RESPAWNTIME(i)         ((i).respawntime + crandom() * (i).respawntimejitter)
@@@ -94,7 -131,7 +131,7 @@@ void Item_Show (entity e, float mode
  
                e.spawnshieldtime = 1;
        }
-       else if((e.flags & FL_WEAPON) && (g_weapon_stay == 3))
+       else if((e.flags & FL_WEAPON) && g_weapon_stay)
        {
                // make the item translucent and not touchable
                e.model = e.mdl;
        setorigin(e, e.origin);
  }
  
 +float it_armor_large_time;
 +float it_health_mega_time;
 +float it_strength_time;
 +float it_invisible_time;
 +float it_extralife_time;
 +float it_speed_time;
 +float it_shield_time;
 +float it_fuelregen_time;
 +float it_jetpack_time;
 +
 +void Item_ClearItemsTime()
 +{
 +      self.item_armor_large_time = 0;
 +      self.item_health_mega_time = 0;
 +      self.item_strength_time = 0;
 +      self.item_invisible_time = 0;
 +      self.item_extralife_time = 0;
 +      self.item_speed_time = 0;
 +      self.item_shield_time = 0;
 +      self.item_fuelregen_time = 0;
 +      self.item_jetpack_time = 0;
 +}
 +void Item_GetItemsTime(entity e)
 +{
 +      e.item_armor_large_time = it_armor_large_time;
 +      e.item_health_mega_time = it_health_mega_time;
 +      e.item_strength_time = it_strength_time;
 +      e.item_invisible_time = it_invisible_time;
 +      e.item_extralife_time = it_extralife_time;
 +      e.item_speed_time = it_speed_time;
 +      e.item_shield_time = it_shield_time;
 +      e.item_fuelregen_time = it_fuelregen_time;
 +      e.item_jetpack_time = it_jetpack_time;
 +}
 +void Item_UpdateTime(entity e, float t)
 +{
 +      if(g_minstagib)
 +      {
 +              switch(e.items)
 +              {
 +                      case IT_STRENGTH://"item-invis"
 +                              if (it_invisible_time > time && t > it_invisible_time)
 +                                      return;
 +                              it_invisible_time = t;
 +                              return;
 +                      case IT_NAILS://"item-extralife"
 +                              if (it_extralife_time > time && t > it_extralife_time)
 +                                      return;
 +                              it_extralife_time = t;
 +                              return;
 +                      case IT_INVINCIBLE://"item-speed"
 +                              if (it_speed_time > time && t > it_speed_time)
 +                                      return;
 +                              it_speed_time = t;
 +                              return;
 +              }
 +      }
 +      else
 +      {
 +              switch(e.items)
 +              {
 +                      case IT_HEALTH:
 +                              //if (e.classname == "item_health_mega")
 +                              {
 +                                      if (it_health_mega_time > time && t > it_health_mega_time)
 +                                              return;
 +                                      it_health_mega_time = t;
 +                              }
 +                              return;
 +                      case IT_ARMOR:
 +                              if (e.classname == "item_armor_large")
 +                              {
 +                                      if (it_armor_large_time > time && t > it_armor_large_time)
 +                                              return;
 +                                      it_armor_large_time = t;
 +                              }
 +                              return;
 +                      case IT_STRENGTH://"item-strength"
 +                              if (it_strength_time > time && t > it_strength_time)
 +                                      return;
 +                              it_strength_time = t;
 +                              return;
 +                      case IT_INVINCIBLE://"item-shield"
 +                              if (it_shield_time > time && t > it_shield_time)
 +                                      return;
 +                              it_shield_time = t;
 +                              return;
 +              }
 +      }
 +      switch(e.items)
 +      {
 +              case IT_FUEL_REGEN://"item-fuelregen"
 +                      if (it_fuelregen_time > time && t > it_fuelregen_time)
 +                              return;
 +                      it_fuelregen_time = t;
 +                      return;
 +              case IT_JETPACK://"item-jetpack"
 +                      if (it_jetpack_time > time && t > it_jetpack_time)
 +                              return;
 +                      it_jetpack_time = t;
 +                      return;
 +      }
 +}
 +
  void Item_Respawn (void)
  {
 +      float t;
 +      entity head;
        Item_Show(self, 1);
        if(!g_minstagib && self.items == IT_STRENGTH)
                sound (self, CH_TRIGGER, "misc/strength_respawn.wav", VOL_BASE, ATTN_NORM);     // play respawn sound
                sound (self, CH_TRIGGER, "misc/itemrespawn.wav", VOL_BASE, ATTN_NORM);  // play respawn sound
        setorigin (self, self.origin);
  
 +      if (self.flags & FL_POWERUP || self.classname == "item_armor_large" || self.items == IT_HEALTH)
 +      {
 +              for(t = 0, head = world; (head = find(head, classname, self.classname)); )
 +              {
 +                      // in minstagib .classname is "minstagib" for every item
 +                      if (g_minstagib && self.items != head.items)
 +                              continue;
 +                      if (head.scheduledrespawntime > time)
 +                              if (t == 0 || head.scheduledrespawntime < t)
 +                                      t = head.scheduledrespawntime;
 +              }
 +              Item_UpdateTime(self, t);
 +              FOR_EACH_REALCLIENT(head)
 +              {
 +                      if (head.classname != "player")
 +                              Item_GetItemsTime(head);
 +              }
 +      }
 +
        //pointparticles(particleeffectnum("item_respawn"), self.origin + self.mins_z * '0 0 1' + '0 0 48', '0 0 0', 1);
        pointparticles(particleeffectnum("item_respawn"), self.origin + 0.5 * (self.mins + self.maxs), '0 0 0', 1);
  }
@@@ -314,14 -226,6 +351,14 @@@ void Item_RespawnCountdown (void
                                {
                                        case IT_STRENGTH:   name = "item-strength"; rgb = '0 0 1'; break;
                                        case IT_INVINCIBLE: name = "item-shield"; rgb = '1 0 1'; break;
 +                                      case IT_HEALTH:
 +                                              //if (self.classname == "item_health_mega")
 +                                                      {name = "item_health_mega"; rgb = '1 0 0';}
 +                                              break;
 +                                      case IT_ARMOR:
 +                                              if (self.classname == "item_armor_large")
 +                                                      {name = "item_armor_large"; rgb = '0 1 0';}
 +                                              break;
                                }
                        }
                        switch(self.items)
                        {
                                WaypointSprite_Spawn(name, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, TRUE, RADARICON_POWERUP, rgb);
                                if(self.waypointsprite_attached)
 +                              {
 +                                      if (self.items == IT_HEALTH || self.items == IT_ARMOR)
 +                                              WaypointSprite_UpdateRule(self.waypointsprite_attached, 0, SPRITERULE_SPECTATOR);
                                        WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, time + ITEM_RESPAWN_TICKS);
 +                              }
                        }
                }
                sound (self, CH_TRIGGER, "misc/itemrespawncountdown.wav", VOL_BASE, ATTN_NORM); // play respawn sound
  
  void Item_ScheduleRespawnIn(entity e, float t)
  {
 -      if(e.flags & FL_POWERUP)
 +      if(e.flags & FL_POWERUP || self.classname == "item_armor_large" || self.items == IT_HEALTH)
        {
                e.think = Item_RespawnCountdown;
                e.nextthink = time + max(0, t - ITEM_RESPAWN_TICKS);
 +              e.scheduledrespawntime = e.nextthink + ITEM_RESPAWN_TICKS;
                e.count = 0;
        }
        else
        {
                e.think = Item_Respawn;
                e.nextthink = time + t;
 +              e.scheduledrespawntime = e.nextthink;
 +      }
 +      Item_UpdateTime(e, e.scheduledrespawntime);
 +      FOR_EACH_REALCLIENT(e)
 +      {
 +              if (e.classname != "player")
 +                      Item_GetItemsTime(e);
        }
  }
  
@@@ -389,6 -281,53 +426,53 @@@ void Item_ScheduleInitialRespawn(entit
        Item_ScheduleRespawnIn(e, game_starttime - time + ITEM_RESPAWNTIME_INITIAL(e));
  }
  
+ float ITEM_MODE_NONE = 0;
+ float ITEM_MODE_HEALTH = 1;
+ float ITEM_MODE_ARMOR = 2;
+ float ITEM_MODE_FUEL = 3;
+ float Item_GiveAmmoTo(entity item, entity player, .float ammofield, float ammomax, float mode)
+ {
+       if (!item.ammofield)
+               return FALSE;
+       if (item.spawnshieldtime)
+       {
+               if ((player.ammofield < ammomax) || item.pickup_anyway)
+               {
+                       player.ammofield = bound(player.ammofield, ammomax, player.ammofield + item.ammofield);
+                       goto YEAH;
+               }
+       }
+       else if(g_weapon_stay == 2)
+       {
+               float mi = min(item.ammofield, ammomax);
+               if (player.ammofield < mi)
+               {
+                       player.ammofield = mi;
+                       goto YEAH;
+               }
+       }
+       return FALSE;
+ :YEAH
+       switch(mode)
+       {
+               case ITEM_MODE_FUEL:
+                       player.pauserotfuel_finished = max(player.pauserotfuel_finished, time + autocvar_g_balance_pause_fuel_rot);
+                       break;
+               case ITEM_MODE_HEALTH:
+                       player.pauserothealth_finished = max(player.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot);
+                       break;
+               case ITEM_MODE_ARMOR:
+                       player.pauserotarmor_finished = max(player.pauserotarmor_finished, time + autocvar_g_balance_pause_armor_rot);
+                       break;
+               default:
+                       break;
+       }
+       return TRUE;
+ }
  float Item_GiveTo(entity item, entity player)
  {
        float _switchweapon;
  
        if (g_minstagib)
        {
-               if(item.spawnshieldtime)
+               float prevcells = player.ammo_cells;
+               pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
+               pickedup |= Item_GiveAmmoTo(item, player, ammo_cells, 999, ITEM_MODE_NONE);
+               if(player.ammo_cells > prevcells)
                {
-                       if (item.ammo_fuel)
-                       if (player.ammo_fuel < g_pickup_fuel_max)
-                       {
-                               pickedup = TRUE;
-                               player.ammo_fuel = bound(player.ammo_fuel, g_pickup_fuel_max, player.ammo_fuel + item.ammo_fuel);
-                               player.pauserotfuel_finished = max(player.pauserotfuel_finished, time + autocvar_g_balance_pause_fuel_rot);
-                       }
-                       if((it = (item.items - (item.items & player.items)) & IT_PICKUPMASK))
+                       _switchweapon = TRUE;
+                       // play some cool sounds ;)
+                       if (clienttype(player) == CLIENTTYPE_REAL)
                        {
-                               pickedup = TRUE;
-                               player.items |= it;
-                               sprint (player, strcat("You got the ^2", item.netname, "\n"));
+                               if(player.health <= 5)
+                                       AnnounceTo(player, "lastsecond");
+                               else if(player.health < 50)
+                                       AnnounceTo(player, "narrowly");
                        }
+                       // sound not available
+                       // else if(item.items == IT_CELLS)
+                       //      AnnounceTo(player, "ammo");
  
-                       _switchweapon = TRUE;
+                       if (item.weapons & WEPBIT_MINSTANEX)
+                               W_GiveWeapon (player, WEP_MINSTANEX, item.netname);
                        if (item.ammo_cells)
-                       {
-                               pickedup = TRUE;
-                               // play some cool sounds ;)
-                               if (clienttype(player) == CLIENTTYPE_REAL)
-                               {
-                                       if(player.health <= 5)
-                                               AnnounceTo(player, "lastsecond");
-                                       else if(player.health < 50)
-                                               AnnounceTo(player, "narrowly");
-                               }
-                               // sound not available
-                               // else if(item.items == IT_CELLS)
-                               //      AnnounceTo(player, "ammo");
-                               if (item.weapons & WEPBIT_MINSTANEX)
-                                       W_GiveWeapon (player, WEP_MINSTANEX, item.netname);
-                               if (item.ammo_cells)
-                                       player.ammo_cells = bound(player.ammo_cells, 999, player.ammo_cells + autocvar_g_minstagib_ammo_drop);
-                               player.health = 100;
-                       }
+                               player.ammo_cells = bound(player.ammo_cells, 999, player.ammo_cells + autocvar_g_minstagib_ammo_drop);
+                       player.health = 100;
+               }
  
-                       // extralife powerup
-                       if (item.max_health)
-                       {
-                               pickedup = TRUE;
-                               // sound not available
-                               // AnnounceTo(player, "_lives");
-                               player.armorvalue = bound(player.armorvalue, 999, player.armorvalue + autocvar_g_minstagib_extralives);
-                               sprint(player, "^3You picked up some extra lives\n");
-                       }
+               if((it = (item.items - (item.items & player.items)) & IT_PICKUPMASK))
+               {
+                       pickedup = TRUE;
+                       player.items |= it;
+                       sprint (player, strcat("You got the ^2", item.netname, "\n"));
+               }
  
-                       // invis powerup
-                       if (item.strength_finished)
-                       {
-                               pickedup = TRUE;
-                               // sound not available
-                               // AnnounceTo(player, "invisible");
-                               player.strength_finished = max(player.strength_finished, time) + autocvar_g_balance_powerup_strength_time;
-                       }
+               // extralife powerup
+               if (item.max_health)
+               {
+                       pickedup = TRUE;
+                       // sound not available
+                       // AnnounceTo(player, "_lives");
+                       player.armorvalue = bound(player.armorvalue, 999, player.armorvalue + autocvar_g_minstagib_extralives);
+                       sprint(player, "^3You picked up some extra lives\n");
+               }
  
-                       // speed powerup
-                       if (item.invincible_finished)
-                       {
-                               pickedup = TRUE;
-                               // sound not available
-                               // AnnounceTo(player, "speed");
-                               player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_strength_time;
-                       }
+               // invis powerup
+               if (item.strength_finished)
+               {
+                       pickedup = TRUE;
+                       // sound not available
+                       // AnnounceTo(player, "invisible");
+                       player.strength_finished = max(player.strength_finished, time) + autocvar_g_balance_powerup_strength_time;
+               }
+               // speed powerup
+               if (item.invincible_finished)
+               {
+                       pickedup = TRUE;
+                       // sound not available
+                       // AnnounceTo(player, "speed");
+                       player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_strength_time;
                }
        }
        else
        {
-               if (g_weapon_stay == 1)
-               if not(item.flags & FL_NO_WEAPON_STAY)
-               if (item.flags & FL_WEAPON)
-               {
-                       if(item.classname == "droppedweapon")
-                       {
-                               if (player.weapons & item.weapons)      // don't let players stack ammo by tossing weapons
-                                       goto skip;
-                       }
-                       else
-                       {
-                               if (player.weapons & item.weapons)
-                                       goto skip;
-                       }
-               }
                // in case the player has autoswitch enabled do the following:
                // if the player is using their best weapon before items are given, they
                // probably want to switch to an even better weapon after items are given
                if not(player.weapons & W_WeaponBit(player.switchweapon))
                        _switchweapon = TRUE;
  
-               if(item.spawnshieldtime)
-               {
-                       if (item.ammo_shells)
-                       if ((player.ammo_shells < g_pickup_shells_max) || item.pickup_anyway)
-                       {
-                               pickedup = TRUE;
-                               player.ammo_shells = bound(player.ammo_shells, g_pickup_shells_max, player.ammo_shells + item.ammo_shells);
-                       }
-                       if (item.ammo_nails)
-                       if ((player.ammo_nails < g_pickup_nails_max) || item.pickup_anyway)
-                       {
-                               pickedup = TRUE;
-                               player.ammo_nails = bound(player.ammo_nails, g_pickup_nails_max, player.ammo_nails + item.ammo_nails);
-                       }
-                       if (item.ammo_rockets)
-                       if ((player.ammo_rockets < g_pickup_rockets_max) || item.pickup_anyway)
-                       {
-                               pickedup = TRUE;
-                               player.ammo_rockets = bound(player.ammo_rockets, g_pickup_rockets_max, player.ammo_rockets + item.ammo_rockets);
-                       }
-                       if (item.ammo_cells)
-                       if ((player.ammo_cells < g_pickup_cells_max) || item.pickup_anyway)
-                       {
-                               pickedup = TRUE;
-                               player.ammo_cells = bound(player.ammo_cells, g_pickup_cells_max, player.ammo_cells + item.ammo_cells);
-                       }
-                       if (item.ammo_fuel)
-                       if ((player.ammo_fuel < g_pickup_fuel_max) || item.pickup_anyway)
-                       {
-                               pickedup = TRUE;
-                               player.ammo_fuel = bound(player.ammo_fuel, g_pickup_fuel_max, player.ammo_fuel + item.ammo_fuel);
-                               player.pauserotfuel_finished = max(player.pauserotfuel_finished, time + autocvar_g_balance_pause_fuel_rot);
-                       }
-               }
+               pickedup |= Item_GiveAmmoTo(item, player, ammo_fuel, g_pickup_fuel_max, ITEM_MODE_FUEL);
+               pickedup |= Item_GiveAmmoTo(item, player, ammo_shells, g_pickup_shells_max, ITEM_MODE_NONE);
+               pickedup |= Item_GiveAmmoTo(item, player, ammo_nails, g_pickup_nails_max, ITEM_MODE_NONE);
+               pickedup |= Item_GiveAmmoTo(item, player, ammo_rockets, g_pickup_rockets_max, ITEM_MODE_NONE);
+               pickedup |= Item_GiveAmmoTo(item, player, ammo_cells, g_pickup_cells_max, ITEM_MODE_NONE);
+               pickedup |= Item_GiveAmmoTo(item, player, health, item.max_health, ITEM_MODE_HEALTH);
+               pickedup |= Item_GiveAmmoTo(item, player, armorvalue, item.max_armorvalue, ITEM_MODE_ARMOR);
  
                if (item.flags & FL_WEAPON)
-                       if ((it = item.weapons - (item.weapons & player.weapons)) || (g_pickup_weapons_anyway && g_weapon_stay == 0))
+               if ((it = item.weapons - (item.weapons & player.weapons)) || (item.spawnshieldtime && g_pickup_weapons_anyway))
                {
                        pickedup = TRUE;
                        for(i = WEP_FIRST; i <= WEP_LAST; ++i)
                        sprint (player, strcat("You got the ^2", item.netname, "\n"));
                }
  
-               if(item.spawnshieldtime)
+               if (item.strength_finished)
                {
-                       if (item.strength_finished)
-                       {
-                               pickedup = TRUE;
-                               player.strength_finished = max(player.strength_finished, time) + autocvar_g_balance_powerup_strength_time;
-                       }
-                       if (item.invincible_finished)
-                       {
-                               pickedup = TRUE;
-                               player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_invincible_time;
-                       }
-                       if (item.health)
-                       if ((player.health < item.max_health) || item.pickup_anyway)
-                       {
-                               pickedup = TRUE;
-                               player.health = bound(player.health, item.max_health, player.health + item.health);
-                               player.pauserothealth_finished = max(player.pauserothealth_finished, time + autocvar_g_balance_pause_health_rot);
-                       }
-                       if (item.armorvalue)
-                       if ((player.armorvalue < item.max_armorvalue) || item.pickup_anyway)
-                       {
-                               pickedup = TRUE;
-                               player.armorvalue = bound(player.armorvalue, item.max_armorvalue, player.armorvalue + item.armorvalue);
-                               player.pauserotarmor_finished = max(player.pauserotarmor_finished, time + autocvar_g_balance_pause_armor_rot);
-                       }
+                       pickedup = TRUE;
+                       player.strength_finished = max(player.strength_finished, time) + autocvar_g_balance_powerup_strength_time;
+               }
+               if (item.invincible_finished)
+               {
+                       pickedup = TRUE;
+                       player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_invincible_time;
                }
        }
  
@@@ -629,8 -502,6 +647,6 @@@ void Item_Touch (void
                remove (self);
        else if not(self.spawnshieldtime)
                return;
-       else if((self.flags & FL_WEAPON) && !(self.flags & FL_NO_WEAPON_STAY) && (g_weapon_stay == 1 || g_weapon_stay == 2))
-               return;
        else
        {
                if(self.team)
@@@ -714,7 -585,7 +730,7 @@@ float weapon_pickupevalfunc(entity play
        if(player.weapons & item.weapons == item.weapons)
        {
                // If I can pick it up
-               if(g_weapon_stay == 1 || g_weapon_stay == 2 || !item.spawnshieldtime)
+               if(!item.spawnshieldtime)
                        c = 0;
                else if(player.ammo_cells || player.ammo_shells || player.ammo_nails || player.ammo_rockets)
                {
@@@ -852,6 -723,13 +868,13 @@@ void StartItem (string itemmodel, strin
                        return;
                }
  
+               if(!have_pickup_item())
+               {
+                       startitem_failed = TRUE;
+                       remove (self);
+                       return;
+               }
                self.reset = Item_Reset;
                // it's a level item
                if(self.spawnflags & 1)
                        self.is_item = TRUE;
                }
  
-               if(g_lms || g_ca)
-               {
-                       startitem_failed = TRUE;
-                       remove(self);
-                       return;
-               }
-               else if (g_weaponarena && ((weaponid & WEPBIT_ALL) || (itemid & IT_AMMO)))
-               {
-                       startitem_failed = TRUE;
-                       remove(self);
-                       return;
-               }
-               else if (g_minstagib)
-               {
-                       // don't remove dropped items and powerups
-                       if (self.classname != "minstagib")
-                       {
-                               startitem_failed = TRUE;
-                               remove (self);
-                               return;
-                       }
-               }
-               else if (!autocvar_g_pickup_items && itemid != IT_STRENGTH && itemid != IT_INVINCIBLE && itemid != IT_HEALTH)
-               {
-                       startitem_failed = TRUE;
-                       remove (self);
-                       return;
-               }
                weaponsInMap |= weaponid;
  
                precache_model (itemmodel);
@@@ -1006,7 -855,7 +1000,7 @@@ void minstagib_items (float itemid
        // replace rocket launchers and nex guns with ammo cells
        if (itemid == IT_CELLS)
        {
-               self.ammo_cells = 1;
+               self.ammo_cells = autocvar_g_minstagib_ammo_drop;
                StartItem ("models/items/a_cells.md3",
                        "misc/itempickup.wav", 45, 0,
                        "MinstaNex Ammo", IT_CELLS, 0, 0, generic_pickupevalfunc, 100);
@@@ -1169,16 -1018,6 +1163,6 @@@ void weapon_defaultspawnfunc(float wpn
        if(self.team)
                self.flags |= FL_NO_WEAPON_STAY;
  
-       if(g_weapon_stay == 2 && self.classname != "droppedweapon")
-       {
-               self.ammo_shells = 0;
-               self.ammo_nails = 0;
-               self.ammo_cells = 0;
-               self.ammo_rockets = 0;
-               // weapon stay 2: don't use ammo on weapon pickups; instead
-               // initialize all ammo types to the pickup ammo unless set by g_start_ammo_*
-       }
        StartItem(e.model, "weapons/weaponpickup.wav", self.respawntime, self.respawntimejitter, e.message, 0, e.weapons, FL_WEAPON, weapon_pickupevalfunc, e.bot_pickupbasevalue);
        if (self.modelindex) // don't precache if self was removed
                weapon_action(e.weapon, WR_PRECACHE);
@@@ -1365,12 -1204,6 +1349,6 @@@ void spawnfunc_item_health_large (void
  }
  
  void spawnfunc_item_health_mega (void) {
-       if(!autocvar_g_powerup_superhealth)
-               return;
-       if((g_arena || g_ca) && !autocvar_g_arena_powerups)
-               return;
        if(g_minstagib) {
                minstagib_items(IT_NAILS);
        } else {
@@@ -1392,12 -1225,6 +1370,6 @@@ void spawnfunc_item_health25() { spawnf
  void spawnfunc_item_health100() { spawnfunc_item_health_mega(); }
  
  void spawnfunc_item_strength (void) {
-       if(!autocvar_g_powerup_strength)
-               return;
-       if((g_arena || g_ca) && !autocvar_g_arena_powerups)
-               return;
        if(g_minstagib) {
                minstagib_items(IT_STRENGTH);
        } else {
  }
  
  void spawnfunc_item_invincible (void) {
-       if(!autocvar_g_powerup_shield)
-               return;
-       if((g_arena || g_ca) && !autocvar_g_arena_powerups)
-               return;
        if(g_minstagib) {
                minstagib_items(IT_INVINCIBLE);
        } else {