]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into terencehill/itemstime
authorterencehill <piuntn@gmail.com>
Tue, 2 Oct 2012 17:08:40 +0000 (19:08 +0200)
committerterencehill <piuntn@gmail.com>
Tue, 2 Oct 2012 17:08:40 +0000 (19:08 +0200)
1  2 
defaultXonotic.cfg
qcsrc/client/autocvars.qh
qcsrc/client/hud.qc
qcsrc/client/waypointsprites.qc
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 b93457ac2d6cc57d66e46f15fe4ef1b57ef731b9,69ab2b1a1d401a77296dd70f3bd665a4143d1a3f..3c269391e8d5d656d93d0b25a0245fe5ec9bc3e3
@@@ -31,15 -31,6 +31,6 @@@ seta cl_startcount 0 "how many times th
  
  seta g_configversion 0        "Configuration file version (used to upgrade settings) 0: first run, or previous start was <2.4.1  Later, it's overridden by config.cfg, version ranges are defined in config_update.cfg"
  
- // say aliases
- alias asay_ctf_flagcarrier "say_team flag carrier at %y"
- alias asay_ctf_haveflag "say_team (%l) have the flag"
- alias asay_willgo "say_team will go to %y"
- alias asay_support "say_team (%l) need help, %h%%"
- alias asay_killed "say_team got killed at %d"
- alias asay_noammo "say_team (%l) need %W for %w"
- alias asay_drop "say_team (%l) dropped %w ; impulse 17"
  // other aliases
  alias +hook +button6
  alias -hook -button6
@@@ -57,7 -48,7 +48,7 @@@ bind f6 team_aut
  mod_q3bsp_lightmapmergepower 4
  
  // player defaults
- _cl_color 112
+ _cl_color "112.211" // same effect as 112, but menuqc can detect this as the default and not intentionally set
  _cl_name Player
  _cl_playermodel models/player/erebus.iqm
  _cl_playerskin 0
@@@ -146,6 -137,14 +137,14 @@@ gl_polyblend 0 // whether to use scree
  r_motionblur 0 // motion blur value, default is 0
  r_damageblur 0 // motion blur when damaged, default is 0 (removed in Xonotic)
  
+ r_bloom_blur 4
+ r_bloom_brighten 2
+ r_bloom_colorexponent 1
+ r_bloom_colorscale 1
+ r_bloom_colorsubtract 0.125
+ r_bloom_resolution 320
+ r_bloom_scenebrightness 0.85
  seta vid_x11_display ""       "xonotic-linux-*.sh will use this to start xonotic on an other/new X display"
  // This can have three possible settings:
  //    ""              run as usual
@@@ -455,45 -454,6 +454,6 @@@ set sv_dodging_height_threshold 10 "th
  set sv_dodging_wall_distance_threshold 10 "the maximum distance from a wall that still allows dodging"
  set sv_dodging_sound 1 "if 1 dodging makes a sound. if 0 dodging is silent"
  
- set leadlimit 0
- set leadlimit_and_fraglimit 0 "if set, leadlimit is ANDed with fraglimit (otherwise ORed)"
- // this means that timelimit can be overidden globally and fraglimit can be overidden for each game mode: DM/TDM, Domination, CTF, and Runematch.
- seta timelimit_override -1    "Time limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta fraglimit_override -1    "Frag limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta leadlimit_override -1    "Lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta capturelimit_override -1 "Capture limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta captureleadlimit_override -1     "Capture llead imit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_arena_point_limit -1   "Arena point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_arena_point_leadlimit -1       "Arena point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_domination_point_limit -1      "Domination point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_domination_point_leadlimit -1  "Domination point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_runematch_point_limit -1       "Runematch point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_runematch_point_leadlimit -1   "Runematch point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_keyhunt_point_limit -1 "Keyhunt point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_keyhunt_point_leadlimit -1     "Keyhunt point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_race_laps_limit -1     "Race laps limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_nexball_goallimit -1 "Nexball goal limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_nexball_goalleadlimit -1 "Nexball goal lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_nexball_safepass_maxdist 5000    // Max distance to allow save fassping (0 to turn off safe passing)
- seta g_nexball_safepass_turnrate 0.1    // How fast the safe-pass ball can habge direction
- seta g_nexball_safepass_holdtime 0.75   // How long to remeber last teammate you pointed at
- seta g_nexball_viewmodel_scale 0.25     // How large the ball for the carrier
- seta g_nexball_viewmodel_offset "8 8 0" // Where the ball is located on carrier "forward right up"
- seta g_nexball_tackling 1               // Allow ball theft?
- seta g_ctf_ignore_frags 0     "1: regular frags give no points"
- set g_freezetag 0 "Freeze Tag: Freeze the opposing team(s) to win, unfreeze teammates by standing next to them"
- seta g_freezetag_warmup 5 "Time players get to run around before the round starts"
- seta g_freezetag_point_limit -1       "Freeze Tag point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_freezetag_point_leadlimit -1   "Freeze Tag point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
- seta g_freezetag_revive_speed 0.4 "Speed for reviving a frozen teammate"
- seta g_freezetag_revive_clearspeed 1.6 "Speed at which reviving progress gets lost when out of range"
- seta g_freezetag_revive_extra_size 100 "Distance in qu that you can stand from a frozen teammate to keep reviving him"
- seta g_freezetag_frozen_force 0.6 "How much to multiply the force on a frozen player with"
  set g_spawn_furthest 0.5 "this amount of the spawns shall be far away from any players"
  set g_spawn_useallspawns 0 "use all spawns, e.g. also team spawns in non-teamplay, and all spawns, even enemy spawns, in teamplay"
  set g_spawn_near_teammate 0 "if set, players prefer spawns near a team mate"
@@@ -501,60 -461,6 +461,6 @@@ set g_spawn_near_teammate_distance 640 
  // respawn delay
  set g_respawn_delay 2 "number of seconds you have to wait before you can respawn again"
  set g_respawn_waves 0 "respawn in waves (every n seconds), intended to decrease overwhelming base attacks"
- // when variables are set to 0, they take over the global setting...
- // to force disable delay or waves, set them to 0.125
- set g_ctf_respawn_delay 0
- set g_ctf_respawn_waves 0
- set g_ctf_weapon_stay 0
- set g_dm_respawn_delay 0
- set g_dm_respawn_waves 0
- set g_dm_weapon_stay 0
- set g_dom_respawn_delay 0
- set g_dom_respawn_waves 0
- set g_dom_weapon_stay 0
- set g_lms_respawn_delay 0
- set g_lms_respawn_waves 0
- set g_lms_weapon_stay 0
- set g_rune_respawn_delay 0
- set g_rune_respawn_waves 0
- set g_rune_weapon_stay 0
- set g_tdm_respawn_delay 0
- set g_tdm_respawn_waves 0
- set g_tdm_weapon_stay 0
- set g_ka_respawn_delay 0
- set g_ka_respawn_waves 0
- set g_ka_weapon_stay 0
- set g_kh_respawn_delay 0
- set g_kh_respawn_waves 0
- set g_kh_weapon_stay 0
- set g_arena_respawn_delay 0
- set g_arena_respawn_waves 0
- set g_arena_weapon_stay 0
- set g_ca_respawn_delay 0
- set g_ca_respawn_waves 0
- set g_ca_weapon_stay 0
- set g_ca_damage2score_multiplier 0.01
- set g_ca_round_timelimit 180
- set g_nb_respawn_delay 0
- set g_nb_respawn_waves 0
- set g_nb_weapon_stay 0
- set g_as_respawn_delay 0
- set g_as_respawn_waves 0
- set g_as_weapon_stay 0
- set g_ons_respawn_delay 0
- set g_ons_respawn_waves 0
- set g_ons_weapon_stay 0
- set g_rc_respawn_waves 0
- set g_rc_respawn_delay 0
- set g_rc_weapon_stay 0
- set g_cts_respawn_waves 0
- 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 2
- set g_ft_respawn_waves 0
- set g_ft_respawn_delay 0
- set g_ft_weapon_stay 0
  
  // overtime
  seta timelimit_overtime 2 "duration in minutes of one added overtime, added to the timelimit"
@@@ -574,215 -480,14 +480,14 @@@ seta g_friendlyfire_virtual_force 1    "fo
  seta g_teamdamage_threshold 40        "for teamplay 4: threshold over which to apply mirror damage"
  seta g_teamdamage_resetspeed 20       "for teamplay 4: how fast player's teamdamage count decreases"
  
- seta g_balance_teams 0        "automatically balance out players entering instead of asking them for their preferred team"
- seta g_balance_teams_force 0  "automatically balance out teams when players move or disconnect"
- seta g_balance_teams_prevent_imbalance        0       "prevent players from changing to larger teams"
- set g_tdm_teams 2 "how many teams are in team deathmatch (set by mapinfo)"
- seta g_tdm_teams_override 0   "how many teams are in team deathmatch"
- set g_tdm_team_spawns 0 "when 1, a map can define team spawnpoints for TDM"
+ seta g_balance_teams 1        "automatically balance out players entering instead of asking them for their preferred team"
+ seta g_balance_teams_prevent_imbalance        1       "prevent players from changing to larger teams"
+ set g_balance_teams_scorefactor 0.34 "at the end of the game, take score into account instead of team size by this amount (beware: values over 0.5 mean that a x:0 score imbalance will cause ALL new players to prefer the losing team at the end, despite numbers)"
  set g_changeteam_banned 0     "not allowed to change team"
  set g_changeteam_fragtransfer 0       "% of frags you get to keep when you change teams (rounded down)"
  
  set sv_teamnagger 1 "enable a nag message when the teams are unbalanced"
  
- // dm
- set g_dm 1 "Deathmatch: killing any other player is one frag, player with most frags wins"
- set gamecfg 1 // "deathmatch"
- // ctf
- set g_ctf 0 "Capture The Flag: take the enemy flag and bring it to yours at your base to score"
- set g_ctf_flag_returntime 30
- set g_ctf_flagcarrier_selfdamage 1
- set g_ctf_flagcarrier_selfforce 1
- set g_ctf_fullbrightflags 0
- set g_ctf_dynamiclights 0
- set g_ctf_allow_drop 1        "dropping allows circumventing carrierkill score, so enable this with care!"
- set g_ctf_reverse 0   "if enabled, flags positions are switched: you have to capture the enemy's flag from your own base by bringing it to your own flag in the enemy base"
- set g_balance_ctf_delay_collect 1.0
- set g_balance_ctf_damageforcescale 1
- set g_ctf_shield_max_ratio 0  "shield at most this percentage of a team from the enemy flag (try: 0.4 for 40%)"
- set g_ctf_shield_min_negscore 20      "shield the player from the flag if he's got this negative amount of points or less"
- set g_ctf_shield_force 100    "push force of the shield"
- // fun for server admins
- set g_ctf_flag_red_model "models/ctf/flags.md3"
- set g_ctf_flag_red_skin 0
- set g_ctf_flag_blue_model "models/ctf/flags.md3"
- set g_ctf_flag_blue_skin 1
- set g_ctf_flag_glowtrails 0
- set g_ctf_flag_pickup_effects 1
- set g_ctf_flag_capture_effects 1
- set g_ctf_captimerecord_always 0 "if enabled, assisted CTF records (with other players on the server) are recorded too"
- // runematch
- set g_runematch                                               0 "Runematch: pick up and hold the runes, special items that give you points, a special power (rune) and a disadvantage (curse)"
- set g_runematch_pointrate                             5
- set g_runematch_fixedspawns                           1 "use fixed runematch spawns if available"
- set g_runematch_pointamt                                      1
- set g_runematch_shuffletime                           30 "how often runes change position"
- set g_runematch_respawntime                           15 "how soon after being dropped to respawn"
- set g_runematch_frags_killedby_runeholder             4
- set g_runematch_frags_killed_runeholder                       5
- set g_runematch_frags_norune                          0
- set g_runematch_drop_runes_max                                2 "only drop up to 2 runes, the rest should respawn"
- set g_runematch_allow_same                            0 "allow matching rune-curse pairs"
- set g_runematch_rune_alpha                            0.78
- set g_runematch_rune_effects                          544 "EF_ADDITIVE + EF_FULLBRIGHT = 544"
- set g_runematch_rune_glow_size                                0
- set g_runematch_rune_glow_color                               0
- set g_runematch_rune_color_strength                   1.0
- // strength/weakness
- set g_balance_rune_strength_damage                    2.0
- set g_balance_rune_strength_force                     1.5
- set g_balance_curse_weak_damage                               0.5
- set g_balance_curse_weak_force                                0.6
- set g_balance_rune_strength_combo_damage      0.9
- set g_balance_rune_strength_combo_force                       1.0
- // defense/vulner
- set g_balance_rune_defense_takedamage                 0.5
- set g_balance_curse_vulner_takedamage                 2.0
- set g_balance_rune_defense_combo_takedamage           1.0
- // vampire/empathy
- set g_balance_rune_vampire_absorb                     0.4
- set g_balance_curse_empathy_takedamage                        -0.4
- set g_balance_rune_vampire_combo_absorb                       -0.1
- set g_balance_rune_vampire_maxhealth                  500
- set g_balance_curse_empathy_minhealth                 20
- set g_balance_rune_vampire_combo_minhealth            40
- // regen/venom
- set g_balance_rune_regen_hpmod                                1.75
- set g_balance_curse_venom_hpmod                               0.6
- set g_balance_rune_regen_combo_hpmod                  0.9
- set g_balance_rune_regen_regenrate                    3.0
- set g_balance_curse_venom_rotrate                     3.0
- set g_balance_rune_regen_combo_regenrate      0.5
- set g_balance_rune_regen_combo_rotrate                        1.5
- set g_balance_rune_regen_limitmod                     1
- set g_balance_curse_venom_limitmod                    1
- set g_balance_rune_regen_combo_limitmod                       1
- // speed/slow
- set g_balance_rune_speed_atkrate                              0.66
- set g_balance_curse_slow_atkrate                              1.5
- set g_balance_rune_speed_combo_atkrate                        1.2
- set g_balance_rune_speed_highspeed                    1.5
- set g_balance_curse_slow_highspeed                    0.6
- set g_balance_rune_speed_combo_highspeed                      0.9
- // domination
- set g_domination                      0 "Domination: capture and hold control points to gain points"
- set g_domination_default_teams                2 "default number of teams for maps that aren't domination-specific"
- seta g_domination_teams_override              0 "use a specific number of teams in domination games (minimum 2), disables dom_team entities"
- set g_domination_disable_frags                0 "players can't get frags normally, only get points from kills"
- set g_domination_point_amt            0 "override: how many points to get per ping"
- set g_domination_point_fullbright     0 "domination point fullbright"
- set g_domination_point_rate           0 "override: how often to give those points"
- set g_domination_point_capturetime    0.1 "how long it takes to capture a point (given no interference)"
- set g_domination_point_glow           0 "domination point glow (warning, slow)"
- //set g_domination_balance_team_points        1 "# of points received is based on team sizes"
- // last man standing
- set g_lms 0 "Last Man Standing: everyone starts with a certain amount of lives, and the survivor wins"
- set g_lms_lives_override -1
- set g_lms_regenerate 0
- set g_lms_campcheck_interval 10
- set g_lms_campcheck_message "^1Don't camp!"
- set g_lms_campcheck_damage 100
- set g_lms_campcheck_distance 1800
- set g_lms_last_join 3 "if g_lms_join_anytime is false, new players can only join if the worst active player has more than (fraglimit - g_lms_last_join) lives"
- set g_lms_join_anytime 1      "if true, new players can join, but get same amount of lives as the worst player"
- // arena
- set g_arena 0 "Arena: many one-on-one rounds are played to find the winner"
- 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"
- // ca
- set g_ca 0 "Clan Arena: Played in rounds, once you're dead you're out! The team with survivors wins the round."
- set g_ca_point_limit 10 "point limit 10 is standard for clan arena"
- set g_ca_point_leadlimit 0
- set g_ca_spectate_enemies 0 "Allow spectating enemy player by dead player during clan arena games."
- set g_ca_warmup 10 "how long the players will have time to run around the map before the round starts"
- // onslaught
- set g_onslaught 0 "Onslaught: take control points towards the enemy generator and then destroy it"
- set g_onslaught_gen_health 2500
- set g_onslaught_cp_health 1000
- set g_onslaught_cp_buildhealth 100
- set g_onslaught_cp_buildtime 5
- set g_onslaught_cp_regen 20
- // assault
- set g_assault 0 "Assault: attack the enemy base as fast as you can, then defend the base against the enemy for that time to win"
- // race
- set g_race 0 "Race: be faster than your opponents"
- set g_race_qualifying_timelimit 0
- set g_race_qualifying_timelimit_override -1
- set g_race_teams 0    "when 2, 3, or 4, the race is played as a team game (the team members can add up their laps)"
- // cts
- set g_cts 0 "CTS: complete the stage"
- // nexball
- set g_nexball 0 "Nexball: Basketball and Soccer go Xonotic"
- set g_nexball_basketball_effects_default     8    "default: dim light. The original version used 1024 (fire) but it gives bad performance"
- set g_balance_nexball_primary_speed       1000    "launching speed"
- set g_balance_nexball_primary_refire         0.7  "launching refire"
- set g_balance_nexball_primary_animtime       0.3  "launching animtime"
- set g_balance_nexball_secondary_animtime     0.3  "launching animtime"
- set g_balance_nexball_secondary_speed     3000    "stealing projectile speed"
- set g_balance_nexball_secondary_lifetime     0.15 "stealing projectile lifetime"
- set g_balance_nexball_secondary_force      500    "stealing projectile force"
- set g_balance_nexball_secondary_refire       0.6  "stealing projectile refire"
- set g_balance_nexball_secondary_animtime     0.3  "stealing projectile animtime"
- // -1: MrBougo's first try, not very playable but working...
- //     The ball gets the player's velocity * 1.5 + a vertical boost
- //  0: Revenant style
- //     Player's velocity + a boost where he's looking at + a boost
- //     perpendicularly to the first boost, that is upwards relatively
- //     to the view angle
- //  1: MrBougo's modded Rev style 1
- //     The 2nd Rev boost is always vertical
- //  2: MrBougo's modded Rev style 2
- //     The 1st Rev boost is always horizontal
- //     The 2nd Rev boost is always vertical
- set g_nexball_football_physics  2  "0: Revenant's original movement, 1: 0 but half independant of aiming height, 2: 1 fully independant, -1: first recode try"
- set g_nexball_basketball_bouncefactor 0.6    "velocity loss when the ball bounces"
- set g_nexball_basketball_bouncestop   0.075  "speed at which the ball stops when it hits the ground (multiplied by sv_gravity)"
- set g_nexball_football_bouncefactor   0.6    "velocity loss when the ball bounces"
- set g_nexball_football_bouncestop     0.075  "speed at which the ball stops when it hits the ground (multiplied by sv_gravity)"
- set g_nexball_football_boost_forward      100   "forward velocity boost when the ball is touched"
- set g_nexball_football_boost_up           200   "vertical velocity boost when the ball is touched"
- set g_nexball_basketball_delay_hold           20    "time before a player who caught the ball loses it (anti-ballcamp)"
- set g_nexball_basketball_delay_hold_forteam   60    "time before a ball reset when a team holds the ball for too long"
- set g_nexball_basketball_teamsteal             1    "1 to allow players to steal from teammates, 0 to disallow"
- set g_nexball_basketball_carrier_highspeed         0.8  "speed multiplier for the ballcarrier"
- set g_nexball_meter_period                  1    "time to make a full cycle on the power meter"
- set g_nexball_basketball_meter              1    "use the power meter for basketball"
- set g_nexball_basketball_meter_minpower   0.5    "minimal multiplier to the launching speed when using the power meter"
- set g_nexball_basketball_meter_maxpower   1.2    "maximal multiplier to the launching speed when using the power meter"
- set g_nexball_delay_goal     3    "delay between a goal and a ball reset"
- set g_nexball_delay_idle     10   "maximal idle time before a reset"
- set g_nexball_delay_start    3    "time the ball stands on its spawn before being released"
- set g_nexball_delay_collect  0.5  "time before the same player can catch the ball he launched"
- set g_nexball_sound_bounce   1    "bouncing sound (0: off)"
- set g_nexball_basketball_trail  1  "1 to leave a trail"
- set g_nexball_football_trail    0  "1 to leave a trail"
- set g_nexball_trail_color     254  "1-256 for different colors (Quake palette, 254 is white)"
- set g_nexball_radar_showallplayers 1  "1: show every player and the ball on the radar  0: only show teammates and the ball on the radar"
  set g_bloodloss 0   "amount of health below which blood loss occurs"
  
  set g_footsteps 1     "serverside footstep sounds"
@@@ -871,7 -576,6 +576,6 @@@ sv_sound_watersplash "
  seta cl_announcer default "name of the announcer you wish to use from data/sound/announcer"
  seta cl_announcer_antispam 2 "number of seconds before an announcement of the same sound can be played again"
  seta cl_announcer_maptime 3 "play announcer sound telling you the remaining maptime - 0: do not play at all, 1: play at one minute, 2: play at five minutes, 3: play both"
- seta cl_notify_carried_items "3" "notify you of carried items when you obtain them (e.g. flags in CTF) - 0: disabled, 1: notify of taken items, 2: notify of picking up dropped items, 3: notify of both"
  
  // startmap_dm is used when running with the -listen or -dedicated commandline options
  set serverconfig server.cfg
@@@ -1141,7 -845,6 +845,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_itemstime 2 "show waypoints to indicate that some important items (mega health, large armor) are about to respawn: 1 when spectating, 2 even playing in warmup stage"
  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"
@@@ -1159,53 -862,9 +863,9 @@@ alias "g_waypointsprite_toggle"  "toggl
  // key for that?
  seta cl_hidewaypoints 0 "disable static waypoints, only show team waypoints"
  
- seta g_waypointsprites_turrets 1 "disable turret waypoints"
- seta g_waypointsprites_turrets_maxdist 4000 "max distace for turret sprites"
- // key hunt
- set g_keyhunt 0 "Key Hunt: collect all keys from the enemies and bring them together to score"
- set g_balance_keyhunt_delay_return 60
- set g_balance_keyhunt_delay_round 5
- set g_balance_keyhunt_delay_tracking 10
- set g_balance_keyhunt_delay_fadeout 2
- set g_balance_keyhunt_delay_collect 1.5
- set g_balance_keyhunt_maxdist 150
- set g_balance_keyhunt_score_collect 3
- set g_balance_keyhunt_score_carrierfrag 2
- set g_balance_keyhunt_score_capture 100
- set g_balance_keyhunt_score_push 60
- set g_balance_keyhunt_score_destroyed 50
- set g_balance_keyhunt_score_destroyed_ownfactor 1
- set g_balance_keyhunt_dropvelocity 300
- set g_balance_keyhunt_throwvelocity 400
- set g_balance_keyhunt_protecttime 0.8
- set g_balance_keyhunt_damageforcescale 1
- seta g_keyhunt_teams_override 0
- set g_keyhunt_teams 0
- // keepaway
- set g_keepaway 0 "game mode which focuses around a ball, look at g_keepaway_win_mode for further details"
- set g_keepaway_score_bckill 1 "enable scoring points (y/n) for ball carrier kills (value is how many points to award)"
- set g_keepaway_score_killac 1 "amount of points to give when you kill someone while you have the ball"
- set g_keepaway_score_timeinterval 1 "amount of time it takes between intervals for timepoints to be added to the score"
- set g_keepaway_score_timepoints 0 "points to add to score per timeinterval, 0 for no points"
- set g_keepaway_ballcarrier_effects 8 "Add together the numbers you want: EF_ADDITIVE (32) / EF_NODEPTHTEST (8192) / EF_DIMLIGHT (8)"
- set g_keepaway_ballcarrier_highspeed 1 "speed multiplier done to the person holding the ball (recommended when used with some mutators)"
- set g_keepaway_ballcarrier_damage     1       "damage multiplier while holding the ball"
- set g_keepaway_ballcarrier_force      1       "force multiplier while holding the ball"
- set g_keepaway_ballcarrier_selfdamage 1       "self damage multiplier while holding the ball"
- set g_keepaway_ballcarrier_selfforce  1       "self force multiplier while holding the ball"
- set g_keepaway_noncarrier_warn        1       "warn players when they kill without holding the ball"
- set g_keepaway_noncarrier_damage      1       "damage done to other players if both you and they don't have the ball"
- set g_keepaway_noncarrier_force       1       "force done to other players if both you and they don't have the ball"
- set g_keepaway_noncarrier_selfdamage  1       "self damage if you don't have the ball"
- set g_keepaway_noncarrier_selfforce   1       "self force if you don't have the ball"
- set g_keepawayball_effects 0 "Add together the numbers you want: EF_ADDITIVE (32) / EF_NODEPTHTEST (8192) / EF_DIMLIGHT (8)"
- set g_keepawayball_trail_color        254     "particle trail color from player/ball"
- set g_keepawayball_damageforcescale   3 "Scale of force which is applied to the ball by weapons/explosions/etc"
- set g_keepawayball_respawntime        10      "if no one picks up the ball, how long to wait until the ball respawns"
- seta g_keepaway_teams_override 0
- set g_keepaway_teams 0
+ seta g_waypointsprite_turrets 1 "disable turret waypoints"
+ seta g_waypointsprite_turrets_maxdist 5000 "max distace for turret sprites"
+ seta g_waypointsprite_tactical 1 "tactical overlay on turrets when in a vehicle"
  
  // so it can be stuffcmd-ed still
  set cl_gravity 800    "but ignored anyway"
@@@ -1429,9 -1088,6 +1089,6 @@@ set sv_maxidle 
  // when sv_maxidle is not 0, assume spectators are idle too
  set sv_maxidle_spectatorsareidle 0
  
- // CTF capture limit placeholder cvar
- set capturelimit 0
  // these entities are not referenced by anything directly, they just represent
  // teams and are found by find() when needed
  prvm_leaktest_ignore_classnames "ctf_team dom_team tdm_team"
@@@ -1597,52 -1253,6 +1254,6 @@@ seta cl_modeldetailreduction 1 "the hig
  
  set g_mapinfo_settemp_acl "+*" "ACL for mapinfo setting cvars"
  
- // hooks
- alias _cl_hook_gamestart "set _cl_hook_gametype $1; _cl_hook_gamestart_stage2"
- alias _cl_hook_gamestart_stage2 "cl_hook_gamestart_all; cl_hook_gamestart_${_cl_hook_gametype}"
- alias cl_hook_gamestart_all
- alias cl_hook_gamestart_nop  //is only called when CSQC unloads before knowing the gametype, very unlikely
- alias cl_hook_gamestart_dm
- alias cl_hook_gamestart_tdm
- alias cl_hook_gamestart_dom
- alias cl_hook_gamestart_ctf
- alias cl_hook_gamestart_rune
- alias cl_hook_gamestart_lms
- alias cl_hook_gamestart_arena
- alias cl_hook_gamestart_ca
- alias cl_hook_gamestart_kh
- alias cl_hook_gamestart_ons
- alias cl_hook_gamestart_as
- alias cl_hook_gamestart_rc
- alias cl_hook_gamestart_nb
- alias cl_hook_gamestart_cts
- alias cl_hook_gamestart_ka
- alias cl_hook_gamestart_ft
- alias cl_hook_gameend
- alias cl_hook_activeweapon
- alias _sv_hook_gamestart "set _sv_hook_gametype $1; _sv_hook_gamestart_stage2"
- alias _sv_hook_gamestart_stage2 "sv_hook_gamestart_all; sv_hook_gamestart_${_sv_hook_gametype}"
- alias sv_hook_gamestart_all
- alias sv_hook_gamestart_dm
- alias sv_hook_gamestart_tdm
- alias sv_hook_gamestart_dom
- alias sv_hook_gamestart_ctf
- alias sv_hook_gamestart_rune
- alias sv_hook_gamestart_lms
- alias sv_hook_gamestart_arena
- alias sv_hook_gamestart_ca
- alias sv_hook_gamestart_kh
- alias sv_hook_gamestart_ons
- alias sv_hook_gamestart_as
- alias sv_hook_gamestart_rc
- alias sv_hook_gamestart_nb
- alias sv_hook_gamestart_cts
- alias sv_hook_gamestart_ka
- alias sv_hook_gamestart_ft
- alias sv_hook_gamerestart
- alias sv_hook_gameend
  seta cl_casings_maxcount 100 "maximum amount of shell casings (must be at least 1)"
  seta cl_gibs_maxcount 100 "maximum amount of gibs (must be at least 1)"
  seta cl_vehicle_spiderbot_cross_alpha 0.6
@@@ -1697,14 -1307,14 +1308,14 @@@ set loddebug 0 "force this LOD level
  set spawn_debugview 0 "display spawnpoints and their rating on spawn to debug spawnpoint rating calculation"
  set g_mutatormsg "" "mutator message"
  set speedmeter 0 "print landing speeds"
- set developer_shtest 0 "experimental speedhack detection"
+ set developer_csqcentities 0 "csqc entity spam"
  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_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"
  seta cl_forceplayermodels 0 "make everyone look like your own model (requires server to have sv_use_csqc_players 1 and sv_defaultcharacter 0)"
- seta cl_forceplayercolors 0 "make everyone look like your own color (requires server to have sv_use_csqc_players 1 and sv_defaultcharacter 0, and is ignored in teamplay)"
+ seta cl_forceplayercolors 0 "make everyone look like your own color (requires server to have sv_use_csqc_players 1 and sv_defaultcharacter 0, and is ignored in teamplay with more than two teams)"
  seta cl_forcemyplayermodel "" "set to the model file name you want to show yourself as (requires server to have sv_use_csqc_players 1; does not affect how enemies look with cl_forceplayermodels)"
  seta cl_forcemyplayerskin 0 "set to the skin number you want to show yourself as (requires server to have sv_use_csqc_players 1; does not affect how enemies look with cl_forceplayermodels)"
  seta cl_forcemyplayercolors 0 "set to the color value (encoding is same as _cl_color) for your own player model (requires server to have sv_use_csqc_players 1, and is ignored in teamplay; does not affect how enemies look with cl_forceplayermodels)"
@@@ -1882,8 -1492,7 +1493,7 @@@ set g_weapon_charge_colormod_green_ful
  set g_weapon_charge_colormod_blue_full -1
  
  // player statistics server URI
- set g_playerstats_uri ""
- set g_playerstats_debug 0 "when 1, player stats are dumped to the console too"
+ set g_playerstats_uri "" "Output player statistics information to either: URL (with ://), console (with a dash like this: -), or supply a filename to output to data directory."
  
  // autoscreenshots
  set g_max_info_autoscreenshot 3 "how many info_autoscreenshot entities are allowed"
@@@ -1929,12 -1538,12 +1539,12 @@@ scr_loadingscreen_scale_limit 
  // other config files
  exec mutator_new_toys.cfg // run BEFORE balance to make sure balance wins
  exec balanceXonotic.cfg
- exec ctfscoring-ai.cfg
  exec effects-normal.cfg
  exec physicsX.cfg
  exec turrets.cfg
  exec vehicles.cfg
  exec crosshairs.cfg
+ exec gamemodes.cfg
  
  // load console command aliases and settings
  exec commands.cfg
@@@ -1963,6 -1572,9 +1573,9 @@@ set cl_ghost_items 0.45 "enable ghoste
  set cl_ghost_items_color "-1 -1 -1" "color of ghosted items, 0 0 0 leaves the color unchanged"
  set sv_simple_items 1 "allow or forbid client use of simple items"
  set cl_simple_items 0 "enable simple items (if server allows)"
+ set cl_simpleitems_postfix "_simple" "posfix to add fo model name when simple items are enabled"
  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"
+ seta g_superspectate 0 "server side, allows extended spectator functions through the cmd interface. followpowerup, followstrength, followstshield or followfc [red|blue] will transfer spectation to the relevent player, if any"
index d7055f25f7ba1978945f8d4943365b8d2f8c8be6,0d4513f92b802a351f83883eecd5ed8e430d1d2f..6214e82b4ac43b8f4ac399e8f8dde10272f5d54d
@@@ -54,7 -54,6 +54,6 @@@ float autocvar_cl_gunalign
  float autocvar_cl_hidewaypoints;
  float autocvar_cl_lockview;
  float autocvar_cl_nogibs;
- float autocvar_cl_notify_carried_items;
  float autocvar_cl_particlegibs;
  float autocvar_cl_particles_oldnexbeam;
  float autocvar_cl_particles_quality;
@@@ -97,6 -96,7 +96,7 @@@ float autocvar_crosshair_effect_speed
  var float autocvar_crosshair_enabled = 1;
  float autocvar_crosshair_hitindication;
  string autocvar_crosshair_hitindication_color;
+ string autocvar_crosshair_hitindication_per_weapon_color;
  float autocvar_crosshair_hitindication_speed;
  float autocvar_crosshair_hittest;
  float autocvar_crosshair_hittest_blur;
@@@ -148,15 -148,14 +148,15 @@@ 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_itemstime;
  float autocvar_g_waypointsprite_minalpha;
  float autocvar_g_waypointsprite_minscale;
  float autocvar_g_waypointsprite_normdistance;
  float autocvar_g_waypointsprite_scale;
  float autocvar_g_waypointsprite_spam;
  float autocvar_g_waypointsprite_timealphaexponent;
//float autocvar_g_waypointsprites_turrets;
//float autocvar_g_waypointsprites_turrets_maxdist;
var float autocvar_g_waypointsprite_turrets = TRUE;
var float autocvar_g_waypointsprite_turrets_maxdist = 5000;
  
  float autocvar_hud_colorflash_alpha;
  float autocvar_hud_configure_checkcollisions;
@@@ -245,16 -244,6 +245,16 @@@ 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_size_dinamic;
 +float autocvar_hud_panel_itemstime_ratio;
 +float autocvar_hud_panel_itemstime_iconalign;
 +float autocvar_hud_panel_itemstime_progressbar;
 +float autocvar_hud_panel_itemstime_progressbar_maxtime;
 +string autocvar_hud_panel_itemstime_progressbar_name;
 +float autocvar_hud_panel_itemstime_progressbar_reduced;
 +float autocvar_hud_panel_itemstime_showspawned;
 +float autocvar_hud_panel_itemstime_text;
  float autocvar_hud_panel_modicons;
  float autocvar_hud_panel_modicons_dom_layout;
  float autocvar_hud_panel_notify;
@@@ -407,7 -396,9 +407,9 @@@ float autocvar_cl_forceplayercolors
  string autocvar_cl_forcemyplayermodel;
  float autocvar_cl_forcemyplayerskin;
  float autocvar_cl_forcemyplayercolors;
+ float autocvar__cl_color;
  float autocvar__cl_playerskin;
  string autocvar__cl_playermodel;
  float autocvar_cl_precacheplayermodels;
  float autocvar_cl_deathglow;
+ float autocvar_developer_csqcentities;
diff --combined qcsrc/client/hud.qc
index e610c5b7dbabc0811f8a4bde86ecc281a777b479,2e3607ff4ffd37baab05b269befe4af27de28418..77022635cdb245c5bac229de144cc5b300c4cc29
@@@ -476,6 -476,8 +476,8 @@@ void HUD_Weapons(void
        HUD_Panel_UpdateCvars(weapons);
        HUD_Panel_ApplyFadeAlpha();
  
+       draw_beginBoldFont();
        // calculate fading effect to weapon images for when the panel is idle
        if(autocvar_hud_panel_weapons_fade)
        {
                        ++column;
                }
        }
+       draw_endBoldFont();
  }
  
  // Ammo (#1)
@@@ -908,6 -912,9 +912,9 @@@ void HUD_Ammo(void
  
        HUD_Panel_UpdateCvars(ammo);
        HUD_Panel_ApplyFadeAlpha();
+       draw_beginBoldFont();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
                if(autocvar__hud_configure)
                {
                        DrawAmmoItem(pos, ammo_size, 2, true, FALSE); //show rockets
-                       return;
                }
+               else
+               {
+                       stat_items = getstati(STAT_ITEMS, 0, 24);
+                       if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
+                               infinite_ammo = TRUE;
+                       for (i = 0; i < AMMO_COUNT; ++i) {
+                               currently_selected = stat_items & GetAmmoItemCode(i);
+                               if (currently_selected)
+                               {
+                                       DrawAmmoItem(pos, ammo_size, i, true, infinite_ammo);
+                                       break;
+                               }
+                       }
+               }
+       }
+       else
+       {
                stat_items = getstati(STAT_ITEMS, 0, 24);
                if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
                        infinite_ammo = TRUE;
                for (i = 0; i < AMMO_COUNT; ++i) {
                        currently_selected = stat_items & GetAmmoItemCode(i);
-                       if (currently_selected)
+                       DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected, infinite_ammo);
+                       ++row;
+                       if(row >= rows)
                        {
-                               DrawAmmoItem(pos, ammo_size, i, true, infinite_ammo);
-                               return;
+                               row = 0;
+                               column = column + 1;
                        }
                }
-               return; // nothing to display
        }
  
-       stat_items = getstati(STAT_ITEMS, 0, 24);
-       if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
-               infinite_ammo = TRUE;
-       for (i = 0; i < AMMO_COUNT; ++i) {
-               currently_selected = stat_items & GetAmmoItemCode(i);
-               DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected, infinite_ammo);
-               ++row;
-               if(row >= rows)
-               {
-                       row = 0;
-                       column = column + 1;
-               }
-       }
+       draw_endBoldFont();
  }
  
  void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, float vertical, float icon_right_align, vector color, float theAlpha, float fadelerp)
@@@ -1107,6 -1119,9 +1119,9 @@@ void HUD_Powerups(void
  
        HUD_Panel_UpdateCvars(powerups);
        HUD_Panel_ApplyFadeAlpha();
+       draw_beginBoldFont();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
                                DrawNumIcon_expanding(pos + superweapons_offset, mySize, superweapons, "superweapons", is_vertical, superweapons_iconalign, '1 1 1', 1, bound(0, (superweapons - superweapons_time) / 0.5, 1));
                }
        }
+       draw_endBoldFont();
  }
  
  // Health/armor (#3)
@@@ -2440,6 -2457,9 +2457,9 @@@ void HUD_Timer(void
  
        HUD_Panel_UpdateCvars(timer);
        HUD_Panel_ApplyFadeAlpha();
+       draw_beginBoldFont();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
        }
  
        drawstring_aspect(pos, timer, mySize, timer_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+       draw_endBoldFont();
  }
  
  // Radar (#6)
@@@ -2806,6 -2828,7 +2828,7 @@@ void HUD_Score(void
                score = me.(scores[ps_primary]);
                timer = TIME_ENCODED_TOSTRING(score);
  
+               draw_beginBoldFont();
                if (pl && ((!(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)) || score)) {
                        // distribution display
                        distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]);
                if (distribution <= 0)
                        HUD_Panel_DrawHighlight(pos, eX * 0.75 * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                drawstring_aspect(pos, timer, eX * 0.75 * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               draw_endBoldFont();
        } else if (!teamplay) { // non-teamgames
                if ((spectatee_status == -1 && !autocvar__hud_configure) || autocvar_hud_panel_score_rankings)
                {
  
                string distribution_str;
                distribution_str = ftos(distribution);
+               draw_beginBoldFont();
                if (distribution >= 0)
                {
                        if (distribution > 0)
                }
                drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize_x + eY * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
                drawstring_aspect(pos + eX * 0.75 * mySize_x, distribution_str, eX * 0.25 * mySize_x + eY * (1/3) * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+               draw_endBoldFont();
        } else { // teamgames
                float scores_count, row, column, rows, columns;
                local noref vector offset; // fteqcc sucks
  
                float max_fragcount;
                max_fragcount = -99;
+               draw_beginBoldFont();
                for(tm = teams.sort_next; tm; tm = tm.sort_next) {
                        if(tm.team == COLOR_SPECTATOR)
                                continue;
                                ++rows;
                        }
                }
+               draw_endBoldFont();
        }
  }
  
@@@ -2961,6 -2989,9 +2989,9 @@@ void HUD_RaceTimer (void
  
        HUD_Panel_UpdateCvars(racetimer);
        HUD_Panel_ApplyFadeAlpha();
+       draw_beginBoldFont();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
                        }
                }
        }
+       draw_endBoldFont();
  }
  
  // Vote window (#9)
@@@ -3911,6 -3944,9 +3944,9 @@@ void HUD_ModIcons(void
  
        HUD_Panel_UpdateCvars(modicons);
        HUD_Panel_ApplyFadeAlpha();
+       draw_beginBoldFont();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
                HUD_Mod_Dom(pos, mySize);
        else if(gametype == MAPINFO_TYPE_KEEPAWAY)
                HUD_Mod_Keepaway(pos, mySize);
+       draw_endBoldFont();
  }
  
  // Draw pressed keys (#11)
@@@ -4371,6 -4409,8 +4409,8 @@@ void HUD_Physics(void
        HUD_Panel_UpdateCvars(physics);
        HUD_Panel_ApplyFadeAlpha();
  
+       draw_beginBoldFont();
        HUD_Panel_DrawBg(1);
        if(panel_bg_padding)
        {
        tmp_offset_y = (panel_size_y - tmp_size_y) / 2;
        if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 3)
                drawstring_aspect(panel_pos + acceleration_offset + tmp_offset, strcat(ftos_decimals(acceleration, 2), "g"), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       draw_endBoldFont();
  }
  
  // CenterPrint (#16)
@@@ -4923,217 -4965,6 +4965,217 @@@ void HUD_CenterPrint (void
        }
  }
  
 +
 +// ItemsTime (#17)
 +//
 +const float ITEMSTIME_MAXITEMS = 10;
 +float ItemsTime_time[ITEMSTIME_MAXITEMS];
 +string GetItemsTimePicture(float i)
 +{
 +      switch(i)
 +      {
 +              case 0: return "item_large_armor";
 +              case 1: return "item_mega_health";
 +              case 2: return "item_strength";
 +              case 3: return "item_shield";
 +              case 4: return "item_mega_health";
 +              case 5: return "item_strength";
 +              case 6: return "item_shield";
 +              case 7: return "fuelregen";
 +              case 8: return "jetpack";
 +              case 9: return "superweapons";
 +              default: return "";
 +      }
 +}
 +
 +void DrawItemsTimeItem(vector myPos, vector mySize, float ar, float itemcode)
 +{
 +      float t;
 +      vector color;
 +      float picalpha;
 +      if(ItemsTime_time[itemcode] <= time)
 +      {
 +              float BLINK_FACTOR = 0.15;
 +              float BLINK_BASE = 0.85;
 +              float BLINK_FREQ = 5;
 +              picalpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
 +      }
 +      else
 +      {
 +              picalpha = 1;
 +              t = floor(ItemsTime_time[itemcode] - time + 0.999);
 +              if(t < 5)
 +                      color = '0.7 0 0';
 +              else if(t < 10)
 +                      color = '0.7 0.7 0';
 +              else
 +                      color = '1 1 1';
 +      }
 +
 +      vector picpos, numpos;
 +      if(autocvar_hud_panel_itemstime_iconalign)
 +      {
 +              numpos = myPos;
 +              picpos = myPos + eX * (ar - 1) * mySize_y;
 +      }
 +      else
 +      {
 +              numpos = myPos + eX * mySize_y;
 +              picpos = myPos;
 +      }
 +
 +      if(t > 0 && autocvar_hud_panel_itemstime_progressbar)
 +      {
 +              vector p_pos, p_size;
 +              if(autocvar_hud_panel_itemstime_progressbar_reduced)
 +              {
 +                      p_pos = numpos;
 +                      p_size = eX * ((ar - 1)/ar) * mySize_x + eY * mySize_y;
 +              }
 +              else
 +              {
 +                      p_pos = myPos;
 +                      p_size = mySize;
 +              }
 +              HUD_Panel_DrawProgressBar(p_pos, p_size, autocvar_hud_panel_itemstime_progressbar_name, t/autocvar_hud_panel_itemstime_progressbar_maxtime, 0, autocvar_hud_panel_itemstime_iconalign, color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
 +      }
 +
 +      if(t > 0 && autocvar_hud_panel_itemstime_text)
 +              drawstring_aspect(numpos, ftos(t), eX * ((ar - 1)/ar) * mySize_x + eY * mySize_y, color, panel_fg_alpha, DRAWFLAG_NORMAL);
 +      drawpic_aspect_skin(picpos, GetItemsTimePicture(itemcode), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * picalpha, DRAWFLAG_NORMAL);
 +}
 +
 +void HUD_ItemsTime(void)
 +{
 +      if(!autocvar__hud_configure)
 +      {
 +              if not(autocvar_hud_panel_itemstime == 1 && spectatee_status != 0
 +              || autocvar_hud_panel_itemstime == 2 && (spectatee_status != 0 || warmup_stage))
 +                      return;
 +
 +              ItemsTime_time[0] = getstatf(STAT_ARMOR_LARGE_TIME);
 +              ItemsTime_time[1] = getstatf(STAT_HEALTH_MEGA_TIME);
 +              ItemsTime_time[2] = getstatf(STAT_INVISIBLE_TIME);
 +              ItemsTime_time[3] = getstatf(STAT_SPEED_TIME);
 +              ItemsTime_time[4] = getstatf(STAT_EXTRALIFE_TIME);
 +              ItemsTime_time[5] = getstatf(STAT_STRENGTH_TIME);
 +              ItemsTime_time[6] = getstatf(STAT_SHIELD_TIME);
 +              ItemsTime_time[7] = getstatf(STAT_FUELREGEN_TIME);
 +              ItemsTime_time[8] = getstatf(STAT_JETPACK_TIME);
 +              ItemsTime_time[9] = getstatf(STAT_SUPERWEAPONS_TIME);
 +      }
 +      else
 +      {
 +              hud_configure_active_panel = HUD_PANEL_ITEMSTIME;
 +
 +              // do not show here mutator-dependent items
 +              ItemsTime_time[0] = time + 25;
 +              ItemsTime_time[1] = time + 8;
 +              ItemsTime_time[2] = -1; // mutator-dependent
 +              ItemsTime_time[3] = -1; // mutator-dependent
 +              ItemsTime_time[4] = -1; // mutator-dependent
 +              ItemsTime_time[5] = time + 0;
 +              ItemsTime_time[6] = time + 4;
 +              ItemsTime_time[7] = time + 19;
 +              ItemsTime_time[8] = time + 46;
 +              ItemsTime_time[9] = time + 28;
 +      }
 +
 +      float i;
 +      float count;
 +      if (autocvar_hud_panel_itemstime_showspawned)
 +              for (i = 0; i < ITEMSTIME_MAXITEMS; ++i)
 +                      count += (ItemsTime_time[i] > time || (ItemsTime_time[i] != -1 && ItemsTime_time[i] <= time));
 +      else
 +              for (i = 0; i < ITEMSTIME_MAXITEMS; ++i)
 +                      count += (ItemsTime_time[i] > time);
 +      if (count == 0)
 +              return;
 +
 +      HUD_Panel_UpdateCvars(itemstime);
 +      HUD_Panel_ApplyFadeAlpha();
 +      vector pos, mySize;
 +      pos = panel_pos;
 +      mySize = panel_size;
 +
 +      if(panel_bg_padding)
 +      {
 +              pos += '1 1 0' * panel_bg_padding;
 +              mySize -= '2 2 0' * panel_bg_padding;
 +      }
 +
 +      float rows, columns, row, column;
 +      float ar = max(2, autocvar_hud_panel_itemstime_ratio) + 1;
 +      rows = mySize_y/mySize_x;
 +      rows = bound(1, floor((sqrt(4 * ar * rows * count + rows * rows) + rows + 0.5) / 2), count);
 +
 +      columns = ceil(count/rows);
 +
 +      vector itemstime_size;
 +      itemstime_size = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows);
 +
 +      local noref vector offset; // fteqcc sucks
 +      float newSize;
 +      if(autocvar_hud_panel_itemstime_size_dinamic)
 +      {
 +              if(autocvar__hud_configure)
 +              if(menu_enabled != 2)
 +                      HUD_Panel_DrawBg(1); // also draw the bg of the entire panel
 +
 +              // reduce panel to avoid spacing items
 +              if(itemstime_size_x / itemstime_size_y < ar)
 +              {
 +                      newSize = rows * itemstime_size_x / ar;
 +                      pos_y += (mySize_y - newSize) / 2;
 +                      mySize_y = newSize;
 +                      itemstime_size_y = mySize_y / rows;
 +              }
 +              else
 +              {
 +                      newSize = columns * itemstime_size_y * ar;
 +                      pos_x += (mySize_x - newSize) / 2;
 +                      mySize_x = newSize;
 +                      itemstime_size_x = mySize_x / columns;
 +              }
 +              panel_pos = pos - '1 1 0' * panel_bg_padding;
 +              panel_size = mySize + '2 2 0' * panel_bg_padding;
 +      }
 +      else
 +      {
 +              if(itemstime_size_x/itemstime_size_y > ar)
 +              {
 +                      newSize = ar * itemstime_size_y;
 +                      offset_x = itemstime_size_x - newSize;
 +                      pos_x += offset_x/2;
 +                      itemstime_size_x = newSize;
 +              }
 +              else
 +              {
 +                      newSize = 1/ar * itemstime_size_x;
 +                      offset_y = itemstime_size_y - newSize;
 +                      pos_y += offset_y/2;
 +                      itemstime_size_y = newSize;
 +              }
 +      }
 +
 +      HUD_Panel_DrawBg(1);
 +
 +      for (i = 0; i < ITEMSTIME_MAXITEMS; ++i) {
 +              if (ItemsTime_time[i] == -1)
 +                      continue;
 +              if (!autocvar_hud_panel_itemstime_showspawned)
 +                      if (ItemsTime_time[i] <= time)
 +                              continue;
 +              DrawItemsTimeItem(pos + eX * column * (itemstime_size_x + offset_x) + eY * row * (itemstime_size_y + offset_y), itemstime_size, ar, i);
 +              ++row;
 +              if(row >= rows)
 +              {
 +                      row = 0;
 +                      column = column + 1;
 +              }
 +      }
 +}
 +
  /*
  ==================
  Main HUD system
@@@ -5185,8 -5016,6 +5227,8 @@@ switch (id) {
                HUD_Physics(); break;\
        case (HUD_PANEL_CENTERPRINT):\
                HUD_CenterPrint(); break;\
 +      case (HUD_PANEL_ITEMSTIME):\
 +              HUD_ItemsTime(); break;\
  } ENDS_WITH_CURLY_BRACE
  
  void HUD_Main (void)
index c923aafb06cc9e917c6063adcd770b14a3e55864,d3d57aba9e8cbcd52ad7606466f912dc394032a9..07fe7c24e07e12589650329c5d7bb8f06941442b
@@@ -212,8 -212,6 +212,8 @@@ float spritelookupblinkvalue(string s
                case "ons-cp-atck-blue": return 2;
                case "ons-cp-dfnd-red":  return 0.5;
                case "ons-cp-dfnd-blue": return 0.5;
 +              case "item_health_mega": return 2;
 +              case "item_armor_large": return 2;
                case "item-invis":       return 2;
                case "item-extralife":   return 2;
                case "item-speed":       return 2;
                case "item-shield":      return 2;
                case "item-fuelregen":   return 2;
                case "item-jetpack":     return 2;
 +              case "wpn-fireball":     return 2; // superweapon
 +              case "wpn-minstanex":    return 2; // superweapon
 +              case "wpn-porto":        return 2; // superweapon
                case "tagged-target":    return 2;
                default:                 return 1;
        }
@@@ -261,6 -256,7 +261,7 @@@ string spritelookuptext(string s
                case "as-defend": return _("Defend");
                case "bluebase": return _("Blue base");
                case "danger": return _("DANGER");
+               case "enemyflagcarrier": return _("Enemy carrier");
                case "flagcarrier": return _("Flag carrier");
                case "flagdropped": return _("Dropped flag");
                case "helpme": return _("Help me!");
                case "dom-blue": return _("Control point");
                case "dom-yellow": return _("Control point");
                case "dom-pink": return _("Control point");
 +              case "item_health_mega": return _("Mega health");
 +              case "item_armor_large": return _("Large armor");
                case "item-invis": return _("Invisibility");
                case "item-extralife": return _("Extra life");
                case "item-speed": return _("Speed");
                case "item-strength": return _("Strength");
                case "item-shield": return _("Shield");
 -              case "item-fuelregen": return _("Fuel regen");
 -              case "item-jetpack": return _("Jet Pack");
 +              case "item-fuelregen": return _("Fuel regenerator");
 +              case "item-jetpack": return _("Jet pack");
                case "freezetag_frozen": return _("Frozen!");
                case "tagged-target": return _("Tagged");
                case "vehicle": return _("Vehicle");
@@@ -417,12 -411,6 +418,12 @@@ void Draw_WaypointSprite(
        // choose the sprite
        switch(self.rule)
        {
 +              case SPRITERULE_SPECTATOR:
 +                      if not(autocvar_g_waypointsprite_itemstime == 1 && t == COLOR_SPECTATOR + 1
 +                      || autocvar_g_waypointsprite_itemstime == 2 && (t == COLOR_SPECTATOR + 1 || warmup_stage))
 +                              return;
 +                      spriteimage = self.netname;
 +                      break;
                case SPRITERULE_DEFAULT:
                        if(self.team)
                        {
        if(autocvar_g_waypointsprite_uppercase)
                txt = strtoupper(txt);
  
+       draw_beginBoldFont();
        if(self.health >= 0)
        {
                o = drawspritetext(o, ang, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
        {
                o = drawspritetext(o, ang, 0, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
        }
+       draw_endBoldFont();
  }
  
  void Ent_RemoveWaypointSprite()
index 6d4b7db692c5904ddecbd335f97d2e8e5dfc3235,c270b61a96efa51308b779c733231f2e6284dd47..833216307876f0f25b5f29c71b27fe3d468ed304
@@@ -98,6 -98,7 +98,7 @@@ const float ENT_CLIENT_SHOWNAMES = 31
  const float ENT_CLIENT_WARPZONE_TELEPORTED = 32;
  const float ENT_CLIENT_MODEL = 33;
  const float ENT_CLIENT_ITEM = 34;
+ const float ENT_CLIENT_BUMBLE_RAYGUN = 35;
  
  const float ENT_CLIENT_TURRET = 40;
  const float ENT_CLIENT_AUXILIARYXHAIR = 50;
@@@ -105,7 -106,6 +106,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;
@@@ -168,28 -168,6 +169,6 @@@ const float STAT_HAGAR_LOAD = 57
  const float STAT_SWITCHINGWEAPON = 58;
  const float STAT_SUPERWEAPONS_FINISHED = 59;
  
- // see DP source, quakedef.h
- const float STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222;
- const float STAT_MOVEVARS_AIRSTRAFEACCEL_QW = 223;
- const float STAT_MOVEVARS_MAXSPEED = 244;
- const float STAT_MOVEVARS_AIRACCEL_QW = 254;
- const float CTF_STATE_ATTACK = 1;
- const float CTF_STATE_DEFEND = 2;
- const float CTF_STATE_COMMANDER = 3;
- const float HUD_NORMAL = 0;
- const float HUD_VEHICLE_FIRST   = 10;
- const float HUD_SPIDERBOT       = 10;
- const float HUD_WAKIZASHI       = 11;
- const float HUD_RAPTOR          = 12;
- const float HUD_BUMBLEBEE       = 13;
- const float HUD_VEHICLE_LAST    = 13;
- const vector eX = '1 0 0';
- const vector eY = '0 1 0';
- const vector eZ = '0 0 1';
  const float STAT_VEHICLESTAT_HEALTH  = 60;
  const float STAT_VEHICLESTAT_SHIELD  = 61;
  const float STAT_VEHICLESTAT_ENERGY  = 62;
@@@ -201,17 -179,6 +180,17 @@@ 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_INVISIBLE_TIME = 82;
 +const float STAT_SPEED_TIME = 83;
 +const float STAT_EXTRALIFE_TIME = 84;
 +const float STAT_STRENGTH_TIME = 85;
 +const float STAT_SHIELD_TIME = 86;
 +const float STAT_FUELREGEN_TIME = 87;
 +const float STAT_JETPACK_TIME = 88;
 +const float STAT_SUPERWEAPONS_TIME = 89;
 +
  // mod stats (1xx)
  const float STAT_REDALIVE = 100;
  const float STAT_BLUEALIVE = 101;
@@@ -222,7 -189,7 +201,7 @@@ const float STAT_PINKALIVE = 103
  const float STAT_FROZEN = 104;
  const float STAT_REVIVE_PROGRESS = 105;
  
+ // domination
  const float STAT_DOM_TOTAL_PPS = 100;
  const float STAT_DOM_PPS_RED = 101;
  const float STAT_DOM_PPS_BLUE = 102;
@@@ -232,6 -199,29 +211,29 @@@ const float STAT_DOM_PPS_YELLOW = 104
  //const float STAT_SPIDERBOT_AIM     53 // compressShotOrigin
  //const float STAT_SPIDERBOT_TARGET  54 // compressShotOrigin
  
+ // see DP source, quakedef.h
+ const float STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222;
+ const float STAT_MOVEVARS_AIRSTRAFEACCEL_QW = 223;
+ const float STAT_MOVEVARS_MAXSPEED = 244;
+ const float STAT_MOVEVARS_AIRACCEL_QW = 254;
+ const float CTF_STATE_ATTACK = 1;
+ const float CTF_STATE_DEFEND = 2;
+ const float CTF_STATE_COMMANDER = 3;
+ const float HUD_NORMAL = 0;
+ const float HUD_VEHICLE_FIRST   = 10;
+ const float HUD_SPIDERBOT       = 10;
+ const float HUD_WAKIZASHI       = 11;
+ const float HUD_RAPTOR          = 12;
+ const float HUD_BUMBLEBEE       = 13;
+ const float HUD_BUMBLEBEE_GUN   = 14;
+ const float HUD_VEHICLE_LAST    = 14;
+ const vector eX = '1 0 0';
+ const vector eY = '0 1 0';
+ const vector eZ = '0 0 1';
  // moved that here so the client knows the max.
  // # of maps, I'll use arrays for them :P
  #define MAPVOTE_COUNT 10
@@@ -554,8 -544,7 +556,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";
@@@ -574,7 -563,6 +576,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";
  
  #define SERVERFLAG_ALLOW_FULLBRIGHT 1
  #define SERVERFLAG_TEAMPLAY 2
diff --combined qcsrc/common/util.qh
index 8bc78fcdc7635cfe4703523c0b49f872fe36fcec,faa605f887598c0dba17c7a6d5ae99654eb8e409..81d5dae2148e645a4acf35de8152fb3fa7616c03
@@@ -1,12 -1,13 +1,13 @@@
  // a dummy macro that prevents the "hanging ;" warning
  #define ENDS_WITH_CURLY_BRACE
  
+ #ifdef HAVE_YO_DAWG_CPP
  // TODO make ascii art pic of xzibit
  // YO DAWG!
  // I HERD YO LIEK MACROS
  // SO I PUT A MACRO DEFINITION IN YO MACRO DEFINITION
  // SO YO CAN EXPAND MACROS WHILE YO EXPAND MACROS
- #define ACCUMULATE_FUNCTION(func,otherfunc) \
+ # define ACCUMULATE_FUNCTION(func,otherfunc) \
        #ifdef func \
        void __merge__##otherfunc() { func(); otherfunc(); } \
        #undef func \
        #else \
        #define func otherfunc \
        #endif
+ # define CALL_ACCUMULATED_FUNCTION(func) \
+       func()
+ #else
+ # define ACCUMULATE_FUNCTION(func,otherfunc) \
+       .void _ACCUMULATE_##func##__##otherfunc;
+ void ACCUMULATE_call(string func)
+ {
+       float i;
+       float n = numentityfields();
+       string funcprefix = strcat("_ACCUMULATE_", func, "__");
+       float funcprefixlen = strlen(funcprefix);
+       for(i = 0; i < n; ++i)
+       {
+               string name = entityfieldname(i);
+               if(substring(name, 0, funcprefixlen) == funcprefix)
+                       callfunction(substring(name, funcprefixlen, -1));
+       }
+ }
+ # define CALL_ACCUMULATED_FUNCTION(func) \
+       ACCUMULATE_call(#func)
+ #endif
  
  // this returns a tempstring containing a copy of s with additional \n newlines added, it also replaces \n in the text with a real newline
  // NOTE: s IS allowed to be a tempstring
@@@ -79,6 -101,7 +101,7 @@@ string mmssss(float t)
  
  string ScoreString(float vflags, float value);
  
+ float dotproduct(vector a, vector b);
  vector cross(vector a, vector b);
  
  void compressShortVector_init();
@@@ -234,7 -257,6 +257,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
@@@ -335,3 -357,7 +358,7 @@@ float cubic_speedfunc(float startspeedf
  // because if this is the case, the function is not usable for platforms
  // as it may exceed 0..1 bounds, or go in reverse
  float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor);
+ typedef entity(entity cur, entity near, entity pass) findNextEntityNearFunction_t;
+ typedef float(entity a, entity b, entity pass) isConnectedFunction_t;
+ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass);
index 18f9bd101112b8d5061564d5d7cafc0386f11a0d,9d6bcf798d8b3026e6fb542731491923ba99b715..e4f6cf14526e3bc7c5d7bdad8388e8ceeb95d518
@@@ -396,7 -396,6 +396,7 @@@ void PutObserverInServer (void
  
        if(clienttype(self) == CLIENTTYPE_REAL)
        {
 +              Item_ItemsTime_Get(self);
                msg_entity = self;
                WriteByte(MSG_ONE, SVC_SETVIEW);
                WriteEntity(MSG_ONE, self);
        }
  
        if(self.vehicle)
-           vehicles_exit(VHEF_RELESE);
-       if(self.flagcarried)
-               DropFlag(self.flagcarried, world, world);
+               vehicles_exit(VHEF_RELESE);         
  
        WaypointSprite_PlayerDead();
  
        
        self.classname = "observer";
        self.iscreature = FALSE;
+       self.teleportable = TELEPORT_SIMPLE;
        self.damagedbycontents = FALSE;
        self.health = -666;
        self.takedamage = DAMAGE_NO;
        self.invincible_finished = 0;
        self.superweapons_finished = 0;
        self.pushltime = 0;
+       self.istypefrag = 0;
        self.think = SUB_Null;
        self.nextthink = 0;
        self.hook_time = 0;
@@@ -641,7 -639,6 +640,6 @@@ PutClientInServe
  Called when a client spawns in the server
  =============
  */
- //void() ctf_playerchanged;
  
  void PutClientInServer (void)
  {
                self.classname = "player";
                self.wasplayer = TRUE;
                self.iscreature = TRUE;
+               self.teleportable = TELEPORT_NORMAL;
                self.damagedbycontents = TRUE;
                self.movetype = MOVETYPE_WALK;
                self.solid = SOLID_SLIDEBOX;
                else
                        self.superweapons_finished = 0;
  
 +              if(!inWarmupStage)
 +                      Item_ItemsTime_ResetForPlayer(self);
 +
                if(g_weaponarena_random)
                {
                        if(g_weaponarena_random_with_laser)
        } else if(self.classname == "observer") {
                PutObserverInServer ();
        }
-       //if(g_ctf)
-       //      ctf_playerchanged();
  }
  
  .float ebouncefactor, ebouncestop; // electro's values
@@@ -1073,8 -1065,7 +1069,7 @@@ void ClientKill_Now_TeamChange(
  {
        if(self.killindicator_teamchange == -1)
        {
-               self.team = -1;
-               JoinBestTeam( self, FALSE, FALSE );
+               JoinBestTeam( self, FALSE, TRUE );
        }
        else if(self.killindicator_teamchange == -2)
        {
@@@ -1122,7 -1113,7 +1117,7 @@@ void KillIndicator_Think(
                return;
        }
  
-       if (self.owner.alpha < 0)
+       if (self.owner.alpha < 0 && !self.owner.vehicle)
        {
                self.owner.killindicator = world;
                remove(self);
@@@ -1344,7 -1335,6 +1339,6 @@@ ClientConnec
  Called when a client connects to the server
  =============
  */
- //void ctf_clientconnect();
  string ColoredTeamName(float t);
  void DecodeLevelParms (void);
  //void dom_player_join_team(entity pl);
@@@ -1443,7 -1433,7 +1437,7 @@@ void ClientConnect (void
        } else {
                if(teamplay)
                {
-                       if(autocvar_g_balance_teams || autocvar_g_balance_teams_force)
+                       if(autocvar_g_balance_teams)
                        {
                                self.classname = "player";
                                campaign_bots_may_start = 1;
                if(g_arena)
                        Spawnqueue_Insert(self);
        }
-       /*else if(g_ctf)
-       {
-               ctf_clientconnect();
-       }*/
  
        attach_entcs();
  
          return;
          
      sv_notice_join();
+     
+     MUTATOR_CALLHOOK(ClientConnect);
  }
  /*
  =============
@@@ -1655,8 -1643,6 +1647,6 @@@ void ClientDisconnect (void
        Portal_ClearAll(self);
  
        RemoveGrapplingHook(self);
-       if(self.flagcarried)
-               DropFlag(self.flagcarried, world, world);
  
        // Here, everything has been done that requires this player to be a client.
  
@@@ -2254,8 -2240,13 +2244,13 @@@ entity CA_SpectateNext(entity start) 
        return other;
  }
  
- float SpectateNext() {
-       other = find(self.enemy, classname, "player");
+ float SpectateNext(entity _prefer) {
+       
+       if(_prefer)
+               other = _prefer;        
+       else
+               other = find(self.enemy, classname, "player");
+       
        if (g_ca && !autocvar_g_ca_spectate_enemies && self.caplayer) {
                // CA and ca players when spectating enemies is forbidden
                other = CA_SpectateNext(other);
@@@ -2331,7 -2322,7 +2326,7 @@@ void LeaveSpectatorMode(
                if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) {
                        self.classname = "player";
  
-                       if(autocvar_g_campaign || autocvar_g_balance_teams || autocvar_g_balance_teams_force)
+                       if(autocvar_g_campaign || autocvar_g_balance_teams)
                                JoinBestTeam(self, FALSE, TRUE);
  
                        if(autocvar_g_campaign)
@@@ -2469,7 -2460,7 +2464,7 @@@ void ObserverThink(
                        self.flags |= FL_SPAWNING;
                } else if(self.BUTTON_ATCK && !self.version_mismatch) {
                        self.flags &~= FL_JUMPRELEASED;
-                       if(SpectateNext() == 1) {
+                       if(SpectateNext(world) == 1) {
                                self.classname = "spectator";
                        }
                } else {
@@@ -2500,7 -2491,7 +2495,7 @@@ void SpectatorThink(
                        self.flags |= FL_SPAWNING;
                } else if(self.BUTTON_ATCK) {
                        self.flags &~= FL_JUMPRELEASED;
-                       if(SpectateNext() == 1) {
+                       if(SpectateNext(world) == 1) {
                                self.classname = "spectator";
                        } else {
                                self.classname = "observer";
        self.flags |= FL_CLIENT | FL_NOTARGET;
  }
  
- float ctf_usekey();
  void PlayerUseKey()
  {
        if(self.classname != "player")
        }
        
        // a use key was pressed; call handlers
-       if(ctf_usekey())
-               return;
        MUTATOR_CALLHOOK(PlayerUseKey);
  }
  
@@@ -2561,7 -2548,6 +2552,6 @@@ Called every frame for each client befo
  =============
  */
  .float usekeypressed;
- void() ctf_setstatus;
  void() nexball_setstatus;
  .float items_added;
  void PlayerPreThink (void)
  
                self.prevorigin = self.origin;
  
-               if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x) // prevent crouching if using melee attack
+               if (!self.vehicle)
+               if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x && !self.freezetag_frozen) // prevent crouching if using melee attack
                {
                        if (!self.crouch)
                        {
                if(frametime)
                        player_anim();
  
-               if(g_ctf)
-                       ctf_setstatus();
                if(g_nexball)
                        nexball_setstatus();
                
diff --combined qcsrc/server/defs.qh
index 3956033698326bb8eae4b18aefc83d3a4eeba29d,9068fa75bf53e95400df5e635e8551faa3ae3a2c..7e4a07b5f6c5565642ecaf7c57f4a0b95bb72a20
@@@ -16,14 -16,10 +16,10 @@@ noref float require_spawnfunc_prefix; /
  
  // Globals
  
- float ctf_score_value(string parameter);
  float g_cloaked, g_footsteps, g_jump_grunt, g_grappling_hook, g_midair, g_minstagib, g_pinata, g_norecoil, g_minstagib_invis_alpha, g_bloodloss;
  float g_warmup_limit;
  float g_warmup_allguns;
  float g_warmup_allow_timeout;
- float g_ctf_ignore_frags;
- float g_ctf_reverse;
  float g_race_qualifying;
  float inWarmupStage;
  float g_pickup_respawntime_weapon;
@@@ -174,7 -170,6 +170,7 @@@ void setanim(entity e, vector anim, flo
  
  .float species;
  
 +.float        scheduledrespawntime;
  .float        respawntime;
  .float        respawntimejitter;
  //.float      chasecam;
  .float watersound_finished;
  .float iscreature;
  .float damagedbycontents;
+ .float damagedbytriggers;
+ .float pushable;
+ .float teleportable;
  .vector oldvelocity;
  
  .float pauseregen_finished;
@@@ -278,6 -276,7 +277,7 @@@ float blockSpectators; //if set, new o
  .float spectatortime; //point in time since the client is spectating or observing
  void checkSpectatorBlock();
  
+ float game_completion_ratio; // 0 at start, 1 near end
  .float winning;
  .float jointime; // time of joining
  .float alivetime; // time of being alive
@@@ -343,7 -342,6 +343,6 @@@ string gamemode_name
  
  float startitem_failed;
  
- void DropFlag(entity flag, entity penalty_receiver, entity attacker);
  void DropAllRunes(entity pl);
  
  
@@@ -570,7 -568,6 +569,6 @@@ float servertime, serverprevtime, serve
  
  string matchid;
  .float hitplotfh;
- .string noise4;
  
  .float last_pickup;
  
@@@ -630,17 -627,6 +628,17 @@@ string deathmessage
  .float (float act_state) setactive;
  .entity realowner;
  
 +.float item_armor_large_time;
 +.float item_health_mega_time;
 +.float item_invisible_time;
 +.float item_speed_time;
 +.float item_extralife_time;
 +.float item_strength_time;
 +.float item_shield_time;
 +.float item_fuelregen_time;
 +.float item_jetpack_time;
 +.float item_superweapons_time;
 +
  .float nex_charge;
  .float nex_charge_rottime;
  .float nex_chargepool_ammo;
diff --combined qcsrc/server/g_world.qc
index cbe31ec1c09f5189f39c79b3ff2d17a503879c4e,4cd5cc810a1c9f456bc372c0e8106e9b2d274488..fb211aaeb7a52653402f11d8f9345887d07cf2a2
@@@ -1,3 -1,7 +1,7 @@@
+ #define LATENCY_THINKRATE 10
+ .float latency_sum;
+ .float latency_cnt;
+ .float latency_time;
  entity pingplreport;
  void PingPLReport_Think()
  {
                WriteShort(MSG_BROADCAST, max(1, e.ping));
                WriteByte(MSG_BROADCAST, ceil(e.ping_packetloss * 255));
                WriteByte(MSG_BROADCAST, ceil(e.ping_movementloss * 255));
+               // record latency times for clients throughout the match so we can report it to playerstats
+               if(time > (e.latency_time + LATENCY_THINKRATE))
+               {
+                       e.latency_sum += e.ping;
+                       e.latency_cnt += 1;
+                       e.latency_time = time;
+                       //print("sum: ", ftos(e.latency_sum), ", cnt: ", ftos(e.latency_cnt), ", avg: ", ftos(e.latency_sum / e.latency_cnt), ".\n");
+               }
        }
        else
        {
@@@ -295,9 -308,8 +308,8 @@@ void cvar_changes_init(
                BADCVAR("g_balance_kill_delay");
                BADCVAR("g_ca_point_leadlimit");
                BADCVAR("g_ctf_captimerecord_always");
-               BADCVAR("g_ctf_flag_capture_effects");
                BADCVAR("g_ctf_flag_glowtrails");
-               BADCVAR("g_ctf_flag_pickup_effects");
+               BADCVAR("g_ctf_flag_pickup_verbosename");
                BADCVAR("g_domination_point_leadlimit");
                BADCVAR("g_forced_respawn");
                BADCVAR("g_keyhunt_point_leadlimit");
                BADCVAR("gametype");
                BADCVAR("g_antilag");
                BADCVAR("g_balance_teams");
-               BADCVAR("g_balance_teams_force");
+               BADCVAR("g_balance_teams_prevent_imbalance");
+               BADCVAR("g_balance_teams_scorefactor");
                BADCVAR("g_ban_sync_trusted_servers");
                BADCVAR("g_ban_sync_uri");
                BADCVAR("g_ctf_ignore_frags");
@@@ -538,8 -551,8 +551,8 @@@ void spawnfunc___init_dedicated_server(
        self.classname = "worldspawn"; // safeguard against various stuff ;)
  
        // needs to be done so early because of the constants they create
-       RegisterWeapons();
-       RegisterGametypes();
+       CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
+       CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
  
        MapInfo_Enumerate();
        MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
  
  void Map_MarkAsRecent(string m);
  float world_already_spawned;
- void RegisterWeapons();
  void Nagger_Init();
 +void Item_ItemsTime_Init();
  void ClientInit_Spawn();
  void WeaponStats_Init();
  void WeaponStats_Shutdown();
@@@ -586,8 -597,8 +598,8 @@@ void spawnfunc_worldspawn (void
        }
  
        // needs to be done so early because of the constants they create
-       RegisterWeapons();
-       RegisterGametypes();
+       CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
+       CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
  
        ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
  
  
        Map_MarkAsRecent(mapname);
  
+       PlayerStats_Init(); // we need this to be initiated before InitGameplayMode
        precache_model ("null"); // we need this one before InitGameplayMode
        InitGameplayMode();
        readlevelcvars();
  
        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_INVISIBLE_TIME, AS_FLOAT, item_invisible_time);
 +      addstat(STAT_SPEED_TIME, AS_FLOAT, item_speed_time);
 +      addstat(STAT_EXTRALIFE_TIME, AS_FLOAT, item_extralife_time);
 +      addstat(STAT_STRENGTH_TIME, AS_FLOAT, item_strength_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);
 +      addstat(STAT_SUPERWEAPONS_TIME, AS_FLOAT, item_superweapons_time);
 +      Item_ItemsTime_Init();
 +
        if(g_ca || g_freezetag)
        {
                addstat(STAT_REDALIVE, AS_INT, redalive_stat);
                cvar_set("sv_curl_serverpackages", substring(s, 1, -1));
        }
  
-       PlayerStats_Init();
        // MOD AUTHORS: change this, and possibly remove a few of the blocks below to ignore certain changes
        modname = "Xonotic";
        // physics/balance/config changes that count as mod
@@@ -1992,6 -1991,9 +2004,9 @@@ float WinningCondition_Scores(float lim
                        limitreached = (limitreached || leadlimitreached);
        }
  
+       if(limit)
+               game_completion_ratio = max(game_completion_ratio, bound(0, WinningConditionHelper_topscore / limit, 1));
        return GetWinningCode(
                WinningConditionHelper_topscore && limitreached,
                WinningConditionHelper_equality
@@@ -2180,6 -2182,11 +2195,11 @@@ void CheckRules_World(
        float wantovertime;
        wantovertime = 0;
  
+       if(timelimit > game_starttime)
+               game_completion_ratio = (time - game_starttime) / (timelimit - game_starttime);
+       else
+               game_completion_ratio = 0;
        if(checkrules_suddendeathend)
        {
                if(!checkrules_suddendeathwarning)
diff --combined qcsrc/server/t_items.qc
index e90055b27873b210ea33d4bdfc9731541a4e5224,48b4fdd31cf695408019ae9dee2b7d1470510ee4..bc8638dd2f123fa2830fc90ca1b2bdbb054d280d
      #define ITS_POWERUP   64
  #define ISF_COLORMAP 16
  #define ISF_DROP 32
+ #define ISF_ANGLES 64
  
  .float ItemStatus;
  
  #ifdef CSQC
  
- var float  autocvar_cl_ghost_items = 1;
+ var float  autocvar_cl_animate_items = 1;
+ var float  autocvar_cl_ghost_items = 0.45;
  var vector autocvar_cl_ghost_items_color = '-1 -1 -1';
- float  autocvar_cl_fullbright_items;
- vector autocvar_cl_staywep_color;
- float  autocvar_cl_staywep_alpha;
- float  autocvar_cl_simple_items;
- float  cl_simple_items;
- float  cl_ghost_items_alpha;
+ var float  autocvar_cl_fullbright_items = 0;
+ var vector autocvar_cl_weapon_stay_color = '2 0.5 0.5';
+ var float  autocvar_cl_weapon_stay_alpha = 0.75;
+ var float  autocvar_cl_simple_items = 0;
+ var string autocvr_cl_simpleitems_postfix = "_simple";
  .float  spawntime;
  .float  gravity;
  .vector colormod;
  void ItemDraw()
  {    
-     if(self.ItemStatus & ITS_ANIMATE1)
-     {
-         self.angles += '0 180 0' * frametime;
-         setorigin(self, '0 0 10' + self.oldorigin + '0 0 8' * sin(time * 2));        
-     }    
-     
-     if(self.ItemStatus & ITS_ANIMATE2)
-     {
-         self.angles += '0 -90 0' * frametime;
-         setorigin(self, '0 0 8' + self.oldorigin + '0 0 4' * sin(time * 3));        
-     }
-     
      if(self.gravity)
+     {        
          Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+         if(self.move_flags & FL_ONGROUND) 
+         { // For some reason move_avelocity gets set to '0 0 0' here ...
+             self.oldorigin = self.origin;
+             self.gravity = 0;
+             if(autocvar_cl_animate_items)   
+             { // ... so reset it if animations are requested. 
+                 if(self.ItemStatus & ITS_ANIMATE1)
+                     self.move_avelocity = '0 180 0';
+                 
+                 if(self.ItemStatus & ITS_ANIMATE2)
+                     self.move_avelocity = '0 -90 0';
+             }
+         }
+     }
+     else if (autocvar_cl_animate_items)
+     {        
+         if(self.ItemStatus & ITS_ANIMATE1)
+         {
+             self.angles += self.move_avelocity * frametime;
+             setorigin(self, '0 0 10' + self.oldorigin + '0 0 8' * sin(time * 2));        
+         }    
+         
+         if(self.ItemStatus & ITS_ANIMATE2)
+         {
+             self.angles += self.move_avelocity * frametime;
+             setorigin(self, '0 0 8' + self.oldorigin + '0 0 4' * sin(time * 3));        
+         }
+     }
  }
  
  void ItemDrawSimple()
  {
      if(self.gravity)
+     {        
          Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);    
- }
- float csqcitems_started; // remove this after a release or two
- void csqcitems_start()
- {
-     if(autocvar_cl_ghost_items == 1)
-         cl_ghost_items_alpha = 0.55;
-     else
-         cl_ghost_items_alpha = bound(0, autocvar_cl_ghost_items, 1);
-     
-     csqcitems_started = TRUE;
+         
+         if(self.move_flags & FL_ONGROUND)
+             self.gravity = 0;
+     }
  }
  
  void ItemRead(float _IsNew)
  {
-     if(!csqcitems_started)
-         csqcitems_start();
-     
      float sf = ReadByte();
  
      if(sf & ISF_LOCATION)
          self.oldorigin = self.origin;
      }
      
+     if(sf & ISF_ANGLES) 
+     {
+         self.angles_x = ReadCoord();
+         self.angles_y = ReadCoord();
+         self.angles_z = ReadCoord();        
+         self.move_angles = self.angles;
+     }
+     
      if(sf & ISF_STATUS) // need to read/write status frist so model can handle simple, fb etc.
      {
          self.ItemStatus = ReadByte();    
          }
          else
          {
-             if (cl_ghost_items_alpha)
+             if (autocvar_cl_ghost_items_color)
              {
                  self.alpha = autocvar_cl_ghost_items;
                  self.colormod = self.glowmod = autocvar_cl_ghost_items_color;
              
          if(self.ItemStatus & ITS_STAYWEP)
          {
-             self.colormod = self.glowmod = autocvar_cl_staywep_color;
-             self.alpha = autocvar_cl_staywep_alpha;
+             self.colormod = self.glowmod = autocvar_cl_weapon_stay_color;
+             self.alpha = autocvar_cl_weapon_stay_alpha;
              
          }
          
          self.mdl = "";
          string _fn = ReadString();
          
-         if(cl_simple_items && (self.ItemStatus & ITS_ALLOWSI))
+         if(autocvar_cl_simple_items && (self.ItemStatus & ITS_ALLOWSI))
          {
              string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
              self.draw = ItemDrawSimple;
                      
-             if(fexists(strcat(_fn2, "_simple.md3")))
-                 self.mdl = strzone(strcat(_fn2, "_simple.md3"));
-             else if(fexists(strcat(_fn2, "_simple.dpm")))
-                 self.mdl = strzone(strcat(_fn2, "_simple.dpm"));
-             else if(fexists(strcat(_fn2, "_simple.iqm")))
-                 self.mdl = strzone(strcat(_fn2, "_simple.iqm"));
-             else if(fexists(strcat(_fn2, "_simple.obj")))
-                 self.mdl = strzone(strcat(_fn2, "_simple.obj"));
+             
+             
+             if(fexists(sprintf("%s%s.md3", _fn2, autocvr_cl_simpleitems_postfix)))
+                 self.mdl = strzone(sprintf("%s%s.md3", _fn2, autocvr_cl_simpleitems_postfix));
+             else if(fexists(sprintf("%s%s.dpm", _fn2, autocvr_cl_simpleitems_postfix)))
+                 self.mdl = strzone(sprintf("%s%s.dpm", _fn2, autocvr_cl_simpleitems_postfix));
+             else if(fexists(sprintf("%s%s.iqm", _fn2, autocvr_cl_simpleitems_postfix)))
+                 self.mdl = strzone(sprintf("%s%s.iqm", _fn2, autocvr_cl_simpleitems_postfix));
+             else if(fexists(sprintf("%s%s.obj", _fn2, autocvr_cl_simpleitems_postfix)))
+                 self.mdl = strzone(sprintf("%s%s.obj", _fn2, autocvr_cl_simpleitems_postfix));
              else
              {
                  self.draw = ItemDraw;
      if(sf & ISF_DROP)
      {
          self.gravity = 1;
+         self.move_angles = '0 0 0';
          self.move_movetype = MOVETYPE_TOSS;
          self.move_velocity_x = ReadCoord();
          self.move_velocity_y = ReadCoord();
          }
          else
              self.move_time = max(self.move_time, time);
-     }    
+     }
+         
+     if(autocvar_cl_animate_items)
+     {        
+         if(self.ItemStatus & ITS_ANIMATE1)
+             self.move_avelocity = '0 180 0';
+                 
+         if(self.ItemStatus & ITS_ANIMATE2)
+             self.move_avelocity = '0 -90 0';
+     }
  }
  #endif
  
  #ifdef SVQC
@@@ -197,7 -227,6 +227,6 @@@ float ItemSend(entity to, float sf
        WriteByte(MSG_ENTITY, ENT_CLIENT_ITEM); 
        WriteByte(MSG_ENTITY, sf);
  
-         
        //WriteByte(MSG_ENTITY, self.cnt);
      if(sf & ISF_LOCATION)
      {
          WriteCoord(MSG_ENTITY, self.origin_y);
          WriteCoord(MSG_ENTITY, self.origin_z);
      }
+     
+     if(sf & ISF_ANGLES)
+     {
+         WriteCoord(MSG_ENTITY, self.angles_x);
+         WriteCoord(MSG_ENTITY, self.angles_y);
+         WriteCoord(MSG_ENTITY, self.angles_z);
+     }
  
      if(sf & ISF_STATUS)
          WriteByte(MSG_ENTITY, self.ItemStatus);
@@@ -397,159 -433,8 +433,159 @@@ void Item_Show (entity e, float mode
      e.SendFlags |= ISF_STATUS;
  }
  
 +float it_armor_large_time;
 +float it_health_mega_time;
 +float it_invisible_time;
 +float it_speed_time;
 +float it_extralife_time;
 +float it_strength_time;
 +float it_shield_time;
 +float it_fuelregen_time;
 +float it_jetpack_time;
 +float it_superweapons_time;
 +
 +void Item_ItemsTime_Init()
 +{
 +      it_armor_large_time = -1;
 +      it_health_mega_time = -1;
 +      it_invisible_time = -1;
 +      it_speed_time = -1;
 +      it_extralife_time = -1;
 +      it_strength_time = -1;
 +      it_shield_time = -1;
 +      it_fuelregen_time = -1;
 +      it_jetpack_time = -1;
 +      it_superweapons_time = -1;
 +}
 +void Item_ItemsTime_Reset()
 +{
 +      it_armor_large_time = (it_armor_large_time == -1) ? -1 : 0;
 +      it_health_mega_time = (it_health_mega_time == -1) ? -1 : 0;
 +      it_invisible_time   = (it_invisible_time   == -1) ? -1 : 0;
 +      it_speed_time       = (it_speed_time       == -1) ? -1 : 0;
 +      it_extralife_time   = (it_extralife_time   == -1) ? -1 : 0;
 +      it_strength_time    = (it_strength_time    == -1) ? -1 : 0;
 +      it_shield_time      = (it_shield_time      == -1) ? -1 : 0;
 +      it_fuelregen_time   = (it_fuelregen_time   == -1) ? -1 : 0;
 +      it_jetpack_time     = (it_jetpack_time     == -1) ? -1 : 0;
 +      it_superweapons_time= (it_superweapons_time== -1) ? -1 : 0;
 +}
 +void Item_ItemsTime_ResetForPlayer(entity e)
 +{
 +      e.item_armor_large_time = (it_armor_large_time == -1) ? -1 : 0;
 +      e.item_health_mega_time = (it_health_mega_time == -1) ? -1 : 0;
 +      e.item_invisible_time   = (it_invisible_time   == -1) ? -1 : 0;
 +      e.item_speed_time       = (it_speed_time       == -1) ? -1 : 0;
 +      e.item_extralife_time   = (it_extralife_time   == -1) ? -1 : 0;
 +      e.item_strength_time    = (it_strength_time    == -1) ? -1 : 0;
 +      e.item_shield_time      = (it_shield_time      == -1) ? -1 : 0;
 +      e.item_fuelregen_time   = (it_fuelregen_time   == -1) ? -1 : 0;
 +      e.item_jetpack_time     = (it_jetpack_time     == -1) ? -1 : 0;
 +      e.item_superweapons_time= (it_superweapons_time== -1) ? -1 : 0;
 +}
 +void Item_ItemsTime_Get(entity e)
 +{
 +      e.item_armor_large_time = it_armor_large_time;
 +      e.item_health_mega_time = it_health_mega_time;
 +      e.item_invisible_time = it_invisible_time;
 +      e.item_speed_time = it_speed_time;
 +      e.item_extralife_time = it_extralife_time;
 +      e.item_strength_time = it_strength_time;
 +      e.item_shield_time = it_shield_time;
 +      e.item_fuelregen_time = it_fuelregen_time;
 +      e.item_jetpack_time = it_jetpack_time;
 +      e.item_superweapons_time = it_superweapons_time;
 +}
 +float Item_ItemsTime_UpdateTime_Check(float item_time, float t)
 +{
 +      if(t == 0 && item_time == -1)
 +              return TRUE;
 +      if(time < t && (item_time <= time || t < item_time))
 +              return TRUE;
 +      return FALSE;
 +}
 +void Item_ItemsTime_UpdateTime(entity e, float t)
 +{
 +      if(g_minstagib)
 +      {
 +              switch(e.items)
 +              {
 +                      case IT_STRENGTH://"item-invis"
 +                              if(Item_ItemsTime_UpdateTime_Check(it_invisible_time, t))
 +                                      it_invisible_time = t;
 +                              break;
 +                      case IT_NAILS://"item-extralife"
 +                              if(Item_ItemsTime_UpdateTime_Check(it_extralife_time, t))
 +                                      it_extralife_time = t;
 +                              break;
 +                      case IT_INVINCIBLE://"item-speed"
 +                              if(Item_ItemsTime_UpdateTime_Check(it_speed_time, t))
 +                                      it_speed_time = t;
 +                              break;
 +              }
 +      }
 +      else
 +      {
 +              switch(e.items)
 +              {
 +                      case IT_HEALTH:
 +                              //if (e.classname == "item_health_mega")
 +                                      if(Item_ItemsTime_UpdateTime_Check(it_health_mega_time, t))
 +                                              it_health_mega_time = t;
 +                              break;
 +                      case IT_ARMOR:
 +                              if (e.classname == "item_armor_large")
 +                                      if(Item_ItemsTime_UpdateTime_Check(it_armor_large_time, t))
 +                                              it_armor_large_time = t;
 +                              break;
 +                      case IT_STRENGTH://"item-strength"
 +                              if(Item_ItemsTime_UpdateTime_Check(it_strength_time, t))
 +                                      it_strength_time = t;
 +                              break;
 +                      case IT_INVINCIBLE://"item-shield"
 +                              if(Item_ItemsTime_UpdateTime_Check(it_shield_time, t))
 +                                      it_shield_time = t;
 +                              break;
 +                      default:
 +                              if(WEPSET_CONTAINS_ANY_EA(e, WEPBIT_SUPERWEAPONS))
 +                                      if(Item_ItemsTime_UpdateTime_Check(it_superweapons_time, t))
 +                                                      it_superweapons_time = t;
 +              }
 +      }
 +      switch(e.items)
 +      {
 +              case IT_FUEL_REGEN://"item-fuelregen"
 +                      if(Item_ItemsTime_UpdateTime_Check(it_fuelregen_time, t))
 +                              it_fuelregen_time = t;
 +                      break;
 +              case IT_JETPACK://"item-jetpack"
 +                      if(Item_ItemsTime_UpdateTime_Check(it_jetpack_time, t))
 +                              it_jetpack_time = t;
 +                      break;
 +      }
 +}
 +void Item_ItemsTime_GetForAll()
 +{
 +      entity e;
 +      if(inWarmupStage)
 +      {
 +              FOR_EACH_REALCLIENT(e)
 +                      Item_ItemsTime_Get(e);
 +      }
 +      else
 +      {
 +              FOR_EACH_REALCLIENT(e)
 +              {
 +                      if (e.classname != "player")
 +                              Item_ItemsTime_Get(e);
 +              }
 +      }
 +}
 +
  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 || WEPSET_CONTAINS_ANY_EA(self, WEPBIT_SUPERWEAPONS))
 +      {
 +              Item_ItemsTime_UpdateTime(self, 0);
 +              Item_ItemsTime_GetForAll();
 +      }
 +
        //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);
  }
@@@ -601,14 -480,6 +637,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) || WEPSET_CONTAINS_ANY_EA(e, WEPBIT_SUPERWEAPONS))
 +      if((e.flags & FL_POWERUP) || WEPSET_CONTAINS_ANY_EA(e, WEPBIT_SUPERWEAPONS) || e.classname == "item_armor_large" || e.items == IT_HEALTH)
        {
 +              entity head;
                e.think = Item_RespawnCountdown;
                e.nextthink = time + max(0, t - ITEM_RESPAWN_TICKS);
 +              e.scheduledrespawntime = e.nextthink + ITEM_RESPAWN_TICKS;
                e.count = 0;
 +              if(WEPSET_CONTAINS_ANY_EA(e, WEPBIT_SUPERWEAPONS))
 +              {
 +                      for(t = e.scheduledrespawntime, head = world; (head = nextent(head)); )
 +                      {
 +                              if(e == head)
 +                                      continue;
 +                              if(clienttype(head) == CLIENTTYPE_NOTACLIENT)
 +                              if(WEPSET_CONTAINS_ANY_EA(head, WEPBIT_SUPERWEAPONS))
 +                              if(head.classname != "weapon_info")
 +                              {
 +                                      if(head.scheduledrespawntime <= time)
 +                                      {
 +                                              t = 0;
 +                                              break;
 +                                      }
 +                                      if(head.scheduledrespawntime < t)
 +                                              t = head.scheduledrespawntime;
 +                              }
 +                      }
 +              }
 +              else
 +              {
 +                      for(t = e.scheduledrespawntime, head = world; (head = find(head, classname, e.classname)); )
 +                      {
 +                              // in minstagib .classname is "minstagib" for every item
 +                              if(e == head || (g_minstagib && e.items != head.items))
 +                                      continue;
 +                              if(head.scheduledrespawntime <= time)
 +                              {
 +                                      t = 0;
 +                                      break;
 +                              }
 +                              if(head.scheduledrespawntime < t)
 +                                      t = head.scheduledrespawntime;
 +                      }
 +              }
 +              Item_ItemsTime_UpdateTime(e, t);
 +              Item_ItemsTime_GetForAll();
        }
        else
        {
                e.think = Item_Respawn;
                e.nextthink = time + t;
 +              e.scheduledrespawntime = e.nextthink;
        }
  }
  
@@@ -841,7 -667,7 +877,7 @@@ float Item_GiveTo(entity item, entity p
                        pickedup = TRUE;
                        // sound not available
                        // AnnounceTo(player, "speed");
-                       player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_strength_time;
+                       player.invincible_finished = max(player.invincible_finished, time) + autocvar_g_balance_powerup_invincible_time;
                }
        }
        else
  void Item_Touch (void)
  {
        entity e, head;
+       
        // remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
        if(self.classname == "droppedweapon")
        {
                return;
        if (self.owner == other)
                return;
+       if(MUTATOR_CALLHOOK(ItemTouch))
+               return;
  
        if (self.classname == "droppedweapon")
        {
@@@ -1253,6 -1081,9 +1291,9 @@@ void StartItem (string itemmodel, strin
                        remove (self);
                        return;
                }
+               
+               if(self.angles != '0 0 0')
+             self.SendFlags |= ISF_ANGLES;
  
                self.reset = Item_Reset;
                // it's a level item
  
                if((itemflags & (FL_POWERUP | FL_WEAPON)) || (itemid & (IT_HEALTH | IT_ARMOR | IT_KEY1 | IT_KEY2)))
                        self.target = "###item###"; // for finding the nearest item using find()
 +
 +              Item_ItemsTime_UpdateTime(self, 0);
        }
  
        self.bot_pickup = TRUE;