]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/ons_updates
authorMario <zacjardine@y7mail.com>
Sun, 2 Aug 2015 04:20:22 +0000 (14:20 +1000)
committerMario <zacjardine@y7mail.com>
Sun, 2 Aug 2015 04:20:22 +0000 (14:20 +1000)
# Conflicts:
# qcsrc/client/hud.qc
# qcsrc/client/hud.qh
# qcsrc/client/main.qc
# qcsrc/common/constants.qh
# qcsrc/common/stats.qh
# qcsrc/server/autocvars.qh
# qcsrc/server/bot/havocbot/havocbot.qc
# qcsrc/server/mutators/gamemode_onslaught.qc

36 files changed:
1  2 
defaultXonotic.cfg
gamemodes.cfg
qcsrc/client/autocvars.qh
qcsrc/client/command/cl_cmd.qc
qcsrc/client/hud.qc
qcsrc/client/hud.qh
qcsrc/client/hud_config.qc
qcsrc/client/hud_config.qh
qcsrc/client/main.qc
qcsrc/client/main.qh
qcsrc/client/mapvoting.qc
qcsrc/client/mapvoting.qh
qcsrc/client/progs.src
qcsrc/client/scoreboard.qc
qcsrc/client/teamradar.qc
qcsrc/client/teamradar.qh
qcsrc/client/view.qc
qcsrc/client/waypointsprites.qc
qcsrc/client/waypointsprites.qh
qcsrc/common/constants.qh
qcsrc/common/mapinfo.qh
qcsrc/common/notifications.qh
qcsrc/common/stats.qh
qcsrc/common/triggers/triggers.qh
qcsrc/server/autocvars.qh
qcsrc/server/bot/havocbot/role_onslaught.qc
qcsrc/server/bot/havocbot/roles.qc
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/mutators/gamemode_onslaught.qc
qcsrc/server/mutators/gamemode_onslaught.qh
qcsrc/server/progs.src
qcsrc/server/teamplay.qc
qcsrc/server/waypointsprites.qc

diff --combined defaultXonotic.cfg
index 19b702224ea4374177be2ae9949a63ee97d169dc,c0d585e9fce4a00cc9a79e59461805f527631f14..470bfee2352d0767f208ea0a031089f6cc823a7a
@@@ -10,7 -10,7 +10,7 @@@
  // e.g. Xonotic 1.5.1 RC1 will be 15101
  set g_xonoticversion git "Xonotic version (formatted for humans)"
  
- gameversion 800 // 0.8.0
+ gameversion 801 // 0.8.1
  gameversion_min 0 // git builds see all versions
  gameversion_max 65535 // git builds see all versions
  
@@@ -234,12 -234,10 +234,12 @@@ seta cl_hitsound_nom_damage 25 "damage 
  seta cl_eventchase_death 1 "camera goes into 3rd person mode when the player is dead; set to 2 to active the effect only when the corpse doesn't move anymore"
  seta cl_eventchase_nexball 1 "camera goes into 3rd person mode when in nexball game-mode"
  seta cl_eventchase_distance 140 "final camera distance"
 +seta cl_eventchase_distance 400 "final camera distance while viewing generator explosion"
  seta cl_eventchase_speed 1.3 "how fast the camera slides back, 0 is instant"
  seta cl_eventchase_maxs "12 12 8" "max size of eventchase camera bbox"
  seta cl_eventchase_mins "-12 -12 -8" "min size of eventchase camera bbox"
  seta cl_eventchase_viewoffset "0 0 20" "viewoffset of eventchase camera"
 +seta cl_eventchase_generator_viewoffset "0 0 80" "viewoffset of eventchase camera while viewing generator explosion"
  
  //nifreks lockonrestart feature, used in team-based game modes, if set to 1 and all players readied up no other player can then join the game anymore, useful to block spectators from joining
  set teamplay_lockonrestart 0 "it set to 1 in a team-based game, the teams are locked once all players readied up and the game restarted (no new players can join after restart unless using the server-command unlockteams)"
@@@ -298,6 -296,7 +298,7 @@@ set sv_fraginfo_stats 1 "Enable statist
  
  // use default physics
  set sv_friction_on_land 0
+ set sv_friction_slick 0.5
  
  set sv_player_viewoffset "0 0 35" "view offset of the player model"
  set sv_player_mins "-16 -16 -24" "playermodel mins"
@@@ -474,7 -473,7 +475,7 @@@ set g_botclip_collisions 1 "0 = disabl
  set g_grappling_hook 0 "let players spawn with the grappling hook which allows them to pull themselves up"
  
  set g_spawn_alloweffects 1 "allow clients to enable spawn point and event effects such as particles and sounds, see cl_spawn_ cvars for more info"
- set g_spawn_furthest 1.0 "this amount of the spawns shall be far away from any players"
+ 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"
  // respawn delay
  set g_respawn_delay_small 2 "small game number of seconds you have to wait before you can respawn again"
@@@ -1401,6 -1400,7 +1402,7 @@@ exec gamemodes.cf
  exec mutators.cfg
  exec notifications.cfg
  exec monsters.cfg
+ exec physics.cfg
  
  // load console command aliases and settings
  exec commands.cfg
diff --combined gamemodes.cfg
index f05ff5238cc61c2a3218dafc9149dac1668107fc,d660aa123aecfcca782679a62cace4864842fb23..547e7cbd1a905d2ebc16aa5126f90dabfa0ffbad
@@@ -66,8 -66,11 +66,11 @@@ alias sv_hook_gameen
  // =====================
  //  gametype vote hooks
  // =====================
- // these are called when the mode is switched via gametype vote screen, earlier than gamestart hooks (useful for enabling per-gamemode mutators)
- alias sv_vote_gametype_hook_all 
+ // These are called when the mode is switched via gametype vote screen,
+ // earlier than gamestart hooks (useful for enabling per-gamemode mutators)
+ // The _all hook is called before the specific one
+ // here it sets g_maxplayers to undo what duel does
+ alias sv_vote_gametype_hook_all "set g_maxplayers 0"
  alias sv_vote_gametype_hook_as
  alias sv_vote_gametype_hook_ca
  alias sv_vote_gametype_hook_ctf
@@@ -84,6 -87,15 +87,15 @@@ alias sv_vote_gametype_hook_on
  alias sv_vote_gametype_hook_rc
  alias sv_vote_gametype_hook_tdm
  
+ // Preset to allow duel to be used for the gametype voting screen
+ // sv_vote_gametype_*_type Must be set to the name of the gametype the option is based on
+ // sv_vote_gametype_*_name Contains a human-readable name of the gametype
+ // sv_vote_gametype_*_description Contains a longer description
+ set sv_vote_gametype_duel_type dm
+ set sv_vote_gametype_duel_name Duel
+ set sv_vote_gametype_duel_description "One vs One match"
+ alias sv_vote_gametype_hook_duel "set g_maxplayers 2"
  
  // ===========
  //  leadlimit
@@@ -479,17 -491,7 +491,17 @@@ seta g_nexball_tackling 1 "Allow ball t
  //  onslaught
  // ===========
  set g_onslaught 0 "Onslaught: take control points towards the enemy generator and then destroy it"
 +set g_onslaught_point_limit 1 "Onslaught point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
 +set g_onslaught_warmup 5
 +set g_onslaught_round_timelimit 280
 +set g_onslaught_debug 0 "show debug prints in onslaught"
 +set g_onslaught_teleport_radius 200 "Allows teleporting from a control point to another"
 +set g_onslaught_teleport_wait 5 "Time before player can teleport again"
 +set g_onslaught_spawn_choose 1 "Allow players to choose the control point to be spawned at"
 +set g_onslaught_click_radius 500 "When choosing from the map, this level of precision is required"
 +
  set g_onslaught_gen_health 2500
 +set g_onslaught_allow_vehicle_touch 0
  set g_onslaught_cp_health 1000
  set g_onslaught_cp_buildhealth 100
  set g_onslaught_cp_buildtime 5
@@@ -497,13 -499,8 +509,13 @@@ set g_onslaught_cp_regen 2
  set g_onslaught_cp_proxydecap 0 "de-capture controlpoints by standing close to them"
  set g_onslaught_cp_proxydecap_distance 512
  set g_onslaught_cp_proxydecap_dps 100
 +set g_onslaught_shield_force 100
  set g_onslaught_spawn_at_controlpoints 0
 +set g_onslaught_spawn_at_controlpoints_chance 0.5
 +set g_onslaught_spawn_at_controlpoints_random 0
  set g_onslaught_spawn_at_generator 0
 +set g_onslaught_spawn_at_generator_chance 0
 +set g_onslaught_spawn_at_generator_random 0
  
  
  // ======
index c51edbd80076ab9912e1f021dd6f1414b573d86e,90faef9411e7a23bee108316cad225b3e4b5e723..18e58e522a4e301503eea2129f2ebe2bbaadb537
@@@ -282,10 -282,12 +282,12 @@@ float autocvar_hud_panel_notify_fontsiz
  float autocvar_hud_panel_notify_time;
  float autocvar_hud_panel_notify_icon_aspect;
  bool autocvar_hud_panel_physics;
+ float autocvar_hud_panel_physics_acceleration_movingaverage = 1;
  float autocvar_hud_panel_physics_acceleration_progressbar_mode;
  float autocvar_hud_panel_physics_acceleration_progressbar_scale;
  float autocvar_hud_panel_physics_acceleration_progressbar_nonlinear;
  float autocvar_hud_panel_physics_acceleration_max;
+ float autocvar_hud_panel_physics_update_interval;
  int autocvar_hud_panel_physics_progressbar;
  bool autocvar_hud_panel_physics_acceleration_vertical;
  int autocvar_hud_panel_physics_baralign;
@@@ -431,8 -433,6 +433,8 @@@ float autocvar_cl_hitsound_nom_damage 
  float autocvar_cl_hitsound_antispam_time;
  int autocvar_cl_eventchase_death = 1;
  int autocvar_cl_eventchase_nexball = 1;
 +vector autocvar_cl_eventchase_generator_viewoffset = '0 0 80';
 +float autocvar_cl_eventchase_generator_distance = 400;
  float autocvar_cl_eventchase_distance = 140;
  float autocvar_cl_eventchase_speed = 1.3;
  vector autocvar_cl_eventchase_maxs = '12 12 8';
index 8d5e45615a7e8ff8565dec1ef4844089ebc96d19,ed8cb190d26ee803a68df32662ff62f3a9e14b2a..147c0bfa225661b70a0a8112378b61be4509cc02
@@@ -3,8 -3,20 +3,20 @@@
  //  Last updated: December 28th, 2011
  // ==============================================
  
+ #include "../../common/command/command.qh"
+ #include "cl_cmd.qh"
+ #include "../autocvars.qh"
+ #include "../defs.qh"
+ #include "../hud.qh"
+ #include "../hud_config.qh"
+ #include "../main.qh"
+ #include "../mapvoting.qh"
+ #include "../miscfunctions.qh"
+ #include "../../common/mapinfo.qh"
  #include "../../common/command/generic.qh"
- #include "../../common/command/shared_defs.qh"
  
  void DrawDebugModel()
  {
@@@ -268,15 -280,9 +280,15 @@@ void LocalCommand_hud(int request, int 
                                case "radar":
                                {
                                        if(argv(2))
 -                                              hud_panel_radar_maximized = InterpretBoolean(argv(2));
 +                                              HUD_Radar_Show_Maximized(InterpretBoolean(argv(2)),0);
                                        else
 -                                              hud_panel_radar_maximized = !hud_panel_radar_maximized;
 +                                              HUD_Radar_Show_Maximized(!hud_panel_radar_maximized,0);
 +                                      return;
 +                              }
 +                              
 +                              case "clickradar":
 +                              {
 +                                      HUD_Radar_Show_Maximized(!hud_panel_radar_mouse,1);
                                        return;
                                }
                        }
@@@ -345,6 -351,31 +357,31 @@@ void LocalCommand_mv_download(int reque
        }
  }
  
+ void LocalCommand_find(int request, int argc)
+ {
+       switch(request)
+       {
+               case CMD_REQUEST_COMMAND:
+               {
+                       entity client;
+                       for(client = world; (client = find(client, classname, argv(1))); )
+                               print(etos(client), "\n");
+                       return;
+               }
+               default:
+                       print("Incorrect parameters for ^2find^7\n");
+               case CMD_REQUEST_USAGE:
+               {
+                       print("\nUsage:^3 cl_cmd find classname\n");
+                       print("  Where 'classname' is the classname to search for.\n");
+                       return;
+               }
+       }
+ }
  void LocalCommand_sendcvar(int request, int argc)
  {
        switch(request)
@@@ -416,6 -447,7 +453,7 @@@ void LocalCommand_(int request
        CLIENT_COMMAND("handlevote", LocalCommand_handlevote(request, arguments), "System to handle selecting a vote or option") \
        CLIENT_COMMAND("hud", LocalCommand_hud(request, arguments), "Commands regarding/controlling the HUD system") \
        CLIENT_COMMAND("localprint", LocalCommand_localprint(request, arguments), "Create your own centerprint sent to yourself") \
+       CLIENT_COMMAND("find", LocalCommand_find(request, arguments), "Search through entities for matching classname") \
        CLIENT_COMMAND("mv_download", LocalCommand_mv_download(request, arguments), "Retrieve mapshot picture from the server") \
        CLIENT_COMMAND("sendcvar", LocalCommand_sendcvar(request, arguments), "Send a cvar to the server (like weaponpriority)") \
        /* nothing */
diff --combined qcsrc/client/hud.qc
index 05c1ed3f22b64b8a35d121858d2578cf7c37a490,e0dc1d91b7c93babe7324ae3cdc585163643006e..06cf453346e5c3f531cbda5e67c28c511496d43e
@@@ -1,11 -1,23 +1,26 @@@
+ #include "hud.qh"
+ #include "_all.qh"
+ #include "hud_config.qh"
 +#include "mapvoting.qh"
  #include "scoreboard.qh"
+ #include "sortlist.qh"
  #include "teamradar.qh"
+ #include "t_items.qh"
++#include "../dpdefs/keycodes.qh"
++
  #include "../common/buffs.qh"
+ #include "../common/constants.qh"
  #include "../common/counting.qh"
+ #include "../common/deathtypes.qh"
  #include "../common/mapinfo.qh"
  #include "../common/nades.qh"
- #include "../server/t_items.qh"
+ #include "../common/stats.qh"
+ #include "../csqcmodellib/cl_player.qh"
+ #include "../warpzonelib/mathlib.qh"
  
  /*
  ==================
@@@ -141,13 -153,13 +156,13 @@@ vector HUD_Get_Num_Color (float x, floa
        return color;
  }
  
- float HUD_GetRowCount(float item_count, vector size, float item_aspect)
+ float HUD_GetRowCount(int item_count, vector size, float item_aspect)
  {
        float aspect = size_y / size_x;
        return bound(1, floor((sqrt(4 * item_aspect * aspect * item_count + aspect * aspect) + aspect + 0.5) / 2), item_count);
  }
  
- vector HUD_GetTableSize(float item_count, vector psize, float item_aspect)
+ vector HUD_GetTableSize(int item_count, vector psize, float item_aspect)
  {
        float columns, rows;
        float ratio, best_ratio = 0;
@@@ -197,20 -209,20 +212,20 @@@ float stringwidth_nocolors(string s, ve
        return stringwidth(s, false, theSize);
  }
  
- void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag)
+ void drawstringright(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
  {
        position.x -= 2 / 3 * strlen(text) * theScale.x;
        drawstring(position, text, theScale, rgb, theAlpha, flag);
  }
  
- void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, float flag)
+ void drawstringcenter(vector position, string text, vector theScale, vector rgb, float theAlpha, int flag)
  {
        position.x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * theScale.x);
        drawstring(position, text, theScale, rgb, theAlpha, flag);
  }
  
  // return the string of the onscreen race timer
- string MakeRaceString(float cp, float mytime, float histime, float lapdelta, string hisname)
+ string MakeRaceString(int cp, float mytime, float theirtime, float lapdelta, string theirname)
  {
        string col;
        string timestr;
        string lapstr;
        lapstr = "";
  
-       if(histime == 0) // goal hit
+       if(theirtime == 0) // goal hit
        {
                if(mytime > 0)
                {
                        col = "^1";
                }
        }
-       else if(histime > 0) // anticipation
+       else if(theirtime > 0) // anticipation
        {
-               if(mytime >= histime)
-                       timestr = strcat("+", ftos_decimals(mytime - histime, TIME_DECIMALS));
+               if(mytime >= theirtime)
+                       timestr = strcat("+", ftos_decimals(mytime - theirtime, TIME_DECIMALS));
                else
-                       timestr = TIME_ENCODED_TOSTRING(TIME_ENCODE(histime));
+                       timestr = TIME_ENCODED_TOSTRING(TIME_ENCODE(theirtime));
                col = "^3";
        }
        else
        else
                cpname = _("Finish line");
  
-       if(histime < 0)
+       if(theirtime < 0)
                return strcat(col, cpname);
-       else if(hisname == "")
+       else if(theirname == "")
                return strcat(col, sprintf("%s (%s)", cpname, timestr));
        else
-               return strcat(col, sprintf("%s (%s %s)", cpname, timestr, strcat(hisname, col, lapstr)));
+               return strcat(col, sprintf("%s (%s %s)", cpname, timestr, strcat(theirname, col, lapstr)));
  }
  
  // Check if the given name already exist in race rankings? In that case, where? (otherwise return 0)
- float race_CheckName(string net_name) {
-       float i;
+ int race_CheckName(string net_name)
+ {
+       int i;
        for (i=RANKINGS_CNT-1;i>=0;--i)
                if(grecordholder[i] == net_name)
                        return i+1;
        return 0;
  }
  
float GetPlayerColorForce(int i)
int GetPlayerColorForce(int i)
  {
        if(!teamplay)
                return 0;
                return stof(getplayerkeyvalue(i, "colors")) & 15;
  }
  
float GetPlayerColor(int i)
int GetPlayerColor(int i)
  {
        if(!playerslots[i].gotscores) // unconnected
                return NUM_SPECTATOR;
@@@ -324,7 -337,7 +340,7 @@@ HUD panel
  } while(0)
  
  //basically the same code of draw_ButtonPicture and draw_VertButtonPicture for the menu
- void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, float vertical, float baralign, vector theColor, float theAlpha, float drawflag)
+ void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag)
  {
        if(!length_ratio || !theAlpha)
                return;
        }
  }
  
- void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, float drawflag)
+ void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, int drawflag)
  {
        if(!theAlpha)
                return;
@@@ -455,9 -468,9 +471,9 @@@ void weaponorder_swap(int i, int j, ent
  }
  
  string weaponorder_cmp_str;
float weaponorder_cmp(float i, float j, entity pass)
int weaponorder_cmp(int i, int j, entity pass)
  {
-       float ai, aj;
+       int ai, aj;
        ai = strstrofs(weaponorder_cmp_str, sprintf(" %d ", weaponorder[i].weapon), 0);
        aj = strstrofs(weaponorder_cmp_str, sprintf(" %d ", weaponorder[j].weapon), 0);
        return aj - ai; // the string is in REVERSE order (higher prio at the right is what we want, but higher prio first is the string)
@@@ -467,11 -480,12 +483,12 @@@ void HUD_Weapons(void
  {
        // declarations
        WepSet weapons_stat = WepSet_GetFromStat();
-       float i, f, a;
+       int i;
+       float f, a;
        float screen_ar;
        vector center = '0 0 0';
-       float weapon_count, weapon_id;
-       float row, column, rows = 0, columns = 0;
+       int weapon_count, weapon_id;
+       int row, column, rows = 0, columns = 0;
        bool vertical_order = true;
        float aspect = autocvar_hud_panel_weapons_aspect;
  
        // update generic hud functions
        HUD_Panel_UpdateCvars();
  
-       draw_beginBoldFont();
        // figure out weapon order (how the weapons are sorted) // TODO make this configurable
        if(weaponorder_bypriority != autocvar_cl_weaponpriority || !weaponorder[0])
        {
  
                // might as well commit suicide now, no reason to live ;)
                if (weapon_count == 0)
-               {
-                       draw_endBoldFont();
                        return;
-               }
  
                vector old_panel_size = panel_size;
                vector padded_panel_size = panel_size - '2 2 0' * panel_bg_padding;
                if(padded_panel_size.x / padded_panel_size.y < aspect)
                {
                        // maximum number of rows that allows to display items with the desired aspect ratio
-                       float max_rows = floor(padded_panel_size.y / (weapon_size.x / aspect));
+                       int max_rows = floor(padded_panel_size.y / (weapon_size.x / aspect));
                        columns = min(columns, ceil(weapon_count / max_rows));
                        rows = ceil(weapon_count / columns);
                        weapon_size.y = min(padded_panel_size.y / rows, weapon_size.x / aspect);
                }
                else
                {
-                       float max_columns = floor(padded_panel_size.x / (weapon_size.y * aspect));
+                       int max_columns = floor(padded_panel_size.x / (weapon_size.y * aspect));
                        rows = min(rows, ceil(weapon_count / max_columns));
                        columns = ceil(weapon_count / rows);
                        weapon_size.x = min(padded_panel_size.x / columns, aspect * weapon_size.y);
        HUD_Panel_DrawBg(1);
  
        if(center.x == -1)
-       {
-               draw_endBoldFont();
                return;
-       }
  
        if(panel_bg_padding)
        {
                        }
                }
        }
-       draw_endBoldFont();
  }
  
  // Ammo (#1)
- void DrawNadeScoreBar(vector myPos, vector mySize, vector color)
+ void DrawNadeProgressBar(vector myPos, vector mySize, float progress, vector color)
  {
        HUD_Panel_DrawProgressBar(
                myPos + eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize.x,
                mySize - eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize.x,
                autocvar_hud_panel_ammo_progressbar_name,
-               getstatf(STAT_NADE_BONUS_SCORE), 0, 0, color,
+               progress, 0, 0, color,
                autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
  }
  
- void DrawAmmoNades(vector myPos, vector mySize, float draw_expanding, float expand_time)
+ void DrawAmmoNades(vector myPos, vector mySize, bool draw_expanding, float expand_time)
  {
-       float theAlpha = 1, a, b;
-       vector nade_color, picpos, numpos;
+       float bonusNades    = getstatf(STAT_NADE_BONUS);
+       float bonusProgress = getstatf(STAT_NADE_BONUS_SCORE);
+       float bonusType     = getstati(STAT_NADE_BONUS_TYPE);
+       vector nadeColor    = Nade_Color(bonusType);
+       string nadeIcon     = Nade_Icon(bonusType);
  
-       nade_color = Nade_Color(getstati(STAT_NADE_BONUS_TYPE));
-       a = getstatf(STAT_NADE_BONUS);
-       b = getstatf(STAT_NADE_BONUS_SCORE);
+       vector iconPos, textPos;
  
        if(autocvar_hud_panel_ammo_iconalign)
        {
-               numpos = myPos;
-               picpos = myPos + eX * 2 * mySize.y;
+               iconPos = myPos + eX * 2 * mySize.y;
+               textPos = myPos;
        }
        else
        {
-               numpos = myPos + eX * mySize.y;
-               picpos = myPos;
+               iconPos = myPos;
+               textPos = myPos + eX * mySize.y;
        }
  
-       DrawNadeScoreBar(myPos, mySize, nade_color);
-       if(b > 0 || a > 0)
+       if(bonusNades > 0 || bonusProgress > 0)
        {
+               DrawNadeProgressBar(myPos, mySize, bonusProgress, nadeColor);
                if(autocvar_hud_panel_ammo_text)
-                       drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
+                       drawstring_aspect(textPos, ftos(bonusNades), eX * (2/3) * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
  
                if(draw_expanding)
-                       drawpic_aspect_skin_expanding(picpos, "nade_nbg", '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL, expand_time);
+                       drawpic_aspect_skin_expanding(iconPos, nadeIcon, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL, expand_time);
  
-               drawpic_aspect_skin(picpos, "nade_bg" , '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
-               drawpic_aspect_skin(picpos, "nade_nbg" , '1 1 0' * mySize.y, nade_color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
+               drawpic_aspect_skin(iconPos, nadeIcon, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
        }
  }
  
- void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent, float isInfinite)
+ void DrawAmmoItem(vector myPos, vector mySize, .int ammoType, bool isCurrent, bool isInfinite)
  {
        if(ammoType == ammo_none)
                return;
  
        // Initialize variables
  
-       float ammo;
+       int ammo;
        if(autocvar__hud_configure)
        {
                isCurrent = (ammoType == ammo_rockets); // Rockets always current
                textPos = myPos + eX * mySize.y;
        }
  
-       float isShadowed = (ammo <= 0 && !isCurrent && !isInfinite);
+       bool isShadowed = (ammo <= 0 && !isCurrent && !isInfinite);
  
        vector iconColor = isShadowed ? '0 0 0' : '1 1 1';
        vector textColor;
        drawpic_aspect_skin(iconPos, GetAmmoPicture(ammoType), '1 1 0' * mySize.y, iconColor, alpha, DRAWFLAG_NORMAL);
  }
  
float nade_prevstatus;
float nade_prevframe;
int nade_prevstatus;
int nade_prevframe;
  float nade_statuschange_time;
  void HUD_Ammo(void)
  {
                mySize -= '2 2 0' * panel_bg_padding;
        }
  
-       float rows = 0, columns, row, column;
+       int rows = 0, columns, row, column;
        float nade_cnt = getstatf(STAT_NADE_BONUS), nade_score = getstatf(STAT_NADE_BONUS_SCORE);
-       float draw_nades = (nade_cnt > 0 || nade_score > 0), nade_statuschange_elapsedtime;
-       float total_ammo_count;
+       bool draw_nades = (nade_cnt > 0 || nade_score > 0);
+       float nade_statuschange_elapsedtime;
+       int total_ammo_count;
  
        vector ammo_size;
        if (autocvar_hud_panel_ammo_onlycurrent)
                ammo_size.y = newSize;
        }
  
-       float i;
-       float infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
+       int i;
+       bool infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
        row = column = 0;
        if(autocvar_hud_panel_ammo_onlycurrent)
        {
        }
        else
        {
-               .float ammotype;
+               .int ammotype;
                row = column = 0;
                for(i = 0; i < AMMO_COUNT; ++i)
                {
        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)
+ void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, bool vertical, bool icon_right_align, vector color, float theAlpha, float fadelerp)
  {
        vector newPos = '0 0 0', newSize = '0 0 0';
        vector picpos, numpos;
        drawpic_aspect_skin_expanding(picpos, icon, '1 1 0' * newSize.y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL, fadelerp);
  }
  
- void DrawNumIcon(vector myPos, vector mySize, float x, string icon, float vertical, float icon_right_align, vector color, float theAlpha)
+ void DrawNumIcon(vector myPos, vector mySize, float x, string icon, bool vertical, bool icon_right_align, vector color, float theAlpha)
  {
        DrawNumIcon_expanding(myPos, mySize, x, icon, vertical, icon_right_align, color, theAlpha, 0);
  }
@@@ -1331,10 -1333,10 +1336,10 @@@ void HUD_Powerups(void
        }
  
        float panel_ar = mySize.x/mySize.y;
-       float is_vertical = (panel_ar < 1);
+       bool is_vertical = (panel_ar < 1);
        vector shield_offset = '0 0 0', strength_offset = '0 0 0', superweapons_offset = '0 0 0';
  
-       float superweapons_is = -1;
+       int superweapons_is = -1;
  
        if(superweapons_time)
        {
                }
        }
  
-       float shield_baralign, strength_baralign, superweapons_baralign;
-       float shield_iconalign, strength_iconalign, superweapons_iconalign;
+       bool shield_baralign, strength_baralign, superweapons_baralign;
+       bool shield_iconalign, strength_iconalign, superweapons_iconalign;
  
        if (autocvar_hud_panel_powerups_flip)
        {
  // Health/armor (#3)
  //
  
- // prev_* vars contain the health/armor at the previous FRAME
- // set to -1 when player is dead or was not playing
- float prev_health, prev_armor;
- float health_damagetime, armor_damagetime;
- float health_beforedamage, armor_beforedamage;
- // old_p_* vars keep track of previous values when smoothing value changes of the progressbar
- float old_p_health, old_p_armor;
- float old_p_healthtime, old_p_armortime;
- // prev_p_* vars contain the health/armor progressbar value at the previous FRAME
- // set to -1 to forcedly stop effects when we switch spectated player (e.g. from playerX: 70h to playerY: 50h)
- float prev_p_health, prev_p_armor;
  
  void HUD_HealthArmor(void)
  {
-       float armor, health, fuel;
+       int armor, health, fuel;
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_healtharmor) return;
        }
  
        HUD_Panel_UpdateCvars();
+       draw_beginBoldFont();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
                mySize -= '2 2 0' * panel_bg_padding;
        }
  
-       float baralign = autocvar_hud_panel_healtharmor_baralign;
-       float iconalign = autocvar_hud_panel_healtharmor_iconalign;
+       int baralign = autocvar_hud_panel_healtharmor_baralign;
+       int iconalign = autocvar_hud_panel_healtharmor_iconalign;
  
-     float maxhealth = autocvar_hud_panel_healtharmor_maxhealth;
-     float maxarmor = autocvar_hud_panel_healtharmor_maxarmor;
+     int maxhealth = autocvar_hud_panel_healtharmor_maxhealth;
+     int maxarmor = autocvar_hud_panel_healtharmor_maxarmor;
        if(autocvar_hud_panel_healtharmor == 2) // combined health and armor display
        {
                vector v;
        else
        {
                float panel_ar = mySize.x/mySize.y;
-               float is_vertical = (panel_ar < 1);
+               bool is_vertical = (panel_ar < 1);
                vector health_offset = '0 0 0', armor_offset = '0 0 0';
                if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1))
                {
                                armor_offset.y = mySize.y;
                }
  
-               float health_baralign, armor_baralign, fuel_baralign;
-               float health_iconalign, armor_iconalign;
+               bool health_baralign, armor_baralign, fuel_baralign;
+               bool health_iconalign, armor_iconalign;
                if (autocvar_hud_panel_healtharmor_flip)
                {
                        armor_baralign = (autocvar_hud_panel_healtharmor_baralign == 2 || autocvar_hud_panel_healtharmor_baralign == 1);
                        HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", fuel/100, is_vertical, fuel_baralign, autocvar_hud_progressbar_fuel_color, panel_fg_alpha * 0.8, DRAWFLAG_NORMAL);
                }
        }
+       draw_endBoldFont();
  }
  
  // Notification area (#4)
@@@ -1824,7 -1820,7 +1823,7 @@@ void HUD_Notify(void
        float fade_time = max(0, autocvar_hud_panel_notify_fadetime);
        float icon_aspect = max(1, autocvar_hud_panel_notify_icon_aspect);
  
-       float entry_count = bound(1, floor(NOTIFY_MAX_ENTRIES * size.y / size.x), NOTIFY_MAX_ENTRIES);
+       int entry_count = bound(1, floor(NOTIFY_MAX_ENTRIES * size.y / size.x), NOTIFY_MAX_ENTRIES);
        float entry_height = size.y / entry_count;
  
        float panel_width_half = size.x * 0.5;
  
        vector attacker_pos, victim_pos, icon_pos;
        string attacker, victim, icon;
-       float i, j, count, step, limit, alpha;
+       int i, j, count, step, limit;
+       float alpha;
  
        if (autocvar_hud_panel_notify_flip)
        {
@@@ -1980,167 -1977,6 +1980,167 @@@ void HUD_Timer(void
  
  // Radar (#6)
  //
 +
 +float HUD_Radar_Clickable()
 +{
 +      return hud_panel_radar_mouse && !hud_panel_radar_temp_hidden;
 +}
 +
 +void HUD_Radar_Show_Maximized(float show,float clickable)
 +{
 +      hud_panel_radar_maximized = show;
 +      hud_panel_radar_temp_hidden = 0;
 +      
 +      if ( show )
 +      {
 +              if (clickable)
 +              {
 +                      if(autocvar_hud_cursormode)
 +                              setcursormode(1);
 +                      hud_panel_radar_mouse = 1; 
 +              }
 +      }
 +      else if ( hud_panel_radar_mouse )
 +      {
 +              hud_panel_radar_mouse = 0;
 +              mouseClicked = 0;
 +              if(autocvar_hud_cursormode)
 +              if(!mv_active)
 +                      setcursormode(0);
 +      }
 +}
 +void HUD_Radar_Hide_Maximized()
 +{
 +      HUD_Radar_Show_Maximized(false,false);
 +}
 +
 +
 +float HUD_Radar_InputEvent(float bInputType, float nPrimary, float nSecondary)
 +{
 +      if(!hud_panel_radar_maximized || !hud_panel_radar_mouse || 
 +              autocvar__hud_configure || mv_active)
 +              return false;
 +
 +      if(bInputType == 3)
 +      {
 +              mousepos_x = nPrimary;
 +              mousepos_y = nSecondary;
 +              return true;
 +      }
 +
 +      if(nPrimary == K_MOUSE1)
 +      {
 +              if(bInputType == 0) // key pressed
 +                      mouseClicked |= S_MOUSE1;
 +              else if(bInputType == 1) // key released
 +                      mouseClicked -= (mouseClicked & S_MOUSE1);
 +      }
 +      else if(nPrimary == K_MOUSE2)
 +      {
 +              if(bInputType == 0) // key pressed
 +                      mouseClicked |= S_MOUSE2;
 +              else if(bInputType == 1) // key released
 +                      mouseClicked -= (mouseClicked & S_MOUSE2);
 +      }
 +      else if ( nPrimary == K_ESCAPE && bInputType == 0 )
 +      {
 +              HUD_Radar_Hide_Maximized();
 +      }
 +      else
 +      {
 +              // allow console/use binds to work without hiding the map
 +              string con_keys;
 +              float keys;
 +              float i;
 +              con_keys = strcat(findkeysforcommand("toggleconsole", 0)," ",findkeysforcommand("+use", 0)) ;
 +              keys = tokenize(con_keys); // findkeysforcommand returns data for this
 +              for (i = 0; i < keys; ++i)
 +              {
 +                      if(nPrimary == stof(argv(i)))
 +                              return false;
 +              }
 +              
 +              if ( getstati(STAT_HEALTH) <= 0 )
 +              {
 +                      // Show scoreboard
 +                      if ( bInputType < 2 )
 +                      {
 +                              con_keys = findkeysforcommand("+showscores", 0);
 +                              keys = tokenize(con_keys);
 +                              for (i = 0; i < keys; ++i)
 +                              {
 +                                      if ( nPrimary == stof(argv(i)) )
 +                                      {
 +                                              hud_panel_radar_temp_hidden = bInputType == 0;
 +                                              return false;
 +                                      }
 +                              }
 +                      }
 +              }
 +              else if ( bInputType == 0 )
 +                      HUD_Radar_Hide_Maximized();
 +              
 +              return false;
 +      }
 +
 +      return true;
 +}
 +
 +void HUD_Radar_Mouse()
 +{
 +      if ( !hud_panel_radar_mouse ) return;
 +      if(mv_active) return;
 +      
 +      if ( intermission )
 +      {
 +              HUD_Radar_Hide_Maximized();
 +              return;
 +      }
 +      
 +      if(mouseClicked & S_MOUSE2)
 +      {
 +              HUD_Radar_Hide_Maximized();
 +              return;
 +      }
 +      
 +      if(!autocvar_hud_cursormode)
 +      {
 +              mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed;
 +
 +              mousepos_x = bound(0, mousepos_x, vid_conwidth);
 +              mousepos_y = bound(0, mousepos_y, vid_conheight);
 +      }
 +
 +      HUD_Panel_UpdateCvars();
 +      
 +      
 +      panel_size = autocvar_hud_panel_radar_maximized_size;
 +      panel_size_x = bound(0.2, panel_size_x, 1) * vid_conwidth;
 +      panel_size_y = bound(0.2, panel_size_y, 1) * vid_conheight;
 +      panel_pos_x = (vid_conwidth - panel_size_x) / 2;
 +      panel_pos_y = (vid_conheight - panel_size_y) / 2;
 +              
 +      if(mouseClicked & S_MOUSE1)
 +      {
 +              // click outside
 +              if ( mousepos_x < panel_pos_x || mousepos_x > panel_pos_x + panel_size_x ||
 +                       mousepos_y < panel_pos_y || mousepos_y > panel_pos_y + panel_size_y )
 +              {
 +                      HUD_Radar_Hide_Maximized();
 +                      return;
 +              }
 +              vector pos = teamradar_texcoord_to_3dcoord(teamradar_2dcoord_to_texcoord(mousepos),view_origin_z);
 +              localcmd(sprintf("cmd ons_spawn %f %f %f",pos_x,pos_y,pos_z));
 +              
 +              HUD_Radar_Hide_Maximized();
 +              return;
 +      }
 +      
 +
 +      const vector cursor_size = '32 32 0';
 +      drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), cursor_size, '1 1 1', 0.8, DRAWFLAG_NORMAL);
 +}
 +
  void HUD_Radar(void)
  {
        if (!autocvar__hud_configure)
                        }
                }
        }
-       
 +      if ( hud_panel_radar_temp_hidden )
 +              return;
 +
        HUD_Panel_UpdateCvars();
  
        float f = 0;
                mySize -= '2 2 0' * panel_bg_padding;
        }
  
-       float color2;
+       int color2;
        entity tm;
        float scale2d, normalsize, bigsize;
  
  
        for(tm = world; (tm = find(tm, classname, "radarlink")); )
                draw_teamradar_link(tm.origin, tm.velocity, tm.team);
-       
++
 +      vector coord;
 +      vector brightcolor;
        for(tm = world; (tm = findflags(tm, teamradar_icon, 0xFFFFFF)); )
-               
 +      {
 +              if ( hud_panel_radar_mouse )
 +              if ( tm.health > 0 )
 +              if ( tm.team == myteam+1 )
 +              {
 +                      coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(tm.origin));
 +                      if ( vlen(mousepos-coord) < 8 )
 +                      {
 +                              brightcolor_x = min(1,tm.teamradar_color_x*1.5);
 +                              brightcolor_y = min(1,tm.teamradar_color_y*1.5);
 +                              brightcolor_z = min(1,tm.teamradar_color_z*1.5);
 +                              drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
 +                      }
 +              }
++
                draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm, tm.teamradar_color, panel_fg_alpha);
 +      }
        for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
        {
                color2 = GetPlayerColor(tm.sv_entnum);
        draw_teamradar_player(view_origin, view_angles, '1 1 1');
  
        drawresetcliparea();
-       
++
 +      if ( hud_panel_radar_mouse )
 +      {                       
 +              string message = "Click to select teleport destination";
-               
++
 +              if ( getstati(STAT_HEALTH) <= 0 )
 +              {
 +                      message = "Click to select spawn location";
 +              }
-               
++
 +              drawcolorcodedstring(pos + '0.5 0 0' * (mySize_x - stringwidth(message, true, hud_fontsize)) - '0 1 0' * hud_fontsize_y * 2,
 +                                                       message, hud_fontsize, hud_panel_radar_foreground_alpha, DRAWFLAG_NORMAL);
-               
++
 +              hud_panel_radar_bottom = pos_y + mySize_y + hud_fontsize_y;
 +      }
  }
  
  // Score (#7)
@@@ -2371,9 -2170,9 +2371,9 @@@ void HUD_Score_Rankings(vector pos, vec
  {
        float score;
        entity tm = world, pl;
-       float SCOREPANEL_MAX_ENTRIES = 6;
+       int SCOREPANEL_MAX_ENTRIES = 6;
        float SCOREPANEL_ASPECTRATIO = 2;
-       float entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize.y/mySize.x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES);
+       int entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize.y/mySize.x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES);
        vector fontsize = '1 1 0' * (mySize.y/entries);
  
        vector rgb, score_color;
        float name_size = mySize.x*0.75;
        float spacing_size = mySize.x*0.04;
        const float highlight_alpha = 0.2;
-       float i = 0, me_printed = 0, first_pl = 0;
+       int i = 0, first_pl = 0;
+       bool me_printed = false;
        string s;
        if (autocvar__hud_configure)
        {
                {
                        if (i == first_pl)
                                rgb = '0 1 0'; //first: green
-                       me_printed = 1;
+                       me_printed = true;
                        drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
                }
                if (team_count)
@@@ -2513,7 -2313,7 +2514,7 @@@ void HUD_Score(void
        vector distribution_color;
        entity tm, pl, me;
  
-       me = playerslots[player_localentnum - 1];
+       me = playerslots[current_player];
  
        if((scores_flags[ps_primary] & SFL_TIME) && !teamplay) { // race/cts record display on HUD
                string timer, distrtimer;
@@@ -2682,8 -2482,6 +2683,6 @@@ void HUD_RaceTimer (void
  
        HUD_Panel_UpdateCvars();
  
-       draw_beginBoldFont();
        vector pos, mySize;
        pos = panel_pos;
        mySize = panel_size;
        if(autocvar__hud_configure)
        {
                s = "0:13:37";
+               draw_beginBoldFont();
                drawstring(pos + eX * 0.5 * mySize.x - '0.5 0 0' * stringwidth(s, false, '0.60 0.60 0' * mySize.y), s, '0.60 0.60 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               draw_endBoldFont();
                s = _("^1Intermediate 1 (+15.42)");
                drawcolorcodedstring(pos + eX * 0.5 * mySize.x - '0.5 0 0' * stringwidth(s, true, '1 1 0' * 0.20 * mySize.y) + eY * 0.60 * mySize.y, s, '1 1 0' * 0.20 * mySize.y, panel_fg_alpha, DRAWFLAG_NORMAL);
                s = sprintf(_("^1PENALTY: %.1f (%s)"), 2, "missing a checkpoint");
                        }
                }
  
+               draw_beginBoldFont();
                if(forcetime != "")
                {
                        a = bound(0, (time - race_checkpointtime) / 0.5, 1);
                        s = TIME_ENCODED_TOSTRING(TIME_ENCODE(time + TIME_DECODE(race_penaltyaccumulator) - race_laptime));
                        drawstring(pos + eX * 0.5 * mySize.x - '0.5 0 0' * stringwidth(s, false, '0.6 0.6 0' * mySize.y), s, '0.6 0.6 0' * mySize.y, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
                }
+               draw_endBoldFont();
        }
        else
        {
                        }
                }
        }
-       draw_endBoldFont();
  }
  
  // Vote window (#9)
  //
- float vote_yescount;
- float vote_nocount;
- float vote_needed;
- float vote_highlighted; // currently selected vote
- float vote_active; // is there an active vote?
- float vote_prev; // previous state of vote_active to check for a change
- float vote_alpha;
- float vote_change; // "time" when vote_active changed
  
  void HUD_Vote(void)
  {
  // Mod icons panel (#10)
  //
  
float mod_active; // is there any active mod icon?
bool mod_active; // is there any active mod icon?
  
- void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, float i)
+ void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
  {
-       float stat = -1;
+       int stat = -1;
        string pic = "";
        vector color = '0 0 0';
        switch(i)
@@@ -3032,7 -2825,8 +3026,8 @@@ void HUD_Mod_CA(vector myPos, vector my
                layout = autocvar_hud_panel_modicons_ca_layout;
        else //if(gametype == MAPINFO_TYPE_FREEZETAG)
                layout = autocvar_hud_panel_modicons_freezetag_layout;
-       float rows, columns, aspect_ratio;
+       int rows, columns;
+       float aspect_ratio;
        aspect_ratio = (layout) ? 2 : 1;
        rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
        columns = ceil(team_count/rows);
  
  // CTF HUD modicon section
  float redflag_prevframe, blueflag_prevframe; // status during previous frame
float redflag_prevstatus, blueflag_prevstatus; // last remembered status
int redflag_prevstatus, blueflag_prevstatus; // last remembered status
  float redflag_statuschange_time, blueflag_statuschange_time; // time when the status changed
  
  void HUD_Mod_CTF_Reset(void)
@@@ -3072,9 -2866,9 +3067,9 @@@ void HUD_Mod_CTF(vector pos, vector myS
        vector flag_size;
        float f; // every function should have that
  
-       float redflag, blueflag; // current status
+       int redflag, blueflag; // current status
        float redflag_statuschange_elapsedtime, blueflag_statuschange_elapsedtime; // time since the status changed
-       float stat_items;
+       int stat_items;
  
        stat_items = getstati(STAT_ITEMS, 0, 24);
        redflag = (stat_items/IT_RED_FLAG_TAKEN) & 3;
@@@ -3216,9 -3010,9 +3211,9 @@@ void HUD_Mod_KH(vector pos, vector mySi
  
        // Read current state
  
-       float state = getstati(STAT_KH_KEYS);
-       float i, key_state;
-       float all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
+       int state = getstati(STAT_KH_KEYS);
+       int i, key_state;
+       int all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
        all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
  
        for(i = 0; i < 4; ++i)
  }
  
  // Keepaway HUD mod icon
float kaball_prevstatus; // last remembered status
int kaball_prevstatus; // last remembered status
  float kaball_statuschange_time; // time when the status changed
  
  // we don't need to reset for keepaway since it immediately
@@@ -3352,8 -3146,8 +3347,8 @@@ void HUD_Mod_Keepaway(vector pos, vecto
        float BLINK_FREQ = 5;
        float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
  
-       float stat_items = getstati(STAT_ITEMS, 0, 24);
-       float kaball = (stat_items/IT_KEY1) & 1;
+       int stat_items = getstati(STAT_ITEMS, 0, 24);
+       int kaball = (stat_items/IT_KEY1) & 1;
  
        if(kaball != kaball_prevstatus)
        {
  // Nexball HUD mod icon
  void HUD_Mod_NexBall(vector pos, vector mySize)
  {
-       float stat_items, nb_pb_starttime, dt, p;
+       float nb_pb_starttime, dt, p;
+       int stat_items;
  
        stat_items = getstati(STAT_ITEMS, 0, 24);
        nb_pb_starttime = getstatf(STAT_NB_METERSTART);
@@@ -3418,7 -3213,7 +3414,7 @@@ float srecordtime_prev; // last remembe
  float srecordtime_change_time; // time when srecordtime last changed
  
  float race_status_time;
float race_status_prev;
int race_status_prev;
  string race_status_name_prev;
  void HUD_Mod_Race(vector pos, vector mySize)
  {
        }
  }
  
- void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, float i)
+ void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
  {
        float stat = -1;
        string pic = "";
@@@ -3627,7 -3422,8 +3623,8 @@@ void HUD_Mod_Dom(vector myPos, vector m
        mod_active = 1; // required in each mod function that always shows something
  
        int layout = autocvar_hud_panel_modicons_dom_layout;
-       float rows, columns, aspect_ratio;
+       int rows, columns;
+       float aspect_ratio;
        aspect_ratio = (layout) ? 3 : 1;
        rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
        columns = ceil(team_count/rows);
@@@ -3667,7 -3463,7 +3664,7 @@@ void HUD_ModIcons_SetFunc(
        }
  }
  
float mod_prev; // previous state of mod_active to check for a change
int mod_prev; // previous state of mod_active to check for a change
  float mod_alpha;
  float mod_change; // "time" when mod_active changed
  
@@@ -3861,7 -3657,7 +3858,7 @@@ void HUD_Chat(void
  //
  float prevfps;
  float prevfps_time;
float framecounter;
int framecounter;
  
  float frametimeavg;
  float frametimeavg1; // 1 frame ago
@@@ -3983,7 -3779,7 +3980,7 @@@ void HUD_InfoMessages(void
                        if(spectatee_status == -1)
                                s = _("^1Observing");
                        else
-                               s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(player_localentnum - 1));
+                               s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(current_player));
                        drawInfoMessage(s);
  
                        if(spectatee_status == -1)
  //
  vector acc_prevspeed;
  float acc_prevtime, acc_avg, top_speed, top_speed_time;
+ float physics_update_time, discrete_speed, discrete_acceleration;
  void HUD_Physics(void)
  {
        if(!autocvar__hud_configure)
                acc_prevspeed = vel;
                acc_prevtime = time;
  
-               f = bound(0, f * 10, 1);
-               acc_avg = acc_avg * (1 - f) + acceleration * f;
+               if(autocvar_hud_panel_physics_acceleration_movingaverage)
+               {
+                       f = bound(0, f * 10, 1);
+                       acc_avg = acc_avg * (1 - f) + acceleration * f;
+                       acceleration = acc_avg;
+               }
+       }
+       int acc_decimals = 2;
+       if(time > physics_update_time)
+       {
+               // workaround for ftos_decimals returning a negative 0
+               if(discrete_acceleration > -1 / pow(10, acc_decimals) && discrete_acceleration < 0)
+                       discrete_acceleration = 0;
+               discrete_acceleration = acceleration;
+               discrete_speed = speed;
+               physics_update_time += autocvar_hud_panel_physics_update_interval;
        }
  
        //compute layout
                else
                        acceleration_offset.y = panel_size.y;
        }
-       float speed_baralign, acceleration_baralign;
+       int speed_baralign, acceleration_baralign;
        if (autocvar_hud_panel_physics_baralign == 1)
                acceleration_baralign = speed_baralign = 1;
      else if(autocvar_hud_panel_physics_baralign == 4)
                //else
                        //tmp_offset_x = 0;
                tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
-               drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(speed), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring_aspect(panel_pos + speed_offset + tmp_offset, ftos(discrete_speed), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
  
                //draw speed unit
                if (speed_baralign)
  
                f = acceleration/autocvar_hud_panel_physics_acceleration_max;
                if (autocvar_hud_panel_physics_acceleration_progressbar_nonlinear)
-                       f = sqrt(f);
+                       f = (f >= 0 ? sqrt(f) : -sqrt(-f));
  
                if (acceleration_progressbar_scale) // allow progressbar to go out of panel bounds
                {
  
                HUD_Panel_DrawProgressBar(panel_pos + acceleration_offset + tmp_offset, tmp_size, "accelbar", f, 0, acceleration_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
        }
-       tmp_size.x = panel_size.x;
-       tmp_size.y = panel_size.y * text_scale;
-       tmp_offset.x = 0;
-       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);
+       if(autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 3)
+       {
+               tmp_size.x = panel_size.x;
+               tmp_size.y = panel_size.y * text_scale;
+               tmp_offset.x = 0;
+               tmp_offset.y = (panel_size.y - tmp_size.y) / 2;
+               drawstring_aspect(panel_pos + acceleration_offset + tmp_offset, strcat(ftos_decimals(discrete_acceleration, acc_decimals), "g"), tmp_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       }
  
        draw_endBoldFont();
  }
  
  // CenterPrint (#16)
  //
- const float CENTERPRINT_MAX_MSGS = 10;
- const float CENTERPRINT_MAX_ENTRIES = 50;
+ const int CENTERPRINT_MAX_MSGS = 10;
+ const int CENTERPRINT_MAX_ENTRIES = 50;
  const float CENTERPRINT_SPACING = 0.7;
float cpm_index;
int cpm_index;
  string centerprint_messages[CENTERPRINT_MAX_MSGS];
float centerprint_msgID[CENTERPRINT_MAX_MSGS];
int centerprint_msgID[CENTERPRINT_MAX_MSGS];
  float centerprint_time[CENTERPRINT_MAX_MSGS];
  float centerprint_expire_time[CENTERPRINT_MAX_MSGS];
float centerprint_countdown_num[CENTERPRINT_MAX_MSGS];
float centerprint_showing;
int centerprint_countdown_num[CENTERPRINT_MAX_MSGS];
bool centerprint_showing;
  
- void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num)
+ void centerprint_generic(int new_id, string strMessage, float duration, int countdown_num)
  {
        //printf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num);
-       float i, j;
+       int i, j;
  
        if(strMessage == "" && new_id == 0)
                return;
@@@ -4467,7 -4283,7 +4484,7 @@@ void centerprint_hud(string strMessage
  
  void reset_centerprint_messages(void)
  {
-       float i;
+       int i;
        for (i=0; i<CENTERPRINT_MAX_MSGS; ++i)
        {
                centerprint_expire_time[i] = 0;
@@@ -4494,15 -4310,23 +4511,23 @@@ void HUD_CenterPrint (void
                        reset_centerprint_messages();
                if (time > hud_configure_cp_generation_time)
                {
-                       float r;
-                       r = random();
-                       if (r > 0.75)
-                               centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: ^COUNT"), 1, 10);
-                       else if (r > 0.5)
-                               centerprint_generic(0, sprintf("^1Multiline message at time %s that\n^1lasts longer than normal", seconds_tostring(time)), 20, 0);
+                       if(HUD_PANEL(CENTERPRINT) == highlightedPanel)
+                       {
+                               float r;
+                               r = random();
+                               if (r > 0.8)
+                                       centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: ^COUNT"), 1, 10);
+                               else if (r > 0.55)
+                                       centerprint_generic(0, sprintf("^1Multiline message at time %s that\n^1lasts longer than normal", seconds_tostring(time)), 20, 0);
+                               else
+                                       centerprint_hud(sprintf("Message at time %s", seconds_tostring(time)));
+                               hud_configure_cp_generation_time = time + 1 + random()*4;
+                       }
                        else
-                               centerprint_hud(sprintf("Message at time %s", seconds_tostring(time)));
-                       hud_configure_cp_generation_time = time + 1 + random()*4;
+                       {
+                               centerprint_generic(0, sprintf("Centerprint message", seconds_tostring(time)), 10, 0);
+                               hud_configure_cp_generation_time = time + 10 - random()*3;
+                       }
                }
        }
  
                hud_fade_alpha = 1 - autocvar__menu_alpha;
        }
        HUD_Panel_UpdateCvars();
-       
 -      if(scoreboard_fade_alpha)
 +      if ( HUD_Radar_Clickable() )
 +      {
 +              if (hud_panel_radar_bottom >= 0.96 * vid_conheight)
 +                      return;
-               
++
 +              panel_pos = eY * hud_panel_radar_bottom + eX * 0.5 * (vid_conwidth - panel_size_x);
 +              panel_size_y = min(panel_size_y, vid_conheight - hud_panel_radar_bottom);
 +      }
 +      else if(scoreboard_fade_alpha)
        {
                hud_fade_alpha = hud_fade_alpha_save;
  
                panel_size -= '2 2 0' * panel_bg_padding;
        }
  
-       float entries, height;
+       int entries;
+       float height;
        vector fontsize;
        // entries = bound(1, floor(CENTERPRINT_MAX_ENTRIES * 4 * panel_size_y/panel_size_x), CENTERPRINT_MAX_ENTRIES);
        // height = panel_size_y/entries;
        fontsize = '1 1 0' * height;
        entries = bound(1, floor(panel_size.y/height), CENTERPRINT_MAX_ENTRIES);
  
-       float i, j, k, n, g;
+       int i, j, k, n, g;
        float a, sz, align, current_msg_posY = 0, msg_size;
        vector pos;
        string ts;
-       float all_messages_expired = true;
+       bool all_messages_expired = true;
  
        pos = panel_pos;
        if (autocvar_hud_panel_centerprint_flip)
  //
  void HUD_Buffs(void)
  {
-       float buffs = getstati(STAT_BUFFS, 0, 24);
+       int buffs = getstati(STAT_BUFFS, 0, 24);
        if(!autocvar__hud_configure)
        {
                if(!autocvar_hud_panel_buffs) return;
                buffs = Buff_Type_first.items; // force first buff
        }
  
-       float b = 0; // counter to tell other functions that we have buffs
+       int b = 0; // counter to tell other functions that we have buffs
        entity e;
        string s = "";
        for(e = Buff_Type_first; e; e = e.enemy) if(buffs & e.items)
        }
  
        //float panel_ar = mySize_x/mySize_y;
-       //float is_vertical = (panel_ar < 1);
+       //bool is_vertical = (panel_ar < 1);
        //float buff_iconalign = autocvar_hud_panel_buffs_iconalign;
        vector buff_offset = '0 0 0';
  
@@@ -4810,12 -4627,10 +4836,10 @@@ void HUD_Main (void
                hud_skin_prev = strzone(autocvar_hud_skin);
        }
  
-     current_player = player_localentnum;
        // draw the dock
        if(autocvar_hud_dock != "" && autocvar_hud_dock != "0")
        {
-               float f;
+               int f;
                vector color;
                float hud_dock_color_team = autocvar_hud_dock_color_team;
                if((teamplay) && hud_dock_color_team) {
                {
                        string hud_dock_color = autocvar_hud_dock_color;
                        if(hud_dock_color == "shirt") {
-                               f = stof(getplayerkeyvalue(current_player - 1, "colors"));
+                               f = stof(getplayerkeyvalue(current_player, "colors"));
                                color = colormapPaletteColor(floor(f / 16), 0);
                        }
                        else if(hud_dock_color == "pants") {
-                               f = stof(getplayerkeyvalue(current_player - 1, "colors"));
+                               f = stof(getplayerkeyvalue(current_player, "colors"));
                                color = colormapPaletteColor(f % 16, 1);
                        }
                        else
                for(i = 0; i < HUD_PANEL_NUM; ++i)
                        panel_order[i] = -1;
                string s = "";
-               float p_num, warning = false;
-               float argc = tokenize_console(autocvar__hud_panelorder);
+               int p_num;
+               bool warning = false;
+               int argc = tokenize_console(autocvar__hud_panelorder);
                if (argc > HUD_PANEL_NUM)
                        warning = true;
                //first detect wrong/missing panel numbers
                for(i = 0; i < HUD_PANEL_NUM; ++i) {
-                       p_num = stof(argv(i));
+                       p_num = stoi(argv(i));
                        if (p_num >= 0 && p_num < HUD_PANEL_NUM) { //correct panel number?
                                if (panel_order[p_num] == -1) //found for the first time?
                                        s = strcat(s, ftos(p_num), " ");
diff --combined qcsrc/client/hud.qh
index 251e9f23be853b51ba2fdea86e525035cd1785d6,5bc2ca4a736c1529b6b91a2bac7478a6291f5e51..74701acffb99198904263b303ec4ced903a49a25
@@@ -1,7 -1,7 +1,7 @@@
  #ifndef HUD_H
  #define HUD_H
  
- #include "../common/weapons/weapons.qh"
+ #include "../common/weapons/all.qh"
  
  const int HUD_PANEL_MAX = 24;
  entity hud_panel[HUD_PANEL_MAX];
@@@ -12,16 -12,24 +12,29 @@@ int HUD_PANEL_LAST
  int panel_order[HUD_PANEL_MAX];
  string hud_panelorder_prev;
  
 -float hud_draw_maximized;
 -float hud_panel_radar_maximized;
 -float chat_panel_modified;
 -float radar_panel_modified;
 -
 +bool hud_draw_maximized;
 +bool hud_panel_radar_maximized;
 +bool hud_panel_radar_mouse;
 +float hud_panel_radar_bottom;
 +bool hud_panel_radar_temp_hidden;
 +bool chat_panel_modified;
 +bool radar_panel_modified;
 +
 +void HUD_Radar_Hide_Maximized();
 +
+ void HUD_Reset (void);
+ void HUD_Main (void);
+ int vote_yescount;
+ int vote_nocount;
+ int vote_needed;
+ int vote_highlighted; // currently selected vote
+ int vote_active; // is there an active vote?
+ int vote_prev; // previous state of vote_active to check for a change
+ float vote_alpha;
+ float vote_change; // "time" when vote_active changed
  vector mousepos;
  vector panel_click_distance; // mouse cursor distance from the top left corner of the panel (saved only upon a click)
  vector panel_click_resizeorigin; // coordinates for opposite point when resizing
@@@ -74,18 -82,19 +87,19 @@@ vector panel_size_backup
  vector panel_size_copied;
  
  entity panel;
- .string panel_name;
- .int panel_id;
- .vector current_panel_pos;
- .vector current_panel_size;
- .string current_panel_bg;
- .float current_panel_bg_alpha;
- .float current_panel_bg_border;
- .vector current_panel_bg_color;
- .float current_panel_bg_color_team;
- .float current_panel_bg_padding;
- .float current_panel_fg_alpha;
- .float update_time;
+ entityclass(HUDPanel);
+ class(HUDPanel) .string panel_name;
+ class(HUDPanel) .int panel_id;
+ class(HUDPanel) .vector current_panel_pos;
+ class(HUDPanel) .vector current_panel_size;
+ class(HUDPanel) .string current_panel_bg;
+ class(HUDPanel) .float current_panel_bg_alpha;
+ class(HUDPanel) .float current_panel_bg_border;
+ class(HUDPanel) .vector current_panel_bg_color;
+ class(HUDPanel) .float current_panel_bg_color_team;
+ class(HUDPanel) .float current_panel_bg_padding;
+ class(HUDPanel) .float current_panel_fg_alpha;
+ class(HUDPanel) .float update_time;
  float panel_enabled;
  vector panel_pos;
  vector panel_size;
@@@ -102,12 -111,31 +116,31 @@@ string panel_bg_border_str
  float panel_bg_padding;
  string panel_bg_padding_str;
  
- .void() panel_draw;
class(HUDPanel) .void() panel_draw;
  
  float current_player;
  
  float GetPlayerColorForce(int i);
  
+ float stringwidth_colors(string s, vector theSize);
+ int GetPlayerColor(int i);
+ string GetPlayerName(int i);
+ float stringwidth_nocolors(string s, vector theSize);
+ void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag);
+ // prev_* vars contain the health/armor at the previous FRAME
+ // set to -1 when player is dead or was not playing
+ int prev_health, prev_armor;
+ float health_damagetime, armor_damagetime;
+ int health_beforedamage, armor_beforedamage;
+ // old_p_* vars keep track of previous values when smoothing value changes of the progressbar
+ int old_p_health, old_p_armor;
+ float old_p_healthtime, old_p_armortime;
+ // prev_p_* vars contain the health/armor progressbar value at the previous FRAME
+ // set to -1 to forcedly stop effects when we switch spectated player (e.g. from playerX: 70h to playerY: 50h)
+ int prev_p_health, prev_p_armor;
  
  #define HUD_PANELS(HUD_PANEL)                                                                                                                                                                                 \
        HUD_PANEL(WEAPONS      , HUD_Weapons      , weapons)                                                                                                                    \
@@@ -199,9 -227,9 +232,9 @@@ HUD_PANELS(HUD_PANEL
                        panel_bg_color = autocvar_hud_panel_bg_color;                                                           \
                } else {                                                                                                    \
                        if (panel_bg_color_str == "shirt") {                                                                    \
-                               panel_bg_color = colormapPaletteColor(floor(stof(getplayerkeyvalue(current_player - 1, "colors")) / 16), 0);\
+                               panel_bg_color = colormapPaletteColor(floor(stof(getplayerkeyvalue(current_player, "colors")) / 16), 0); \
                        } else if (panel_bg_color_str == "pants") {                                                             \
-                               panel_bg_color = colormapPaletteColor(stof(getplayerkeyvalue(current_player - 1, "colors")) % 16, 1);\
+                               panel_bg_color = colormapPaletteColor(stof(getplayerkeyvalue(current_player, "colors")) % 16, 1); \
                        } else {                                                                                                \
                                panel_bg_color = stov(panel_bg_color_str);                                                          \
                        }                                                                                                       \
  } while(0)
  
  // return smoothly faded pos and size of given panel when a dialog is active
- #define HUD_Panel_UpdatePosSize_ForMenu() do {                                                                      \
-       vector menu_enable_pos;                                                                                         \
-       vector menu_enable_size = '0 0 0';                                                                              \
-       float menu_enable_maxsize_x = 0.3 * vid_conwidth;                                                               \
-       float menu_enable_maxsize_y = 0.18 * vid_conheight;                                                             \
-       if (panel_size.x > panel_size.y) {                                                                              \
-               if (panel_size.y > menu_enable_maxsize_y) {                                                                 \
-                       menu_enable_size.y = menu_enable_maxsize_y;                                                             \
-                       menu_enable_size.x = panel_size.x * (menu_enable_maxsize_y/panel_size.y);                               \
-                       panel_size = (1 - autocvar__menu_alpha) * panel_size + (autocvar__menu_alpha) * menu_enable_size;       \
-               }                                                                                                           \
-               menu_enable_pos = eX * 0.5 * vid_conwidth - eX * 0.5 * panel_size.x + eY * (vid_conheight - menu_enable_maxsize_y);\
-       } else {                                                                                                        \
-               if (panel_size.x > menu_enable_maxsize_x) {                                                                 \
-                       menu_enable_size.x = menu_enable_maxsize_x;                                                             \
-                       menu_enable_size.y = panel_size.y * (menu_enable_maxsize_x/panel_size.x);                               \
-                       panel_size = (1 - autocvar__menu_alpha) * panel_size + (autocvar__menu_alpha) * menu_enable_size;       \
-               }                                                                                                           \
-               menu_enable_pos = eY * 0.5 * vid_conheight - eY * 0.5 * panel_size.y + eX * (vid_conwidth - menu_enable_maxsize_x);\
-       }                                                                                                               \
-       panel_pos = (1 - autocvar__menu_alpha) * panel_pos + (autocvar__menu_alpha) * menu_enable_pos;                  \
+ // don't center too wide panels, it doesn't work with different resolutions
+ #define HUD_Panel_UpdatePosSize_ForMenu() do { \
+       vector menu_enable_size = panel_size; \
+       float max_panel_width = 0.52 * vid_conwidth; \
+       if(panel_size.x > max_panel_width) \
+       { \
+               menu_enable_size.x = max_panel_width; \
+               menu_enable_size.y = panel_size.y * (menu_enable_size.x / panel_size.x); \
+       } \
+       vector menu_enable_pos = eX * (panel_bg_border + 0.5 * max_panel_width) + eY * 0.5 * vid_conheight - 0.5 * menu_enable_size; \
+       panel_pos = (1 - autocvar__menu_alpha) * panel_pos + (autocvar__menu_alpha) * menu_enable_pos; \
+       panel_size = (1 - autocvar__menu_alpha) * panel_size + (autocvar__menu_alpha) * menu_enable_size; \
  } while(0)
  
  // Scale the pos and size vectors to absolute coordinates
index 4ddc049ba167395173809af150f5cd88707525ac,4b55bb40e9850ab92c104210f6d2fb3712373c93..abe6740223420baa08570bfb060c6fdacc986dd3
@@@ -1,13 -1,11 +1,11 @@@
- #if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "defs.qh"
-       #include "../dpdefs/keycodes.qh"
-       #include "../common/constants.qh"
-       #include "autocvars.qh"
-       #include "hud.qh"
- #elif defined(MENUQC)
- #elif defined(SVQC)
- #endif
+ #include "hud_config.qh"
+ #include "_all.qh"
+ #include "hud.qh"
+ #include "../common/constants.qh"
+ #include "../dpdefs/keycodes.qh"
  
  
  #define HUD_Write(s) fputs(fh, s)
@@@ -433,8 -431,7 +431,7 @@@ void HUD_Panel_SetPosSize(vector mySize
  {
        panel = highlightedPanel;
        HUD_Panel_UpdatePosSize();
-       vector resizeorigin;
-       resizeorigin = panel_click_resizeorigin;
+       vector resizeorigin = panel_click_resizeorigin;
        vector myPos;
  
        // minimum panel size cap
@@@ -567,7 -564,6 +564,6 @@@ void HUD_Panel_Arrow_Action(float nPrim
  
        if (hudShiftState & S_ALT) // resize
        {
-               highlightedAction = 1;
                if(nPrimary == K_UPARROW)
                        resizeCorner = 1;
                else if(nPrimary == K_RIGHTARROW)
        }
        else // move
        {
-               highlightedAction = 2;
                vector pos;
                pos = panel_pos;
                if(nPrimary == K_UPARROW)
        }
  }
  
--const int S_MOUSE1 = 1;
--const int S_MOUSE2 = 2;
--const int S_MOUSE3 = 4;
--int mouseClicked;
--int prevMouseClicked; // previous state
--float prevMouseClickedTime; // time during previous left mouse click, to check for doubleclicks
--vector prevMouseClickedPos; // pos during previous left mouse click, to check for doubleclicks
--
  void HUD_Panel_EnableMenu();
  entity tab_panels[HUD_PANEL_MAX];
  entity tab_panel;
@@@ -746,15 -741,14 +733,14 @@@ float HUD_Panel_InputEvent(float bInput
                if (!menu_enabled)
                        cvar_set("_hud_configure", "0");
        }
-       else if(nPrimary == K_TAB && hudShiftState & S_CTRL) // select and highlight another panel
+       else if(nPrimary == K_TAB && hudShiftState & S_CTRL) // switch panel
        {
                if (bInputType == 1 || mouseClicked)
                        return true;
  
-               //FIXME: if a panel is highlighted, has the same pos_x and lays in the same level
-               //of other panels then next consecutive ctrl-tab will select the highlighted panel too
-               //(it should only after every other panel of the hud)
-               //It's a minor bug anyway, we can live with it
+               // FIXME minor bug: if a panel is highlighted, has the same pos_x and
+               // lays in the same level of another panel then the next consecutive
+               // CTRL TAB presses will reselect once more the highlighted panel
  
                entity starting_panel;
                entity old_tab_panel = tab_panel;
                        highlightedPanel_backup = world;
                }
        }
+       else if(nPrimary == 's' && hudShiftState & S_CTRL) // save config
+       {
+               if (bInputType == 1 || mouseClicked)
+                       return true;
+               localcmd("hud save myconfig\n");
+       }
        else if(nPrimary == K_UPARROW || nPrimary == K_DOWNARROW || nPrimary == K_LEFTARROW || nPrimary == K_RIGHTARROW)
        {
                if (bInputType == 1)
                if (highlightedPanel)
                        HUD_Panel_EnableMenu();
        }
-       else if(hit_con_bind)
+       else if(hit_con_bind || nPrimary == K_PAUSE)
                return false;
  
        return true;
@@@ -1178,6 -1178,8 +1170,8 @@@ void HUD_Panel_Mouse(
        }
        else
        {
+               if(prevMouseClicked)
+                       highlightedAction = 0;
                if(menu_enabled == 2)
                        mouse_over_panel = 0;
                else
index 0000000000000000000000000000000000000000,cc1d4d563c6048c7d7fd0a07d0369a9e18a69dbe..39dc6599181c7956c6a3a9f89f01d5bb73e01f8e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,14 +1,22 @@@
+ #ifndef HUD_CONFIG_H
+ #define HUD_CONFIG_H
+ void HUD_Panel_ExportCfg(string cfgname);
+ void HUD_Panel_Mouse();
+ void HUD_Configure_Frame();
+ void HUD_Configure_PostDraw();
+ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary);
++const int S_MOUSE1 = 1;
++const int S_MOUSE2 = 2;
++const int S_MOUSE3 = 4;
++int mouseClicked;
++int prevMouseClicked; // previous state
++float prevMouseClickedTime; // time during previous left mouse click, to check for doubleclicks
++vector prevMouseClickedPos; // pos during previous left mouse click, to check for doubleclicks
++
+ #endif
diff --combined qcsrc/client/main.qc
index 11c3217d346b5d06225a1578f8a23ebf3674ec6b,982056fcbb13f363cac97a3dfc4bc00f787ac122..5068a6a4e716eef294bf8528bbd88ef31c85629f
@@@ -1,23 -1,51 +1,53 @@@
+ #include "main.qh"
+ #include "_all.qh"
+ #include "casings.qh"
 +#include "controlpoint.qh"
+ #include "csqcmodel_hooks.qh"
+ #include "damage.qh"
+ #include "effects.qh"
 +#include "generator.qh"
+ #include "gibs.qh"
+ #include "hook.qh"
+ #include "hud.qh"
+ #include "hud_config.qh"
+ #include "laser.qh"
  #include "mapvoting.qh"
  #include "modeleffects.qh"
  #include "particles.qh"
+ #include "prandom.qh"
  #include "scoreboard.qh"
  #include "shownames.qh"
- #include "target_music.qh"
+ #include "sortlist.qh"
  #include "tturrets.qh"
  #include "tuba.qh"
+ #include "t_items.qh"
  #include "wall.qh"
  #include "waypointsprites.qh"
  
- #include "vehicles/vehicles.qh"
+ #include "vehicles/bumblebee.qh"
+ #include "vehicles/all.qh"
  
- #include "../server/vehicles/bumblebee.qh"
+ #include "weapons/projectile.qh"
  
+ #include "../common/buffs.qh"
+ #include "../common/deathtypes.qh"
+ #include "../common/mapinfo.qh"
+ #include "../common/monsters/all.qh"
+ #include "../common/nades.qh"
  #include "../common/net_notice.qh"
+ #include "../common/notifications.qh"
+ #include "../common/stats.qh"
+ #include "../common/teams.qh"
+ #include "../common/items/all.qh"
+ #include "../common/weapons/all.qh"
  
- #include "../common/monsters/monsters.qh"
+ #include "../csqcmodellib/cl_model.qh"
+ #include "../csqcmodellib/interpolate.qh"
+ #include "../common/triggers/include.qh"
  
  #include "../warpzonelib/client.qh"
  
@@@ -111,6 -139,7 +141,7 @@@ void CSQC_Init(void
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
+       CALL_ACCUMULATED_FUNCTION(RegisterItems);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
        precache_sound("misc/hit.wav");
        precache_sound("misc/typehit.wav");
  
 +      generator_precache();
        Projectile_Precache();
        Hook_Precache();
        GibSplash_Precache();
@@@ -336,9 -364,6 +367,9 @@@ float CSQC_InputEvent(float bInputType
        if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary))
                return true;
  
 +      if ( HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary) )
 +              return true;
 +
        if (MapVote_InputEvent(bInputType, nPrimary, nSecondary))
                return true;
  
  
  // --------------------------------------------------------------------------
  // BEGIN OPTIONAL CSQC FUNCTIONS
  void Ent_RemoveEntCS()
  {
        entcs_receiver[self.sv_entnum] = world;
@@@ -671,7 -697,7 +703,7 @@@ void Ent_ReadSpawnPoint(float is_new) /
        if(is_new)
        {
                self.origin = spn_origin;
-               setsize(self, PL_MIN, PL_MAX);
+               setsize(self, PL_MIN_CONST, PL_MAX_CONST);
                droptofloor();
  
                /*if(autocvar_cl_spawn_point_model) // needs a model first
@@@ -753,7 -779,7 +785,7 @@@ void Ent_ReadSpawnEvent(float is_new
                        button_zoom = false;
                }
        }
 -
 +      HUD_Radar_Hide_Maximized();
        //printf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum);
  }
  
@@@ -835,12 -861,11 +867,13 @@@ void CSQC_Ent_Update(float bIsNewEntity
                case ENT_CLIENT_WARPZONE_TELEPORTED: WarpZone_Teleported_Read(bIsNewEntity); break;
                case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break;
                case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break;
+               case ENT_CLIENT_INVENTORY: Inventory_Read(self); break;
                case ENT_CLIENT_ARC_BEAM: Ent_ReadArcBeam(bIsNewEntity); break;
                case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
                case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
                case ENT_CLIENT_TURRET: ent_turret(); break;
 +              case ENT_CLIENT_GENERATOR: ent_generator(); break;
 +              case ENT_CLIENT_CONTROLPOINT_ICON: ent_cpicon(); break;
                case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
                case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
                case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
                case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break;
                case ENT_CLIENT_NOTIFICATION: Read_Notification(bIsNewEntity); break;
                case ENT_CLIENT_HEALING_ORB: ent_healer(); break;
+               case ENT_CLIENT_LADDER: ent_func_ladder(); break;
+               case ENT_CLIENT_TRIGGER_PUSH: ent_trigger_push(); break;
+               case ENT_CLIENT_TARGET_PUSH: ent_target_push(); break;
+               case ENT_CLIENT_CONVEYOR: ent_conveyor(); break;
+               case ENT_CLIENT_DOOR: ent_door(); break;
+               case ENT_CLIENT_PLAT: ent_plat(); break;
+               case ENT_CLIENT_SWAMP: ent_swamp(); break;
+               case ENT_CLIENT_CORNER: ent_corner(); break;
+               case ENT_CLIENT_KEYLOCK: ent_keylock(); break;
+               case ENT_CLIENT_TRAIN: ent_train(); break;
+               case ENT_CLIENT_TRIGGER_IMPULSE: ent_trigger_impulse(); break;
  
                default:
                        //error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype));
diff --combined qcsrc/client/main.qh
index 5689d24284dc027cd3da2490121f323e10199c9d,0bc85a441db9d6e83570061748ba23efa7a05c9e..c8de3afdc93522a7542ce65b66e9558921688522
@@@ -1,6 -1,8 +1,8 @@@
  #ifndef MAIN_H
  #define MAIN_H
  
+ #include "../common/constants.qh"
  // --------------------------------------------------------------------------
  // MENU Functionality
  
@@@ -106,6 -108,8 +108,8 @@@ float current_viewzoom
  float zoomin_effect;
  float warmup_stage;
  
+ void Fog_Force();
  string getcommandkey(string text, string command);
  
  string vote_called_vote;
@@@ -149,6 -153,4 +153,6 @@@ entity entcs_receiver[255]; // 255 is t
  float hud;
  float view_quality;
  int framecount;
 +.float health;
 +
  #endif
index 28b81fc51ffc9e85c917ff69f34e748bbc18c3a9,f00ee544c059f76cd3ec85bdf5375914df4caa9e..e75214a4edfeead37ef838789679090067f46e5e
@@@ -1,6 -1,49 +1,48 @@@
  #include "mapvoting.qh"
+ #include "_all.qh"
+ #include "hud.qh"
  #include "scoreboard.qh"
  
 -float mv_active;
+ #include "../common/mapinfo.qh"
+ #include "../common/util.qh"
+ #include "../dpdefs/keycodes.qh"
+ int mv_num_maps;
+ string mv_maps[MAPVOTE_COUNT];
+ string mv_pics[MAPVOTE_COUNT];
+ string mv_pk3[MAPVOTE_COUNT]; // map pk3 name or gametype human readable name
+ string mv_desc[MAPVOTE_COUNT];
+ float mv_preview[MAPVOTE_COUNT];
+ float mv_votes[MAPVOTE_COUNT];
+ float mv_flags[MAPVOTE_COUNT];
+ float mv_flags_start[MAPVOTE_COUNT];
+ entity mv_pk3list;
+ float mv_abstain;
+ float mv_ownvote;
+ float mv_detail;
+ float mv_timeout;
+ float mv_top2_time;
+ float mv_top2_alpha;
+ vector mv_mousepos;
+ int mv_selection;
+ int mv_columns;
+ int mv_mouse_selection;
+ int mv_selection_keyboard;
+ float gametypevote;
+ string mapvote_chosenmap;
+ vector gtv_text_size;
+ vector gtv_text_size_small;
+ const int NUM_SSDIRS = 4;
+ string ssdirs[NUM_SSDIRS];
+ int n_ssdirs;
  string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, vector fontsize)
  {
        string pre, post;
@@@ -9,7 -52,7 +51,7 @@@
        {
                if(_count == 1)
                        post = _(" (1 vote)");
-               else if(_count >= 0 && mv_avail[id] == GTV_AVAILABLE)
+               else if(_count >= 0 && (mv_flags[id] & GTV_AVAILABLE))
                        post = sprintf(_(" (%d votes)"), _count);
                else
                        post = "";
        return strcat(pre, map, post);
  }
  
- string GameTypeVote_DescriptionByID(int id)
- {
-       return MapInfo_Type_Description(MapInfo_Type_FromString(mv_maps[id]));
- }
  vector MapVote_RGB(int id)
  {
-       if(mv_avail[id] != GTV_AVAILABLE)
+       if(!(mv_flags[id] & GTV_AVAILABLE))
                return '1 1 1';
        if(id == mv_ownvote)
                return '0 1 0';
  
  void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float _count, int id)
  {
+       // Find the correct alpha
        float alpha;
-       float desc_padding = gtv_text_size.x * 3;
+       if(!(mv_flags_start[id] & GTV_AVAILABLE))
+               alpha = 0.2; // The gametype isn't supported by the map
+       else if ( !(mv_flags[id] & GTV_AVAILABLE) && mv_top2_alpha)
+               alpha = mv_top2_alpha; // Fade away if not one of the top 2 choice
+       else
+               alpha = 1; // Normal, full alpha
+       // Bounding box details
        float rect_margin = hud_fontsize.y / 2;
        vector rect_pos = pos - '0.5 0.5 0' * rect_margin;
        vector rect_size = '1 1 0';
        rect_size.x = tsize + rect_margin;
        rect_size.y = maxh + rect_margin;
-       vector rgb = MapVote_RGB(id);
-       vector offset = pos;
-       float nlines = 0;
-       if(mv_avail_start[id] != GTV_AVAILABLE)
-               alpha = 0.2;
-       else if ( mv_avail[id] != GTV_AVAILABLE && mv_top2_alpha)
-               alpha = mv_top2_alpha;
-       else
-               alpha = 1;
  
-       if(id == mv_selection && mv_avail[id] == GTV_AVAILABLE)
+       // Highlight selected item
+       if(id == mv_selection && (mv_flags[id] & GTV_AVAILABLE))
        {
                drawfill(rect_pos, rect_size, '1 1 1', 0.1, DRAWFLAG_NORMAL);
        }
+       // Highlight current vote
+       vector rgb = MapVote_RGB(id);
        if(id == mv_ownvote)
        {
                drawfill(rect_pos, rect_size, rgb, 0.1*alpha, DRAWFLAG_NORMAL);
                drawborderlines(autocvar_scoreboard_border_thickness, rect_pos, rect_size, rgb, alpha, DRAWFLAG_NORMAL);
        }
  
-       entity title;
-       title = spawn();
-       title.message = MapVote_FormatMapItem(id, MapInfo_Type_ToText(MapInfo_Type_FromString(gtype)),
-                                                                                 _count, tsize, gtv_text_size);
-       title.origin = pos-offset;
-       pos.y += gtv_text_size_small.y;
-       pos.y += gtv_text_size.y/2;
+       vector offset = pos;
  
-       maxh -= gtv_text_size.y;
+       float title_gap = gtv_text_size.y * 1.4; // distance between the title and the description
+       pos.y += title_gap;
+       maxh -= title_gap;
  
-       entity picent = spawn();
-       picent.origin = pos-offset;
-       picent.maxs = '1 1 0 ' * min(maxh, desc_padding) * 0.8;
+       // Evaluate the image size
+       vector image_size = '1 1 0' * gtv_text_size.x * 3;
+       if ( maxh < image_size.y )
+               image_size = '1 1 0' * maxh;
+       image_size *= 0.8;
+       float desc_padding = gtv_text_size.x * 0.6;
+       pos.x += image_size.x + desc_padding;
+       tsize -= image_size.x + desc_padding;
  
-       pos.x += desc_padding;
-       tsize -= desc_padding;
+       // Split the description into lines
+       entity title;
+       title = spawn();
+       title.message = MapVote_FormatMapItem(id, mv_pk3[id], _count, tsize, gtv_text_size);
  
-       string thelabel = GameTypeVote_DescriptionByID(id), ts;
+       string thelabel = mv_desc[id], ts;
        entity last = title;
        entity next = world;
+       float nlines = 0;
        if( thelabel != "")
        {
                float i,n = tokenizebyseparator(thelabel, "\n");
                }
        }
  
-       maxh -= max(nlines*gtv_text_size_small.y,picent.maxs.y);
+       // Center the contents in the bounding box
+       maxh -= max(nlines*gtv_text_size_small.y,image_size.y);
        if ( maxh > 0 )
                offset.y += maxh/2;
-       drawstring(title.origin+offset, title.message, gtv_text_size, rgb, alpha, DRAWFLAG_NORMAL);
  
+       // Draw the title
+       drawstring(offset, title.message, gtv_text_size, rgb, alpha, DRAWFLAG_NORMAL);
+       // Draw the icon
        if(pic != "")
-               drawpic(picent.origin+offset, pic, picent.maxs, '1 1 1', alpha, DRAWFLAG_NORMAL);
+               drawpic('0 1 0'*title_gap+'0.5 0 0'*desc_padding+offset, pic, image_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
  
+       // Draw the description
        for ( last = title.chain; last ; )
        {
                drawstring(last.origin+offset, last.message, gtv_text_size_small, '1 1 1', alpha, DRAWFLAG_NORMAL);
                remove(next);
        }
  
-       remove(picent);
+       // Cleanup
        remove(title);
  }
  
@@@ -153,7 -201,7 +200,7 @@@ void MapVote_DrawMapItem(vector pos, fl
        text_size = stringwidth(label, false, hud_fontsize);
  
        float theAlpha;
-       if (mv_avail[id] != GTV_AVAILABLE && mv_top2_alpha)
+       if (!(mv_flags[id] & GTV_AVAILABLE) && mv_top2_alpha)
                theAlpha = mv_top2_alpha;
        else
                theAlpha = 1;
        else
                drawborderlines(autocvar_scoreboard_border_thickness, pos, img_size, '0 0 0', theAlpha, DRAWFLAG_NORMAL);
  
-       if(id == mv_selection && mv_avail[id] == GTV_AVAILABLE)
+       if(id == mv_selection && (mv_flags[id] & GTV_AVAILABLE))
                drawfill(pos, img_size, '1 1 1', 0.1, DRAWFLAG_NORMAL);
  }
  
@@@ -458,20 -506,68 +505,68 @@@ void MapVote_ReadMask(
                        mask = ReadLong();
  
                for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2)
-                       mv_avail[i] = (mask & power) ? GTV_AVAILABLE : GTV_FORBIDDEN;
+               {
+                       if ( mask & power )
+                               mv_flags[i] |= GTV_AVAILABLE;
+                       else
+                               mv_flags[i] &= ~GTV_AVAILABLE;
+               }
        }
        else
        {
                for(i = 0; i < mv_num_maps; ++i )
-                       mv_avail[i] = ReadByte();
+                       mv_flags[i] = ReadByte();
        }
  }
  
- void MapVote_Init()
+ void MapVote_ReadOption(int i)
+ {
+       string map = strzone(ReadString());
+       string pk3 = strzone(ReadString());
+       int j = bound(0, ReadByte(), n_ssdirs - 1);
+       mv_maps[i] = map;
+       mv_pk3[i] = pk3;
+       mv_flags[i] = GTV_AVAILABLE;
+       string pic = strzone(strcat(ssdirs[j], "/", map));
+       mv_pics[i] = pic;
+       mv_preview[i] = false;
+       MapVote_CheckPic(pic, pk3, i);
+ }
+ void GameTypeVote_ReadOption(int i)
  {
-       int i, j;
-       string map, pk3, s;
+       string gt = strzone(ReadString());
+       mv_maps[i] = gt;
+       mv_flags[i] = ReadByte();
  
+       string mv_picpath = sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, gt);
+       if(precache_pic(mv_picpath) == "")
+               mv_picpath = strcat("gfx/menu/default/gametype_", gt);
+       string pic = strzone(mv_picpath);
+       mv_pics[i] = pic;
+       mv_preview[i] = PreviewExists(pic);
+       if ( mv_flags[i] & GTV_CUSTOM )
+       {
+               string name = ReadString();
+               if ( strlen(name) < 1 )
+                       name = gt;
+               mv_pk3[i] = strzone(name);
+               mv_desc[i] = strzone(ReadString());
+       }
+       else
+       {
+               int type = MapInfo_Type_FromString(gt);
+               mv_pk3[i] = strzone(MapInfo_Type_ToText(type));
+               mv_desc[i] = MapInfo_Type_Description(type);
+       }
+ }
+ void MapVote_Init()
+ {
        precache_sound ("misc/invshot.wav");
  
        mv_active = 1;
        mv_selection = -1;
        mv_selection_keyboard = 0;
  
+       string s;
        for(n_ssdirs = 0; ; ++n_ssdirs)
        {
                s = ReadString();
        }
  
        MapVote_ReadMask();
+       int i;
        for(i = 0; i < mv_num_maps; ++i )
-               mv_avail_start[i] = mv_avail[i];
+               mv_flags_start[i] = mv_flags[i];
  
        // Assume mv_pk3list is world, there should only be 1 mapvote per round
        mv_pk3list = world; // I'm still paranoid!
        {
                mv_votes[i] = 0;
  
-               map = strzone(ReadString());
-               pk3 = strzone(ReadString());
-               j = bound(0, ReadByte(), n_ssdirs - 1);
-               mv_maps[i] = map;
-               mv_pk3[i] = pk3;
-               mv_avail[i] = ReadByte();
-               if(gametypevote)
-               {
-                       //map = strzone(strcat("gfx/menu/default/gametype_", map));
-                       //map = strzone(sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, map));
-                       string mv_picpath = sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, map);
-                       if(precache_pic(mv_picpath) == "")
-                               mv_picpath = strcat("gfx/menu/default/gametype_", map);
-                       map = strzone(mv_picpath);
-                       mv_pics[i] = map;
-                       mv_preview[i] = PreviewExists(map);
-               }
+               if ( gametypevote )
+                       GameTypeVote_ReadOption(i);
                else
-               {
-                       map = strzone(strcat(ssdirs[j], "/", map));
-                       mv_pics[i] = map;
-                       mv_preview[i] = false;
-                       MapVote_CheckPic(map, pk3, i);
-               }
+                       MapVote_ReadOption(i);
        }
  
        for(i = 0; i < n_ssdirs; ++i)
@@@ -585,7 -661,7 +660,7 @@@ int MapVote_MoveLeft(int pos
                imp = mv_num_maps - 1;
        else
                imp = pos < 1 ? mv_num_maps - 1 : pos - 1;
-       if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+       if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
                imp = MapVote_MoveLeft(imp);
        return imp;
  }
@@@ -596,7 -672,7 +671,7 @@@ int MapVote_MoveRight(int pos
                imp = 0;
        else
                imp = pos >= mv_num_maps - 1 ? 0 : pos + 1;
-       if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+       if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
                imp = MapVote_MoveRight(imp);
        return imp;
  }
@@@ -615,7 -691,7 +690,7 @@@ int MapVote_MoveUp(int pos
                                imp -= mv_columns;
                }
        }
-       if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+       if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
                imp = MapVote_MoveUp(imp);
        return imp;
  }
@@@ -630,7 -706,7 +705,7 @@@ int MapVote_MoveDown(int pos
                if ( imp >= mv_num_maps )
                        imp = imp % mv_columns;
        }
-       if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+       if ( !(mv_flags[imp] & GTV_AVAILABLE) && imp != mv_ownvote )
                imp = MapVote_MoveDown(imp);
        return imp;
  }
@@@ -723,7 -799,7 +798,7 @@@ void MapVote_UpdateVotes(
        int i;
        for(i = 0; i < mv_num_maps; ++i)
        {
-               if(mv_avail[i] == GTV_AVAILABLE)
+               if(mv_flags[i] & GTV_AVAILABLE)
                {
                        if(mv_detail)
                                mv_votes[i] = ReadByte();
index 8a4133e50ab798a42708012525c11be11da895f9,9c7086efc10d6a0060f691718689aecc42508278..7a9a511a2be129fb6e292c85e2e24f468bcea786
@@@ -1,81 -1,14 +1,16 @@@
  #ifndef MAPVOTING_H
  #define MAPVOTING_H
  
- int mv_num_maps;
- float mv_active;
- string mv_maps[MAPVOTE_COUNT];
- string mv_pics[MAPVOTE_COUNT];
- string mv_pk3[MAPVOTE_COUNT];
- float mv_preview[MAPVOTE_COUNT];
- float mv_votes[MAPVOTE_COUNT];
- float mv_avail[MAPVOTE_COUNT];
- float mv_avail_start[MAPVOTE_COUNT];
- entity mv_pk3list;
- float mv_abstain;
- float mv_ownvote;
- float mv_detail;
- float mv_timeout;
- float mv_top2_time;
- float mv_top2_alpha;
- vector mv_mousepos;
- int mv_selection;
- int mv_columns;
- int mv_mouse_selection;
- int mv_selection_keyboard;
- float gametypevote;
- string mapvote_chosenmap;
- vector gtv_text_size;
- vector gtv_text_size_small;
- string MapVote_FormatMapItem(int id, string map, float count, float maxwidth, vector fontsize);
- string GameTypeVote_DescriptionByID(int id);
- vector MapVote_RGB(int id);
- void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float count, int id);
- void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, string pic, float count, int id);
- void MapVote_DrawAbstain(vector pos, float isize, float tsize, float count, int id);
- vector MapVote_GridVec(vector gridspec, int i, int m);
- float MapVote_Selection(vector topleft, vector cellsize, float rows, float columns);
+ #include "../common/constants.qh"
  void MapVote_Draw();
  
  void Cmd_MapVote_MapDownload(float argc);
  
- void MapVote_CheckPK3(string pic, string pk3, int id);
- void MapVote_CheckPic(string pic, string pk3, int id);
- void MapVote_ReadMask();
- const int NUM_SSDIRS = 4;
- string ssdirs[NUM_SSDIRS];
- int n_ssdirs;
- void MapVote_Init();
- void MapVote_SendChoice(float index);
- int MapVote_MoveLeft(int pos);
- int MapVote_MoveRight(int pos);
- int MapVote_MoveUp(int pos);
- int MapVote_MoveDown(int pos);
  float MapVote_InputEvent(float bInputType, float nPrimary, float nSecondary);
  
- void MapVote_UpdateMask();
- void MapVote_UpdateVotes();
  void Ent_MapVote();
  
  void Net_MapVote_Picture();
++
++float mv_active;
  #endif
diff --combined qcsrc/client/progs.src
index 81d349ff6bcdad35f39de3d8434203a829b4fecf,a9d0c565a7e1ffc3b627db8ca4b0b00abdc4f746..60cb996755d6e68ceb2f9fe14deeecc563d2b993
@@@ -6,21 -6,18 +6,20 @@@
  announcer.qc
  bgmscript.qc
  casings.qc
 +controlpoint.qc
  csqcmodel_hooks.qc
  damage.qc
  effects.qc
 +generator.qc
  gibs.qc
  hook.qc
- hud_config.qc
  hud.qc
laser.qc
hud_config.qc
  main.qc
  mapvoting.qc
  miscfunctions.qc
  modeleffects.qc
- movetypes.qc
+ movelib.qc
  noise.qc
  particles.qc
  player_skeleton.qc
@@@ -29,47 -26,50 +28,50 @@@ rubble.q
  scoreboard.qc
  shownames.qc
  sortlist.qc
- target_music.qc
  teamradar.qc
  tturrets.qc
  tuba.qc
vehicles/vehicles.qc
t_items.qc
  view.qc
  wall.qc
  waypointsprites.qc
  
- command/cl_cmd.qc
+ command/all.qc
+ vehicles/bumblebee.qc
+ vehicles/all.qc
  
  weapons/projectile.qc // TODO
  
  ../common/animdecide.qc
  ../common/buffs.qc
  ../common/mapinfo.qc
+ ../common/movetypes/include.qc
  ../common/nades.qc
  ../common/net_notice.qc
  ../common/notifications.qc
+ ../common/physics.qc
  ../common/playerstats.qc
  ../common/test.qc
  ../common/urllib.qc
  ../common/util.qc
  
- ../common/command/generic.qc
- ../common/command/markup.qc
- ../common/command/rpn.qc
+ ../common/items/all.qc
+ ../common/monsters/all.qc
  
- ../common/monsters/monsters.qc
+ ../common/weapons/all.qc // TODO
  
- ../common/weapons/weapons.qc // TODO
+ ../common/triggers/include.qc
  
  ../csqcmodellib/cl_model.qc
  ../csqcmodellib/cl_player.qc
  ../csqcmodellib/interpolate.qc
  
- ../server/movelib.qc
- ../server/t_items.qc
- ../server/vehicles/bumblebee.qc
+ ../server/mutators/mutator_multijump.qc
  
  ../warpzonelib/anglestransform.qc
  ../warpzonelib/client.qc
  ../warpzonelib/common.qc
  ../warpzonelib/mathlib.qc
+ ../warpzonelib/util_server.qc
index d86956b4d730818a75822f9a85a6983ea544e503,418e1db08b2697239e7d81194fe91e82279d8ff6..ec27b404e0d2d2842659abcfb8dfd02b2fe81974
@@@ -1,4 -1,15 +1,15 @@@
  #include "scoreboard.qh"
+ #include "_all.qh"
+ #include "hud.qh"
+ #include "sortlist.qh"
+ #include "../common/constants.qh"
+ #include "../common/counting.qh"
+ #include "../common/mapinfo.qh"
+ #include "../common/stats.qh"
+ #include "../common/teams.qh"
+ #include "../common/util.qh"
  
  float scoreboard_alpha_bg;
  float scoreboard_alpha_fg;
@@@ -291,7 -302,7 +302,7 @@@ void Cmd_HUD_Help(
  #define HUD_DefaultColumnLayout() \
  "ping pl name | " \
  "-teams,race,lms/kills +ft,tdm/kills -teams,lms/deaths +ft,tdm/deaths -teams,lms,race,ka/suicides +ft,tdm/suicides -race,dm,tdm,ka,ft/frags " /* tdm already has this in "score" */ \
 -"+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns " \
 +"+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes " \
  "+lms/lives +lms/rank " \
  "+kh/caps +kh/pushes +kh/destroyed " \
  "?+race/laps ?+race/time ?+race/fastest " \
@@@ -349,7 -360,6 +360,6 @@@ void Cmd_HUD_SetFields(float argc
  
        hud_fontsize = HUD_GetFontsize("hud_fontsize");
  
-       draw_beginBoldFont();
        for(i = 1; i < argc - 1; ++i)
        {
                float nocomplain;
        }
  
        hud_field[hud_num_fields] = SP_END;
-       draw_endBoldFont();
  }
  
  // MOVEUP::
@@@ -868,7 -877,6 +877,6 @@@ vector HUD_Scoreboard_MakeTable(vector 
        }
  
        // print the strings of the columns headers and draw the columns
-       draw_beginBoldFont();
        int i;
        for(i = 0; i < hud_num_fields; ++i)
        {
                        pos.x -= hud_fontsize.x;
                }
        }
-       draw_endBoldFont();
  
        pos.x = xmin;
        pos.y += 1.25 * hud_fontsize.y; // skip the header
  float HUD_WouldDrawScoreboard() {
        if (autocvar__hud_configure)
                return 0;
 +      else if (HUD_Radar_Clickable())
 +              return 0;
        else if (scoreboard_showscores)
                return 1;
        else if (intermission == 1)
index 088ba60d9bad2e89467e90096fe3fc21f80d4fd6,aa7923bafc7a74bddc21f3ac08c3dd29a100492b..e1f118c2cfaac02678e42e589b056e2eb89fcc86
@@@ -1,8 -1,11 +1,11 @@@
- #if defined(CSQC)
-       #include "teamradar.qh"
- #elif defined(MENUQC)
- #elif defined(SVQC)
- #endif
+ #include "teamradar.qh"
+ #include "_all.qh"
+ #include "hud.qh"
+ #include "../common/util.qh"
+ #include "../csqcmodellib/interpolate.qh"
  
  float vlen2d(vector v)
  {
@@@ -43,34 -46,6 +46,34 @@@ vector teamradar_texcoord_to_2dcoord(ve
        return out;
  }
  
 +
 +vector teamradar_2dcoord_to_texcoord(vector in)
 +{
 +      vector out;
 +      out = in;
 +      
 +      out -= teamradar_origin2d;
 +      if(v_flipped)
 +              out_x = -out_x;
 +      out = out / teamradar_size;
 +      
 +      out_y = - out_y; // screen space is reversed
 +      out = rotate(out, -teamradar_angle * DEG2RAD);
 +      
 +      out += teamradar_origin3d_in_texcoord;
 +
 +      return out;
 +}
 +
 +vector teamradar_texcoord_to_3dcoord(vector in,float z)
 +{
 +      vector out;
 +      out_x = in_x * (mi_picmax_x - mi_picmin_x) + mi_picmin_x;
 +      out_y = in_y * (mi_picmax_y - mi_picmin_y) + mi_picmin_y;
 +      out_z = z;
 +      return out;
 +}
 +
  vector yinvert(vector v)
  {
        v.y = 1 - v.y;
index da99652feef5dec0f3833e26e6eb0ad175c8e688,f7c186ac6258c119f75657e3cb0de13d189d1285..b2329cfb06c715137474f0ce11eb5dbe23c187e1
@@@ -3,11 -3,12 +3,12 @@@
  
  const int MAX_TEAMRADAR_TIMES = 32;
  
+ entityclass(TeamRadar);
  // to make entities have dots on the team radar
- .float teamradar_icon;
- .float teamradar_times[MAX_TEAMRADAR_TIMES];
- .int teamradar_time_index;
- .vector teamradar_color;
class(TeamRadar) .float teamradar_icon;
class(TeamRadar) .float teamradar_times[MAX_TEAMRADAR_TIMES];
class(TeamRadar) .int teamradar_time_index;
class(TeamRadar) .vector teamradar_color;
  
  float teamradar_angle; // player yaw angle
  vector teamradar_origin3d_in_texcoord; // player origin
@@@ -32,14 -33,10 +33,14 @@@ float vlen_maxnorm2d(vector v)
  
  float vlen_minnorm2d(vector v);
  
 +vector teamradar_2dcoord_to_texcoord(vector in);
 +
  vector teamradar_3dcoord_to_texcoord(vector in);
  
  vector teamradar_texcoord_to_2dcoord(vector in);
  
 +vector teamradar_texcoord_to_3dcoord(vector in,float z);
 +
  vector yinvert(vector v);
  
  void draw_teamradar_background(float fg);
diff --combined qcsrc/client/view.qc
index fb94704282d59395415c9b533f31f355896c37ed,35793364fafd3c60c9853065064f39a32f6bc840..177261d3f8e959b6eea500797704a383c6669b5a
@@@ -1,25 -1,31 +1,31 @@@
- #if defined(CSQC)
-       #include "../dpdefs/csprogsdefs.qh"
-       #include "defs.qh"
-       #include "../common/constants.qh"
-       #include "../common/stats.qh"
-       #include "../warpzonelib/mathlib.qh"
-       #include "../warpzonelib/common.qh"
-       #include "../warpzonelib/client.qh"
-       #include "../common/teams.qh"
-       #include "../common/util.qh"
-       #include "../common/nades.qh"
-       #include "../common/weapons/weapons.qh"
-       #include "../common/mapinfo.qh"
-       #include "autocvars.qh"
-       #include "hud.qh"
-       #include "scoreboard.qh"
-       #include "noise.qh"
-       #include "main.qh"
-       #include "../csqcmodellib/cl_player.qh"
- #elif defined(MENUQC)
- #elif defined(SVQC)
- #endif
+ #include "_all.qh"
+ #include "announcer.qh"
+ #include "hook.qh"
+ #include "hud.qh"
+ #include "hud_config.qh"
+ #include "mapvoting.qh"
+ #include "noise.qh"
+ #include "scoreboard.qh"
+ #include "shownames.qh"
+ #include "vehicles/all.qh"
+ #include "waypointsprites.qh"
+ #include "../common/constants.qh"
+ #include "../common/mapinfo.qh"
+ #include "../common/nades.qh"
+ #include "../common/stats.qh"
+ #include "../common/triggers/target/music.qh"
+ #include "../common/teams.qh"
+ #include "../common/util.qh"
+ #include "../common/weapons/all.qh"
+ #include "../csqcmodellib/cl_player.qh"
+ #include "../warpzonelib/client.qh"
+ #include "../warpzonelib/common.qh"
+ #include "../warpzonelib/mathlib.qh"
  
  entity porto;
  vector polyline[16];
@@@ -1048,7 -1054,11 +1054,11 @@@ void CSQC_UpdateView(float w, float h
  
        CSQCPlayer_SetCamera();
  
-       myteam = GetPlayerColor(player_localentnum - 1);
+       if(player_localentnum <= maxclients) // is it a client?
+               current_player = player_localentnum - 1;
+       else // then player_localentnum is the vehicle I'm driving
+               current_player = player_localnum;
+       myteam = GetPlayerColor(current_player);
  
        if(myteam != prev_myteam)
        {
        // event chase camera
        if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
        {
 -              if(WantEventchase())
 +              float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && getstati(STAT_ROUNDLOST));
 +              entity gen = world;
 +              
 +              if(ons_roundlost)
 +              {
 +                      entity e;
 +                      for(e = world; (e = find(e, classname, "onslaught_generator")); )
 +                      {
 +                              if(e.health <= 0)
 +                              {
 +                                      gen = e;
 +                                      break;
 +                              }
 +                      }
 +                      if(!gen)
 +                              ons_roundlost = FALSE; // don't enforce the 3rd person camera if there is no dead generator to show
 +              }
 +              if(WantEventchase() || (!autocvar_cl_orthoview && ons_roundlost))
                {
                        eventchase_running = true;
  
                        // make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.)
                        vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
 +                      if(ons_roundlost) { current_view_origin = gen.origin; }
  
                        // detect maximum viewoffset and use it
 -                      if(autocvar_cl_eventchase_viewoffset)
 +                      vector view_offset = autocvar_cl_eventchase_viewoffset;
 +                      if(ons_roundlost) { view_offset = autocvar_cl_eventchase_generator_viewoffset; }
 +
 +                      if(view_offset)
                        {
 -                              WarpZone_TraceLine(current_view_origin, current_view_origin + autocvar_cl_eventchase_viewoffset + ('0 0 1' * autocvar_cl_eventchase_maxs.z), MOVE_WORLDONLY, self);
 -                              if(trace_fraction == 1) { current_view_origin += autocvar_cl_eventchase_viewoffset; }
 +                              WarpZone_TraceLine(current_view_origin, current_view_origin + view_offset + ('0 0 1' * autocvar_cl_eventchase_maxs.z), MOVE_WORLDONLY, self);
 +                              if(trace_fraction == 1) { current_view_origin += view_offset; }
                                else { current_view_origin.z += max(0, (trace_endpos.z - current_view_origin.z) - autocvar_cl_eventchase_maxs.z); }
                        }
  
                        if(!autocvar_chase_active) { cvar_set("chase_active", "-1"); }
  
                        // make the camera smooth back
 -                      if(autocvar_cl_eventchase_speed && eventchase_current_distance < autocvar_cl_eventchase_distance)
 -                              eventchase_current_distance += autocvar_cl_eventchase_speed * (autocvar_cl_eventchase_distance - eventchase_current_distance) * frametime; // slow down the further we get
 -                      else if(eventchase_current_distance != autocvar_cl_eventchase_distance)
 -                              eventchase_current_distance = autocvar_cl_eventchase_distance;
 +                      float chase_distance = autocvar_cl_eventchase_distance;
 +                      if(ons_roundlost) { chase_distance = autocvar_cl_eventchase_generator_distance; }
 +
 +                      if(autocvar_cl_eventchase_speed && eventchase_current_distance < chase_distance)
 +                              eventchase_current_distance += autocvar_cl_eventchase_speed * (chase_distance - eventchase_current_distance) * frametime; // slow down the further we get
 +                      else if(eventchase_current_distance != chase_distance)
 +                              eventchase_current_distance = chase_distance;
  
                        makevectors(view_angles);
  
  
        if(autocvar__hud_configure)
                HUD_Panel_Mouse();
 +      else 
 +              HUD_Radar_Mouse();
  
      if(hud && !intermission)
      {
index d20f8a896958de3200f81bacf48fa02e0420469f,0b32de7e920b5e598d1a3aaed844f8f1f22941cb..671f0593722e5041d62a62055d35672e3916316a
@@@ -1,4 -1,20 +1,20 @@@
  #include "waypointsprites.qh"
+ #include "_all.qh"
+ #include "hud.qh"
+ #include "teamradar.qh"
+ #include "../common/buffs.qh"
+ #include "../common/constants.qh"
+ #include "../common/teams.qh"
+ #include "../common/weapons/all.qh"
+ #include "../csqcmodellib/interpolate.qh"
+ #include "../warpzonelib/mathlib.qh"
+ .float alpha;
  
  void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, vector rgb, float a, float f)
  {
@@@ -38,7 -54,7 +54,7 @@@ void drawquad(vector o, vector ri, vect
        R_EndPolygon();
  }
  
- void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float height, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f)
+ void drawhealthbar(vector org, float rot, float h, vector sz, vector hotspot, float width, float theheight, float margin, float border, float align, vector rgb, float a, vector hrgb, float ha, float f)
  {
        vector o, ri, up;
        float owidth; // outer width
        up = rotate(up, rot);
  
        owidth = width + 2 * border;
-       o = o - up * (margin + border + height) + ri * (sz.x - owidth) * 0.5;
+       o = o - up * (margin + border + theheight) + ri * (sz.x - owidth) * 0.5;
  
        drawquad(o - up * border,                               ri * owidth,    up * border, "", rgb,  a,  f);
-       drawquad(o + up * height,                               ri * owidth,    up * border, "", rgb,  a,  f);
-       drawquad(o,                                             ri * border,    up * height, "", rgb,  a,  f);
-       drawquad(o + ri * (owidth - border),                    ri * border,    up * height, "", rgb,  a,  f);
-       drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * height, "", hrgb, ha, f);
+       drawquad(o + up * theheight,                               ri * owidth,    up * border, "", rgb,  a,  f);
+       drawquad(o,                                             ri * border,    up * theheight, "", rgb,  a,  f);
+       drawquad(o + ri * (owidth - border),                    ri * border,    up * theheight, "", rgb,  a,  f);
+       drawquad(o + ri * (border + align * ((1 - h) * width)), ri * width * h, up * theheight, "", hrgb, ha, f);
  }
  
  // returns location of sprite text
@@@ -152,8 -168,11 +168,8 @@@ float spritelookupblinkvalue(string s
  {
        switch(s)
        {
 -              case "ons-cp-atck-neut": return 2;
 -              case "ons-cp-atck-red":  return 2;
 -              case "ons-cp-atck-blue": return 2;
 -              case "ons-cp-dfnd-red":  return 0.5;
 -              case "ons-cp-dfnd-blue": return 0.5;
 +              case "ons-cp-atck":      return 2;
 +              case "ons-cp-dfnd":      return 0.5;
                case "item-invis":       return 2;
                case "item-extralife":   return 2;
                case "item-speed":       return 2;
@@@ -202,11 -221,17 +218,11 @@@ string spritelookuptext(string s
                case "keycarrier-yellow": return _("Key carrier");
                case "redbase": return _("Red base");
                case "waypoint": return _("Waypoint");
 -              case "ons-gen-red": return _("Generator");
 -              case "ons-gen-blue": return _("Generator");
 +              case "ons-gen": return _("Generator");
                case "ons-gen-shielded": return _("Generator");
 -              case "ons-cp-neut": return _("Control point");
 -              case "ons-cp-red": return _("Control point");
 -              case "ons-cp-blue": return _("Control point");
 -              case "ons-cp-atck-neut": return _("Control point");
 -              case "ons-cp-atck-red": return _("Control point");
 -              case "ons-cp-atck-blue": return _("Control point");
 -              case "ons-cp-dfnd-red": return _("Control point");
 -              case "ons-cp-dfnd-blue": return _("Control point");
 +              case "ons-cp": return _("Control point");
 +              case "ons-cp-atck": return _("Control point");
 +              case "ons-cp-dfnd": return _("Control point");
                case "race-checkpoint": return _("Checkpoint");
                case "race-finish": return _("Finish");
                case "race-start": return _("Start");
index 56fcd8e5f70874b4ff503fb3f9ae512d5bd1957d,adea76ca7e47a6df9053f7c9edf1d87d24436946..cb4f7adbd623ad09f47d276987b6bbeac87d563c
@@@ -26,21 -26,22 +26,22 @@@ float waypointsprite_distancefadescale
  float waypointsprite_distancefadedistance;
  float waypointsprite_alpha;
  
- .float helpme;
- .float rule;
- .string netname; // primary picture
- .string netname2; // secondary picture
- .string netname3; // tertiary picture
- .float team; // team that gets netname2
- .float lifetime;
- .float fadetime;
- .float maxdistance;
- .int hideflags;
- .float spawntime;
- .float health;
- .float build_started;
- .float build_starthealth;
- .float build_finished;
+ entityclass(WaypointSprite);
+ class(WaypointSprite) .float helpme;
+ class(WaypointSprite) .float rule;
+ class(WaypointSprite) .string netname; // primary picture
+ class(WaypointSprite) .string netname2; // secondary picture
+ class(WaypointSprite) .string netname3; // tertiary picture
+ class(WaypointSprite) .int team; // team that gets netname2
+ class(WaypointSprite) .float lifetime;
+ class(WaypointSprite) .float fadetime;
+ class(WaypointSprite) .float maxdistance;
+ class(WaypointSprite) .int hideflags;
+ class(WaypointSprite) .float spawntime;
+ class(WaypointSprite) .float health;
+ class(WaypointSprite) .float build_started;
+ class(WaypointSprite) .float build_starthealth;
+ class(WaypointSprite) .float build_finished;
  
  const float SPRITE_HEALTHBAR_WIDTH = 144;
  const float SPRITE_HEALTHBAR_HEIGHT = 9;
@@@ -77,7 -78,6 +78,7 @@@ void Draw_WaypointSprite()
  // they are drawn using a .draw function
  
  void Ent_RemoveWaypointSprite();
 +
  void Ent_WaypointSprite();
  
  void WaypointSprite_Load_Frames(string ext);
index df4f4ffc756462c27cfb6ae2d38176a3c9b57460,939c6d7c17ffaf882155ac46c63ffed740fd7e86..4fb15af865c6de0c3180c54dc26c1881d3504030
@@@ -1,6 -1,31 +1,31 @@@
  #ifndef CONSTANTS_H
  #define CONSTANTS_H
  
+ // COMMIT-TODO: Update if necessary before committing
+ // Revision 1: additional statistics sent (flag caps, returns, deaths)
+ // Revision 2: Mapvote preview pictures
+ // Revision 3: optimized map vote protocol
+ // Revision 4: CSQC config var system
+ // Revision 5: mapvote time fix
+ // Revision 6: more robust against packet loss/delays, also show not yet connected clients
+ // Revision 7: packet loss column
+ // Revision 8: race
+ // Revision 9: race delta
+ // Revision 10: scoreboard force
+ // Revision 11: scoreboard unforce; spectator support beginning
+ // Revision 12: smaller scores updates (SERVER: requires new engine)
+ // Revision 13: pointparticles
+ // Revision 14: laser
+ // Revision 15: zoom
+ // Revision 16: multi-weapons
+ // Revision 17: multi-weaponimpulses
+ // Revision 18: warmup
+ // Revision 19: fog
+ // Revision 20: naggers
+ // Revision 21: entcs for players optimized (position data down from 12 to 7 bytes); waypointsprites in csqc for team radar
+ // Revision 22: hook shot origin
+ #define CSQC_REVISION 22
  const int AS_STRING = 1;
  const int AS_INT = 2;
  const int AS_FLOAT_TRUNCATED = 2;
@@@ -64,6 -89,7 +89,7 @@@ const int ENT_CLIENT_WARPZONE = 24
  const int ENT_CLIENT_WARPZONE_CAMERA = 25;
  const int ENT_CLIENT_TRIGGER_MUSIC = 26;
  const int ENT_CLIENT_HOOK = 27;
+ const int ENT_CLIENT_INVENTORY = 28;
  const int ENT_CLIENT_ARC_BEAM = 29; // WEAPONTODO: fix numbers
  const int ENT_CLIENT_ACCURACY = 30;
  const int ENT_CLIENT_SHOWNAMES = 31;
@@@ -78,8 -104,17 +104,19 @@@ const int ENT_CLIENT_ELIMINATEDPLAYERS 
  const int ENT_CLIENT_TURRET = 40;
  const int ENT_CLIENT_AUXILIARYXHAIR = 50;
  const int ENT_CLIENT_VEHICLE = 60;
- const int ENT_CLIENT_GENERATOR = 61;
- const int ENT_CLIENT_CONTROLPOINT_ICON = 62;
+ const int ENT_CLIENT_LADDER = 61;
+ const int ENT_CLIENT_TRIGGER_PUSH = 62;
+ const int ENT_CLIENT_TARGET_PUSH = 63;
+ const int ENT_CLIENT_CONVEYOR = 64;
+ const int ENT_CLIENT_DOOR = 65;
+ const int ENT_CLIENT_TRAIN = 66;
+ const int ENT_CLIENT_PLAT = 67;
+ const int ENT_CLIENT_TRIGGER_IMPULSE = 68;
+ const int ENT_CLIENT_SWAMP = 69;
+ const int ENT_CLIENT_CORNER = 70;
+ const int ENT_CLIENT_KEYLOCK = 71;
++const int ENT_CLIENT_GENERATOR = 72;
++const int ENT_CLIENT_CONTROLPOINT_ICON = 73;
  
  const int ENT_CLIENT_HEALING_ORB = 80;
  
@@@ -278,7 -313,7 +315,7 @@@ const int SERVERFLAG_ALLOW_FULLBRIGHT 
  const int SERVERFLAG_TEAMPLAY = 2;
  const int SERVERFLAG_PLAYERSTATS = 4;
  
- // FIXME/EXPLAINME: why?
+ // FIXME/EXPLAINME: why? Mario: because
  vector autocvar_sv_player_maxs = '16 16 45';
  vector autocvar_sv_player_mins = '-16 -16 -24';
  vector autocvar_sv_player_viewoffset = '0 0 20';
@@@ -287,6 -322,9 +324,9 @@@ vector autocvar_sv_player_crouch_mins 
  vector autocvar_sv_player_crouch_viewoffset = '0 0 20';
  vector autocvar_sv_player_headsize = '24 24 12';
  
+ // not so constant
+ #ifdef SVQC
  #define PL_VIEW_OFS autocvar_sv_player_viewoffset
  #define PL_MIN autocvar_sv_player_mins
  #define PL_MAX autocvar_sv_player_maxs
  #define PL_CROUCH_MIN autocvar_sv_player_crouch_mins
  #define PL_CROUCH_MAX autocvar_sv_player_crouch_maxs
  #define PL_HEAD autocvar_sv_player_headsize
+ #elif defined(CSQC)
+ #define PL_VIEW_OFS vec3(getstatf(STAT_PL_VIEW_OFS1), getstatf(STAT_PL_VIEW_OFS2), getstatf(STAT_PL_VIEW_OFS3))
+ #define PL_MIN vec3(getstatf(STAT_PL_MIN1), getstatf(STAT_PL_MIN2), getstatf(STAT_PL_MIN3))
+ #define PL_MAX vec3(getstatf(STAT_PL_MAX1), getstatf(STAT_PL_MAX2), getstatf(STAT_PL_MAX3))
+ #define PL_CROUCH_VIEW_OFS vec3(getstatf(STAT_PL_CROUCH_VIEW_OFS1), getstatf(STAT_PL_CROUCH_VIEW_OFS2), getstatf(STAT_PL_CROUCH_VIEW_OFS3))
+ #define PL_CROUCH_MIN vec3(getstatf(STAT_PL_CROUCH_MIN1), getstatf(STAT_PL_CROUCH_MIN2), getstatf(STAT_PL_CROUCH_MIN3))
+ #define PL_CROUCH_MAX vec3(getstatf(STAT_PL_CROUCH_MAX1), getstatf(STAT_PL_CROUCH_MAX2), getstatf(STAT_PL_CROUCH_MAX3))
+ #endif
  
- // helpers
- #define PL_VIEW_OFS_z autocvar_sv_player_viewoffset.z
- #define PL_MIN_z autocvar_sv_player_mins.z
- #define PL_MAX_z autocvar_sv_player_maxs.z
- #define PL_CROUCH_VIEW_OFS_z autocvar_sv_player_crouch_viewoffset.z
- #define PL_CROUCH_MIN_z autocvar_sv_player_mins.z
- #define PL_HEAD_x autocvar_sv_player_headsize.x
- #define PL_HEAD_y autocvar_sv_player_headsize.y
- #define PL_HEAD_z autocvar_sv_player_headsize.z
+ // a bit more constant
+ const vector PL_MAX_CONST = '16 16 45';
+ const vector PL_MIN_CONST = '-16 -16 -24';
  
  // spawnpoint prios
  const int SPAWN_PRIO_NEAR_TEAMMATE_FOUND = 200;
@@@ -321,8 -361,8 +363,8 @@@ const int URI_GET_UPDATENOTIFICATION = 
  const int URI_GET_URLLIB = 128;
  const int URI_GET_URLLIB_END = 191;
  
- // gametype votes
- const int GTV_AVAILABLE = 0;
- // for later use in per-map gametype filtering
- const int GTV_FORBIDDEN = 2;
+ // gametype vote flags
+ const int GTV_FORBIDDEN = 0; // Cannot be voted
+ const int GTV_AVAILABLE = 1; // Can be voted
+ const int GTV_CUSTOM    = 2; // Custom entry
  #endif
diff --combined qcsrc/common/mapinfo.qh
index eae3fb4324a8dc12a7bf5e58ef1222cbf1ed240b,134103b89f3f9b49ea014916403ea772452ebf4b..1dccb2fbd699a0edba8977cd2a3d47166a70e85a
@@@ -1,6 -1,8 +1,8 @@@
  #ifndef MAPINFO_H
  #define MAPINFO_H
  
+ #include "util.qh"
  int MAPINFO_TYPE_ALL;
  entity MapInfo_Type_first;
  entity MapInfo_Type_last;
@@@ -10,7 -12,7 +12,7 @@@
  .string netname; // game type name as in cvar (with g_ prefix)
  .string mdl; // game type short name
  .string message; // human readable name
- .float team; // does this gametype support teamplay?
+ .int team; // does this gametype support teamplay?
  .string model2; // game type defaults
  .string gametype_description; // game type description
  
@@@ -70,7 -72,7 +72,7 @@@ REGISTER_GAMETYPE(_("Key Hunt"),kh,g_ke
  REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,true,"timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out"));
  #define g_assault IS_GAMETYPE(ASSAULT)
  
 -REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,true,"timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
 +REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,true,"pointlimit=1 timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
  #define g_onslaught IS_GAMETYPE(ONSLAUGHT)
  
  REGISTER_GAMETYPE(_("Nexball"),nb,g_nexball,NEXBALL,true,"timelimit=20 pointlimit=5 leadlimit=0",_("XonSports"));
index 95e13c137e511ed8b3552a8e79b2d2d9174aef9b,8057190639464fd20eb66b5fb4fcc95fb2ee5620..0fd753453a5e85c7d8206223631d657dcfb1f848
@@@ -3,6 -3,7 +3,7 @@@
  
  #include "constants.qh"
  #include "teams.qh"
+ #include "util.qh"
  
  // ================================================
  //  Unified notification system, written by Samual
@@@ -371,11 -372,11 +372,11 @@@ void Send_Notification_WOCOVA
      MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_FIRE,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_death",         _("^BG%s%s^K1 was burnt up into a crisp by ^BG%s^K1%s%s"), _("^BG%s%s^K1 felt a little hot from ^BG%s^K1's fire^K1%s%s")) \
      MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_LAVA,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_lava",          _("^BG%s%s^K1 was cooked by ^BG%s^K1%s%s"), "") \
      MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_MONSTER,           3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_death",         _("^BG%s%s^K1 was pushed infront of a monster by ^BG%s^K1%s%s"), "") \
-     MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_nade",          _("^BG%s%s^K1 was blown up by ^BG%s^K1's Nade%s%s"), "") \
-     MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_NAPALM,       3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_nade_napalm",   _("^BG%s%s^K1 was burned to death by ^BG%s^K1's Napalm Nade%s%s"), _("^BG%s%s^K1 got too close to a napalm explosion%s%s")) \
-     MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_ICE,          3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_nade_ice",      _("^BG%s%s^K1 was blown up by ^BG%s^K1's Ice Nade%s%s"), "") \
-     MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_ICE_FREEZE,   3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_nade_ice",      _("^BG%s%s^K1 was frozen to death by ^BG%s^K1's Ice Nade%s%s"), "") \
-     MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_HEAL,         3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_nade_heal",     _("^BG%s%s^K1 has not been healed by ^BG%s^K1's Healing Nade%s%s"), "") \
+     MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "nade_normal",          _("^BG%s%s^K1 was blown up by ^BG%s^K1's Nade%s%s"), "") \
+     MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_NAPALM,       3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "nade_napalm",          _("^BG%s%s^K1 was burned to death by ^BG%s^K1's Napalm Nade%s%s"), _("^BG%s%s^K1 got too close to a napalm explosion%s%s")) \
+     MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_ICE,          3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "nade_ice",             _("^BG%s%s^K1 was blown up by ^BG%s^K1's Ice Nade%s%s"), "") \
+     MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_ICE_FREEZE,   3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "nade_ice",             _("^BG%s%s^K1 was frozen to death by ^BG%s^K1's Ice Nade%s%s"), "") \
+     MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_HEAL,         3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "nade_heal",            _("^BG%s%s^K1 has not been healed by ^BG%s^K1's Healing Nade%s%s"), "") \
      MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SHOOTING_STAR,     3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_shootingstar",  _("^BG%s%s^K1 was shot into space by ^BG%s^K1%s%s"), "") \
      MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SLIME,             3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_slime",         _("^BG%s%s^K1 was slimed by ^BG%s^K1%s%s"), "") \
      MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SWAMP,             3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "notify_slime",         _("^BG%s%s^K1 was preserved by ^BG%s^K1%s%s"), "") \
      MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_WYVERN,          2, 1, "s1 s2loc spree_lost", "s1",       "notify_death",         _("^BG%s^K1 was fireballed by a Wyvern%s%s"), "") \
      MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_JUMP,     2, 1, "s1 s2loc spree_lost", "s1",       "notify_death",         _("^BG%s^K1 joins the Zombies%s%s"), "") \
      MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_MELEE,    2, 1, "s1 s2loc spree_lost", "s1",       "notify_death",         _("^BG%s^K1 was given kung fu lessons by a Zombie%s%s"), "") \
-     MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE,                2, 1, "s1 s2loc spree_lost", "s1",       "notify_nade",          _("^BG%s^K1 mastered the art of self-nading%s%s"), "") \
-     MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_NAPALM,         2, 1, "s1 s2loc spree_lost", "s1",       "notify_nade_napalm",   _("^BG%s^K1 was burned to death by their own Napalm Nade%s%s"), _("^BG%s^K1 decided to take a look at the results of their napalm explosion%s%s")) \
-     MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_ICE,            2, 1, "s1 s2loc spree_lost", "s1",       "notify_nade_ice",      _("^BG%s^K1 mastered the art of self-nading%s%s"), "") \
-     MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_ICE_FREEZE,     2, 1, "s1 s2loc spree_lost", "s1",       "notify_nade_ice",      _("^BG%s^K1 was frozen to death by their own Ice Nade%s%s"), _("^BG%s^K1 felt a little chilly%s%s")) \
-     MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_HEAL,           2, 1, "s1 s2loc spree_lost", "s1",       "notify_nade_heal",     _("^BG%s^K1's Healing Nade didn't quite heal them%s%s"), "") \
+     MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE,                2, 1, "s1 s2loc spree_lost", "s1",       "nade_normal",          _("^BG%s^K1 mastered the art of self-nading%s%s"), "") \
+     MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_NAPALM,         2, 1, "s1 s2loc spree_lost", "s1",       "nade_napalm",          _("^BG%s^K1 was burned to death by their own Napalm Nade%s%s"), _("^BG%s^K1 decided to take a look at the results of their napalm explosion%s%s")) \
+     MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_ICE,            2, 1, "s1 s2loc spree_lost", "s1",       "nade_ice",             _("^BG%s^K1 mastered the art of self-nading%s%s"), "") \
+     MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_ICE_FREEZE,     2, 1, "s1 s2loc spree_lost", "s1",       "nade_ice",             _("^BG%s^K1 was frozen to death by their own Ice Nade%s%s"), _("^BG%s^K1 felt a little chilly%s%s")) \
+     MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_HEAL,           2, 1, "s1 s2loc spree_lost", "s1",       "nade_heal",            _("^BG%s^K1's Healing Nade didn't quite heal them%s%s"), "") \
      MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NOAMMO,              2, 1, "s1 s2loc spree_lost", "s1",       "notify_outofammo",     _("^BG%s^K1 died%s%s. What's the point of living without ammo?"), _("^BG%s^K1 ran out of ammo%s%s")) \
      MSG_INFO_NOTIF(1, INFO_DEATH_SELF_ROT,                 2, 1, "s1 s2loc spree_lost", "s1",       "notify_death",         _("^BG%s^K1 rotted away%s%s"), "") \
      MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SHOOTING_STAR,       2, 1, "s1 s2loc spree_lost", "s1",       "notify_shootingstar",  _("^BG%s^K1 became a shooting star%s%s"), "") \
      MSG_INFO_NOTIF(1, INFO_LMS_FORFEIT,                    1, 0, "s1", "",                          "",                     _("^BG%s^F3 forfeited"), "") \
      MSG_INFO_NOTIF(1, INFO_LMS_NOLIVES,                    1, 0, "s1", "",                          "",                     _("^BG%s^F3 has no more lives left"), "") \
      MSG_INFO_NOTIF(1, INFO_MONSTERS_DISABLED,              0, 0, "", "",                            "",                     _("^BGMonsters are currently disabled"), "") \
 +    MSG_INFO_NOTIF(1, INFO_ONSLAUGHT_CAPTURE,              2, 0, "s1 s2", "",                       "",                     _("^BG%s^BG captured %s^BG control point"), "") \
 +    MULTITEAM_INFO(1, INFO_ONSLAUGHT_CPDESTROYED_, 4,      2, 0, "s1 s2", "",                       "",                     _("^TC^TT^BG team %s^BG control point has been destroyed by %s"), "") \
 +    MULTITEAM_INFO(1, INFO_ONSLAUGHT_GENDESTROYED_, 4,     0, 0, "", "",                            "",                     _("^TC^TT^BG generator has been destroyed"), "") \
 +    MULTITEAM_INFO(1, INFO_ONSLAUGHT_GENDESTROYED_OVERTIME_, 4,  0, 0, "", "",                      "",                     _("^TC^TT^BG generator spontaneously combusted due to overtime!"), "") \
      MSG_INFO_NOTIF(1, INFO_POWERUP_INVISIBILITY,           1, 0, "s1", "s1",                        "strength",             _("^BG%s^K1 picked up Invisibility"), "") \
      MSG_INFO_NOTIF(1, INFO_POWERUP_SHIELD,                 1, 0, "s1", "s1",                        "shield",               _("^BG%s^K1 picked up Shield"), "") \
      MSG_INFO_NOTIF(1, INFO_POWERUP_SPEED,                  1, 0, "s1", "s1",                        "shield",               _("^BG%s^K1 picked up Speed"), "") \
      MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_REVIVE_SELF,       0, 0, "",             NO_CPID,             "0 0", _("^K3You revived yourself"), "") \
      MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_REVIVED,           1, 0, "s1",           NO_CPID,             "0 0", _("^K3You were revived by ^BG%s"), "") \
      MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_AUTO_REVIVED,      0, 1, "f1",           NO_CPID,             "0 0", _("^K3You were automatically revived after %s second(s)"), "") \
 +    MSG_CENTER_NOTIF(1, CENTER_GENERATOR_UNDERATTACK,       0, 0, "",             NO_CPID,             "0 0", _("^BGThe generator is under attack!"), "") \
      MULTITEAM_CENTER(1, CENTER_ROUND_TEAM_WIN_, 4,          0, 0, "",             CPID_ROUND,          "0 0", _("^TC^TT^BG team wins the round"), "") \
      MSG_CENTER_NOTIF(1, CENTER_ROUND_PLAYER_WIN,            1, 0, "s1",           CPID_ROUND,          "0 0", _("^BG%s^BG wins the round"), "") \
      MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_SELF,              0, 0, "",             NO_CPID,             "0 0", _("^K1You froze yourself"), "") \
      MSG_CENTER_NOTIF(1, CENTER_NIX_COUNTDOWN,               0, 2, "item_wepname",  CPID_NIX,              "1 f2", _("^F2^COUNT^BG until weapon change...\nNext weapon: ^F1%s"), "") \
      MSG_CENTER_NOTIF(1, CENTER_NIX_NEWWEAPON,               0, 1, "item_wepname",  CPID_NIX,              "0 0", _("^F2Active weapon: ^F1%s"), "") \
      MSG_CENTER_NOTIF(1, CENTER_NADE,                        0, 0, "",              NO_CPID,               "0 0", _("^BGPress ^F2DROPWEAPON^BG again to toss the grenade!"), "") \
 -    MSG_CENTER_NOTIF(1, CENTER_ONS_NOTSHIELDED,             0, 0, "",              CPID_ONSLAUGHT,        "0 0", _("^K1Your generator is NOT shielded!\n^BGRe-capture controlpoints to shield it!"), "") \
 +    MSG_CENTER_NOTIF(1, CENTER_ONS_CAPTURE,                 1, 0, "s1",            CPID_ONSLAUGHT,        "0 0", _("^BGYou captured %s^BG control point"), "") \
 +    MULTITEAM_CENTER(1, CENTER_ONS_CAPTURE_, 4,             1, 0, "s1",            CPID_ONSLAUGHT,        "0 0", _("^TC^TT^BG team captured %s^BG control point"), "") \
 +    MSG_CENTER_NOTIF(1, CENTER_ONS_CONTROLPOINT_SHIELDED,   0, 0, "",              CPID_ONS_CAPSHIELD,    "0 0", _("^BGThis control point currently cannot be captured"), "") \
 +    MSG_CENTER_NOTIF(1, CENTER_ONS_GENERATOR_SHIELDED,      0, 0, "",              CPID_ONS_CAPSHIELD,    "0 0", _("^BGThe enemy generator cannot be destroyed yet\n^F2Capture some control points to unshield it"), "") \
 +    MULTITEAM_CENTER(1, CENTER_ONS_NOTSHIELDED_, 4,         0, 0, "",              CPID_ONSLAUGHT,        "0 0", _("^BGThe ^TCenemy^BG generator is no longer shielded!"), "") \
 +    MSG_CENTER_NOTIF(1, CENTER_ONS_NOTSHIELDED_TEAM,        0, 0, "",              CPID_ONSLAUGHT,        "0 0", _("^K1Your generator is NOT shielded!\n^BGRe-capture control points to shield it!"), "") \
 +    MSG_CENTER_NOTIF(1, CENTER_ONS_TELEPORT,                0, 0, "pass_key",      CPID_ONSLAUGHT,        "0 0", _("^BGPress ^F2DROPFLAG%s^BG to teleport"), "") \
 +    MSG_CENTER_NOTIF(1, CENTER_ONS_TELEPORT_ANTISPAM,       0, 1, "f1secs",        CPID_ONSLAUGHT,        "0 0", _("^BGTeleporting disabled for %s"), "") \
      MSG_CENTER_NOTIF(1, CENTER_OVERTIME_FRAG,               0, 0, "",              CPID_OVERTIME,         "0 0", _("^F2Now playing ^F4OVERTIME^F2!\nKeep fragging until we have a winner!"), _("^F2Now playing ^F4OVERTIME^F2!\nKeep scoring until we have a winner!")) \
      MSG_CENTER_NOTIF(1, CENTER_OVERTIME_CONTROLPOINT,       0, 0, "",              CPID_OVERTIME,         "5 0", _("^F2Now playing ^F4OVERTIME^F2!\n\nGenerators are now decaying.\nThe more control points your team holds,\nthe faster the enemy generator decays"), "") \
      MSG_CENTER_NOTIF(1, CENTER_OVERTIME_TIME,               0, 1, "f1time",        CPID_OVERTIME,         "0 0", _("^F2Now playing ^F4OVERTIME^F2!\n^BGAdded ^F4%s^BG to the game!"), "") \
@@@ -1313,7 -1302,6 +1314,7 @@@ enum 
  ,   CPID_MOTD
  ,   CPID_NIX
  ,   CPID_ONSLAUGHT
 +,   CPID_ONS_CAPSHIELD
  ,   CPID_OVERTIME
  ,   CPID_POWERUP
  ,   CPID_RACE_FINISHLAP
diff --combined qcsrc/common/stats.qh
index cbb0d7ba9c162252cdc6ca332a489f09f22ba18f,b488df1cfd709edacf36401d42990adbd4f4ed93..f461d8b62cfee12e99b0f2a4cccf6b1a585e969c
@@@ -5,23 -5,38 +5,38 @@@
  // 255 is the current limit (MAX_CL_STATS - 1), engine will need to be modified if you wish to add more stats
  
  const int MAX_CL_STATS                = 256;
- const int STAT_HEALTH                 = 0;
+ // -Wdouble-declaration
+ // const int STAT_HEALTH                 = 0;
  // 1 empty?
  const int STAT_WEAPON                 = 2;
- const int STAT_AMMO                   = 3;
- const int STAT_ARMOR                  = 4;
- const int STAT_WEAPONFRAME            = 5;
- const int STAT_SHELLS                 = 6;
- const int STAT_NAILS                  = 7;
- const int STAT_ROCKETS                = 8;
- const int STAT_CELLS                  = 9;
- const int STAT_ACTIVEWEAPON           = 10;
- const int STAT_TOTALSECRETS           = 11;
- const int STAT_TOTALMONSTERS          = 12;
- const int STAT_SECRETS                = 13;
- const int STAT_MONSTERS               = 14;
- const int STAT_ITEMS                  = 15;
- const int STAT_VIEWHEIGHT             = 16;
+ // -Wdouble-declaration
+ // const int STAT_AMMO                   = 3;
+ // -Wdouble-declaration
+ // const int STAT_ARMOR                  = 4;
+ // -Wdouble-declaration
+ // const int STAT_WEAPONFRAME            = 5;
+ // -Wdouble-declaration
+ // const int STAT_SHELLS                 = 6;
+ // -Wdouble-declaration
+ // const int STAT_NAILS                  = 7;
+ // -Wdouble-declaration
+ // const int STAT_ROCKETS                = 8;
+ // -Wdouble-declaration
+ // const int STAT_CELLS                  = 9;
+ // -Wdouble-declaration
+ // const int STAT_ACTIVEWEAPON           = 10;
+ // -Wdouble-declaration
+ // const int STAT_TOTALSECRETS           = 11;
+ // -Wdouble-declaration
+ // const int STAT_TOTALMONSTERS          = 12;
+ // -Wdouble-declaration
+ // const int STAT_SECRETS                = 13;
+ // -Wdouble-declaration
+ // const int STAT_MONSTERS               = 14;
+ // -Wdouble-declaration
+ // const int STAT_ITEMS                  = 15;
+ // -Wdouble-declaration
+ // const int STAT_VIEWHEIGHT             = 16;
  // 17 empty?
  // 18 empty?
  // 19 empty?
@@@ -92,9 -107,9 +107,9 @@@ const int STAT_HEALING_ORB_ALPHA      
  const int STAT_PLASMA                 = 84;
  const int STAT_OK_AMMO_CHARGE         = 85;
  const int STAT_OK_AMMO_CHARGEPOOL     = 86;
- const int STAT_ROUNDLOST              = 87;
- // 88 empty?
- // 89 empty?
+ const int STAT_FROZEN                 = 87;
+ const int STAT_REVIVE_PROGRESS        = 88;
 -// 89 empty?
++const int STAT_ROUNDLOST              = 89;
  // 90 empty?
  // 91 empty?
  // 92 empty?
@@@ -138,22 -153,24 +153,24 @@@ const int STAT_KH_PINKKEY_TEAM        
  
  /* Gamemode-specific stats end here */
  
- const int STAT_FROZEN                 = 105;
- const int STAT_REVIVE_PROGRESS        = 106;
- // 107 empty?
- // 108 empty?
- // 109 empty?
- // 110 empty?
- // 111 empty?
- // 112 empty?
- // 113 empty?
- // 114 empty?
- // 115 empty?
- // 116 empty?
- // 117 empty?
- // 118 empty?
- // 119 empty?
+ const int STAT_PL_VIEW_OFS1           = 105;
+ const int STAT_PL_VIEW_OFS2           = 106;
+ const int STAT_PL_VIEW_OFS3           = 107;
+ const int STAT_PL_MIN1                = 108;
+ const int STAT_PL_MIN2                = 109;
+ const int STAT_PL_MIN3                = 110;
+ const int STAT_PL_MAX1                = 111;
+ const int STAT_PL_MAX2                = 112;
+ const int STAT_PL_MAX3                = 113;
+ const int STAT_PL_CROUCH_MIN1         = 114;
+ const int STAT_PL_CROUCH_MIN2         = 115;
+ const int STAT_PL_CROUCH_MIN3         = 116;
+ const int STAT_PL_CROUCH_MAX1         = 117;
+ const int STAT_PL_CROUCH_MAX2         = 118;
+ const int STAT_PL_CROUCH_MAX3         = 119;
+ const int STAT_PL_CROUCH_VIEW_OFS1    = 117;
+ const int STAT_PL_CROUCH_VIEW_OFS2    = 118;
+ const int STAT_PL_CROUCH_VIEW_OFS3    = 119;
  // 120 empty?
  // 121 empty?
  // 122 empty?
  // 165 empty?
  // 166 empty?
  // 167 empty?
- // 168 empty?
- // 169 empty?
- // 170 empty?
- // 171 empty?
- // 172 empty?
- // 173 empty?
- // 174 empty?
- // 175 empty?
- // 176 empty?
- // 177 empty?
- // 178 empty?
- // 179 empty?
- // 180 empty?
- // 181 empty?
- // 182 empty?
- // 183 empty?
- // 184 empty?
- // 185 empty?
- // 186 empty?
- // 187 empty?
- // 188 empty?
- // 189 empty?
- // 190 empty?
- // 191 empty?
- // 192 empty?
- // 193 empty?
- // 194 empty?
- // 195 empty?
- // 196 empty?
- // 197 empty?
- // 198 empty?
- // 199 empty?
- // 200 empty?
- // 201 empty?
- // 202 empty?
- // 203 empty?
- // 204 empty?
- // 205 empty?
- // 206 empty?
- // 207 empty?
- // 208 empty?
- // 209 empty?
- // 210 empty?
- // 211 empty?
- // 212 empty?
- // 213 empty?
- // 214 empty?
- // 215 empty?
- // 216 empty?
- // 217 empty?
- // 218 empty?
- // 219 empty?
+ const int STAT_GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND   = 168;
+ const int STAT_BUGRIGS_REVERSE_STOPPING               = 169;
+ const int STAT_BUGRIGS_REVERSE_SPINNING               = 170;
+ const int STAT_BUGRIGS_CAR_JUMPING                    = 171;
+ const int STAT_BUGRIGS_FRICTION_AIR                   = 172;
+ const int STAT_BUGRIGS_STEER                          = 173;
+ const int STAT_BUGRIGS_SPEED_POW                      = 174;
+ const int STAT_BUGRIGS_SPEED_REF                      = 175;
+ const int STAT_BUGRIGS_ACCEL                          = 176;
+ const int STAT_BUGRIGS_FRICTION_BRAKE                 = 177;
+ const int STAT_BUGRIGS_AIR_STEERING                   = 178;
+ const int STAT_BUGRIGS_FRICTION_FLOOR                 = 179;
+ const int STAT_BUGRIGS_REVERSE_SPEEDING               = 180;
+ const int STAT_BUGRIGS_PLANAR_MOVEMENT                = 181;
+ const int STAT_BUGRIGS_ANGLE_SMOOTHING                = 182;
+ const int STAT_BUGRIGS                                = 183;
+ const int STAT_GAMEPLAYFIX_STEPDOWN                   = 184;
+ const int STAT_MOVEVARS_JUMPSTEP                      = 185;
+ const int STAT_NOSTEP                                 = 186;
+ const int STAT_GAMEPLAYFIX_UNSTICKPLAYERS             = 187;
+ const int STAT_GAMEPLAYFIX_STEPMULTIPLETIMES          = 188;
+ const int STAT_GAMEPLAYFIX_DOWNTRACEONGROUND          = 189;
+ const int STAT_GAMEPLAYFIX_EASIERWATERJUMP            = 190;
+ const int STAT_MOVEVARS_FRICTION_SLICK                = 191;
+ const int STAT_MOVEVARS_FRICTION_ONLAND               = 192;
+ const int STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS  = 193;
+ const int STAT_MOVEVARS_JUMPSPEEDCAP_MAX              = 194;
+ const int STAT_MOVEVARS_JUMPSPEEDCAP_MIN              = 195;
+ const int STAT_DOUBLEJUMP                             = 196;
+ const int STAT_MOVEVARS_TRACK_CANJUMP                 = 197;
+ const int STAT_MULTIJUMP_ADD                          = 198;
+ const int STAT_MULTIJUMP_SPEED                        = 199;
+ const int STAT_MULTIJUMP                              = 200;
+ const int STAT_DODGING_TIMEOUT                        = 201;
+ const int STAT_DODGING_WALL                           = 202;
+ const int STAT_DODGING_UP_SPEED                       = 203;
+ const int STAT_DODGING_RAMP_TIME                      = 204;
+ const int STAT_DODGING_HEIGHT_THRESHOLD               = 205;
+ const int STAT_DODGING_DISTANCE_THRESHOLD             = 206;
+ const int STAT_DODGING_HORIZ_SPEED                    = 207;
+ const int STAT_DODGING_DELAY                          = 208;
+ const int STAT_DODGING_FROZEN_NO_DOUBLETAP            = 209;
+ const int STAT_DODGING_HORIZ_SPEED_FROZEN             = 210;
+ const int STAT_DODGING                                = 211;
+ const int STAT_DODGING_FROZEN                         = 212;
+ const int STAT_JETPACK_MAXSPEED_UP                    = 213;
+ const int STAT_JETPACK_MAXSPEED_SIDE                  = 214;
+ const int STAT_JETPACK_FUEL                           = 215;
+ const int STAT_JETPACK_ANTIGRAVITY                    = 216;
+ const int STAT_JETPACK_ACCEL_SIDE                     = 217;
+ const int STAT_JETPACK_ACCEL_UP                       = 218;
+ const int STAT_MOVEVARS_HIGHSPEED                     = 219;
  const int STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR     = 220;
  const int STAT_MOVEVARS_AIRCONTROL_PENALTY            = 221;
  const int STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW           = 222;
@@@ -270,14 -287,19 +287,19 @@@ const int STAT_MOVEVARS_AIRSTOPACCELERA
  const int STAT_MOVEVARS_AIRSTRAFEACCELERATE           = 232;
  const int STAT_MOVEVARS_MAXAIRSTRAFESPEED             = 233;
  const int STAT_MOVEVARS_AIRCONTROL                    = 234;
- const int STAT_FRAGLIMIT                              = 235;
- const int STAT_TIMELIMIT                              = 236;
+ // -Wdouble-declaration
+ // const int STAT_FRAGLIMIT                              = 235;
+ // -Wdouble-declaration
+ // const int STAT_TIMELIMIT                              = 236;
  const int STAT_MOVEVARS_WALLFRICTION                  = 237;
  const int STAT_MOVEVARS_FRICTION                      = 238;
  const int STAT_MOVEVARS_WATERFRICTION                 = 239;
- const int STAT_MOVEVARS_TICRATE                       = 240;
- const int STAT_MOVEVARS_TIMESCALE                     = 241;
- const int STAT_MOVEVARS_GRAVITY                       = 242;
+ // -Wdouble-declaration
+ // const int STAT_MOVEVARS_TICRATE                       = 240;
+ // -Wdouble-declaration
+ // const int STAT_MOVEVARS_TIMESCALE                     = 241;
+ // -Wdouble-declaration
+ // const int STAT_MOVEVARS_GRAVITY                       = 242;
  const int STAT_MOVEVARS_STOPSPEED                     = 243;
  const int STAT_MOVEVARS_MAXSPEED                      = 244;
  const int STAT_MOVEVARS_SPECTATORMAXSPEED             = 245;
index 0000000000000000000000000000000000000000,474f797afea7ad67e1611b8c12644f836ab0af1d..c8e593f9cb53666eb6418b2d18033b7dac31783b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,52 +1,54 @@@
+ #ifndef TRIGGERS_H
+ #define TRIGGERS_H
+ const float SF_TRIGGER_INIT = 1;
+ const float SF_TRIGGER_UPDATE = 2;
+ const float SF_TRIGGER_RESET = 4;
+ const float   SPAWNFLAG_NOMESSAGE = 1;
+ const float   SPAWNFLAG_NOTOUCH = 1;
+ .void() trigger_touch;
+ .float antiwall_flag; // Variable to define what to do with func_clientwall
+ // 0 == do nothing, 1 == deactivate, 2 == activate
+ .float height;
+ .float nottargeted;
+ #define IFTARGETED if(!self.nottargeted && self.targetname != "")
+ .float lip;
+ // used elsewhere (will fix)
+ #ifdef SVQC
+ void trigger_common_write(bool withtarget);
+ string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin);
+ void target_voicescript_next(entity pl);
+ void target_voicescript_clear(entity pl);
+ #endif
+ .float volume, atten;
+ .vector dest;
++void FixSize(entity e);
++
+ #ifdef CSQC
+ void trigger_common_read(bool withtarget);
+ void trigger_remove_generic();
+ .float active;
+ .string target;
+ .string targetname;
+ const int ACTIVE_NOT          = 0;
+ const int ACTIVE_ACTIVE       = 1;
+ const int ACTIVE_IDLE                 = 2;
+ const int ACTIVE_BUSY                 = 2;
+ const int ACTIVE_TOGGLE               = 3;
+ #endif
+ #endif
index 0044b16b7aa243bd6595123ae407208b7c2f520b,51b14aa0812e2c2af73a354b7cd204608beb736c..4a779e0343c6d487e89608eca0257ab41f33554f
@@@ -128,12 -128,12 +128,12 @@@ float autocvar_g_balance_keyhunt_delay_
  float autocvar_g_balance_keyhunt_dropvelocity;
  float autocvar_g_balance_keyhunt_maxdist;
  float autocvar_g_balance_keyhunt_protecttime;
float autocvar_g_balance_keyhunt_score_capture;
float autocvar_g_balance_keyhunt_score_carrierfrag;
float autocvar_g_balance_keyhunt_score_collect;
float autocvar_g_balance_keyhunt_score_destroyed;
float autocvar_g_balance_keyhunt_score_destroyed_ownfactor;
float autocvar_g_balance_keyhunt_score_push;
int autocvar_g_balance_keyhunt_score_capture;
int autocvar_g_balance_keyhunt_score_carrierfrag;
int autocvar_g_balance_keyhunt_score_collect;
int autocvar_g_balance_keyhunt_score_destroyed;
int autocvar_g_balance_keyhunt_score_destroyed_ownfactor;
int autocvar_g_balance_keyhunt_score_push;
  float autocvar_g_balance_keyhunt_throwvelocity;
  float autocvar_g_balance_kill_delay;
  float autocvar_g_balance_kill_antispam;
@@@ -145,18 -145,18 +145,18 @@@ float autocvar_g_balance_nexball_second
  float autocvar_g_balance_nexball_secondary_lifetime;
  float autocvar_g_balance_nexball_secondary_refire;
  float autocvar_g_balance_nexball_secondary_speed;
float autocvar_g_balance_nix_ammo_cells;
float autocvar_g_balance_nix_ammo_plasma;
float autocvar_g_balance_nix_ammo_fuel;
float autocvar_g_balance_nix_ammo_nails;
float autocvar_g_balance_nix_ammo_rockets;
float autocvar_g_balance_nix_ammo_shells;
float autocvar_g_balance_nix_ammoincr_cells;
float autocvar_g_balance_nix_ammoincr_plasma;
float autocvar_g_balance_nix_ammoincr_fuel;
float autocvar_g_balance_nix_ammoincr_nails;
float autocvar_g_balance_nix_ammoincr_rockets;
float autocvar_g_balance_nix_ammoincr_shells;
int autocvar_g_balance_nix_ammo_cells;
int autocvar_g_balance_nix_ammo_plasma;
int autocvar_g_balance_nix_ammo_fuel;
int autocvar_g_balance_nix_ammo_nails;
int autocvar_g_balance_nix_ammo_rockets;
int autocvar_g_balance_nix_ammo_shells;
int autocvar_g_balance_nix_ammoincr_cells;
int autocvar_g_balance_nix_ammoincr_plasma;
int autocvar_g_balance_nix_ammoincr_fuel;
int autocvar_g_balance_nix_ammoincr_nails;
int autocvar_g_balance_nix_ammoincr_rockets;
int autocvar_g_balance_nix_ammoincr_shells;
  float autocvar_g_balance_nix_incrtime;
  float autocvar_g_balance_nix_roundtime;
  float autocvar_g_balance_pause_armor_rot;
@@@ -179,8 -179,8 +179,8 @@@ float autocvar_g_balance_powerup_streng
  float autocvar_g_balance_powerup_strength_time;
  float autocvar_g_balance_superweapons_time;
  float autocvar_g_balance_selfdamagepercent;
float autocvar_g_balance_teams;
float autocvar_g_balance_teams_prevent_imbalance;
bool autocvar_g_balance_teams;
bool autocvar_g_balance_teams_prevent_imbalance;
  float autocvar_g_balance_teams_scorefactor;
  float autocvar_g_ballistics_density_corpse;
  float autocvar_g_ballistics_density_player;
@@@ -190,47 -190,47 +190,47 @@@ float autocvar_g_ban_default_masksize
  float autocvar_g_ban_sync_interval;
  float autocvar_g_ban_sync_timeout;
  string autocvar_g_ban_sync_trusted_servers;
float autocvar_g_ban_sync_trusted_servers_verify;
bool autocvar_g_ban_sync_trusted_servers_verify;
  string autocvar_g_ban_sync_uri;
  string autocvar_g_banned_list;
float autocvar_g_banned_list_idmode;
float autocvar_g_bastet;
float autocvar_g_botclip_collisions;
float autocvar_g_bugrigs;
bool autocvar_g_banned_list_idmode;
bool autocvar_g_bastet;
bool autocvar_g_botclip_collisions;
bool autocvar_g_bugrigs;
  float autocvar_g_ca_damage2score_multiplier;
float autocvar_g_ca_point_leadlimit;
float autocvar_g_ca_point_limit;
int autocvar_g_ca_point_leadlimit;
int autocvar_g_ca_point_limit;
  float autocvar_g_ca_round_timelimit;
float autocvar_g_ca_spectate_enemies;
float autocvar_g_ca_teams;
float autocvar_g_ca_teams_override;
float autocvar_g_ca_team_spawns;
bool autocvar_g_ca_spectate_enemies;
int autocvar_g_ca_teams;
int autocvar_g_ca_teams_override;
bool autocvar_g_ca_team_spawns;
  float autocvar_g_ca_warmup;
float autocvar_g_campaign;
bool autocvar_g_campaign;
  #define autocvar_g_campaign_forceteam cvar("g_campaign_forceteam")
float autocvar_g_campaign_skill;
float autocvar_g_casings;
float autocvar_g_changeteam_banned;
int autocvar_g_campaign_skill;
int autocvar_g_casings;
bool autocvar_g_changeteam_banned;
  float autocvar_g_chat_flood_burst;
  float autocvar_g_chat_flood_burst_team;
  float autocvar_g_chat_flood_burst_tell;
  float autocvar_g_chat_flood_lmax;
  float autocvar_g_chat_flood_lmax_team;
  float autocvar_g_chat_flood_lmax_tell;
float autocvar_g_chat_flood_notify_flooder;
bool autocvar_g_chat_flood_notify_flooder;
  float autocvar_g_chat_flood_spl;
  float autocvar_g_chat_flood_spl_team;
  float autocvar_g_chat_flood_spl_tell;
float autocvar_g_chat_nospectators;
float autocvar_g_chat_teamcolors;
float autocvar_g_chat_tellprivacy;
float autocvar_g_ctf_allow_vehicle_carry;
float autocvar_g_ctf_allow_vehicle_touch;
float autocvar_g_ctf_allow_monster_touch;
float autocvar_g_ctf_throw;
int autocvar_g_chat_nospectators;
bool autocvar_g_chat_teamcolors;
bool autocvar_g_chat_tellprivacy;
bool autocvar_g_ctf_allow_vehicle_carry;
bool autocvar_g_ctf_allow_vehicle_touch;
bool autocvar_g_ctf_allow_monster_touch;
bool autocvar_g_ctf_throw;
  float autocvar_g_ctf_throw_angle_max;
  float autocvar_g_ctf_throw_angle_min;
float autocvar_g_ctf_throw_punish_count;
int autocvar_g_ctf_throw_punish_count;
  float autocvar_g_ctf_throw_punish_delay;
  float autocvar_g_ctf_throw_punish_time;
  float autocvar_g_ctf_throw_strengthmultiplier;
@@@ -238,31 -238,31 +238,31 @@@ float autocvar_g_ctf_throw_velocity_for
  float autocvar_g_ctf_throw_velocity_up;
  float autocvar_g_ctf_drop_velocity_up;
  float autocvar_g_ctf_drop_velocity_side;
float autocvar_g_ctf_portalteleport;
float autocvar_g_ctf_pass;
bool autocvar_g_ctf_portalteleport;
bool autocvar_g_ctf_pass;
  float autocvar_g_ctf_pass_arc;
  float autocvar_g_ctf_pass_arc_max;
  float autocvar_g_ctf_pass_directional_max;
  float autocvar_g_ctf_pass_directional_min;
  float autocvar_g_ctf_pass_radius;
  float autocvar_g_ctf_pass_wait;
float autocvar_g_ctf_pass_request;
bool autocvar_g_ctf_pass_request;
  float autocvar_g_ctf_pass_turnrate;
  float autocvar_g_ctf_pass_timelimit;
  float autocvar_g_ctf_pass_velocity;
float autocvar_g_ctf_dynamiclights;
bool autocvar_g_ctf_dynamiclights;
  string autocvar_g_ctf_flag_blue_model;
float autocvar_g_ctf_flag_blue_skin;
int autocvar_g_ctf_flag_blue_skin;
  float autocvar_g_ctf_flag_collect_delay;
  float autocvar_g_ctf_flag_damageforcescale;
float autocvar_g_ctf_flag_dropped_waypoint;
int autocvar_g_ctf_flag_dropped_waypoint;
  float autocvar_g_ctf_flag_dropped_floatinwater;
float autocvar_g_ctf_flag_glowtrails;
bool autocvar_g_ctf_flag_glowtrails;
  float autocvar_g_ctf_flag_health;
  string autocvar_g_ctf_flag_red_model;
float autocvar_g_ctf_flag_red_skin;
int autocvar_g_ctf_flag_red_skin;
  float autocvar_g_ctf_flag_return_time;
float autocvar_g_ctf_flag_return_when_unreachable;
bool autocvar_g_ctf_flag_return_when_unreachable;
  float autocvar_g_ctf_flag_return_damage;
  float autocvar_g_ctf_flag_return_dropped;
  float autocvar_g_ctf_flagcarrier_auto_helpme_damage;
@@@ -272,82 -272,82 +272,82 @@@ float autocvar_g_ctf_flagcarrier_selffo
  float autocvar_g_ctf_flagcarrier_damagefactor;
  float autocvar_g_ctf_flagcarrier_forcefactor;
  //float autocvar_g_ctf_flagcarrier_waypointforenemy_spotting;
float autocvar_g_ctf_fullbrightflags;
float autocvar_g_ctf_ignore_frags;
float autocvar_g_ctf_score_capture;
float autocvar_g_ctf_score_capture_assist;
float autocvar_g_ctf_score_kill;
float autocvar_g_ctf_score_penalty_drop;
- //float autocvar_g_ctf_score_penalty_suicidedrop;
float autocvar_g_ctf_score_penalty_returned;
float autocvar_g_ctf_score_pickup_base;
float autocvar_g_ctf_score_pickup_dropped_early;
float autocvar_g_ctf_score_pickup_dropped_late;
float autocvar_g_ctf_score_return;
bool autocvar_g_ctf_fullbrightflags;
bool autocvar_g_ctf_ignore_frags;
int autocvar_g_ctf_score_capture;
int autocvar_g_ctf_score_capture_assist;
int autocvar_g_ctf_score_kill;
int autocvar_g_ctf_score_penalty_drop;
+ //int autocvar_g_ctf_score_penalty_suicidedrop;
int autocvar_g_ctf_score_penalty_returned;
int autocvar_g_ctf_score_pickup_base;
int autocvar_g_ctf_score_pickup_dropped_early;
int autocvar_g_ctf_score_pickup_dropped_late;
int autocvar_g_ctf_score_return;
  float autocvar_g_ctf_shield_force;
  float autocvar_g_ctf_shield_max_ratio;
float autocvar_g_ctf_shield_min_negscore;
float autocvar_g_ctf_stalemate;
float autocvar_g_ctf_stalemate_endcondition;
int autocvar_g_ctf_shield_min_negscore;
bool autocvar_g_ctf_stalemate;
int autocvar_g_ctf_stalemate_endcondition;
  float autocvar_g_ctf_stalemate_time;
float autocvar_g_ctf_reverse;
bool autocvar_g_ctf_reverse;
  float autocvar_g_ctf_dropped_capture_delay;
  float autocvar_g_ctf_dropped_capture_radius;
  float autocvar_g_cts_finish_kill_delay;
float autocvar_g_cts_selfdamage;
float autocvar_g_debug_bot_commands;
float autocvar_g_domination_default_teams;
float autocvar_g_domination_disable_frags;
float autocvar_g_domination_point_amt;
float autocvar_g_domination_point_fullbright;
float autocvar_g_domination_point_leadlimit;
float autocvar_g_domination_roundbased;
float autocvar_g_domination_roundbased_point_limit;
bool autocvar_g_cts_selfdamage;
bool autocvar_g_debug_bot_commands;
int autocvar_g_domination_default_teams;
bool autocvar_g_domination_disable_frags;
int autocvar_g_domination_point_amt;
bool autocvar_g_domination_point_fullbright;
int autocvar_g_domination_point_leadlimit;
bool autocvar_g_domination_roundbased;
int autocvar_g_domination_roundbased_point_limit;
  float autocvar_g_domination_round_timelimit;
  float autocvar_g_domination_warmup;
  #define autocvar_g_domination_point_limit cvar("g_domination_point_limit")
  float autocvar_g_domination_point_rate;
float autocvar_g_domination_teams_override;
float autocvar_g_forced_respawn;
int autocvar_g_domination_teams_override;
bool autocvar_g_forced_respawn;
  string autocvar_g_forced_team_blue;
  string autocvar_g_forced_team_otherwise;
  string autocvar_g_forced_team_pink;
  string autocvar_g_forced_team_red;
  string autocvar_g_forced_team_yellow;
float autocvar_g_freezetag_frozen_damage_trigger;
bool autocvar_g_freezetag_frozen_damage_trigger;
  float autocvar_g_freezetag_frozen_force;
  float autocvar_g_freezetag_frozen_maxtime;
  float autocvar_g_freezetag_revive_falldamage;
  float autocvar_g_freezetag_revive_falldamage_health;
float autocvar_g_freezetag_revive_nade;
bool autocvar_g_freezetag_revive_nade;
  float autocvar_g_freezetag_revive_nade_health;
float autocvar_g_freezetag_point_leadlimit;
float autocvar_g_freezetag_point_limit;
int autocvar_g_freezetag_point_leadlimit;
int autocvar_g_freezetag_point_limit;
  float autocvar_g_freezetag_revive_extra_size;
  float autocvar_g_freezetag_revive_speed;
  float autocvar_g_freezetag_revive_clearspeed;
  float autocvar_g_freezetag_round_timelimit;
float autocvar_g_freezetag_teams;
float autocvar_g_freezetag_teams_override;
float autocvar_g_freezetag_team_spawns;
int autocvar_g_freezetag_teams;
int autocvar_g_freezetag_teams_override;
bool autocvar_g_freezetag_team_spawns;
  float autocvar_g_freezetag_warmup;
  #define autocvar_g_friendlyfire cvar("g_friendlyfire")
  #define autocvar_g_friendlyfire_virtual cvar("g_friendlyfire_virtual")
  #define autocvar_g_friendlyfire_virtual_force cvar("g_friendlyfire_virtual_force")
float autocvar_g_full_getstatus_responses;
float autocvar_g_fullbrightitems;
float autocvar_g_fullbrightplayers;
bool autocvar_g_full_getstatus_responses;
bool autocvar_g_fullbrightitems;
bool autocvar_g_fullbrightplayers;
  #define autocvar_g_grappling_hook cvar("g_grappling_hook")
float autocvar_g_grappling_hook_tarzan;
float autocvar_g_hitplots;
int autocvar_g_grappling_hook_tarzan;
bool autocvar_g_hitplots;
  string autocvar_g_hitplots_individuals;
  float autocvar_g_jetpack_acceleration_side;
  float autocvar_g_jetpack_acceleration_up;
  float autocvar_g_jetpack_antigravity;
float autocvar_g_jetpack_fuel;
int autocvar_g_jetpack_fuel;
  float autocvar_g_jetpack_maxspeed_side;
  float autocvar_g_jetpack_maxspeed_up;
float autocvar_g_keepaway_ballcarrier_effects;
int autocvar_g_keepaway_ballcarrier_effects;
  float autocvar_g_keepaway_ballcarrier_damage;
  float autocvar_g_keepaway_ballcarrier_force;
  float autocvar_g_keepaway_ballcarrier_highspeed;
@@@ -357,61 -357,61 +357,61 @@@ float autocvar_g_keepaway_noncarrier_da
  float autocvar_g_keepaway_noncarrier_force;
  float autocvar_g_keepaway_noncarrier_selfdamage;
  float autocvar_g_keepaway_noncarrier_selfforce;
float autocvar_g_keepaway_noncarrier_warn;
float autocvar_g_keepaway_score_bckill;
float autocvar_g_keepaway_score_killac;
float autocvar_g_keepaway_score_timepoints;
bool autocvar_g_keepaway_noncarrier_warn;
int autocvar_g_keepaway_score_bckill;
int autocvar_g_keepaway_score_killac;
int autocvar_g_keepaway_score_timepoints;
  float autocvar_g_keepaway_score_timeinterval;
  float autocvar_g_keepawayball_damageforcescale;
float autocvar_g_keepawayball_effects;
int autocvar_g_keepawayball_effects;
  float autocvar_g_keepawayball_respawntime;
float autocvar_g_keepawayball_trail_color;
float autocvar_g_keyhunt_point_leadlimit;
int autocvar_g_keepawayball_trail_color;
int autocvar_g_keyhunt_point_leadlimit;
  #define autocvar_g_keyhunt_point_limit cvar("g_keyhunt_point_limit")
float autocvar_g_keyhunt_teams;
float autocvar_g_keyhunt_teams_override;
float autocvar_g_lms_extra_lives;
float autocvar_g_lms_join_anytime;
float autocvar_g_lms_last_join;
int autocvar_g_keyhunt_teams;
int autocvar_g_keyhunt_teams_override;
int autocvar_g_lms_extra_lives;
bool autocvar_g_lms_join_anytime;
int autocvar_g_lms_last_join;
  #define autocvar_g_lms_lives_override cvar("g_lms_lives_override")
float autocvar_g_lms_regenerate;
bool autocvar_g_lms_regenerate;
  #define autocvar_g_maplist cvar_string("g_maplist")
float autocvar_g_maplist_check_waypoints;
float autocvar_g_maplist_index;
bool autocvar_g_maplist_check_waypoints;
int autocvar_g_maplist_index;
  string autocvar_g_maplist_mostrecent;
float autocvar_g_maplist_mostrecent_count;
float autocvar_g_maplist_selectrandom;
int autocvar_g_maplist_mostrecent_count;
bool autocvar_g_maplist_selectrandom;
  float autocvar_g_maplist_shuffle;
  #define autocvar_g_maplist_votable cvar("g_maplist_votable")
float autocvar_g_maplist_votable_abstain;
bool autocvar_g_maplist_votable_abstain;
  float autocvar_g_maplist_votable_keeptwotime;
float autocvar_g_maplist_votable_nodetail;
bool autocvar_g_maplist_votable_nodetail;
  string autocvar_g_maplist_votable_screenshot_dir;
float autocvar_g_maplist_votable_suggestions;
float autocvar_g_maplist_votable_suggestions_override_mostrecent;
bool autocvar_g_maplist_votable_suggestions;
bool autocvar_g_maplist_votable_suggestions_override_mostrecent;
  float autocvar_g_maplist_votable_timeout;
float autocvar_g_maxplayers;
int autocvar_g_maxplayers;
  float autocvar_g_maxplayers_spectator_blocktime;
  float autocvar_g_maxpushtime;
  float autocvar_g_maxspeed;
  float autocvar_g_midair_shieldtime;
  #define autocvar_g_instagib cvar("g_instagib")
float autocvar_g_instagib_ammo_drop;
float autocvar_g_instagib_extralives;
int autocvar_g_instagib_ammo_drop;
int autocvar_g_instagib_extralives;
  float autocvar_g_instagib_speed_highspeed;
  float autocvar_g_instagib_invis_alpha;
  #define autocvar_g_mirrordamage cvar("g_mirrordamage")
  #define autocvar_g_mirrordamage_virtual cvar("g_mirrordamage_virtual")
  
  float autocvar_g_movement_highspeed = 1;
float autocvar_g_multijump;
int autocvar_g_multijump;
  float autocvar_g_multijump_add;
  float autocvar_g_multijump_speed;
  string autocvar_g_mutatormsg;
  float autocvar_g_nexball_basketball_bouncefactor;
  float autocvar_g_nexball_basketball_bouncestop;
  float autocvar_g_nexball_basketball_carrier_highspeed;
float autocvar_g_nexball_basketball_meter;
bool autocvar_g_nexball_basketball_meter;
  float autocvar_g_nexball_basketball_meter_maxpower;
  float autocvar_g_nexball_basketball_meter_minpower;
  float autocvar_g_nexball_delay_collect;
@@@ -419,74 -419,79 +419,74 @@@ float autocvar_g_nexball_delay_goal
  float autocvar_g_nexball_delay_start;
  float autocvar_g_nexball_football_bouncefactor;
  float autocvar_g_nexball_football_bouncestop;
float autocvar_g_nexball_goalleadlimit;
int autocvar_g_nexball_goalleadlimit;
  #define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
float autocvar_g_nexball_radar_showallplayers;
float autocvar_g_nexball_sound_bounce;
float autocvar_g_nexball_trail_color;
bool autocvar_g_nexball_radar_showallplayers;
bool autocvar_g_nexball_sound_bounce;
int autocvar_g_nexball_trail_color;
  //float autocvar_g_nick_flood_penalty;
float autocvar_g_nick_flood_penalty_red;
float autocvar_g_nick_flood_penalty_yellow;
int autocvar_g_nick_flood_penalty_red;
int autocvar_g_nick_flood_penalty_yellow;
  //float autocvar_g_nick_flood_timeout;
- float autocvar_g_nix_with_healtharmor;
- float autocvar_g_nix_with_blaster;
- float autocvar_g_nix_with_powerups;
- float autocvar_g_nodepthtestitems;
- float autocvar_g_nodepthtestplayers;
- float autocvar_g_norecoil;
- float autocvar_g_pickup_cells_max;
- float autocvar_g_pickup_plasma_max;
- float autocvar_g_pickup_fuel_max;
- float autocvar_g_pickup_items;
- float autocvar_g_pickup_nails_max;
- float autocvar_g_pickup_rockets_max;
- float autocvar_g_pickup_shells_max;
+ bool autocvar_g_nix_with_healtharmor;
+ bool autocvar_g_nix_with_blaster;
+ bool autocvar_g_nix_with_powerups;
+ bool autocvar_g_nodepthtestitems;
+ bool autocvar_g_nodepthtestplayers;
+ bool autocvar_g_norecoil;
 -float autocvar_g_onslaught_cp_buildhealth;
 -float autocvar_g_onslaught_cp_buildtime;
 -float autocvar_g_onslaught_cp_health;
 -float autocvar_g_onslaught_cp_regen;
 -float autocvar_g_onslaught_gen_health;
+ int autocvar_g_pickup_cells_max;
+ int autocvar_g_pickup_plasma_max;
+ int autocvar_g_pickup_fuel_max;
+ int autocvar_g_pickup_items;
+ int autocvar_g_pickup_nails_max;
+ int autocvar_g_pickup_rockets_max;
+ int autocvar_g_pickup_shells_max;
  float autocvar_g_player_alpha;
  float autocvar_g_player_brightness;
float autocvar_g_playerclip_collisions;
float autocvar_g_powerups;
float autocvar_g_projectiles_damage;
float autocvar_g_projectiles_keep_owner;
float autocvar_g_projectiles_newton_style;
bool autocvar_g_playerclip_collisions;
int autocvar_g_powerups;
int autocvar_g_projectiles_damage;
bool autocvar_g_projectiles_keep_owner;
int autocvar_g_projectiles_newton_style;
  float autocvar_g_projectiles_newton_style_2_maxfactor;
  float autocvar_g_projectiles_newton_style_2_minfactor;
float autocvar_g_projectiles_spread_style;
int autocvar_g_projectiles_spread_style;
  #define autocvar_g_race_laps_limit cvar("g_race_laps_limit")
  float autocvar_g_race_qualifying_timelimit;
  float autocvar_g_race_qualifying_timelimit_override;
float autocvar_g_race_teams;
int autocvar_g_race_teams;
  float autocvar_g_respawn_delay_small;
float autocvar_g_respawn_delay_small_count;
int autocvar_g_respawn_delay_small_count;
  float autocvar_g_respawn_delay_large;
float autocvar_g_respawn_delay_large_count;
int autocvar_g_respawn_delay_large_count;
  float autocvar_g_respawn_delay_max;
float autocvar_g_respawn_ghosts;
bool autocvar_g_respawn_ghosts;
  float autocvar_g_respawn_ghosts_maxtime;
  float autocvar_g_respawn_ghosts_speed;
float autocvar_g_respawn_waves;
float autocvar_g_running_guns;
float autocvar_g_shootfromcenter;
float autocvar_g_shootfromclient;
float autocvar_g_shootfromeye;
int autocvar_g_respawn_waves;
bool autocvar_g_running_guns;
bool autocvar_g_shootfromcenter;
int autocvar_g_shootfromclient;
bool autocvar_g_shootfromeye;
  string autocvar_g_shootfromfixedorigin;
float autocvar_g_showweaponspawns;
float autocvar_g_spawn_alloweffects;
int autocvar_g_showweaponspawns;
bool autocvar_g_spawn_alloweffects;
  float autocvar_g_spawn_furthest;
float autocvar_g_spawn_useallspawns;
float autocvar_g_spawnpoints_auto_move_out_of_solid;
bool autocvar_g_spawn_useallspawns;
bool autocvar_g_spawnpoints_auto_move_out_of_solid;
  #define autocvar_g_spawnshieldtime cvar("g_spawnshieldtime")
float autocvar_g_tdm_team_spawns;
float autocvar_g_tdm_point_limit;
float autocvar_g_tdm_point_leadlimit;
float autocvar_g_tdm_teams;
float autocvar_g_tdm_teams_override;
bool autocvar_g_tdm_team_spawns;
int autocvar_g_tdm_point_limit;
int autocvar_g_tdm_point_leadlimit;
int autocvar_g_tdm_teams;
int autocvar_g_tdm_teams_override;
  float autocvar_g_teamdamage_resetspeed;
  float autocvar_g_teamdamage_threshold;
float autocvar_g_telefrags;
float autocvar_g_telefrags_avoid;
float autocvar_g_telefrags_teamplay;
bool autocvar_g_telefrags;
bool autocvar_g_telefrags_avoid;
bool autocvar_g_telefrags_teamplay;
  float autocvar_g_teleport_maxspeed;
float autocvar_g_throughfloor_debug;
bool autocvar_g_throughfloor_debug;
  float autocvar_g_throughfloor_damage;
  float autocvar_g_throughfloor_force;
  float autocvar_g_throughfloor_damage_max_stddev;
@@@ -499,10 -504,10 +499,10 @@@ float autocvar_g_triggerimpulse_accel_m
  float autocvar_g_triggerimpulse_accel_power;
  float autocvar_g_triggerimpulse_directional_multiplier;
  float autocvar_g_triggerimpulse_radial_multiplier;
float autocvar_g_turrets;
bool autocvar_g_turrets;
  float autocvar_g_turrets_aimidle_delay;
float autocvar_g_turrets_nofire;
float autocvar_g_turrets_reloadcvars;
bool autocvar_g_turrets_nofire;
bool autocvar_g_turrets_reloadcvars;
  float autocvar_g_turrets_targetscan_maxdelay;
  float autocvar_g_turrets_targetscan_mindelay;
  float autocvar_g_turrets_unit_ewheel_speed_fast;
@@@ -540,10 -545,10 +540,10 @@@ float autocvar_g_turrets_unit_walker_tu
  float autocvar_g_turrets_unit_walker_turn_run;
  float autocvar_g_turrets_unit_walker_turn_strafe;
  float autocvar_g_turrets_unit_walker_turn_swim;
float autocvar_g_use_ammunition;
float autocvar_g_waypointeditor;
float autocvar_g_waypointeditor_auto;
float autocvar_g_waypoints_for_items;
bool autocvar_g_use_ammunition;
bool autocvar_g_waypointeditor;
int autocvar_g_waypointeditor_auto;
int autocvar_g_waypoints_for_items;
  float autocvar_g_weapon_charge_colormod_blue_full;
  float autocvar_g_weapon_charge_colormod_blue_half;
  float autocvar_g_weapon_charge_colormod_green_full;
@@@ -552,158 -557,139 +552,139 @@@ float autocvar_g_weapon_charge_colormod
  float autocvar_g_weapon_charge_colormod_red_full;
  float autocvar_g_weapon_charge_colormod_red_half;
  #define autocvar_g_weapon_stay cvar("g_weapon_stay")
float autocvar_g_weapon_throwable;
bool autocvar_g_weapon_throwable;
  #define autocvar_g_weaponarena cvar_string("g_weaponarena")
  string autocvar_g_xonoticversion;
  float autocvar_gameversion;
  float autocvar_gameversion_min;
  float autocvar_gameversion_max;
  string autocvar_hostname;
float autocvar_lastlevel;
float autocvar_leadlimit;
float autocvar_leadlimit_and_fraglimit;
float autocvar_leadlimit_override;
float autocvar_loddebug;
float autocvar_minplayers;
bool autocvar_lastlevel;
int autocvar_leadlimit;
int autocvar_leadlimit_and_fraglimit;
int autocvar_leadlimit_override;
int autocvar_loddebug;
int autocvar_minplayers;
  string autocvar_nextmap;
float autocvar_prvm_backtraceforwarnings;
bool autocvar_prvm_backtraceforwarnings;
  string autocvar_quit_and_redirect;
  float autocvar_quit_and_redirect_timer;
float autocvar_quit_when_empty;
bool autocvar_quit_when_empty;
  float autocvar_r_showbboxes;
float autocvar_rescan_pending;
float autocvar_samelevel;
int autocvar_rescan_pending;
bool autocvar_samelevel;
  string autocvar_sessionid;
  #define autocvar_skill cvar("skill")
  float autocvar_skill_auto;
  #define autocvar_slowmo cvar("slowmo")
  float autocvar_snd_soundradius;
- float autocvar_spawn_debug;
- float autocvar_speedmeter;
- float autocvar_sv_accelerate;
+ int autocvar_spawn_debug;
+ bool autocvar_speedmeter;
  float autocvar_sv_accuracy_data_share = 1;
  string autocvar_sv_adminnick;
- float autocvar_sv_airaccel_qw;
- float autocvar_sv_airaccel_qw_stretchfactor;
- float autocvar_sv_airaccel_sideways_friction;
- float autocvar_sv_airaccelerate;
- float autocvar_sv_aircontrol;
- float autocvar_sv_aircontrol_penalty;
- float autocvar_sv_aircontrol_power;
- float autocvar_sv_airspeedlimit_nonqw;
- float autocvar_sv_airstopaccelerate;
- float autocvar_sv_airstrafeaccel_qw;
- float autocvar_sv_airstrafeaccelerate;
- float autocvar_sv_autoscreenshot;
- float autocvar_sv_cheats;
+ bool autocvar_sv_autoscreenshot;
+ int autocvar_sv_cheats;
  float autocvar_sv_clientcommand_antispam_time;
float autocvar_sv_clientcommand_antispam_count;
float autocvar_sv_curl_serverpackages_auto;
float autocvar_sv_db_saveasdump;
float autocvar_sv_defaultcharacter;
int autocvar_sv_clientcommand_antispam_count;
bool autocvar_sv_curl_serverpackages_auto;
bool autocvar_sv_db_saveasdump;
bool autocvar_sv_defaultcharacter;
  string autocvar_sv_defaultplayercolors;
  string autocvar_sv_defaultplayermodel;
  string autocvar_sv_defaultplayermodel_blue;
  string autocvar_sv_defaultplayermodel_pink;
  string autocvar_sv_defaultplayermodel_red;
  string autocvar_sv_defaultplayermodel_yellow;
float autocvar_sv_defaultplayerskin;
int autocvar_sv_defaultplayerskin;
  float autocvar_sv_dodging_delay;
  float autocvar_sv_dodging_height_threshold;
  float autocvar_sv_dodging_horiz_speed;
  float autocvar_sv_dodging_horiz_speed_frozen;
  float autocvar_sv_dodging_ramp_time;
float autocvar_sv_dodging_sound;
bool autocvar_sv_dodging_sound;
  float autocvar_sv_dodging_up_speed;
  float autocvar_sv_dodging_wall_distance_threshold;
float autocvar_sv_dodging_wall_dodging;
float autocvar_sv_dodging_frozen;
float autocvar_sv_dodging_frozen_doubletap;
float autocvar_sv_doublejump;
float autocvar_sv_eventlog;
float autocvar_sv_eventlog_console;
float autocvar_sv_eventlog_files;
float autocvar_sv_eventlog_files_counter;
bool autocvar_sv_dodging_wall_dodging;
bool autocvar_sv_dodging_frozen;
bool autocvar_sv_dodging_frozen_doubletap;
bool autocvar_sv_doublejump;
bool autocvar_sv_eventlog;
bool autocvar_sv_eventlog_console;
bool autocvar_sv_eventlog_files;
int autocvar_sv_eventlog_files_counter;
  string autocvar_sv_eventlog_files_nameprefix;
  string autocvar_sv_eventlog_files_namesuffix;
- float autocvar_sv_eventlog_files_timestamps;
- float autocvar_sv_friction;
+ bool autocvar_sv_eventlog_files_timestamps;
  float autocvar_sv_friction_on_land;
+ var float autocvar_sv_friction_slick = 0.5;
  float autocvar_sv_gameplayfix_q2airaccelerate;
float autocvar_sv_gentle;
int autocvar_sv_gentle;
  #define autocvar_sv_gravity cvar("sv_gravity")
  string autocvar_sv_intermission_cdtrack;
string autocvar_sv_jumpspeedcap_max;
float autocvar_sv_jumpspeedcap_max;
  float autocvar_sv_jumpspeedcap_max_disable_on_ramps;
string autocvar_sv_jumpspeedcap_min;
float autocvar_sv_jumpspeedcap_min;
  float autocvar_sv_jumpvelocity;
float autocvar_sv_logscores_bots;
float autocvar_sv_logscores_console;
float autocvar_sv_logscores_file;
bool autocvar_sv_logscores_bots;
bool autocvar_sv_logscores_console;
bool autocvar_sv_logscores_file;
  string autocvar_sv_logscores_filename;
  float autocvar_sv_mapchange_delay;
  float autocvar_sv_maxairspeed;
- float autocvar_sv_maxairstrafespeed;
  float autocvar_sv_maxspeed;
  string autocvar_sv_motd;
float autocvar_sv_precacheplayermodels;
bool autocvar_sv_precacheplayermodels;
  //float autocvar_sv_precacheweapons; // WEAPONTODO?
float autocvar_sv_q3acompat_machineshotgunswap;
float autocvar_sv_ready_restart;
float autocvar_sv_ready_restart_after_countdown;
float autocvar_sv_ready_restart_repeatable;
float autocvar_sv_servermodelsonly;
float autocvar_sv_spectate;
bool autocvar_sv_q3acompat_machineshotgunswap;
bool autocvar_sv_ready_restart;
bool autocvar_sv_ready_restart_after_countdown;
bool autocvar_sv_ready_restart_repeatable;
bool autocvar_sv_servermodelsonly;
int autocvar_sv_spectate;
  float autocvar_sv_spectator_speed_multiplier;
float autocvar_sv_status_privacy;
bool autocvar_sv_status_privacy;
  float autocvar_sv_stepheight;
- float autocvar_sv_stopspeed;
  float autocvar_sv_strengthsound_antispam_refire_threshold;
  float autocvar_sv_strengthsound_antispam_time;
float autocvar_sv_teamnagger;
float autocvar_sv_timeout;
bool autocvar_sv_teamnagger;
bool autocvar_sv_timeout;
  float autocvar_sv_timeout_leadtime;
  float autocvar_sv_timeout_length;
float autocvar_sv_timeout_number;
int autocvar_sv_timeout_number;
  float autocvar_sv_timeout_resumetime;
float autocvar_sv_vote_call;
float autocvar_sv_vote_change;
bool autocvar_sv_vote_call;
bool autocvar_sv_vote_change;
  string autocvar_sv_vote_commands;
float autocvar_sv_vote_gametype;
bool autocvar_sv_vote_gametype;
  float autocvar_sv_vote_gametype_timeout;
  string autocvar_sv_vote_gametype_options;
  float autocvar_sv_vote_gametype_keeptwotime;
float autocvar_sv_vote_gametype_default_current;
float autocvar_sv_vote_limit;
bool autocvar_sv_vote_gametype_default_current;
int autocvar_sv_vote_limit;
  float autocvar_sv_vote_majority_factor;
  float autocvar_sv_vote_majority_factor_of_voted;
float autocvar_sv_vote_master;
float autocvar_sv_vote_master_callable;
bool autocvar_sv_vote_master;
bool autocvar_sv_vote_master_callable;
  string autocvar_sv_vote_master_commands;
  string autocvar_sv_vote_master_password;
float autocvar_sv_vote_master_playerlimit;
float autocvar_sv_vote_no_stops_vote;
float autocvar_sv_vote_nospectators;
int autocvar_sv_vote_master_playerlimit;
bool autocvar_sv_vote_no_stops_vote;
int autocvar_sv_vote_nospectators;
  //string autocvar_sv_vote_only_commands;
float autocvar_sv_vote_override_mostrecent;
float autocvar_sv_vote_singlecount;
bool autocvar_sv_vote_override_mostrecent;
bool autocvar_sv_vote_singlecount;
  float autocvar_sv_vote_stop;
  float autocvar_sv_vote_timeout;
  float autocvar_sv_vote_wait;
- float autocvar_sv_vote_gamestart;
- float autocvar_sv_warsowbunny_accel;
- float autocvar_sv_warsowbunny_airforwardaccel;
- float autocvar_sv_warsowbunny_backtosideratio;
- float autocvar_sv_warsowbunny_topspeed;
- float autocvar_sv_warsowbunny_turnaccel;
+ bool autocvar_sv_vote_gamestart;
  float autocvar_sv_waypointsprite_deadlifetime;
  float autocvar_sv_waypointsprite_deployed_lifetime;
  float autocvar_sv_waypointsprite_limitedrange;
  string autocvar_sv_weaponstats_file;
  float autocvar_sv_gibhealth;
  float autocvar_sys_ticrate;
float autocvar_teamplay_lockonrestart;
float autocvar_teamplay_mode;
bool autocvar_teamplay_lockonrestart;
int autocvar_teamplay_mode;
  #define autocvar_timelimit cvar("timelimit")
  #define autocvar_timelimit_override cvar("timelimit_override")
  float autocvar_timelimit_increment;
@@@ -711,66 -697,67 +692,67 @@@ float autocvar_timelimit_decrement
  float autocvar_timelimit_min;
  float autocvar_timelimit_max;
  float autocvar_timelimit_overtime;
float autocvar_timelimit_overtimes;
int autocvar_timelimit_overtimes;
  float autocvar_timelimit_suddendeath;
  #define autocvar_utf8_enable cvar("utf8_enable")
float autocvar_waypoint_benchmark;
bool autocvar_waypoint_benchmark;
  float autocvar_sv_gameplayfix_gravityunaffectedbyticrate;
+ bool autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag;
  float autocvar_g_trueaim_minrange;
float autocvar_g_debug_defaultsounds;
bool autocvar_g_debug_defaultsounds;
  float autocvar_g_grab_range;
float autocvar_g_sandbox_info;
float autocvar_g_sandbox_readonly;
int autocvar_g_sandbox_info;
bool autocvar_g_sandbox_readonly;
  string autocvar_g_sandbox_storage_name;
  float autocvar_g_sandbox_storage_autosave;
float autocvar_g_sandbox_storage_autoload;
bool autocvar_g_sandbox_storage_autoload;
  float autocvar_g_sandbox_editor_flood;
float autocvar_g_sandbox_editor_maxobjects;
float autocvar_g_sandbox_editor_free;
int autocvar_g_sandbox_editor_maxobjects;
int autocvar_g_sandbox_editor_free;
  float autocvar_g_sandbox_editor_distance_spawn;
  float autocvar_g_sandbox_editor_distance_edit;
  float autocvar_g_sandbox_object_scale_min;
  float autocvar_g_sandbox_object_scale_max;
  float autocvar_g_sandbox_object_material_velocity_min;
  float autocvar_g_sandbox_object_material_velocity_factor;
float autocvar_g_max_info_autoscreenshot;
float autocvar_physics_ode;
float autocvar_g_physical_items;
int autocvar_g_max_info_autoscreenshot;
bool autocvar_physics_ode;
int autocvar_g_physical_items;
  float autocvar_g_physical_items_damageforcescale;
  float autocvar_g_physical_items_reset;
  float autocvar_g_monsters;
float autocvar_g_monsters_edit;
float autocvar_g_monsters_sounds;
bool autocvar_g_monsters_edit;
bool autocvar_g_monsters_sounds;
  float autocvar_g_monsters_think_delay;
float autocvar_g_monsters_max;
float autocvar_g_monsters_max_perplayer;
int autocvar_g_monsters_max;
int autocvar_g_monsters_max_perplayer;
  float autocvar_g_monsters_target_range;
float autocvar_g_monsters_target_infront;
bool autocvar_g_monsters_target_infront;
  float autocvar_g_monsters_attack_range;
float autocvar_g_monsters_score_kill;
float autocvar_g_monsters_score_spawned;
float autocvar_g_monsters_typefrag;
float autocvar_g_monsters_owners;
int autocvar_g_monsters_score_kill;
int autocvar_g_monsters_score_spawned;
bool autocvar_g_monsters_typefrag;
bool autocvar_g_monsters_owners;
  float autocvar_g_monsters_miniboss_chance;
  float autocvar_g_monsters_miniboss_healthboost;
  float autocvar_g_monsters_drop_time;
  float autocvar_g_monsters_spawnshieldtime;
float autocvar_g_monsters_teams;
bool autocvar_g_monsters_teams;
  float autocvar_g_monsters_respawn_delay;
float autocvar_g_monsters_respawn;
bool autocvar_g_monsters_respawn;
  float autocvar_g_monsters_armor_blockpercent;
  float autocvar_g_touchexplode_radius;
  float autocvar_g_touchexplode_damage;
  float autocvar_g_touchexplode_edgedamage;
  float autocvar_g_touchexplode_force;
  float autocvar_g_invasion_round_timelimit;
float autocvar_g_invasion_teams;
float autocvar_g_invasion_team_spawns;
int autocvar_g_invasion_teams;
bool autocvar_g_invasion_team_spawns;
  float autocvar_g_invasion_spawnpoint_spawn_delay;
  #define autocvar_g_invasion_point_limit cvar("g_invasion_point_limit")
  float autocvar_g_invasion_warmup;
float autocvar_g_invasion_monster_count;
float autocvar_g_invasion_zombies_only;
int autocvar_g_invasion_monster_count;
bool autocvar_g_invasion_zombies_only;
  float autocvar_g_invasion_spawn_delay;
  #define autocvar_g_bloodloss cvar("g_bloodloss")
  float autocvar_g_random_gravity_negative_chance;
@@@ -779,11 -766,11 +761,11 @@@ float autocvar_g_random_gravity_max
  float autocvar_g_random_gravity_positive;
  float autocvar_g_random_gravity_negative;
  float autocvar_g_random_gravity_delay;
float autocvar_g_nades;
bool autocvar_g_nades;
  vector autocvar_g_nades_throw_offset;
float autocvar_g_nades_spawn;
float autocvar_g_nades_spawn_count;
float autocvar_g_nades_client_select;
bool autocvar_g_nades_spawn;
int autocvar_g_nades_spawn_count;
bool autocvar_g_nades_client_select;
  float autocvar_g_nades_nade_lifetime;
  float autocvar_g_nades_nade_minforce;
  float autocvar_g_nades_nade_maxforce;
@@@ -793,39 -780,39 +775,39 @@@ float autocvar_g_nades_nade_damage
  float autocvar_g_nades_nade_edgedamage;
  float autocvar_g_nades_nade_radius;
  float autocvar_g_nades_nade_force;
float autocvar_g_nades_nade_newton_style;
int autocvar_g_nades_nade_newton_style;
  int autocvar_g_nades_napalm_ball_count;
  float autocvar_g_nades_napalm_ball_spread;
  float autocvar_g_nades_napalm_ball_damage;
  float autocvar_g_nades_napalm_ball_damageforcescale;
  float autocvar_g_nades_napalm_ball_lifetime;
  float autocvar_g_nades_napalm_ball_radius;
float autocvar_g_nades_napalm_blast;
bool autocvar_g_nades_napalm_blast;
  float autocvar_g_nades_napalm_fountain_lifetime;
  float autocvar_g_nades_napalm_fountain_delay;
  float autocvar_g_nades_napalm_fountain_radius;
  float autocvar_g_nades_napalm_fountain_damage;
  float autocvar_g_nades_napalm_fountain_edgedamage;
  float autocvar_g_nades_napalm_burntime;
float autocvar_g_nades_napalm_selfdamage;
float autocvar_g_nades_nade_type;
float autocvar_g_nades_bonus_type;
float autocvar_g_nades_bonus;
float autocvar_g_nades_bonus_onstrength;
float autocvar_g_nades_bonus_client_select;
float autocvar_g_nades_bonus_max;
float autocvar_g_nades_bonus_score_max;
float autocvar_g_nades_bonus_score_time;
float autocvar_g_nades_bonus_score_time_flagcarrier;
float autocvar_g_nades_bonus_score_minor;
float autocvar_g_nades_bonus_score_low;
float autocvar_g_nades_bonus_score_high;
float autocvar_g_nades_bonus_score_medium;
float autocvar_g_nades_bonus_score_spree;
bool autocvar_g_nades_napalm_selfdamage;
int autocvar_g_nades_nade_type;
int autocvar_g_nades_bonus_type;
bool autocvar_g_nades_bonus;
bool autocvar_g_nades_bonus_onstrength;
bool autocvar_g_nades_bonus_client_select;
int autocvar_g_nades_bonus_max;
int autocvar_g_nades_bonus_score_max;
int autocvar_g_nades_bonus_score_time;
int autocvar_g_nades_bonus_score_time_flagcarrier;
int autocvar_g_nades_bonus_score_minor;
int autocvar_g_nades_bonus_score_low;
int autocvar_g_nades_bonus_score_high;
int autocvar_g_nades_bonus_score_medium;
int autocvar_g_nades_bonus_score_spree;
  float autocvar_g_nades_ice_freeze_time;
  float autocvar_g_nades_ice_health;
float autocvar_g_nades_ice_explode;
float autocvar_g_nades_ice_teamcheck;
bool autocvar_g_nades_ice_explode;
bool autocvar_g_nades_ice_teamcheck;
  float autocvar_g_nades_heal_time;
  float autocvar_g_nades_heal_rate;
  float autocvar_g_nades_heal_friend;
@@@ -835,51 -822,30 +817,54 @@@ float autocvar_g_nades_pokenade_monster
  float autocvar_g_campcheck_damage;
  float autocvar_g_campcheck_distance;
  float autocvar_g_campcheck_interval;
float autocvar_g_jump_grunt;
float autocvar_g_overkill_powerups_replace;
bool autocvar_g_jump_grunt;
bool autocvar_g_overkill_powerups_replace;
  float autocvar_g_overkill_superguns_respawn_time;
float autocvar_g_overkill_100h_anyway;
float autocvar_g_overkill_100a_anyway;
float autocvar_g_overkill_ammo_charge;
bool autocvar_g_overkill_100h_anyway;
bool autocvar_g_overkill_100a_anyway;
bool autocvar_g_overkill_ammo_charge;
  float autocvar_g_overkill_ammo_charge_notice;
  float autocvar_g_overkill_ammo_charge_limit;
  float autocvar_g_spawn_near_teammate_distance;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint;
bool autocvar_g_spawn_near_teammate_ignore_spawnpoint;
  float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
  float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
- float autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
- float autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
 +float autocvar_g_onslaught_debug;
 +float autocvar_g_onslaught_teleport_wait;
- float autocvar_g_onslaught_spawn_at_controlpoints;
- var float autocvar_g_onslaught_spawn_at_controlpoints_chance = 0.5;
++bool autocvar_g_onslaught_spawn_at_controlpoints;
++bool autocvar_g_onslaught_spawn_at_generator;
++float autocvar_g_onslaught_cp_proxydecap;
++float autocvar_g_onslaught_cp_proxydecap_distance = 512;
++float autocvar_g_onslaught_cp_proxydecap_dps = 100;
++float autocvar_g_onslaught_spawn_at_controlpoints_chance = 0.5;
 +float autocvar_g_onslaught_spawn_at_controlpoints_random;
- float autocvar_g_onslaught_spawn_at_generator;
 +float autocvar_g_onslaught_spawn_at_generator_chance;
 +float autocvar_g_onslaught_spawn_at_generator_random;
- float autocvar_g_onslaught_cp_proxydecap;
- var float autocvar_g_onslaught_cp_proxydecap_distance = 512;
- var float autocvar_g_onslaught_cp_proxydecap_dps = 100;
 +float autocvar_g_onslaught_cp_buildhealth;
 +float autocvar_g_onslaught_cp_buildtime;
 +float autocvar_g_onslaught_cp_health;
 +float autocvar_g_onslaught_cp_regen;
 +float autocvar_g_onslaught_gen_health;
- var float autocvar_g_onslaught_shield_force = 100;
++float autocvar_g_onslaught_shield_force = 100;
 +float autocvar_g_onslaught_allow_vehicle_touch;
 +float autocvar_g_onslaught_round_timelimit;
 +float autocvar_g_onslaught_point_limit;
 +float autocvar_g_onslaught_warmup;
 +float autocvar_g_onslaught_teleport_radius;
 +float autocvar_g_onslaught_spawn_choose;
 +float autocvar_g_onslaught_click_radius;
+ int autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
+ bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
+ bool autocvar_g_physics_clientselect;
+ string autocvar_g_physics_clientselect_options;
+ string autocvar_g_physics_clientselect_default;
  float autocvar_g_buffs_waypoint_distance;
float autocvar_g_buffs_randomize;
bool autocvar_g_buffs_randomize;
  float autocvar_g_buffs_random_lifetime;
float autocvar_g_buffs_random_location;
float autocvar_g_buffs_random_location_attempts;
float autocvar_g_buffs_spawn_count;
float autocvar_g_buffs_replace_powerups;
bool autocvar_g_buffs_random_location;
int autocvar_g_buffs_random_location_attempts;
int autocvar_g_buffs_spawn_count;
bool autocvar_g_buffs_replace_powerups;
  float autocvar_g_buffs_cooldown_activate;
  float autocvar_g_buffs_cooldown_respawn;
  float autocvar_g_buffs_resistance_blockpercent;
@@@ -902,5 -868,5 +887,5 @@@ float autocvar_g_buffs_vampire_damage_s
  float autocvar_g_buffs_invisible_alpha;
  float autocvar_g_buffs_flight_gravity;
  float autocvar_g_buffs_jump_height;
+ float autocvar_sv_player_scale;
  #endif
diff --combined qcsrc/server/bot/havocbot/role_onslaught.qc
index 119ea83c81b77c90b659518bf03a601d49f2f360,6924f5122949e8edf715cded97d9c9ea6e98f159..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,369 -1,381 +1,0 @@@
 -#include "../../_all.qh"
 -
 -#include "havocbot.qh"
 -
 -#include "../bot.qh"
 -#include "../navigation.qh"
 -#include "../waypoints.qh"
 -
 -#include "../../mutators/mutators_include.qh"
 -
 -#include "../../../common/teams.qh"
 -
--const int HAVOCBOT_ONS_ROLE_NONE              = 0;
--const int HAVOCBOT_ONS_ROLE_DEFENSE   = 2;
--const int HAVOCBOT_ONS_ROLE_ASSISTANT         = 4;
--const int HAVOCBOT_ONS_ROLE_OFFENSE   = 8;
--
--.int havocbot_role_flags;
--.float havocbot_attack_time;
--
--.void() havocbot_role;
--.void() havocbot_previous_role;
--
--void() havocbot_role_ons_defense;
--void() havocbot_role_ons_offense;
--void() havocbot_role_ons_assistant;
--
--void(entity bot) havocbot_ons_reset_role;
--void(float ratingscale, vector org, float sradius) havocbot_goalrating_items;
--void(float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers;
--
--.float isshielded;
--.float iscaptured;
--.float islinked;
--.float isgenneighbor_blue, iscpneighbor_blue;
--.float isgenneighbor_red, iscpneighbor_red;
--
--.entity havocbot_ons_target;
--
--void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
--{
--      entity head;
--      float t, i, c, needarmor = false, needweapons = false;
--
--      // Needs armor/health?
--      if(self.health<100)
--              needarmor = true;
--
--      // Needs weapons?
--      c = 0;
--      for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
--      {
--              // Find weapon
--              if(self.weapons & WepSet_FromWeapon(i))
--              if(++c>=4)
--                      break;
--      }
--
--      if(c<4)
--              needweapons = true;
--
--      if(!needweapons && !needarmor)
--              return;
--
--//    dprint(self.netname, " needs weapons ", ftos(needweapons) , "\n");
--//    dprint(self.netname, " needs armor ", ftos(needarmor) , "\n");
--
--      // See what is around
--      head = findchainfloat(bot_pickup, true);
--      while (head)
--      {
--              // gather health and armor only
--              if (head.solid)
--              if ( ((head.health || head.armorvalue) && needarmor) || (head.weapons && needweapons ) )
--              if (vlen(head.origin - org) < sradius)
--              {
--                      t = head.bot_pickupevalfunc(self, head);
--                      if (t > 0)
--                              navigation_routerating(head, t * ratingscale, 500);
--              }
--              head = head.chain;
--      }
--}
--
--void havocbot_role_ons_setrole(entity bot, float role)
--{
--      dprint(strcat(bot.netname," switched to "));
--      switch(role)
--      {
--              case HAVOCBOT_ONS_ROLE_DEFENSE:
--                      dprint("defense");
--                      bot.havocbot_role = havocbot_role_ons_defense;
--                      bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_DEFENSE;
--                      bot.havocbot_role_timeout = 0;
--                      break;
--              case HAVOCBOT_ONS_ROLE_ASSISTANT:
--                      dprint("assistant");
--                      bot.havocbot_role = havocbot_role_ons_assistant;
--                      bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_ASSISTANT;
--                      bot.havocbot_role_timeout = 0;
--                      break;
--              case HAVOCBOT_ONS_ROLE_OFFENSE:
--                      dprint("offense");
--                      bot.havocbot_role = havocbot_role_ons_offense;
--                      bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_OFFENSE;
--                      bot.havocbot_role_timeout = 0;
--                      break;
--      }
--      dprint("\n");
--}
--
--float havocbot_ons_teamcount(entity bot, int role)
--{
--      float c = 0;
--      entity head;
--
--      FOR_EACH_PLAYER(head)
--      if(head.team==self.team)
--      if(head.havocbot_role_flags & role)
--              ++c;
--
--      return c;
--}
--
--void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
--{
--      entity cp, cp1, cp2, best, pl, wp;
--      float radius, found, bestvalue, c;
--
--      cp1 = cp2 = findchain(classname, "onslaught_controlpoint");
--
--      // Filter control points
--      for (; cp2; cp2 = cp2.chain)
--      {
--              cp2.wpcost = c = 0;
--              cp2.wpconsidered = false;
--
--              if(cp2.isshielded)
--                      continue;
--
--              // Ignore owned controlpoints
--              if(self.team == NUM_TEAM_1)
--              {
--                      if( (cp2.isgenneighbor_blue || cp2.iscpneighbor_blue) && !(cp2.isgenneighbor_red || cp2.iscpneighbor_red) )
--                              continue;
--              }
--              else if(self.team == NUM_TEAM_2)
--              {
--                      if( (cp2.isgenneighbor_red || cp2.iscpneighbor_red) && !(cp2.isgenneighbor_blue || cp2.iscpneighbor_blue) )
--                              continue;
--              }
--
--              // Count team mates interested in this control point
--              // (easier and cleaner than keeping counters per cp and teams)
--              FOR_EACH_PLAYER(pl)
--              if(pl.team==self.team)
--              if(pl.havocbot_role_flags & HAVOCBOT_ONS_ROLE_OFFENSE)
--              if(pl.havocbot_ons_target==cp2)
--                      ++c;
--
--              // NOTE: probably decrease the cost of attackable control points
--              cp2.wpcost = c;
--              cp2.wpconsidered = true;
--      }
--
--      // We'll consider only the best case
--      bestvalue = 99999999999;
--      cp = world;
--      for (; cp1; cp1 = cp1.chain)
--      {
--              if (!cp1.wpconsidered)
--                      continue;
--
--              if(cp1.wpcost<bestvalue)
--              {
--                      bestvalue = cp1.wpcost;
--                      cp = cp1;
--                      self.havocbot_ons_target = cp1;
--              }
--      }
--
--      if (!cp)
--              return;
--
--//    dprint(self.netname, " chose cp ranked ", ftos(bestvalue), "\n");
--
--      if(cp.goalentity)
--      {
--              // Should be attacked
--              // Rate waypoints near it
--              found = false;
--              best = world;
--              bestvalue = 99999999999;
--              for(radius=0; radius<1000 && !found; radius+=500)
--              {
--                      for(wp=findradius(cp.origin,radius); wp; wp=wp.chain)
--                      {
--                              if(!(wp.wpflags & WAYPOINTFLAG_GENERATED))
--                              if(wp.classname=="waypoint")
--                              if(checkpvs(wp.origin,cp))
--                              {
--                                      found = true;
--                                      if(wp.cnt<bestvalue)
--                                      {
--                                              best = wp;
--                                              bestvalue = wp.cnt;
--                                      }
--                              }
--                      }
--              }
--
--              if(best)
--              {
--                      navigation_routerating(best, ratingscale, 10000);
--                      best.cnt += 1;
--
--                      self.havocbot_attack_time = 0;
--                      if(checkpvs(self.view_ofs,cp))
--                      if(checkpvs(self.view_ofs,best))
--                              self.havocbot_attack_time = time + 2;
--              }
--              else
--              {
--                      navigation_routerating(cp, ratingscale, 10000);
--              }
--      //      dprint(self.netname, " found an attackable controlpoint at ", vtos(cp.origin) ,"\n");
--      }
--      else
--      {
--              // Should be touched
--              // dprint(self.netname, " found a touchable controlpoint at ", vtos(cp.origin) ,"\n");
--              found = false;
--
--              // Look for auto generated waypoint
--              if (!bot_waypoints_for_items)
--              for (wp = findradius(cp.origin,100); wp; wp = wp.chain)
--              {
--                      if(wp.classname=="waypoint")
--                      {
--                              navigation_routerating(wp, ratingscale, 10000);
--                              found = true;
--                      }
--              }
--
--              // Nothing found, rate the controlpoint itself
--              if (!found)
--                      navigation_routerating(cp, ratingscale, 10000);
--      }
--}
--
--float havocbot_goalrating_ons_generator_attack(float ratingscale)
--{
--      entity g, wp, bestwp;
--      float found, best;
--
--      for (g = findchain(classname, "onslaught_generator"); g; g = g.chain)
--      {
--              if(g.team == self.team || g.isshielded)
--                      continue;
--
--              // Should be attacked
--              // Rate waypoints near it
--              found = false;
--              bestwp = world;
--              best = 99999999999;
--
--              for(wp=findradius(g.origin,400); wp; wp=wp.chain)
--              {
--                      if(wp.classname=="waypoint")
--                      if(checkpvs(wp.origin,g))
--                      {
--                              found = true;
--                              if(wp.cnt<best)
--                              {
--                                      bestwp = wp;
--                                      best = wp.cnt;
--                              }
--                      }
--              }
--
--              if(bestwp)
--              {
--              //      dprint("waypoints found around generator\n");
--                      navigation_routerating(bestwp, ratingscale, 10000);
--                      bestwp.cnt += 1;
--
--                      self.havocbot_attack_time = 0;
--                      if(checkpvs(self.view_ofs,g))
--                      if(checkpvs(self.view_ofs,bestwp))
--                              self.havocbot_attack_time = time + 5;
--
--                      return true;
--              }
--              else
--              {
--              //      dprint("generator found without waypoints around\n");
--                      // if there aren't waypoints near the generator go straight to it
--                      navigation_routerating(g, ratingscale, 10000);
--                      self.havocbot_attack_time = 0;
--                      return true;
--              }
--      }
--      return false;
--}
--
--void havocbot_role_ons_offense()
--{
--      if(self.deadflag != DEAD_NO)
--      {
--              self.havocbot_attack_time = 0;
--              havocbot_ons_reset_role(self);
--              return;
--      }
--
--      // Set the role timeout if necessary
--      if (!self.havocbot_role_timeout)
--              self.havocbot_role_timeout = time + 120;
--
--      if (time > self.havocbot_role_timeout)
--      {
--              havocbot_ons_reset_role(self);
--              return;
--      }
--
--      if(self.havocbot_attack_time>time)
--              return;
--
--      if (self.bot_strategytime < time)
--      {
--              navigation_goalrating_start();
--              havocbot_goalrating_enemyplayers(20000, self.origin, 650);
--              if(!havocbot_goalrating_ons_generator_attack(20000))
--                      havocbot_goalrating_ons_controlpoints_attack(20000);
--              havocbot_goalrating_ons_offenseitems(10000, self.origin, 10000);
--              navigation_goalrating_end();
--
--              self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
--      }
--}
--
--void havocbot_role_ons_assistant()
--{
--      havocbot_ons_reset_role(self);
--}
--
--void havocbot_role_ons_defense()
--{
--      havocbot_ons_reset_role(self);
--}
--
--void havocbot_ons_reset_role(entity bot)
--{
--      entity head;
--      float c;
--
--      if(self.deadflag != DEAD_NO)
--              return;
--
--      bot.havocbot_ons_target = world;
--
--      // TODO: Defend control points or generator if necessary
--
--      // if there is only me on the team switch to offense
--      c = 0;
--      FOR_EACH_PLAYER(head)
--      if(head.team==self.team)
--              ++c;
--
--      if(c==1)
--      {
--              havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
--              return;
--      }
--
--      havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
--}
--
--void havocbot_chooserole_ons()
--{
--      havocbot_ons_reset_role(self);
--}
index 9b62088deb4d21f04af6a26f35317e28d687915f,65ea2a809b6be9d105d88ab5d1bd272952bf9028..6df91ce6e0c30ae263ec8bebbf22a8834f6f267a
@@@ -1,3 -1,11 +1,10 @@@
 -#include "role_onslaught.qh"
+ #include "../../_all.qh"
+ #include "havocbot.qh"
+ #include "role_keyhunt.qh"
+ #include "../bot.qh"
+ #include "../navigation.qh"
  
  .float max_armorvalue;
  .float havocbot_role_timeout;
@@@ -238,6 -246,8 +245,6 @@@ void havocbot_chooserole(
                return;
        else if (g_keyhunt)
                havocbot_chooserole_kh();
 -      else if (g_onslaught)
 -              havocbot_chooserole_ons();
        else // assume anything else is deathmatch
                havocbot_chooserole_dm();
  }
diff --combined qcsrc/server/g_damage.qc
index 446c4cf4e15ba1e7b38c435b2a3506a5da8c022e,68e8f4f7325a1795a5e3d744572ab8b57e702153..050607b4c95f005f46ffae43e6abc4d98ca81b53
@@@ -1,33 -1,29 +1,29 @@@
  #include "g_damage.qh"
- #if defined(CSQC)
- #elif defined(MENUQC)
- #elif defined(SVQC)
-     #include "../warpzonelib/common.qh"
-     #include "../common/constants.qh"
-     #include "../common/teams.qh"
-     #include "../common/util.qh"
-     #include "../common/weapons/weapons.qh"
-     #include "weapons/accuracy.qh"
-     #include "weapons/csqcprojectile.qh"
-     #include "weapons/selection.qh"
-     #include "t_items.qh"
-     #include "autocvars.qh"
-     #include "constants.qh"
-     #include "defs.qh"
-     #include "../common/notifications.qh"
-     #include "../common/deathtypes.qh"
-     #include "mutators/mutators_include.qh"
-     #include "tturrets/include/turrets_early.qh"
-     #include "vehicles/vehicles_def.qh"
-     #include "../csqcmodellib/sv_model.qh"
-     #include "../common/playerstats.qh"
-     #include "g_hook.qh"
-     #include "scores.qh"
-     #include "spawnpoints.qh"
- #endif
- float Damage_DamageInfo_SendEntity(entity to, float sf)
+ #include "_all.qh"
+ #include "g_hook.qh"
+ #include "mutators/mutators_include.qh"
+ #include "scores.qh"
+ #include "waypointsprites.qh"
+ #include "spawnpoints.qh"
+ #include "tturrets/include/turrets_early.qh"
+ #include "t_items.qh"
+ #include "vehicles/vehicle.qh"
+ #include "weapons/accuracy.qh"
+ #include "weapons/csqcprojectile.qh"
+ #include "weapons/selection.qh"
+ #include "../common/constants.qh"
+ #include "../common/deathtypes.qh"
+ #include "../common/notifications.qh"
+ #include "../common/movetypes/movetypes.qh"
+ #include "../common/playerstats.qh"
+ #include "../common/teams.qh"
+ #include "../common/util.qh"
+ #include "../common/weapons/all.qh"
+ #include "../csqcmodellib/sv_model.qh"
+ #include "../warpzonelib/common.qh"
+ float Damage_DamageInfo_SendEntity(entity to, int sf)
  {
        WriteByte(MSG_ENTITY, ENT_CLIENT_DAMAGEINFO);
        WriteShort(MSG_ENTITY, self.projectiledeathtype);
@@@ -42,7 -38,7 +38,7 @@@
        return true;
  }
  
- void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, float deathtype, float bloodtype, entity dmgowner)
+ void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner)
  {
        // TODO maybe call this from non-edgedamage too?
        // TODO maybe make the client do the particle effects for the weapons and the impact sounds using this info?
        Net_LinkEntity(e, false, 0.2, Damage_DamageInfo_SendEntity);
  }
  
- float IsFlying(entity a)
- {
-       if(a.flags & FL_ONGROUND)
-               return 0;
-       if(a.waterlevel >= WATERLEVEL_SWIMMING)
-               return 0;
-       traceline(a.origin, a.origin - '0 0 48', MOVE_NORMAL, a);
-       if(trace_fraction < 1)
-               return 0;
-       return 1;
- }
  void UpdateFrags(entity player, float f)
  {
        PlayerTeamScore_AddScore(player, f);
  }
  
- void GiveFrags (entity attacker, entity targ, float f, float deathtype)
+ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
  {
        // TODO route through PlayerScores instead
        if(gameover) return;
@@@ -203,7 -187,7 +187,7 @@@ string AppendItemcodes(string s, entit
        return s;
  }
  
- void LogDeath(string mode, float deathtype, entity killer, entity killed)
+ void LogDeath(string mode, int deathtype, entity killer, entity killed)
  {
        string s;
        if(!autocvar_sv_eventlog)
  void Obituary_SpecialDeath(
        entity notif_target,
        float murder,
-       float deathtype,
+       int deathtype,
        string s1, string s2, string s3,
        float f1, float f2, float f3)
  {
  float Obituary_WeaponDeath(
        entity notif_target,
        float murder,
-       float deathtype,
+       int deathtype,
        string s1, string s2, string s3,
        float f1, float f2)
  {
        if(death_weapon)
        {
                w_deathtype = deathtype;
-               float death_message = WEP_ACTION(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
+               int death_message = WEP_ACTION(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
                w_deathtype = false;
  
-               if(death_message)
+               if (death_message)
                {
                        Send_Notification_WOCOVA(
                                NOTIF_ONE,
        return false;
  }
  
- void Obituary(entity attacker, entity inflictor, entity targ, float deathtype)
+ void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
  {
        // Sanity check
        if (!IS_PLAYER(targ)) { backtrace("Obituary called on non-player?!\n"); return; }
@@@ -635,7 -619,7 +619,7 @@@ void Unfreeze (entity targ
        targ.iceblock = world;
  }
  
- void Damage (entity targ, entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+ void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
  {
        float mirrordamage;
        float mirrorforce;
                        else
                                victim = targ;
  
 -                      if(IS_PLAYER(victim) || (victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET) || (victim.flags & FL_MONSTER))
 +                      if(IS_PLAYER(victim) || (victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET) || (victim.flags & FL_MONSTER) || victim.classname == "func_assault_destructible" || (victim.classname == "onslaught_generator" && !victim.isshielded) || (victim.classname == "onslaught_controlpoint_icon" && !victim.owner.isshielded))
                        {
                                if(DIFF_TEAM(victim, attacker) && !victim.frozen)
                                {
                        farcent.think = SUB_Remove;
                }
                else
+               {
                        self.velocity = self.velocity + farce;
+                       self.move_velocity = self.velocity;
+               }
                self.flags &= ~FL_ONGROUND;
+               self.move_flags &= ~FL_ONGROUND;
                UpdateCSQCProjectile(self);
        }
        // apply damage
        }
  }
  
- float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float deathtype, entity directhitentity)
+ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, int deathtype, entity directhitentity)
        // Returns total damage applies to creatures
  {
        entity  targ;
        return total_damage_to_creatures;
  }
  
- float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, float deathtype, entity directhitentity)
+ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, entity directhitentity)
  {
        return RadiusDamageForSource (inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, false, forceintensity, deathtype, directhitentity);
  }
diff --combined qcsrc/server/g_world.qc
index b5bbf0b95837ec26c8ab614301c912e8d05b7117,9c2003cc19d506afbe5de24d4b7e5adf0c7bdacb..33cfc81b4fe0ad37a95e1a80f7fd9ef99092a80d
@@@ -1,39 -1,38 +1,38 @@@
  #include "g_world.qh"
+ #include "_all.qh"
+ #include "anticheat.qh"
+ #include "antilag.qh"
+ #include "bot/bot.qh"
+ #include "campaign.qh"
+ #include "cheats.qh"
+ #include "cl_client.qh"
+ #include "command/common.qh"
+ #include "command/getreplies.qh"
+ #include "command/sv_cmd.qh"
+ #include "command/vote.qh"
+ #include "g_hook.qh"
+ #include "ipban.qh"
+ #include "mapvoting.qh"
+ #include "mutators/mutators_include.qh"
+ #include "race.qh"
+ #include "scores.qh"
+ #include "teamplay.qh"
+ #include "waypointsprites.qh"
+ #include "weapons/weaponstats.qh"
  #include "../common/buffs.qh"
- #if defined(CSQC)
- #elif defined(MENUQC)
- #elif defined(SVQC)
-     #include "../common/constants.qh"
-     #include "../common/stats.qh"
-     #include "../common/teams.qh"
-     #include "../common/util.qh"
-     #include "../common/monsters/sv_monsters.qh"
-     #include "../common/weapons/weapons.qh"
-     #include "weapons/weaponstats.qh"
-     #include "autocvars.qh"
-     #include "constants.qh"
-     #include "defs.qh"
-     #include "../common/notifications.qh"
-     #include "mutators/mutators_include.qh"
-     #include "campaign.qh"
-     #include "../common/mapinfo.qh"
-     #include "command/common.qh"
-     #include "command/vote.qh"
-     #include "command/getreplies.qh"
-     #include "command/sv_cmd.qh"
-     #include "anticheat.qh"
-     #include "cheats.qh"
-     #include "../common/playerstats.qh"
-     #include "g_hook.qh"
-     #include "scores.qh"
-     #include "mapvoting.qh"
-     #include "ipban.qh"
-     #include "race.qh"
-     #include "antilag.qh"
-     #include "secret.qh"
- #endif
+ #include "../common/constants.qh"
+ #include "../common/deathtypes.qh"
+ #include "../common/mapinfo.qh"
+ #include "../common/monsters/all.qh"
+ #include "../common/monsters/sv_monsters.qh"
+ #include "../common/notifications.qh"
+ #include "../common/playerstats.qh"
+ #include "../common/stats.qh"
+ #include "../common/teams.qh"
+ #include "../common/util.qh"
+ #include "../common/items/all.qh"
+ #include "../common/weapons/all.qh"
  
  const float LATENCY_THINKRATE = 10;
  .float latency_sum;
@@@ -93,9 -92,7 +92,7 @@@ string redirection_target
  float world_initialized;
  
  string GetGametype();
- void GotoNextMap(float reinit);
  void ShuffleMaplist();
- float(float reinit) DoNextMapOverride;
  
  void SetDefaultAlpha()
  {
@@@ -191,6 -188,8 +188,8 @@@ void cvar_changes_init(
                BADCVAR("g_configversion");
                BADCVAR("g_maplist_index");
                BADCVAR("halflifebsp");
+               BADCVAR("sv_mapformat_is_quake2");
+               BADCVAR("sv_mapformat_is_quake3");
                BADPREFIX("sv_world");
  
                // client
                BADCVAR("g_domination_default_teams");
                BADCVAR("g_freezetag");
                BADCVAR("g_freezetag_teams");
+               BADCVAR("g_invasion_teams");
                BADCVAR("g_keepaway");
                BADCVAR("g_keyhunt");
                BADCVAR("g_keyhunt_teams");
                BADCVAR("g_ca_teams_override");
                BADCVAR("g_ctf_ignore_frags");
                BADCVAR("g_domination_point_limit");
+               BADCVAR("g_domination_teams_override");
                BADCVAR("g_freezetag_teams_override");
                BADCVAR("g_friendlyfire");
                BADCVAR("g_fullbrightitems");
                BADCVAR("g_nexball_goallimit");
                BADCVAR("g_powerups");
                BADCVAR("g_start_delay");
+               BADCVAR("g_tdm_teams_override");
                BADCVAR("g_warmup");
                BADCVAR("g_weapon_stay"); BADPRESUFFIX("g_", "_weapon_stay");
                BADCVAR("hostname");
@@@ -509,7 -511,7 +511,7 @@@ void detect_maptype(
  }
  
  entity randomseed;
- float RandomSeed_Send(entity to, float sf)
+ float RandomSeed_Send(entity to, int sf)
  {
        WriteByte(MSG_ENTITY, ENT_CLIENT_RANDOMSEED);
        WriteShort(MSG_ENTITY, self.cnt);
@@@ -559,6 -561,7 +561,7 @@@ void spawnfunc___init_dedicated_server(
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
+       CALL_ACCUMULATED_FUNCTION(RegisterItems);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
@@@ -574,9 -577,10 +577,10 @@@ void Nagger_Init()
  void ClientInit_Spawn();
  void WeaponStats_Init();
  void WeaponStats_Shutdown();
+ void Physics_AddStats();
  void spawnfunc_worldspawn (void)
  {
-       float fd, l, i, j, n;
+       float fd, l, j, n;
        string s;
  
        cvar = cvar_normal;
        // needs to be done so early because of the constants they create
        CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
        CALL_ACCUMULATED_FUNCTION(RegisterMonsters);
+       CALL_ACCUMULATED_FUNCTION(RegisterItems);
        CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
        // character set: ASCII 33-126 without the following characters: : ; ' " \ $
        if(autocvar_sv_eventlog)
        {
-               s = sprintf("%d.%s.%06d", ftos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000));
+               s = sprintf("%d.%s.%06d", itos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000));
                matchid = strzone(s);
  
                GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s));
        addstat(STAT_FROZEN, AS_INT, frozen);
        addstat(STAT_REVIVE_PROGRESS, AS_FLOAT, revive_progress);
  
-       // g_movementspeed hack
-       addstat(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW, AS_FLOAT, stat_sv_airspeedlimit_nonqw);
-       addstat(STAT_MOVEVARS_MAXSPEED, AS_FLOAT, stat_sv_maxspeed);
-       addstat(STAT_MOVEVARS_AIRACCEL_QW, AS_FLOAT, stat_sv_airaccel_qw);
-       addstat(STAT_MOVEVARS_AIRSTRAFEACCEL_QW, AS_FLOAT, stat_sv_airstrafeaccel_qw);
+       // physics
+       Physics_AddStats();
+       // new properties
+       addstat(STAT_MOVEVARS_JUMPVELOCITY, AS_FLOAT, stat_sv_jumpvelocity);
+       addstat(STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR, AS_FLOAT, stat_sv_airaccel_qw_stretchfactor);
+       addstat(STAT_MOVEVARS_MAXAIRSTRAFESPEED, AS_FLOAT, stat_sv_maxairstrafespeed);
+       addstat(STAT_MOVEVARS_MAXAIRSPEED, AS_FLOAT, stat_sv_maxairspeed);
+       addstat(STAT_MOVEVARS_AIRSTRAFEACCELERATE, AS_FLOAT, stat_sv_airstrafeaccelerate);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL, AS_FLOAT, stat_sv_warsowbunny_turnaccel);
+       addstat(STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION, AS_FLOAT, stat_sv_airaccel_sideways_friction);
+       addstat(STAT_MOVEVARS_AIRCONTROL, AS_FLOAT, stat_sv_aircontrol);
+       addstat(STAT_MOVEVARS_AIRCONTROL_POWER, AS_FLOAT, stat_sv_aircontrol_power);
+       addstat(STAT_MOVEVARS_AIRCONTROL_PENALTY, AS_FLOAT, stat_sv_aircontrol_penalty);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL, AS_FLOAT, stat_sv_warsowbunny_airforwardaccel);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED, AS_FLOAT, stat_sv_warsowbunny_topspeed);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_ACCEL, AS_FLOAT, stat_sv_warsowbunny_accel);
+       addstat(STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO, AS_FLOAT, stat_sv_warsowbunny_backtosideratio);
+       addstat(STAT_MOVEVARS_FRICTION, AS_FLOAT, stat_sv_friction);
+       addstat(STAT_MOVEVARS_ACCELERATE, AS_FLOAT, stat_sv_accelerate);
+       addstat(STAT_MOVEVARS_STOPSPEED, AS_FLOAT, stat_sv_stopspeed);
+       addstat(STAT_MOVEVARS_AIRACCELERATE, AS_FLOAT, stat_sv_airaccelerate);
+       addstat(STAT_MOVEVARS_AIRSTOPACCELERATE, AS_FLOAT, stat_sv_airstopaccelerate);
  
        // secrets
        addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total);
        maplist_reply = strzone(getmaplist());
        lsmaps_reply = strzone(getlsmaps());
        monsterlist_reply = strzone(getmonsterlist());
-       for(i = 0; i < 10; ++i)
+       for(int i = 0; i < 10; ++i)
        {
                s = getrecords(i);
                if (s)
        {
                s = "";
                n = tokenize_console(cvar_string("sv_curl_serverpackages"));
-               for(i = 0; i < n; ++i)
+               for(int i = 0; i < n; ++i)
                        if(substring(argv(i), -18, -1) != "-serverpackage.txt")
                        if(substring(argv(i), -14, -1) != ".serverpackage") // OLD legacy
                                s = strcat(s, " ", argv(i));
                if(fd >= 0)
                {
                        j = search_getsize(fd);
-                       for(i = 0; i < j; ++i)
+                       for(int i = 0; i < j; ++i)
                                s = strcat(s, " ", search_getfilename(fd, i));
                        search_end(fd);
                }
                if(fd >= 0)
                {
                        j = search_getsize(fd);
-                       for(i = 0; i < j; ++i)
+                       for(int i = 0; i < j; ++i)
                                s = strcat(s, " ", search_getfilename(fd, i));
                        search_end(fd);
                }
@@@ -1650,7 -1673,7 +1673,7 @@@ void SetWinners(.float field, float val
  {
        entity head;
        FOR_EACH_PLAYER(head)
-               head.winning = (head.field == value);
+               head.winning = (head.(field) == value);
  }
  
  // set the .winning flag for those players with a given field value
@@@ -1658,7 -1681,7 +1681,7 @@@ void AddWinners(.float field, float val
  {
        entity head;
        FOR_EACH_PLAYER(head)
-               if(head.field == value)
+               if (head.(field) == value)
                        head.winning = 1;
  }
  
@@@ -1670,6 -1693,48 +1693,6 @@@ void ClearWinners(void
                head.winning = 0;
  }
  
 -// Onslaught winning condition:
 -// game terminates if only one team has a working generator (or none)
 -float WinningCondition_Onslaught()
 -{
 -      entity head;
 -      float t1, t2, t3, t4;
 -
 -      WinningConditionHelper(); // set worldstatus
 -
 -      if(warmup_stage)
 -              return WINNING_NO;
 -
 -      // first check if the game has ended
 -      t1 = t2 = t3 = t4 = 0;
 -      head = find(world, classname, "onslaught_generator");
 -      while (head)
 -      {
 -              if (head.health > 0)
 -              {
 -                      if (head.team == NUM_TEAM_1) t1 = 1;
 -                      if (head.team == NUM_TEAM_2) t2 = 1;
 -                      if (head.team == NUM_TEAM_3) t3 = 1;
 -                      if (head.team == NUM_TEAM_4) t4 = 1;
 -              }
 -              head = find(head, classname, "onslaught_generator");
 -      }
 -      if (t1 + t2 + t3 + t4 < 2)
 -      {
 -              // game over, only one team remains (or none)
 -              ClearWinners();
 -              if (t1) SetWinners(team, NUM_TEAM_1);
 -              if (t2) SetWinners(team, NUM_TEAM_2);
 -              if (t3) SetWinners(team, NUM_TEAM_3);
 -              if (t4) SetWinners(team, NUM_TEAM_4);
 -              dprint("Have a winner, ending game.\n");
 -              return WINNING_YES;
 -      }
 -
 -      // Two or more teams remain
 -      return WINNING_NO;
 -}
 -
  // Assault winning condition: If the attackers triggered a round end (by fulfilling all objectives)
  // they win. Otherwise the defending team wins once the timelimit passes.
  void assault_new_round();
@@@ -1922,7 -1987,7 +1945,7 @@@ float WinningCondition_RanOutOfSpawns(
        if(have_team_spawns <= 0)
                return WINNING_NO;
  
-       if(autocvar_g_spawn_useallspawns <= 0)
+       if(!autocvar_g_spawn_useallspawns)
                return WINNING_NO;
  
        if(!some_spawn_has_been_used)
@@@ -1994,7 -2059,6 +2017,6 @@@ CheckRules_Worl
  Exit deathmatch games upon conditions
  ============
  */
- void ReadyRestart();
  void CheckRules_World()
  {
        float timelimit;
                return;
        }
  
 -      if(g_onslaught)
 -              timelimit = 0; // ONS has its own overtime rule
 -
        float wantovertime;
        wantovertime = 0;
  
        {
                checkrules_status = WinningCondition_LMS();
        }
 -      else if (g_onslaught)
 -      {
 -              checkrules_status = WinningCondition_Onslaught(); // TODO remove this?
 -      }
        else
        {
                checkrules_status = WinningCondition_Scores(fraglimit, leadlimit);
index c41c7b3b930f35c76b70396fdb46fff833116d4d,2354e128e30bd9d1874e1ca0e57c16ec2f8c07d2..b1f56b941348a646086cdaba51ec415a3b288ebc
@@@ -1,34 -1,30 +1,30 @@@
- #if defined(CSQC)
- #elif defined(MENUQC)
- #elif defined(SVQC)
-       #include "miscfunctions.qh"
-       #include "../dpdefs/progsdefs.qh"
-     #include "../dpdefs/dpextensions.qh"
-     #include "../common/playerstats.qh"
-     #include "../warpzonelib/anglestransform.qh"
-     #include "../warpzonelib/server.qh"
-     #include "../common/constants.qh"
-     #include "../common/teams.qh"
-     #include "../common/util.qh"
-     #include "../common/urllib.qh"
-     #include "../common/command/generic.qh"
-     #include "../common/weapons/weapons.qh"
-     #include "weapons/accuracy.qh"
-     #include "weapons/csqcprojectile.qh"
-     #include "weapons/selection.qh"
-     #include "t_items.qh"
-     #include "autocvars.qh"
-     #include "constants.qh"
-     #include "defs.qh"
-     #include "../common/notifications.qh"
-     #include "../common/deathtypes.qh"
-     #include "mutators/mutators_include.qh"
-     #include "tturrets/include/turrets_early.qh"
-     #include "../common/mapinfo.qh"
-     #include "command/common.qh"
-     #include "../csqcmodellib/sv_model.qh"
-     #include "ipban.qh"
- #endif
+ #include "miscfunctions.qh"
+ #include "_all.qh"
+ #include "antilag.qh"
+ #include "command/common.qh"
+ #include "constants.qh"
+ #include "g_hook.qh"
+ #include "ipban.qh"
+ #include "mutators/mutators_include.qh"
+ #include "tturrets/include/turrets_early.qh"
+ #include "t_items.qh"
+ #include "weapons/accuracy.qh"
+ #include "weapons/csqcprojectile.qh"
+ #include "weapons/selection.qh"
+ #include "../common/command/generic.qh"
+ #include "../common/constants.qh"
+ #include "../common/deathtypes.qh"
+ #include "../common/mapinfo.qh"
+ #include "../common/notifications.qh"
+ #include "../common/playerstats.qh"
+ #include "../common/teams.qh"
+ #include "../common/triggers/subs.qh"
+ #include "../common/urllib.qh"
+ #include "../common/util.qh"
+ #include "../common/weapons/all.qh"
+ #include "../csqcmodellib/sv_model.qh"
+ #include "../warpzonelib/anglestransform.qh"
+ #include "../warpzonelib/server.qh"
  
  void crosshair_trace(entity pl)
  {
@@@ -101,7 -97,7 +97,7 @@@ float DistributeEvenly_GetRandomized(fl
  void GameLogEcho(string s)
  {
      string fn;
-     float matches;
+     int matches;
  
      if (autocvar_sv_eventlog_files)
      {
          {
              logfile_open = true;
              matches = autocvar_sv_eventlog_files_counter + 1;
-             cvar_set("sv_eventlog_files_counter", ftos(matches));
+             cvar_set("sv_eventlog_files_counter", itos(matches));
              fn = ftos(matches);
              if (strlen(fn) < 8)
                  fn = strcat(substring("00000000", 0, 8 - strlen(fn)), fn);
@@@ -226,19 -222,6 +222,6 @@@ entity findnearest(vector point, .strin
      return nearest_entity[0];
  }
  
- void spawnfunc_target_location()
- {
-     self.classname = "target_location";
-     // location name in netname
-     // eventually support: count, teamgame selectors, line of sight?
- }
- void spawnfunc_info_location()
- {
-     self.classname = "target_location";
-     self.message = self.netname;
- }
  string NearestLocation(vector p)
  {
      entity loc;
@@@ -357,17 -340,17 +340,17 @@@ void GetCvars_handleString(string thisn
  {
        if (f < 0)
        {
-               if (self.field)
-                       strunzone(self.field);
-               self.field = string_null;
+               if (self.(field))
+                       strunzone(self.(field));
+               self.(field) = string_null;
        }
        else if (f > 0)
        {
                if (thisname == name)
                {
-                       if (self.field)
-                               strunzone(self.field);
-                       self.field = strzone(argv(f + 1));
+                       if (self.(field))
+                               strunzone(self.(field));
+                       self.(field) = strzone(argv(f + 1));
                }
        }
        else
@@@ -379,12 -362,11 +362,11 @@@ void GetCvars_handleString_Fixup(strin
        if (f >= 0) // also initialize to the fitting value for "" when sending cvars out
                if (thisname == name)
                {
-                       string s;
-                       s = func(strcat1(self.field));
-                       if (s != self.field)
+                       string s = func(strcat1(self.(field)));
+                       if (s != self.(field))
                        {
-                               strunzone(self.field);
-                               self.field = strzone(s);
+                               strunzone(self.(field));
+                               self.(field) = strzone(s);
                        }
                }
  }
@@@ -396,7 -378,7 +378,7 @@@ void GetCvars_handleFloat(string thisna
        else if (f > 0)
        {
                if (thisname == name)
-                       self.field = stof(argv(f + 1));
+                       self.(field) = stof(argv(f + 1));
        }
        else
                stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
@@@ -410,17 -392,17 +392,17 @@@ void GetCvars_handleFloatOnce(string th
        {
                if (thisname == name)
                {
-                       if(!self.field)
+                       if (!self.(field))
                        {
-                               self.field = stof(argv(f + 1));
-                               if(!self.field)
-                                       self.field = -1;
+                               self.(field) = stof(argv(f + 1));
+                               if (!self.(field))
+                                       self.(field) = -1;
                        }
                }
        }
        else
        {
-               if(!self.field)
+               if (!self.(field))
                        stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
        }
  }
@@@ -454,6 -436,7 +436,7 @@@ void GetCvars(float f
        GetCvars_handleFloat(s, f, cvar_cl_autoscreenshot, "cl_autoscreenshot");
        GetCvars_handleFloat(s, f, cvar_cl_jetpack_jump, "cl_jetpack_jump");
        GetCvars_handleString(s, f, cvar_g_xonoticversion, "g_xonoticversion");
+       GetCvars_handleString(s, f, cvar_cl_physics, "cl_physics");
        GetCvars_handleFloat(s, f, cvar_cl_handicap, "cl_handicap");
        GetCvars_handleFloat(s, f, cvar_cl_clippedspectating, "cl_clippedspectating");
        GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriority, "cl_weaponpriority", W_FixWeaponOrder_ForceComplete_AndBuildImpulseList);
@@@ -507,6 -490,16 +490,6 @@@ string playername(entity p
          return p.netname;
  }
  
 -vector randompos(vector m1, vector m2)
 -{
 -    vector v;
 -    m2 = m2 - m1;
 -    v.x = m2_x * random() + m1_x;
 -    v.y = m2_y * random() + m1_y;
 -    v.z = m2_z * random() + m1_z;
 -    return  v;
 -}
 -
  float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still needs done?
  {
        int i = weaponinfo.weapon;
@@@ -575,7 -568,7 +558,7 @@@ void readplayerstartcvars(
        s = cvar_string("g_weaponarena");
        if (s == "0" || s == "")
        {
-               if(g_ca)
+               if(g_ca || g_freezetag)
                        s = "most";
        }
  
                warmup_start_weapons_default = start_weapons_default;
                warmup_start_weapons_defaultmask = start_weapons_defaultmask;
  
-               if (!g_weaponarena && !g_ca)
+               if (!g_weaponarena && !g_ca && !g_freezetag)
                {
                        warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
                        warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
        warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
  }
  
- float sound_allowed(float _dest, entity e)
+ float sound_allowed(float destin, entity e)
  {
      // sounds from world may always pass
      for (;;)
              break;
      }
      // sounds to self may always pass
-     if (_dest == MSG_ONE)
+     if (destin == MSG_ONE)
          if (e == msg_entity)
              return true;
      // sounds by players can be removed
  }
  
  #undef sound
- void sound(entity e, float chan, string samp, float vol, float _atten)
+ void sound(entity e, float chan, string samp, float vol, float attenu)
  {
      if (!sound_allowed(MSG_BROADCAST, e))
          return;
-     sound7(e, chan, samp, vol, _atten, 0, 0);
+     sound7(e, chan, samp, vol, attenu, 0, 0);
  }
  
- void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float _atten)
+ void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float attenu)
  {
      float entno, idx;
  
      entno = num_for_edict(e);
      idx = precache_sound_index(samp);
  
-     float sflags;
+     int sflags;
      sflags = 0;
  
-     _atten = floor(_atten * 64);
+     attenu = floor(attenu * 64);
      vol = floor(vol * 255);
  
      if (vol != 255)
          sflags |= SND_VOLUME;
-     if (_atten != 64)
+     if (attenu != 64)
          sflags |= SND_ATTENUATION;
      if (entno >= 8192 || chan < 0 || chan > 7)
          sflags |= SND_LARGEENTITY;
      if (sflags & SND_VOLUME)
          WriteByte(_dest, vol);
      if (sflags & SND_ATTENUATION)
-         WriteByte(_dest, _atten);
+         WriteByte(_dest, attenu);
      if (sflags & SND_LARGEENTITY)
      {
          WriteShort(_dest, entno);
@@@ -1264,8 -1257,7 +1247,7 @@@ void SetCustomizer(entity e, float(void
      e.uncustomizeentityforclient_set = !!uncustomizer;
  }
  
- void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc)
+ void Net_LinkEntity(entity e, bool docull, float dt, bool(entity, int) sendfunc)
  {
      vector mi, ma;
  
  }
  
  
- entity eliminatedPlayers;
  .float(entity) isEliminated;
  float EliminatedPlayers_SendEntity(entity to, float sendflags)
  {
@@@ -1458,7 -1449,6 +1439,6 @@@ float SUB_NoImpactCheck(
  
  #define SUB_OwnerCheck() (other && (other == self.owner))
  
- void RemoveGrapplingHook(entity pl);
  void W_Crylink_Dequeue(entity e);
  float WarpZone_Projectile_Touch_ImpactFilter_Callback()
  {
@@@ -1826,7 -1816,7 +1806,7 @@@ vector gettaginfo_relative(entity e, fl
  
  .float scale2;
  
- float modeleffect_SendEntity(entity to, float sf)
+ float modeleffect_SendEntity(entity to, int sf)
  {
        float f;
        WriteByte(MSG_ENTITY, ENT_CLIENT_MODELEFFECT);
index f19f53fd0b3010d021308c2a29235f195097d1d1,12dbe3a2c795a72512c012cf9deaba5cb1dbbfe6..80637a877431049cbbaf598f64ff19b7c2ad2cd3
@@@ -15,7 -15,7 +15,7 @@@
  #else
  string cvar_string_normal(string n)
  {
-       if (!(cvar_type(n) & 1))
+       if (!(cvar_type(n) & CVAR_TYPEFLAG_EXISTS))
                backtrace(strcat("Attempt to access undefined cvar: ", n));
        return builtin_cvar_string(n);
  }
@@@ -32,6 -32,46 +32,44 @@@ float cvar_normal(string n
  .float uncustomizeentityforclient_set;
  .float nottargeted;
  
 -vector randompos(vector m1, vector m2);
 -
+ entity eliminatedPlayers;
+ void EliminatedPlayers_Init(float(entity) isEliminated_func);
+ string admin_name(void);
+ void write_recordmarker(entity pl, float tstart, float dt);
+ void play2all(string samp);
+ void DistributeEvenly_Init(float amount, float totalweight);
+ float DistributeEvenly_Get(float weight);
+ void modeleffect_spawn(string m, float s, float f, vector o, vector v, vector ang, vector angv, float s0, float s2, float a, float t1, float t2);
+ void shockwave_spawn(string m, vector org, float sz, float t1, float t2);
+ void play2team(float t, string filename);
+ void GetCvars_handleFloat(string thisname, float f, .float field, string name);
+ float spamsound(entity e, float chan, string samp, float vol, float _atten);
+ void GetCvars_handleString(string thisname, float f, .string field, string name);
+ void precache_all_playermodels(string pattern);
+ void soundat(entity e, vector o, float chan, string samp, float vol, float _atten);
+ void defer(float fdelay, void() func);
+ void UncustomizeEntitiesRun();
+ void InitializeEntitiesRun();
+ void stopsoundto(float _dest, entity e, float chan);
+ void soundtoat(float _dest, entity e, vector o, float chan, string samp, float vol, float _atten);
+ float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d);
+ vector shotorg_adjust(vector vecs, float y_is_right, float visual);
  
  float DistributeEvenly_amount;
  float DistributeEvenly_totalweight;
@@@ -68,6 -108,8 +106,8 @@@ float isPushable(entity e)
  
  float LostMovetypeFollow(entity ent);
  
+ string uid2name(string myuid);
  float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance);
  
  string NearestLocation(vector p);
@@@ -99,15 -141,11 +139,11 @@@ void WarpZone_crosshair_trace(entity pl
  void WarpZone_traceline_antilag (entity source, vector v1, vector v2, float nomonst, entity forent, float lag);
  
  
- #define IFTARGETED if(!self.nottargeted && self.targetname != "")
  #define ITEM_TOUCH_NEEDKILL() (((trace_dpstartcontents | trace_dphitcontents) & DPCONTENTS_NODROP) || (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY))
  #define ITEM_DAMAGE_NEEDKILL(dt) (((dt) == DEATH_HURTTRIGGER) || ((dt) == DEATH_SLIME) || ((dt) == DEATH_LAVA) || ((dt) == DEATH_SWAMP))
  
  #define PROJECTILE_TOUCH if(WarpZone_Projectile_Touch()) return
  
- #define move_out_of_solid(e) WarpZoneLib_MoveOutOfSolid(e)
  const string STR_PLAYER = "player";
  const string STR_SPECTATOR = "spectator";
  const string STR_OBSERVER = "observer";
@@@ -401,10 -439,6 +437,6 @@@ const float SND_ATTENUATION = 2
  const float SND_LARGEENTITY = 8;
  const float SND_LARGESOUND = 16;
  
- // WARNING: this kills the trace globals
- #define EXACTTRIGGER_TOUCH if(WarpZoneLib_ExactTrigger_Touch()) return
- #define EXACTTRIGGER_INIT  WarpZoneLib_ExactTrigger_Init()
  const float INITPRIO_FIRST                            = 0;
  const float INITPRIO_GAMETYPE                         = 0;
  const float INITPRIO_GAMETYPE_FALLBACK        = 1;
@@@ -426,6 -460,6 +458,6 @@@ entity initialize_entity_first
  float sound_allowed(float dest, entity e);
  void InitializeEntity(entity e, void(void) func, float order);
  void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer);
- void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc);
+ void Net_LinkEntity(entity e, bool docull, float dt, bool(entity, int) sendfunc);
  
  #endif
index a05e6c1376340a991bb8201d1f235d46db6c3104,c99643169ba598907d83c97e22a4dc58e7f6f89b..a785cc15b9f8e015604a7906dd170537b6205486
+ #include "../_all.qh"
+ #include "gamemode.qh"
 +#include "../controlpoint.qh"
 +#include "../generator.qh"
  
 -float autocvar_g_onslaught_spawn_at_controlpoints;
 -float autocvar_g_onslaught_spawn_at_generator;
 -float autocvar_g_onslaught_cp_proxydecap;
 -float autocvar_g_onslaught_cp_proxydecap_distance = 512;
 -float autocvar_g_onslaught_cp_proxydecap_dps = 100;
++vector randompos(vector m1, vector m2)
++{
++      vector v;
++      m2 = m2 - m1;
++      v_x = m2_x * random() + m1_x;
++      v_y = m2_y * random() + m1_y;
++      v_z = m2_z * random() + m1_z;
++      return  v;
++}
 -void onslaught_generator_updatesprite(entity e);
 -void onslaught_controlpoint_updatesprite(entity e);
 -void onslaught_link_checkupdate();
 +// =======================
 +// CaptureShield Functions
 +// =======================
  
 -.entity sprite;
 -.string target2;
 -.float iscaptured;
 -.float islinked;
 -.float isgenneighbor_red;
 -.float isgenneighbor_blue;
 -.float iscpneighbor_red;
 -.float iscpneighbor_blue;
 -.float isshielded;
 -.float lasthealth;
 -.float lastteam;
 -.float lastshielded;
 -.float lastcaptured;
 +bool ons_CaptureShield_Customize()
 +{
 +      entity e = WaypointSprite_getviewentity(other);
  
 -entity ons_red_generator;
 -entity ons_blue_generator;
 +      if(!self.enemy.isshielded && (ons_ControlPoint_Attackable(self.enemy, e.team) > 0 || self.enemy.classname != "onslaught_controlpoint")) { return false; }
 +      if(SAME_TEAM(self, e)) { return false; }
  
 -void ons_gib_damage (entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector vforce)
 -{
 -      self.velocity = self.velocity + vforce;
 +      return true;
  }
  
 -.float giblifetime;
 -void ons_throwgib_think()
 +void ons_CaptureShield_Touch()
  {
 -      float d;
 +      if(!self.enemy.isshielded && (ons_ControlPoint_Attackable(self.enemy, other.team) > 0 || self.enemy.classname != "onslaught_controlpoint")) { return; }
 +      if(!IS_PLAYER(other)) { return; }
 +      if(SAME_TEAM(other, self)) { return; }
  
 -      self.nextthink = time + 0.05;
 +      vector mymid = (self.absmin + self.absmax) * 0.5;
 +      vector othermid = (other.absmin + other.absmax) * 0.5;
  
 -      d = self.giblifetime - time;
 +      Damage(other, self, self, 0, DEATH_HURTTRIGGER, mymid, normalize(othermid - mymid) * ons_captureshield_force);
  
 -      if(d<0)
 +      if(IS_REAL_CLIENT(other))
        {
 -              self.think = SUB_Remove;
 -              return;
 +              play2(other, "onslaught/damageblockedbyshield.wav");
 +
 +              if(self.enemy.classname == "onslaught_generator")
 +                      Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_GENERATOR_SHIELDED);
 +              else
 +                      Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_CONTROLPOINT_SHIELDED);
        }
 -      if(d<1)
 -              self.alpha = d;
 +}
  
 -      if(d>2)
 -      if(random()<0.6)
 -              pointparticles(particleeffectnum("onslaught_generator_gib_flame"), self.origin, '0 0 0', 1);
 +void ons_CaptureShield_Reset()
 +{
 +      self.colormap = self.enemy.colormap;
 +      self.team = self.enemy.team;
  }
  
 -void ons_throwgib(vector v_from, vector v_to, string smodel, float f_lifetime, float b_burn)
 +void ons_CaptureShield_Spawn(entity generator, bool is_generator)
  {
 -      entity gib;
 +      entity shield = spawn();
 +
 +      shield.enemy = generator;
 +      shield.team = generator.team;
 +      shield.colormap = generator.colormap;
 +      shield.reset = ons_CaptureShield_Reset;
 +      shield.touch = ons_CaptureShield_Touch;
 +      shield.customizeentityforclient = ons_CaptureShield_Customize;
 +      shield.classname = "ons_captureshield";
 +      shield.effects = EF_ADDITIVE;
 +      shield.movetype = MOVETYPE_NOCLIP;
 +      shield.solid = SOLID_TRIGGER;
 +      shield.avelocity = '7 0 11';
 +      shield.scale = 1;
 +      shield.model = ((is_generator) ? "models/onslaught/generator_shield.md3" : "models/onslaught/controlpoint_shield.md3");
 +      
 +      precache_model(shield.model);
 +      setorigin(shield, generator.origin);
 +      setmodel(shield, shield.model);
 +      setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs);
 +}
  
 -      gib = spawn();
  
 -      setmodel(gib, smodel);
 -      setorigin(gib, v_from);
 -      gib.solid = SOLID_BBOX;
 -      gib.movetype = MOVETYPE_BOUNCE;
 -      gib.takedamage = DAMAGE_YES;
 -      gib.event_damage = ons_gib_damage;
 -      gib.health = -1;
 -      gib.effects = EF_LOWPRECISION;
 -      gib.flags = FL_NOTARGET;
 -      gib.velocity = v_to;
 -      gib.giblifetime = time + f_lifetime;
 +// ==========
 +// Junk Pile
 +// ==========
  
 -      if (b_burn)
 +void ons_debug(string input)
 +{
 +      switch(autocvar_g_onslaught_debug)
        {
 -              gib.think = ons_throwgib_think;
 -              gib.nextthink = time + 0.05;
 +              case 1: dprint(input); break;
 +              case 2: print(input); break;
        }
 -      else
 -              SUB_SetFade(gib, gib.giblifetime, 2);
 +}
 +
- void FixSize(entity e)
- {
-       e.mins_x = rint(e.mins_x);
-       e.mins_y = rint(e.mins_y);
-       e.mins_z = rint(e.mins_z);
-       
-       e.maxs_x = rint(e.maxs_x);
-       e.maxs_y = rint(e.maxs_y);
-       e.maxs_z = rint(e.maxs_z);
- }
- vector randompos(vector m1, vector m2)
- {
-       vector v;
-       m2 = m2 - m1;
-       v_x = m2_x * random() + m1_x;
-       v_y = m2_y * random() + m1_y;
-       v_z = m2_z * random() + m1_z;
-       return  v;
- }
 +void setmodel_fixsize(entity e, string m)
 +{
 +      setmodel(e, m);
 +      FixSize(e);
  }
  
  void onslaught_updatelinks()
  {
 -      entity l, links;
 -      float stop, t1, t2, t3, t4;
 +      entity l;
        // first check if the game has ended
 -      dprint("--- updatelinks ---\n");
 -      links = findchain(classname, "onslaught_link");
 +      ons_debug("--- updatelinks ---\n");
        // mark generators as being shielded and networked
 -      l = findchain(classname, "onslaught_generator");
 -      while (l)
 +      for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
        {
                if (l.iscaptured)
 -                      dprint(etos(l), " (generator) belongs to team ", ftos(l.team), "\n");
 +                      ons_debug(strcat(etos(l), " (generator) belongs to team ", ftos(l.team), "\n"));
                else
 -                      dprint(etos(l), " (generator) is destroyed\n");
 +                      ons_debug(strcat(etos(l), " (generator) is destroyed\n"));
                l.islinked = l.iscaptured;
                l.isshielded = l.iscaptured;
 -              l = l.chain;
 +              l.sprite.SendFlags |= 16;
        }
        // mark points as shielded and not networked
 -      l = findchain(classname, "onslaught_controlpoint");
 -      while (l)
 +      for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
        {
                l.islinked = false;
                l.isshielded = true;
 -              l.isgenneighbor_red = false;
 -              l.isgenneighbor_blue = false;
 -              l.iscpneighbor_red = false;
 -              l.iscpneighbor_blue = false;
 -              dprint(etos(l), " (point) belongs to team ", ftos(l.team), "\n");
 -              l = l.chain;
 +              int i;
 +              for(i = 0; i < 17; ++i) { l.isgenneighbor[i] = false; l.iscpneighbor[i] = false; }
 +              ons_debug(strcat(etos(l), " (point) belongs to team ", ftos(l.team), "\n"));
 +              l.sprite.SendFlags |= 16;
        }
        // flow power outward from the generators through the network
 -      l = links;
 -      while (l)
 -      {
 -              dprint(etos(l), " (link) connects ", etos(l.goalentity), " with ", etos(l.enemy), "\n");
 -              l = l.chain;
 -      }
 -      stop = false;
 +      bool stop = false;
        while (!stop)
        {
                stop = true;
 -              l = links;
 -              while (l)
 +              for(l = ons_worldlinklist; l; l = l.ons_worldlinknext)
                {
                        // if both points are captured by the same team, and only one of
                        // them is powered, mark the other one as powered as well
                        if (l.enemy.iscaptured && l.goalentity.iscaptured)
                                if (l.enemy.islinked != l.goalentity.islinked)
 -                                      if (l.enemy.team == l.goalentity.team)
 +                                      if(SAME_TEAM(l.enemy, l.goalentity))
                                        {
                                                if (!l.goalentity.islinked)
                                                {
                                                        stop = false;
                                                        l.goalentity.islinked = true;
 -                                                      dprint(etos(l), " (link) is marking ", etos(l.goalentity), " (point) because its team matches ", etos(l.enemy), " (point)\n");
 +                                                      ons_debug(strcat(etos(l), " (link) is marking ", etos(l.goalentity), " (point) because its team matches ", etos(l.enemy), " (point)\n"));
                                                }
                                                else if (!l.enemy.islinked)
                                                {
                                                        stop = false;
                                                        l.enemy.islinked = true;
 -                                                      dprint(etos(l), " (link) is marking ", etos(l.enemy), " (point) because its team matches ", etos(l.goalentity), " (point)\n");
 +                                                      ons_debug(strcat(etos(l), " (link) is marking ", etos(l.enemy), " (point) because its team matches ", etos(l.goalentity), " (point)\n"));
                                                }
                                        }
 -                      l = l.chain;
                }
        }
        // now that we know which points are powered we can mark their neighbors
        // as unshielded if team differs
 -      l = links;
 -      while (l)
 +      for(l = ons_worldlinklist; l; l = l.ons_worldlinknext)
        {
                if (l.goalentity.islinked)
                {
 -                      if (l.goalentity.team != l.enemy.team)
 +                      if(DIFF_TEAM(l.goalentity, l.enemy))
                        {
 -                              dprint(etos(l), " (link) is unshielding ", etos(l.enemy), " (point) because its team does not match ", etos(l.goalentity), " (point)\n");
 +                              ons_debug(strcat(etos(l), " (link) is unshielding ", etos(l.enemy), " (point) because its team does not match ", etos(l.goalentity), " (point)\n"));
                                l.enemy.isshielded = false;
                        }
                        if(l.goalentity.classname == "onslaught_generator")
 -                      {
 -                              if(l.goalentity.team == NUM_TEAM_1)
 -                                      l.enemy.isgenneighbor_red = true;
 -                              else if(l.goalentity.team == NUM_TEAM_2)
 -                                      l.enemy.isgenneighbor_blue = true;
 -                      }
 +                              l.enemy.isgenneighbor[l.goalentity.team] = true;
                        else
 -                      {
 -                              if(l.goalentity.team == NUM_TEAM_1)
 -                                      l.enemy.iscpneighbor_red = true;
 -                              else if(l.goalentity.team == NUM_TEAM_2)
 -                                      l.enemy.iscpneighbor_blue = true;
 -                      }
 +                              l.enemy.iscpneighbor[l.goalentity.team] = true;
                }
                if (l.enemy.islinked)
                {
 -                      if (l.goalentity.team != l.enemy.team)
 +                      if(DIFF_TEAM(l.goalentity, l.enemy))
                        {
 -                              dprint(etos(l), " (link) is unshielding ", etos(l.goalentity), " (point) because its team does not match ", etos(l.enemy), " (point)\n");
 +                              ons_debug(strcat(etos(l), " (link) is unshielding ", etos(l.goalentity), " (point) because its team does not match ", etos(l.enemy), " (point)\n"));
                                l.goalentity.isshielded = false;
                        }
                        if(l.enemy.classname == "onslaught_generator")
 -                      {
 -                              if(l.enemy.team == NUM_TEAM_1)
 -                                      l.goalentity.isgenneighbor_red = true;
 -                              else if(l.enemy.team == NUM_TEAM_2)
 -                                      l.goalentity.isgenneighbor_blue = true;
 -                      }
 +                              l.goalentity.isgenneighbor[l.enemy.team] = true;
                        else
 -                      {
 -                              if(l.enemy.team == NUM_TEAM_1)
 -                                      l.goalentity.iscpneighbor_red = true;
 -                              else if(l.enemy.team == NUM_TEAM_2)
 -                                      l.goalentity.iscpneighbor_blue = true;
 -                      }
 +                              l.goalentity.iscpneighbor[l.enemy.team] = true;
                }
 -              l = l.chain;
        }
 -      // now update the takedamage and alpha variables on generator shields
 -      l = findchain(classname, "onslaught_generator");
 -      while (l)
 +      // now update the generators
 +      for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
        {
                if (l.isshielded)
                {
 -                      dprint(etos(l), " (generator) is shielded\n");
 -                      l.enemy.alpha = 1;
 +                      ons_debug(strcat(etos(l), " (generator) is shielded\n"));
                        l.takedamage = DAMAGE_NO;
                        l.bot_attack = false;
                }
                else
                {
 -                      dprint(etos(l), " (generator) is not shielded\n");
 -                      l.enemy.alpha = -1;
 +                      ons_debug(strcat(etos(l), " (generator) is not shielded\n"));
                        l.takedamage = DAMAGE_AIM;
                        l.bot_attack = true;
                }
 -              l = l.chain;
 +
 +              ons_Generator_UpdateSprite(l);
        }
        // now update the takedamage and alpha variables on control point icons
 -      l = findchain(classname, "onslaught_controlpoint");
 -      while (l)
 +      for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
        {
                if (l.isshielded)
                {
 -                      dprint(etos(l), " (point) is shielded\n");
 -                      l.enemy.alpha = 1;
 +                      ons_debug(strcat(etos(l), " (point) is shielded\n"));
                        if (l.goalentity)
                        {
                                l.goalentity.takedamage = DAMAGE_NO;
                }
                else
                {
 -                      dprint(etos(l), " (point) is not shielded\n");
 -                      l.enemy.alpha = -1;
 +                      ons_debug(strcat(etos(l), " (point) is not shielded\n"));
                        if (l.goalentity)
                        {
                                l.goalentity.takedamage = DAMAGE_AIM;
                                l.goalentity.bot_attack = true;
                        }
                }
 -              onslaught_controlpoint_updatesprite(l);
 -              l = l.chain;
 +              ons_ControlPoint_UpdateSprite(l);
        }
 -      // count generators owned by each team
 -      t1 = t2 = t3 = t4 = 0;
 -      l = findchain(classname, "onslaught_generator");
 -      while (l)
 +      l = findchain(classname, "ons_captureshield");
 +      while(l)
        {
 -              if (l.iscaptured)
 -              {
 -                      if (l.team == NUM_TEAM_1) t1 = 1;
 -                      if (l.team == NUM_TEAM_2) t2 = 1;
 -                      if (l.team == NUM_TEAM_3) t3 = 1;
 -                      if (l.team == NUM_TEAM_4) t4 = 1;
 -              }
 -              onslaught_generator_updatesprite(l);
 +              l.team = l.enemy.team;
 +              l.colormap = l.enemy.colormap;
                l = l.chain;
        }
 -      // see if multiple teams remain (if not, it's game over)
 -      if (t1 + t2 + t3 + t4 < 2)
 -              dprint("--- game over ---\n");
 -      else
 -              dprint("--- done updating links ---\n");
  }
  
 -float onslaught_controlpoint_can_be_linked(entity cp, float t)
 +
 +// ===================
 +// Main Link Functions
 +// ===================
 +
 +bool ons_Link_Send(entity to, int sendflags)
  {
 -      if(t == NUM_TEAM_1)
 +      WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
 +      WriteByte(MSG_ENTITY, sendflags);
 +      if(sendflags & 1)
        {
 -              if(cp.isgenneighbor_red)
 -                      return 2;
 -              if(cp.iscpneighbor_red)
 -                      return 1;
 +              WriteCoord(MSG_ENTITY, self.goalentity.origin_x);
 +              WriteCoord(MSG_ENTITY, self.goalentity.origin_y);
 +              WriteCoord(MSG_ENTITY, self.goalentity.origin_z);
        }
 -      else if(t == NUM_TEAM_2)
 +      if(sendflags & 2)
        {
 -              if(cp.isgenneighbor_blue)
 -                      return 2;
 -              if(cp.iscpneighbor_blue)
 -                      return 1;
 +              WriteCoord(MSG_ENTITY, self.enemy.origin_x);
 +              WriteCoord(MSG_ENTITY, self.enemy.origin_y);
 +              WriteCoord(MSG_ENTITY, self.enemy.origin_z);
        }
 -      return 0;
 -      /*
 -         entity e;
 -      // check to see if this player has a legitimate claim to capture this
 -      // control point - more specifically that there is a captured path of
 -      // points leading back to the team generator
 -      e = findchain(classname, "onslaught_link");
 -      while (e)
 -      {
 -      if (e.goalentity == cp)
 -      {
 -      dprint(etos(e), " (link) connects to ", etos(e.enemy), " (point)");
 -      if (e.enemy.islinked)
 -      {
 -      dprint(" which is linked");
 -      if (e.enemy.team == t)
 +      if(sendflags & 4)
        {
 -      dprint(" and has the correct team!\n");
 -      return 1;
 -      }
 -      else
 -      dprint(" but has the wrong team\n");
 -      }
 -      else
 -      dprint("\n");
 +              WriteByte(MSG_ENTITY, self.clientcolors); // which is goalentity's color + enemy's color * 16
        }
 -      else if (e.enemy == cp)
 -      {
 -      dprint(etos(e), " (link) connects to ", etos(e.goalentity), " (point)");
 -      if (e.goalentity.islinked)
 -      {
 -      dprint(" which is linked");
 -      if (e.goalentity.team == t)
 +      return true;
 +}
 +
 +void ons_Link_CheckUpdate()
 +{
 +      // TODO check if the two sides have moved (currently they won't move anyway)
 +      float cc = 0, cc1 = 0, cc2 = 0;
 +      
 +      if(self.goalentity.islinked || self.goalentity.iscaptured) { cc1 = (self.goalentity.team - 1) * 0x01; }
 +      if(self.enemy.islinked || self.enemy.iscaptured) { cc2 = (self.enemy.team - 1) * 0x10; }
 +      
 +      cc = cc1 + cc2;
 +
 +      if(cc != self.clientcolors)
        {
 -      dprint(" and has a team!\n");
 -      return 1;
 -      }
 -      else
 -      dprint(" but has the wrong team\n");
 -      }
 -      else
 -      dprint("\n");
 -      }
 -      e = e.chain;
 +              self.clientcolors = cc;
 +              self.SendFlags |= 4;
        }
 +
 +      self.nextthink = time;
 +}
 +
 +void ons_DelayedLinkSetup()
 +{
 +      self.goalentity = find(world, targetname, self.target);
 +      self.enemy = find(world, targetname, self.target2);
 +      if(!self.goalentity) { objerror("can not find target\n"); }
 +      if(!self.enemy) { objerror("can not find target2\n"); }
 +
 +      ons_debug(strcat(etos(self.goalentity), " linked with ", etos(self.enemy), "\n"));
 +      self.SendFlags |= 3;
 +      self.think = ons_Link_CheckUpdate;
 +      self.nextthink = time;
 +}
 +
 +
 +// =============================
 +// Main Control Point Functions
 +// =============================
 +
 +int ons_ControlPoint_CanBeLinked(entity cp, int teamnumber)
 +{
 +      if(cp.isgenneighbor[teamnumber]) { return 2; }
 +      if(cp.iscpneighbor[teamnumber]) { return 1; }
 +
        return 0;
 -       */
  }
  
 -float onslaught_controlpoint_attackable(entity cp, float t)
 +int ons_ControlPoint_Attackable(entity cp, int teamnumber)
        // -2: SAME TEAM, attackable by enemy!
        // -1: SAME TEAM!
        // 0: off limits
        // 3: attack it (HIGH PRIO)
        // 4: touch it (HIGH PRIO)
  {
 -      float a;
 +      int a;
  
        if(cp.isshielded)
        {
        else if(cp.goalentity)
        {
                // if there's already an icon built, nothing happens
 -              if(cp.team == t)
 +              if(cp.team == teamnumber)
                {
 -                      a = onslaught_controlpoint_can_be_linked(cp, NUM_TEAM_1 + NUM_TEAM_2 - t);
 +                      a = ons_ControlPoint_CanBeLinked(cp, teamnumber);
                        if(a) // attackable by enemy?
                                return -2; // EMERGENCY!
                        return -1;
                }
                // we know it can be linked, so no need to check
                // but...
 -              a = onslaught_controlpoint_can_be_linked(cp, t);
 +              a = ons_ControlPoint_CanBeLinked(cp, teamnumber);
                if(a == 2) // near our generator?
                        return 3; // EMERGENCY!
                return 1;
        else
        {
                // free point
 -              if(onslaught_controlpoint_can_be_linked(cp, t))
 +              if(ons_ControlPoint_CanBeLinked(cp, teamnumber))
                {
 -                      a = onslaught_controlpoint_can_be_linked(cp, NUM_TEAM_1 + NUM_TEAM_2 - t);
 +                      a = ons_ControlPoint_CanBeLinked(cp, teamnumber); // why was this here NUM_TEAM_1 + NUM_TEAM_2 - t
                        if(a == 2)
                                return 4; // GET THIS ONE NOW!
                        else
        return 0;
  }
  
 -float overtime_msg_time;
 -void onslaught_generator_think()
 +void ons_ControlPoint_Icon_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
  {
 -      float d;
 -      entity e;
 -      self.nextthink = ceil(time + 1);
 -      if (!gameover)
 +      entity oself;
 +      
 +      if(damage <= 0) { return; }
 +
 +      if (self.owner.isshielded)
        {
 -              if (autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60)
 -              {
 -                      if (!overtime_msg_time)
 -                      {
 -                              Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT);
 -                              overtime_msg_time = time;
 -                      }
 -                      // self.max_health / 300 gives 5 minutes of overtime.
 -                      // control points reduce the overtime duration.
 -                      sound(self, CH_TRIGGER, "onslaught/generator_decay.wav", VOL_BASE, ATTEN_NORM);
 -                      d = 1;
 -                      e = findchain(classname, "onslaught_controlpoint");
 -                      while (e)
 +              // this is protected by a shield, so ignore the damage
 +              if (time > self.pain_finished)
 +                      if (IS_PLAYER(attacker))
                        {
 -                              if (e.team != self.team)
 -                                      if (e.islinked)
 -                                              d = d + 1;
 -                              e = e.chain;
 +                              play2(attacker, "onslaught/damageblockedbyshield.wav");
 +                              self.pain_finished = time + 1;
 +                              attacker.typehitsound += 1; // play both sounds (shield is way too quiet)
                        }
  
 -                      if(autocvar_g_campaign && autocvar__campaign_testrun)
 -                              d = d * self.max_health;
 -                      else
 -                              d = d * self.max_health / max(30, 60 * autocvar_timelimit_suddendeath);
 -
 -                      Damage(self, self, self, d, DEATH_HURTTRIGGER, self.origin, '0 0 0');
 -              }
 -              else if (overtime_msg_time)
 -                      overtime_msg_time = 0;
 -
 -        if(!self.isshielded && self.wait < time)
 -        {
 -            self.wait = time + 5;
 -            FOR_EACH_REALPLAYER(e)
 -            {
 -                              if(SAME_TEAM(e, self))
 -                {
 -                                      Send_Notification(NOTIF_ONE, e, MSG_CENTER, CENTER_ONS_NOTSHIELDED);
 -                    soundto(MSG_ONE, e, CHAN_AUTO, "kh/alarm.wav", VOL_BASE, ATTEN_NONE);    // FIXME: Uniqe sound?
 -                }
 -            }
 -        }
 +              return;
        }
 -}
 -
 -void onslaught_generator_ring_spawn(vector org)
 -{
 -      modeleffect_spawn("models/onslaught/shockwavetransring.md3", 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, -16, 0.1, 1.25, 0.25);
 -}
  
 -void onslaught_generator_ray_think()
 -{
 -      self.nextthink = time + 0.05;
 -      if(self.count > 10)
 +      if(IS_PLAYER(attacker))
 +      if(time - ons_notification_time[self.team] > 10)
        {
 -              self.think = SUB_Remove;
 -              return;
 +              play2team(self.team, "onslaught/controlpoint_underattack.wav");
 +              ons_notification_time[self.team] = time;
        }
  
 -      if(self.count > 5)
 -              self.alpha -= 0.1;
 +      self.health = self.health - damage;
 +      if(self.owner.iscaptured)
 +              WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
 +      else
 +              WaypointSprite_UpdateBuildFinished(self.owner.sprite, time + (self.max_health - self.health) / (self.count / ONS_CP_THINKRATE));
 +      self.pain_finished = time + 1;
 +      // particles on every hit
 +      pointparticles(particleeffectnum("sparks"), hitloc, force*-1, 1);
 +      //sound on every hit
 +      if (random() < 0.5)
 +              sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTEN_NORM);
        else
 -              self.alpha += 0.1;
 +              sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTEN_NORM);
  
 -      self.scale += 0.2;
 -      self.count +=1;
 -}
 +      if (self.health < 0)
 +      {
 +              sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
 +              pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
 +              Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_CPDESTROYED_), self.owner.message, attacker.netname);
 +              
 +              PlayerScore_Add(attacker, SP_ONS_TAKES, 1);
 +              PlayerScore_Add(attacker, SP_SCORE, 10);
 +              
 +              self.owner.goalentity = world;
 +              self.owner.islinked = false;
 +              self.owner.iscaptured = false;
 +              self.owner.team = 0;
 +              self.owner.colormap = 1024;
  
 -void onslaught_generator_ray_spawn(vector org)
 -{
 -      entity e;
 -      e = spawn();
 -      setmodel(e, "models/onslaught/ons_ray.md3");
 -      setorigin(e, org);
 -      e.angles = randomvec() * 360;
 -      e.alpha = 0;
 -      e.scale = random() * 5 + 8;
 -      e.think = onslaught_generator_ray_think;
 -      e.nextthink = time + 0.05;
 -}
 +              WaypointSprite_UpdateMaxHealth(self.owner.sprite, 0);
  
 -void onslaught_generator_shockwave_spawn(vector org)
 -{
 -      shockwave_spawn("models/onslaught/shockwave.md3", org, -64, 0.75, 0.5);
 -}
 +              onslaught_updatelinks();
  
 -void onslaught_generator_damage_think()
 -{
 -      if(self.owner.health < 0)
 -      {
 -              self.think = SUB_Remove;
 -              return;
 -      }
 -      self.nextthink = time+0.1;
 +              // Use targets now (somebody make sure this is in the right place..)
 +              oself = self;
 +              self = self.owner;
 +              activator = self;
 +              SUB_UseTargets ();
 +              self = oself;
  
 -      // damaged fx (less probable the more damaged is the generator)
 -      if(random() < 0.9 - self.owner.health / self.owner.max_health)
 -              if(random() < 0.01)
 -              {
 -                      pointparticles(particleeffectnum("electro_ballexplode"), self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1);
 -                      sound(self, CH_TRIGGER, "onslaught/electricity_explode.wav", VOL_BASE, ATTEN_NORM);
 -              }
 -              else
 -                      pointparticles(particleeffectnum("torch_small"), self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1);
 -}
 +              self.owner.waslinked = self.owner.islinked;
 +              if(self.owner.model != "models/onslaught/controlpoint_pad.md3")
 +                      setmodel_fixsize(self.owner, "models/onslaught/controlpoint_pad.md3");
 +              //setsize(self, '-32 -32 0', '32 32 8');
  
 -void onslaught_generator_damage_spawn(entity gd_owner)
 -{
 -      entity e;
 -      e = spawn();
 -      e.owner = gd_owner;
 -      e.health = self.owner.health;
 -      setorigin(e, gd_owner.origin);
 -      e.think = onslaught_generator_damage_think;
 -      e.nextthink = time+1;
 +              remove(self);
 +      }
 +      
 +      self.SendFlags |= CPSF_STATUS;
  }
  
 -void onslaught_generator_deaththink()
 +void ons_ControlPoint_Icon_Think()
  {
 -      vector org;
 -      float i;
 -
 -      if (!self.count)
 -              self.count = 40;
 +      entity oself;
 +      self.nextthink = time + ONS_CP_THINKRATE;
  
 -      // White shockwave
 -      if(self.count==40||self.count==20)
 +      if(autocvar_g_onslaught_cp_proxydecap)
        {
 -              onslaught_generator_ring_spawn(self.origin);
 -              sound(self, CH_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTEN_NORM);
 -      }
 +        int _enemy_count = 0;
 +        int _friendly_count = 0;
 +        float _dist;
 +        entity _player;
  
 -      // Throw some gibs
 -      if(random() < 0.3)
 -      {
 -              i = random();
 -              if(i < 0.3)
 -                      ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 11 + '0 0 20', "models/onslaught/gen_gib1.md3", 6, true);
 -              else if(i > 0.7)
 -                      ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 12 + '0 0 20', "models/onslaught/gen_gib2.md3", 6, true);
 -              else
 -                      ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 13 + '0 0 20', "models/onslaught/gen_gib3.md3", 6, true);
 -      }
 +        FOR_EACH_PLAYER(_player)
 +        {
 +            if(!_player.deadflag)
 +            {
 +                _dist = vlen(_player.origin - self.origin);
 +                if(_dist < autocvar_g_onslaught_cp_proxydecap_distance)
 +                {
 +                                      if(SAME_TEAM(_player, self))
 +                        ++_friendly_count;
 +                    else
 +                        ++_enemy_count;
 +                }
 +            }
 +        }
 +
 +        _friendly_count = _friendly_count * (autocvar_g_onslaught_cp_proxydecap_dps * ONS_CP_THINKRATE);
 +        _enemy_count = _enemy_count * (autocvar_g_onslaught_cp_proxydecap_dps * ONS_CP_THINKRATE);
 +
 +        self.health = bound(0, self.health + (_friendly_count - _enemy_count), self.max_health);
 +              self.SendFlags |= CPSF_STATUS;
 +        if(self.health <= 0)
 +        {
 +            ons_ControlPoint_Icon_Damage(self, self, 1, 0, self.origin, '0 0 0');
 +            return;
 +        }
 +    }
  
 -      // Spawn fire balls
 -      for(i=0;i < 10;++i)
 +      if (time > self.pain_finished + 5)
        {
 -              org = self.origin + randompos('-30 -30 -30' * i + '0 0 -20', '30 30 30' * i + '0 0 20');
 -              pointparticles(particleeffectnum("onslaught_generator_gib_explode"), org, '0 0 0', 1);
 +              if(self.health < self.max_health)
 +              {
 +                      self.health = self.health + self.count;
 +                      if (self.health >= self.max_health)
 +                              self.health = self.max_health;
 +                      WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
 +              }
        }
  
 -      // Short explosion sound + small explosion
 -      if(random() < 0.25)
 +      if(self.owner.islinked != self.owner.waslinked)
        {
 -              te_explosion(self.origin);
 -              sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
 -      }
 +              // unteam the spawnpoint if needed
 +              int t = self.owner.team;
 +              if(!self.owner.islinked)
 +                      self.owner.team = 0;
  
 -      // Particles
 -      org = self.origin + randompos(self.mins + '8 8 8', self.maxs + '-8 -8 -8');
 -      pointparticles(particleeffectnum("onslaught_generator_smallexplosion"), org, '0 0 0', 1);
 +              oself = self;
 +              self = self.owner;
 +              activator = self;
 +              SUB_UseTargets ();
 +              self = oself;
  
 -      // rays
 -      if(random() > 0.25 )
 -      {
 -              onslaught_generator_ray_spawn(self.origin);
 +              self.owner.team = t;
 +
 +              self.owner.waslinked = self.owner.islinked;
        }
  
 -      // Final explosion
 -      if(self.count==1)
 +      // damaged fx
 +      if(random() < 0.6 - self.health / self.max_health)
        {
 -              org = self.origin;
 -              te_explosion(org);
 -              onslaught_generator_shockwave_spawn(org);
 -              pointparticles(particleeffectnum("onslaught_generator_finalexplosion"), org, '0 0 0', 1);
 -              sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
 -      }
 -      else
 -              self.nextthink = time + 0.05;
 +              pointparticles(particleeffectnum("electricity_sparks"), self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1);
  
 -      self.count = self.count - 1;
 +              if(random() > 0.8)
 +                      sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTEN_NORM);
 +              else if (random() > 0.5)
 +                      sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTEN_NORM);
 +      }
  }
  
 -void onslaught_generator_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 +void ons_ControlPoint_Icon_BuildThink()
  {
 -      float i;
 -      if (damage <= 0)
 -              return;
 -      if(warmup_stage)
 +      entity oself;
 +      int a;
 +
 +      self.nextthink = time + ONS_CP_THINKRATE;
 +
 +      // only do this if there is power
 +      a = ons_ControlPoint_CanBeLinked(self.owner, self.owner.team);
 +      if(!a)
                return;
 -      if (attacker != self)
 +
 +      self.health = self.health + self.count;
 +      
 +      self.SendFlags |= CPSF_STATUS;
 +
 +      if (self.health >= self.max_health)
        {
 -              if (self.isshielded)
 -              {
 -                      // this is protected by a shield, so ignore the damage
 -                      if (time > self.pain_finished)
 -                              if (IS_PLAYER(attacker))
 -                              {
 -                                      play2(attacker, "onslaught/damageblockedbyshield.wav");
 -                                      self.pain_finished = time + 1;
 -                              }
 -                      return;
 -              }
 -              if (time > self.pain_finished)
 -              {
 -                      self.pain_finished = time + 10;
 -                      bprint(Team_ColoredFullName(self.team), " generator under attack!\n");
 -                      play2team(self.team, "onslaught/generator_underattack.wav");
 -              }
 -      }
 -      self.health = self.health - damage;
 -      WaypointSprite_UpdateHealth(self.sprite, self.health);
 -      // choose an animation frame based on health
 -      self.frame = 10 * bound(0, (1 - self.health / self.max_health), 1);
 -      // see if the generator is still functional, or dying
 -      if (self.health > 0)
 -      {
 -#ifdef ONSLAUGHT_SPAM
 -              float h, lh;
 -              lh = ceil(self.lasthealth / 100) * 100;
 -              h = ceil(self.health / 100) * 100;
 -              if(lh != h)
 -                      bprint(Team_ColoredFullName(self.team), " generator has less than ", ftos(h), " health remaining\n");
 -#endif
 -              self.lasthealth = self.health;
 -      }
 -      else if (!warmup_stage)
 -      {
 -              if (attacker == self)
 -                      bprint(Team_ColoredFullName(self.team), " generator spontaneously exploded due to overtime!\n");
 -              else
 -              {
 -                      string t;
 -                      t = Team_ColoredFullName(attacker.team);
 -                      bprint(Team_ColoredFullName(self.team), " generator destroyed by ", t, "!\n");
 -              }
 -              self.iscaptured = false;
 -              self.islinked = false;
 -              self.isshielded = false;
 -              self.takedamage = DAMAGE_NO; // can't be hurt anymore
 -              self.event_damage = func_null; // won't do anything if hurt
 -              self.count = 0; // reset counter
 -              self.think = onslaught_generator_deaththink; // explosion sequence
 -              self.nextthink = time; // start exploding immediately
 -              self.think(); // do the first explosion now
 +              self.health = self.max_health;
 +              self.count = autocvar_g_onslaught_cp_regen * ONS_CP_THINKRATE; // slow repair rate from now on
 +              self.think = ons_ControlPoint_Icon_Think;
 +              sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTEN_NORM);
 +              self.owner.iscaptured = true;
 +              self.solid = SOLID_BBOX;
  
 -              WaypointSprite_UpdateMaxHealth(self.sprite, 0);
 +              pointparticles(particleeffectnum(sprintf("%s_cap", Static_Team_ColorName_Lower(self.owner.team))), self.owner.origin, '0 0 0', 1);
  
 -              onslaught_updatelinks();
 -      }
 +              WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
 +              WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
  
 -      if(self.health <= 0)
 -              setmodel(self, "models/onslaught/generator_dead.md3");
 -      else if(self.health < self.max_health * 0.10)
 -              setmodel(self, "models/onslaught/generator_dmg9.md3");
 -      else if(self.health < self.max_health * 0.20)
 -              setmodel(self, "models/onslaught/generator_dmg8.md3");
 -      else if(self.health < self.max_health * 0.30)
 -              setmodel(self, "models/onslaught/generator_dmg7.md3");
 -      else if(self.health < self.max_health * 0.40)
 -              setmodel(self, "models/onslaught/generator_dmg6.md3");
 -      else if(self.health < self.max_health * 0.50)
 -              setmodel(self, "models/onslaught/generator_dmg5.md3");
 -      else if(self.health < self.max_health * 0.60)
 -              setmodel(self, "models/onslaught/generator_dmg4.md3");
 -      else if(self.health < self.max_health * 0.70)
 -              setmodel(self, "models/onslaught/generator_dmg3.md3");
 -      else if(self.health < self.max_health * 0.80)
 -              setmodel(self, "models/onslaught/generator_dmg2.md3");
 -      else if(self.health < self.max_health * 0.90)
 -              setmodel(self, "models/onslaught/generator_dmg1.md3");
 -      setsize(self, '-52 -52 -14', '52 52 75');
 +              if(IS_PLAYER(self.owner.ons_toucher))
 +              {
 +                      Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ONSLAUGHT_CAPTURE, self.owner.ons_toucher.netname, self.owner.message);
 +                      Send_Notification(NOTIF_ALL_EXCEPT, self.owner.ons_toucher, MSG_CENTER, APP_TEAM_ENT_4(self.owner.ons_toucher, CENTER_ONS_CAPTURE_), self.owner.message);
 +                      Send_Notification(NOTIF_ONE, self.owner.ons_toucher, MSG_CENTER, CENTER_ONS_CAPTURE, self.owner.message);
 +                      PlayerScore_Add(self.owner.ons_toucher, SP_ONS_CAPS, 1);
 +                      PlayerTeamScore_AddScore(self.owner.ons_toucher, 10);
 +              }
 +              
 +              self.owner.ons_toucher = world;
  
 -      // Throw some flaming gibs on damage, more damage = more chance for gib
 -      if(random() < damage/220)
 -      {
 -              sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
 -              i = random();
 -              if(i < 0.3)
 -                      ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib1.md3", 5, true);
 -              else if(i > 0.7)
 -                      ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib2.md3", 5, true);
 -              else
 -                      ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib3.md3", 5, true);
 -      }
 -      else
 -      {
 -              // particles on every hit
 -              pointparticles(particleeffectnum("sparks"), hitloc, force * -1, 1);
 +              onslaught_updatelinks();
  
 -              //sound on every hit
 -              if (random() < 0.5)
 -                      sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTEN_NORM);
 -              else
 -                      sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);
 +              // Use targets now (somebody make sure this is in the right place..)
 +              oself = self;
 +              self = self.owner;
 +              activator = self;
 +              SUB_UseTargets ();
 +              self = oself;
 +              
 +              self.SendFlags |= CPSF_SETUP;
        }
 -
 -      //throw some gibs on damage
 -      if(random() < damage/200+0.2)
 -              if(random() < 0.5)
 -                      ons_throwgib(hitloc + '0 0 20', randomvec()*360, "models/onslaught/gen_gib1.md3", 5, false);
 +      if(self.owner.model != "models/onslaught/controlpoint_pad2.md3")
 +              setmodel_fixsize(self.owner, "models/onslaught/controlpoint_pad2.md3");
 +              
 +      if(random() < 0.9 - self.health / self.max_health)
 +              pointparticles(particleeffectnum("rage"), self.origin + 10 * randomvec(), '0 0 -1', 1);
  }
  
 -// update links after a delay
 -void onslaught_generator_delayed()
 +void ons_ControlPoint_Icon_Spawn(entity cp, entity player)
  {
 -      onslaught_updatelinks();
 -      // now begin normal thinking
 -      self.think = onslaught_generator_think;
 -      self.nextthink = time;
 -}
 +      entity e = spawn();
 +      
 +      setsize(e, CPICON_MIN, CPICON_MAX);
 +      setorigin(e, cp.origin + CPICON_OFFSET);
 +      
 +      e.classname = "onslaught_controlpoint_icon";
 +      e.owner = cp;
 +      e.max_health = autocvar_g_onslaught_cp_health;
 +      e.health = autocvar_g_onslaught_cp_buildhealth;
 +      e.solid = SOLID_NOT;
 +      e.takedamage = DAMAGE_AIM;
 +      e.bot_attack = true;
 +      e.event_damage = ons_ControlPoint_Icon_Damage;
 +      e.team = player.team;
 +      e.colormap = 1024 + (e.team - 1) * 17;
 +      e.count = (e.max_health - e.health) * ONS_CP_THINKRATE / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
 +      
 +      sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTEN_NORM);
 +      
 +      cp.goalentity = e;
 +      cp.team = e.team;
 +      cp.colormap = e.colormap;
  
 -string onslaught_generator_waypointsprite_for_team(entity e, float t)
 -{
 -      if(t == e.team)
 -      {
 -              if(e.team == NUM_TEAM_1)
 -                      return "ons-gen-red";
 -              else if(e.team == NUM_TEAM_2)
 -                      return "ons-gen-blue";
 -      }
 -      if(e.isshielded)
 -              return "ons-gen-shielded";
 -      if(e.team == NUM_TEAM_1)
 -              return "ons-gen-red";
 -      else if(e.team == NUM_TEAM_2)
 -              return "ons-gen-blue";
 -      return "";
 -}
 +      pointparticles(particleeffectnum(sprintf("%sflag_touch", Static_Team_ColorName_Lower(player.team))), e.origin, '0 0 0', 1);
  
 -void onslaught_generator_updatesprite(entity e)
 -{
 -      string s1, s2, s3;
 -      s1 = onslaught_generator_waypointsprite_for_team(e, NUM_TEAM_1);
 -      s2 = onslaught_generator_waypointsprite_for_team(e, NUM_TEAM_2);
 -      s3 = onslaught_generator_waypointsprite_for_team(e, -1);
 -      WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
 +      WaypointSprite_UpdateBuildFinished(cp.sprite, time + (e.max_health - e.health) / (e.count / ONS_CP_THINKRATE));
 +      WaypointSprite_UpdateRule(cp.sprite,cp.team,SPRITERULE_TEAMPLAY);
 +      cp.sprite.SendFlags |= 16;
  
 -      if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded)
 -      {
 -              e.lastteam = e.team + 2;
 -              e.lastshielded = e.isshielded;
 -              if(e.lastshielded)
 -              {
 -                      if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
 -                              WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, 0.5 * colormapPaletteColor(e.team - 1, false));
 -                      else
 -                              WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.5 0.5 0.5');
 -              }
 -              else
 -              {
 -                      if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
 -                              WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, colormapPaletteColor(e.team - 1, false));
 -                      else
 -                              WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.75 0.75 0.75');
 -              }
 -              WaypointSprite_Ping(e.sprite);
 -      }
 +      onslaught_controlpoint_icon_link(e, ons_ControlPoint_Icon_BuildThink);
  }
  
 -string onslaught_controlpoint_waypointsprite_for_team(entity e, float t)
 +string ons_ControlPoint_Waypoint(entity e)
  {
 -      float a;
 -      if(t != -1)
 +      if(e.team)
        {
 -              a = onslaught_controlpoint_attackable(e, t);
 -              if(a == 3 || a == 4) // ATTACK/TOUCH THIS ONE NOW
 -              {
 -                      if(e.team == NUM_TEAM_1)
 -                              return "ons-cp-atck-red";
 -                      else if(e.team == NUM_TEAM_2)
 -                              return "ons-cp-atck-blue";
 -                      else
 -                              return "ons-cp-atck-neut";
 -              }
 -              else if(a == -2) // DEFEND THIS ONE NOW
 -              {
 -                      if(e.team == NUM_TEAM_1)
 -                              return "ons-cp-dfnd-red";
 -                      else if(e.team == NUM_TEAM_2)
 -                              return "ons-cp-dfnd-blue";
 -              }
 -              else if(e.team == t || a == -1 || a == 1) // own point, or fire at it
 -              {
 -                      if(e.team == NUM_TEAM_1)
 -                              return "ons-cp-red";
 -                      else if(e.team == NUM_TEAM_2)
 -                              return "ons-cp-blue";
 -              }
 -              else if(a == 2) // touch it
 -                      return "ons-cp-neut";
 +              int a = ons_ControlPoint_Attackable(e, e.team);
 +              
 +              if(a == -2) { return "ons-cp-dfnd"; } // defend now
 +              if(a == -1 || a == 1 || a == 2) { return "ons-cp"; } // touch
 +              if(a == 3 || a == 4) { return "ons-cp-atck"; } // attack
        }
        else
 -      {
 -              if(e.team == NUM_TEAM_1)
 -                      return "ons-cp-red";
 -              else if(e.team == NUM_TEAM_2)
 -                      return "ons-cp-blue";
 -              else
 -                      return "ons-cp-neut";
 -      }
 +              return "ons-cp";
 +
        return "";
  }
  
 -void onslaught_controlpoint_updatesprite(entity e)
 +void ons_ControlPoint_UpdateSprite(entity e)
  {
 -      string s1, s2, s3;
 -      s1 = onslaught_controlpoint_waypointsprite_for_team(e, NUM_TEAM_1);
 -      s2 = onslaught_controlpoint_waypointsprite_for_team(e, NUM_TEAM_2);
 -      s3 = onslaught_controlpoint_waypointsprite_for_team(e, -1);
 -      WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
 +      string s1;
 +      s1 = ons_ControlPoint_Waypoint(e);
 +      WaypointSprite_UpdateSprites(e.sprite, s1, s1, s1);
  
 -      float sh;
 -      sh = !(onslaught_controlpoint_can_be_linked(e, NUM_TEAM_1) || onslaught_controlpoint_can_be_linked(e, NUM_TEAM_2));
 +      bool sh;
 +      sh = !(ons_ControlPoint_CanBeLinked(e, NUM_TEAM_1) || ons_ControlPoint_CanBeLinked(e, NUM_TEAM_2) || ons_ControlPoint_CanBeLinked(e, NUM_TEAM_3) || ons_ControlPoint_CanBeLinked(e, NUM_TEAM_4));
  
        if(e.lastteam != e.team + 2 || e.lastshielded != sh || e.iscaptured != e.lastcaptured)
        {
                }
                if(e.lastshielded)
                {
 -                      if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
 +                      if(e.team)
                                WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, 0.5 * colormapPaletteColor(e.team - 1, false));
                        else
                                WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.5 0.5 0.5');
                }
                else
                {
 -                      if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
 +                      if(e.team)
                                WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, colormapPaletteColor(e.team - 1, false));
                        else
                                WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.75 0.75 0.75');
        }
  }
  
 -void onslaught_generator_reset()
 +void ons_ControlPoint_Touch()
  {
 -      self.team = self.team_saved;
 -      self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
 -      self.takedamage = DAMAGE_AIM;
 -      self.bot_attack = true;
 -      self.iscaptured = true;
 -      self.islinked = true;
 -      self.isshielded = true;
 -      self.enemy.solid = SOLID_NOT;
 -      self.think = onslaught_generator_delayed;
 -      self.nextthink = time + 0.2;
 -      setmodel(self, "models/onslaught/generator.md3");
 -      setsize(self, '-52 -52 -14', '52 52 75');
 -
 -      if(!self.noalign)
 -      {
 -              setorigin(self, self.origin + '0 0 20');
 -              droptofloor();
 +      entity toucher = other;
 +      int attackable;
 +      
 +      if((toucher.vehicle_flags & VHF_ISVEHICLE) && toucher.owner)
 +      if(autocvar_g_onslaught_allow_vehicle_touch)
 +              toucher = toucher.owner;
 +      else
 +              return;
 +              
 +      if(!IS_PLAYER(toucher)) { return; }
 +      if(toucher.frozen) { return; }
 +      if(toucher.deadflag != DEAD_NO) { return; }
 +      
 +      if ( SAME_TEAM(self,toucher) )
 +      if ( self.iscaptured )
 +      {
 +              if(time <= toucher.teleport_antispam)
 +                      Send_Notification(NOTIF_ONE, toucher, MSG_CENTER, CENTER_ONS_TELEPORT_ANTISPAM, rint(toucher.teleport_antispam - time));
 +              else
 +                      Send_Notification(NOTIF_ONE, toucher, MSG_CENTER, CENTER_ONS_TELEPORT);
        }
 +              
 +      attackable = ons_ControlPoint_Attackable(self, toucher.team);
 +      if(attackable != 2 && attackable != 4)
 +              return;
 +      // we've verified that this player has a legitimate claim to this point,
 +      // so start building the captured point icon (which only captures this
 +      // point if it successfully builds without being destroyed first)
 +      ons_ControlPoint_Icon_Spawn(self, toucher);
 +      
 +      self.ons_toucher = toucher;
  
 -      WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
 -      WaypointSprite_UpdateHealth(self.sprite, self.health);
 +      onslaught_updatelinks();
  }
  
 -/*QUAKED spawnfunc_onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
 -  Base generator.
 -
 -  spawnfunc_onslaught_link entities can target this.
 +void ons_ControlPoint_Think()
 +{
 +      self.nextthink = time + ONS_CP_THINKRATE;
 +      CSQCMODEL_AUTOUPDATE();
 +}
  
 -keys:
 -"team" - team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
 -"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
 - */
 -void spawnfunc_onslaught_generator()
 +void ons_ControlPoint_Reset()
  {
 -      if (!g_onslaught)
 -      {
 -              remove(self);
 -              return;
 -      }
 +      if(self.goalentity)
 +              remove(self.goalentity);
  
 -      //entity e;
 -      precache_model("models/onslaught/generator.md3");
 -      precache_model("models/onslaught/generator_shield.md3");
 -      precache_model("models/onslaught/generator_dmg1.md3");
 -      precache_model("models/onslaught/generator_dmg2.md3");
 -      precache_model("models/onslaught/generator_dmg3.md3");
 -      precache_model("models/onslaught/generator_dmg4.md3");
 -      precache_model("models/onslaught/generator_dmg5.md3");
 -      precache_model("models/onslaught/generator_dmg6.md3");
 -      precache_model("models/onslaught/generator_dmg7.md3");
 -      precache_model("models/onslaught/generator_dmg8.md3");
 -      precache_model("models/onslaught/generator_dmg9.md3");
 -      precache_model("models/onslaught/generator_dead.md3");
 -      precache_model("models/onslaught/shockwave.md3");
 -      precache_model("models/onslaught/shockwavetransring.md3");
 -      precache_model("models/onslaught/gen_gib1.md3");
 -      precache_model("models/onslaught/gen_gib2.md3");
 -      precache_model("models/onslaught/gen_gib3.md3");
 -      precache_model("models/onslaught/ons_ray.md3");
 -      precache_sound("onslaught/generator_decay.wav");
 -      precache_sound("weapons/grenade_impact.wav");
 -      precache_sound("weapons/rocket_impact.wav");
 -      precache_sound("onslaught/generator_underattack.wav");
 -      precache_sound("onslaught/shockwave.wav");
 -      precache_sound("onslaught/ons_hit1.wav");
 -      precache_sound("onslaught/ons_hit2.wav");
 -      precache_sound("onslaught/electricity_explode.wav");
 -      if (!self.team)
 -              objerror("team must be set");
 +      self.goalentity = world;
 +      self.team = 0;
 +      self.colormap = 1024;
 +      self.iscaptured = false;
 +      self.islinked = false;
 +      self.isshielded = true;
 +      self.think = ons_ControlPoint_Think;
 +      self.ons_toucher = world;
 +      self.nextthink = time + ONS_CP_THINKRATE;
 +      setmodel_fixsize(self, "models/onslaught/controlpoint_pad.md3");
  
 -      if(self.team == NUM_TEAM_1)
 -        ons_red_generator = self;
 +      WaypointSprite_UpdateMaxHealth(self.sprite, 0);
 +      WaypointSprite_UpdateRule(self.sprite,self.team,SPRITERULE_TEAMPLAY);
  
 -      if(self.team == NUM_TEAM_2)
 -        ons_blue_generator = self;
 +      onslaught_updatelinks();
  
 -      self.team_saved = self.team;
 -      self.colormap = 1024 + (self.team - 1) * 17;
 -      self.solid = SOLID_BBOX;
 -      self.movetype = MOVETYPE_NONE;
 -      self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
 -      setmodel(self, "models/onslaught/generator.md3");
 -      setsize(self, '-52 -52 -14', '52 52 75');
 -      setorigin(self, self.origin);
 -      self.takedamage = DAMAGE_AIM;
 -      self.bot_attack = true;
 -      self.event_damage = onslaught_generator_damage;
 -      self.iscaptured = true;
 -      self.islinked = true;
 -      self.isshielded = true;
 -      // helper entity that create fx when generator is damaged
 -      onslaught_generator_damage_spawn(self);
 -      // spawn shield model which indicates whether this can be damaged
 -      self.enemy = spawn();
 -      setattachment(self.enemy , self, "");
 -      self.enemy.classname = "onslaught_generator_shield";
 -      self.enemy.solid = SOLID_NOT;
 -      self.enemy.movetype = MOVETYPE_NONE;
 -      self.enemy.effects = EF_ADDITIVE;
 -      setmodel(self.enemy, "models/onslaught/generator_shield.md3");
 -      //setorigin(e, self.origin);
 -      self.enemy.colormap = self.colormap;
 -      self.enemy.team = self.team;
 -      //self.think = onslaught_generator_delayed;
 -      //self.nextthink = time + 0.2;
 -      InitializeEntity(self, onslaught_generator_delayed, INITPRIO_LAST);
 -
 -      WaypointSprite_SpawnFixed(string_null, self.origin + '0 0 128', self, sprite, RADARICON_NONE, '0 0 0');
 -      WaypointSprite_UpdateRule(self.sprite, NUM_TEAM_2, SPRITERULE_TEAMPLAY);
 -      WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
 -      WaypointSprite_UpdateHealth(self.sprite, self.health);
 +      activator = self;
 +      SUB_UseTargets(); // to reset the structures, playerspawns etc.
  
 -      waypoint_spawnforitem(self);
 +      CSQCMODEL_AUTOUPDATE();
 +}
  
 +void ons_DelayedControlPoint_Setup(void)
 +{
        onslaught_updatelinks();
 +      
 +      // captureshield setup
 +      ons_CaptureShield_Spawn(self, false);
 +
 +      CSQCMODEL_AUTOINIT();
 +}
  
 -      self.reset = onslaught_generator_reset;
 +void ons_ControlPoint_Setup(entity cp)
 +{
 +      // declarations
 +      self = cp; // for later usage with droptofloor()
 +      
 +      // main setup
 +      cp.ons_worldcpnext = ons_worldcplist; // link control point into ons_worldcplist
 +      ons_worldcplist = cp;
 +      
 +      cp.netname = "Control point";
 +      cp.team = 0;
 +      cp.solid = SOLID_BBOX;
 +      cp.movetype = MOVETYPE_NONE;
 +      cp.touch = ons_ControlPoint_Touch;
 +      cp.think = ons_ControlPoint_Think;
 +      cp.nextthink = time + ONS_CP_THINKRATE;
 +      cp.reset = ons_ControlPoint_Reset;
 +      cp.colormap = 1024;
 +      cp.iscaptured = false;
 +      cp.islinked = false;
 +      cp.isshielded = true;
 +      
 +      if(cp.message == "") { cp.message = "a"; }
 +
 +      // precache - TODO: clean up!
 +      precache_model("models/onslaught/controlpoint_pad.md3");
 +      precache_model("models/onslaught/controlpoint_pad2.md3");
 +      precache_model("models/onslaught/controlpoint_shield.md3");
 +      precache_model("models/onslaught/controlpoint_icon.md3");
 +      precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
 +      precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
 +      precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
 +      precache_model("models/onslaught/controlpoint_icon_gib1.md3");
 +      precache_model("models/onslaught/controlpoint_icon_gib2.md3");
 +      precache_model("models/onslaught/controlpoint_icon_gib4.md3");
 +      precache_sound("onslaught/controlpoint_build.wav");
 +      precache_sound("onslaught/controlpoint_built.wav");
 +      precache_sound("weapons/grenade_impact.wav");
 +      precache_sound("onslaught/damageblockedbyshield.wav");
 +      precache_sound("onslaught/controlpoint_underattack.wav");
 +      precache_sound("onslaught/ons_spark1.wav");
 +      precache_sound("onslaught/ons_spark2.wav");
 +      
 +      // appearence
 +      setmodel_fixsize(cp, "models/onslaught/controlpoint_pad.md3");
 +      
 +      // control point placement
 +      if((cp.spawnflags & 1) || cp.noalign) // don't drop to floor, just stay at fixed location
 +      {
 +              cp.noalign = true;
 +              cp.movetype = MOVETYPE_NONE;
 +      }
 +      else // drop to floor, automatically find a platform and set that as spawn origin
 +      {
 +              setorigin(cp, cp.origin + '0 0 20');
 +              cp.noalign = false;
 +              self = cp;
 +              droptofloor();
 +              cp.movetype = MOVETYPE_TOSS;
 +      }
 +      
 +      // waypointsprites
 +      WaypointSprite_SpawnFixed(string_null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE, '0 0 0');
 +      WaypointSprite_UpdateRule(self.sprite, self.team, SPRITERULE_TEAMPLAY);
 +      
 +      InitializeEntity(cp, ons_DelayedControlPoint_Setup, INITPRIO_SETLOCATION);
  }
  
 -.float waslinked;
 -.float cp_bob_spd;
 -.vector cp_origin, cp_bob_origin, cp_bob_dmg;
  
 -float ons_notification_time_team1;
 -float ons_notification_time_team2;
 +// =========================
 +// Main Generator Functions
 +// =========================
  
 -void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 +string ons_Generator_Waypoint(entity e)
  {
 -      entity oself;
 -      float nag;
 +      if(e.isshielded)
 +              return "ons-gen-shielded";
 +      return "ons-gen";
 +}
  
 -      if (damage <= 0)
 -              return;
 -      if (self.owner.isshielded)
 -      {
 -              // this is protected by a shield, so ignore the damage
 -              if (time > self.pain_finished)
 -                      if (IS_PLAYER(attacker))
 -                      {
 -                              play2(attacker, "onslaught/damageblockedbyshield.wav");
 -                              self.pain_finished = time + 1;
 -                      }
 -              return;
 -      }
 +void ons_Generator_UpdateSprite(entity e)
 +{
 +      string s1 = ons_Generator_Waypoint(e);
 +      WaypointSprite_UpdateSprites(e.sprite, s1, s1, s1);
  
 -      if (IS_PLAYER(attacker))
 +      if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded)
        {
 -              nag = false;
 -              if(self.team == NUM_TEAM_1)
 +              e.lastteam = e.team + 2;
 +              e.lastshielded = e.isshielded;
 +              if(e.lastshielded)
                {
 -                      if(time - ons_notification_time_team1 > 10)
 -                      {
 -                              nag = true;
 -                              ons_notification_time_team1 = time;
 -                      }
 +                      if(e.team)
 +                              WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, 0.5 * colormapPaletteColor(e.team - 1, false));
 +                      else
 +                              WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.5 0.5 0.5');
                }
 -              else if(self.team == NUM_TEAM_2)
 +              else
                {
 -                      if(time - ons_notification_time_team2 > 10)
 -                      {
 -                              nag = true;
 -                              ons_notification_time_team2 = time;
 -                      }
 +                      if(e.team)
 +                              WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, colormapPaletteColor(e.team - 1, false));
 +                      else
 +                              WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.75 0.75 0.75');
                }
 -              else
 -                      nag = true;
 -
 -              if(nag)
 -                      play2team(self.team, "onslaught/controlpoint_underattack.wav");
 +              WaypointSprite_Ping(e.sprite);
        }
 +}
  
 -      self.health = self.health - damage;
 -      if(self.owner.iscaptured)
 -              WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
 -      else
 -              WaypointSprite_UpdateBuildFinished(self.owner.sprite, time + (self.max_health - self.health) / (self.count / sys_frametime));
 -      self.pain_finished = time + 1;
 -      self.punchangle = (2 * randomvec() - '1 1 1') * 45;
 -      self.cp_bob_dmg_z = (2 * random() - 1) * 15;
 -      // colormod flash when shot
 -      self.colormod = '2 2 2';
 -      // particles on every hit
 -      pointparticles(particleeffectnum("sparks"), hitloc, force*-1, 1);
 -      //sound on every hit
 -      if (random() < 0.5)
 -              sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTEN_NORM);
 -      else
 -              sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTEN_NORM);
 +void ons_GeneratorDamage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 +{
 +      if(damage <= 0) { return; }
 +      if(warmup_stage || gameover) { return; }
 +      if(!round_handler_IsRoundStarted()) { return; }
  
 -      if (self.health < 0)
 +      if (attacker != self)
        {
 -              sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
 -              pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
 +              if (self.isshielded)
                {
 -                      string t;
 -                      t = Team_ColoredFullName(attacker.team);
 -                      bprint(Team_ColoredFullName(self.team), " ", self.message, " control point destroyed by ", t, "\n");
 -                      ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 25, "models/onslaught/controlpoint_icon_gib1.md3", 3, false);
 -                      ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 45, "models/onslaught/controlpoint_icon_gib2.md3", 3, false);
 -                      ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 45, "models/onslaught/controlpoint_icon_gib2.md3", 3, false);
 -                      ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, false);
 -                      ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, false);
 -                      ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, false);
 -                      ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, false);
 +                      // this is protected by a shield, so ignore the damage
 +                      if (time > self.pain_finished)
 +                              if (IS_PLAYER(attacker))
 +                              {
 +                                      play2(attacker, "onslaught/damageblockedbyshield.wav");
 +                                      attacker.typehitsound += 1;
 +                                      self.pain_finished = time + 1;
 +                              }
 +                      return;
                }
 -              self.owner.goalentity = world;
 -              self.owner.islinked = false;
 -              self.owner.iscaptured = false;
 -              self.owner.team = 0;
 -              self.owner.colormap = 1024;
 +              if (time > self.pain_finished)
 +              {
 +                      self.pain_finished = time + 10;
 +                      entity head;
 +                      FOR_EACH_REALPLAYER(head) if(SAME_TEAM(head, self)) { Send_Notification(NOTIF_ONE, head, MSG_CENTER, CENTER_GENERATOR_UNDERATTACK); }
 +                      play2team(self.team, "onslaught/generator_underattack.wav");
 +              }
 +      }
 +      self.health = self.health - damage;
 +      WaypointSprite_UpdateHealth(self.sprite, self.health);
 +      // choose an animation frame based on health
 +      self.frame = 10 * bound(0, (1 - self.health / self.max_health), 1);
 +      // see if the generator is still functional, or dying
 +      if (self.health > 0)
 +      {
 +              self.lasthealth = self.health;
 +      }
 +      else
 +      {
 +              if (attacker == self)
 +                      Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_GENDESTROYED_OVERTIME_));
 +              else
 +              {
 +                      Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_GENDESTROYED_));
 +                      PlayerScore_Add(attacker, SP_SCORE, 100);
 +              }
 +              self.iscaptured = false;
 +              self.islinked = false;
 +              self.isshielded = false;
 +              self.takedamage = DAMAGE_NO; // can't be hurt anymore
 +              self.event_damage = func_null; // won't do anything if hurt
 +              self.count = 0; // reset counter
 +              self.think = func_null;
 +              self.nextthink = 0;
 +              //self.think(); // do the first explosion now
  
 -              WaypointSprite_UpdateMaxHealth(self.owner.sprite, 0);
 +              WaypointSprite_UpdateMaxHealth(self.sprite, 0);
 +              WaypointSprite_Ping(self.sprite);
 +              //WaypointSprite_Kill(self.sprite); // can't do this yet, code too poor
  
                onslaught_updatelinks();
 +      }
  
 -              // Use targets now (somebody make sure this is in the right place..)
 -              oself = self;
 -              self = self.owner;
 -              activator = self;
 -              SUB_UseTargets ();
 -              self = oself;
 -
 -
 -              self.owner.waslinked = self.owner.islinked;
 -              if(self.owner.model != "models/onslaught/controlpoint_pad.md3")
 -                      setmodel(self.owner, "models/onslaught/controlpoint_pad.md3");
 -              //setsize(self, '-32 -32 0', '32 32 8');
 +      // Throw some flaming gibs on damage, more damage = more chance for gib
 +      if(random() < damage/220)
 +      {
 +              sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
 +      }
 +      else
 +      {
 +              // particles on every hit
 +              pointparticles(particleeffectnum("sparks"), hitloc, force * -1, 1);
  
 -              remove(self);
 +              //sound on every hit
 +              if (random() < 0.5)
 +                      sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTEN_NORM);
 +              else
 +                      sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);
        }
 +
 +      self.SendFlags |= GSF_STATUS;
  }
  
 -void onslaught_controlpoint_icon_think()
 +void ons_GeneratorThink()
  {
 -      entity oself;
 -      self.nextthink = time + sys_frametime;
 -
 -      if(autocvar_g_onslaught_cp_proxydecap)
 +      entity e;
 +      self.nextthink = time + GEN_THINKRATE;
 +      if (!gameover)
        {
 -        float _enemy_count = 0;
 -        float _friendly_count = 0;
 -        float _dist;
 -        entity _player;
 -
 -        FOR_EACH_PLAYER(_player)
 +        if(!self.isshielded && self.wait < time)
          {
 -            if(!_player.deadflag)
 +            self.wait = time + 5;
 +            FOR_EACH_REALPLAYER(e)
              {
 -                _dist = vlen(_player.origin - self.origin);
 -                if(_dist < autocvar_g_onslaught_cp_proxydecap_distance)
 -                {
 -                    if(_player.team == self.team)
 -                        ++_friendly_count;
 -                    else
 -                        ++_enemy_count;
 +                              if(SAME_TEAM(e, self))
 +                              {
 +                                      Send_Notification(NOTIF_ONE, e, MSG_CENTER, CENTER_ONS_NOTSHIELDED_TEAM);
 +                    soundto(MSG_ONE, e, CHAN_AUTO, "kh/alarm.wav", VOL_BASE, ATTEN_NONE);    // FIXME: unique sound?
                  }
 +                              else
 +                                      Send_Notification(NOTIF_ONE, e, MSG_CENTER, APP_TEAM_NUM_4(self.team, CENTER_ONS_NOTSHIELDED_));
              }
          }
 +      }
 +}
  
 -        _friendly_count = _friendly_count * (autocvar_g_onslaught_cp_proxydecap_dps * sys_frametime);
 -        _enemy_count = _enemy_count * (autocvar_g_onslaught_cp_proxydecap_dps * sys_frametime);
 +void ons_GeneratorReset()
 +{
 +      self.team = self.team_saved;
 +      self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
 +      self.takedamage = DAMAGE_AIM;
 +      self.bot_attack = true;
 +      self.iscaptured = true;
 +      self.islinked = true;
 +      self.isshielded = true;
 +      self.event_damage = ons_GeneratorDamage;
 +      self.think = ons_GeneratorThink;
 +      self.nextthink = time + GEN_THINKRATE;
 +      
 +      Net_LinkEntity(self, false, 0, generator_send);
 +      
 +      self.SendFlags = GSF_SETUP; // just incase
 +      self.SendFlags |= GSF_STATUS;
  
 -        self.health = bound(0, self.health + (_friendly_count - _enemy_count), self.max_health);
 -        if(self.health <= 0)
 -        {
 -            onslaught_controlpoint_icon_damage(self, self, 1, 0, self.origin, '0 0 0');
 -            return;
 -        }
 -    }
 +      WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
 +      WaypointSprite_UpdateHealth(self.sprite, self.health);
 +      WaypointSprite_UpdateRule(self.sprite,self.team,SPRITERULE_TEAMPLAY);
 +      
 +      onslaught_updatelinks();
 +}
  
 -      if (time > self.pain_finished + 5)
 +void ons_DelayedGeneratorSetup()
 +{
 +      // bot waypoints
 +      waypoint_spawnforitem_force(self, self.origin);
 +      self.nearestwaypointtimeout = 0; // activate waypointing again
 +      self.bot_basewaypoint = self.nearestwaypoint;
 +
 +      // captureshield setup
 +      ons_CaptureShield_Spawn(self, true);
 +      
 +      onslaught_updatelinks();
 +      
 +      Net_LinkEntity(self, false, 0, generator_send);
 +}
 +
 +
 +void onslaught_generator_touch()
 +{
 +      if ( IS_PLAYER(other) )
 +      if ( SAME_TEAM(self,other) )
 +      if ( self.iscaptured )
        {
 -              if(self.health < self.max_health)
 -              {
 -                      self.health = self.health + self.count;
 -                      if (self.health >= self.max_health)
 -                              self.health = self.max_health;
 -                      WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
 -              }
 +              Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_TELEPORT);
        }
 -      if (self.health < self.max_health * 0.25)
 -              setmodel(self, "models/onslaught/controlpoint_icon_dmg3.md3");
 -      else if (self.health < self.max_health * 0.50)
 -              setmodel(self, "models/onslaught/controlpoint_icon_dmg2.md3");
 -      else if (self.health < self.max_health * 0.75)
 -              setmodel(self, "models/onslaught/controlpoint_icon_dmg1.md3");
 -      else if (self.health < self.max_health * 0.90)
 -              setmodel(self, "models/onslaught/controlpoint_icon.md3");
 -      // colormod flash when shot
 -      self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
 +}
  
 -      if(self.owner.islinked != self.owner.waslinked)
 -      {
 -              // unteam the spawnpoint if needed
 -              float t;
 -              t = self.owner.team;
 -              if(!self.owner.islinked)
 -                      self.owner.team = 0;
 +void ons_GeneratorSetup(entity gen) // called when spawning a generator entity on the map as a spawnfunc
 +{
 +      // declarations
 +      int teamnumber = gen.team;
 +      self = gen; // for later usage with droptofloor()
 +      
 +      // main setup
 +      gen.ons_worldgeneratornext = ons_worldgeneratorlist; // link generator into ons_worldgeneratorlist
 +      ons_worldgeneratorlist = gen;
 +      
 +      gen.netname = sprintf("%s generator", Team_ColoredFullName(teamnumber));
 +      gen.classname = "onslaught_generator";
 +      gen.solid = SOLID_BBOX;
 +      gen.team_saved = teamnumber;
 +      gen.movetype = MOVETYPE_NONE;
 +      gen.lasthealth = gen.max_health = gen.health = autocvar_g_onslaught_gen_health;
 +      gen.takedamage = DAMAGE_AIM;
 +      gen.bot_attack = true;
 +      gen.event_damage = ons_GeneratorDamage;
 +      gen.reset = ons_GeneratorReset;
 +      gen.think = ons_GeneratorThink;
 +      gen.nextthink = time + GEN_THINKRATE;
 +      gen.iscaptured = true;
 +      gen.islinked = true;
 +      gen.isshielded = true;
 +      gen.touch = onslaught_generator_touch;
 +      
 +      // precache - TODO: clean up!
 +      precache_model("models/onslaught/generator_shield.md3");
 +      precache_model("models/onslaught/gen_gib1.md3");
 +      precache_model("models/onslaught/gen_gib2.md3");
 +      precache_model("models/onslaught/gen_gib3.md3");
 +      precache_sound("onslaught/generator_decay.wav");
 +      precache_sound("weapons/grenade_impact.wav");
 +      precache_sound("weapons/rocket_impact.wav");
 +      precache_sound("onslaught/generator_underattack.wav");
 +      precache_sound("onslaught/shockwave.wav");
 +      precache_sound("onslaught/ons_hit1.wav");
 +      precache_sound("onslaught/ons_hit2.wav");
 +      precache_sound("onslaught/generator_underattack.wav");
 +      
 +      // appearence
 +      // model handled by CSQC
 +      setsize(gen, GENERATOR_MIN, GENERATOR_MAX);
 +      setorigin(gen, (gen.origin + CPGEN_SPAWN_OFFSET));
 +      gen.colormap = 1024 + (teamnumber - 1) * 17;
 +      
 +      // generator placement
 +      self = gen;
 +      droptofloor();
 +      
 +      // waypointsprites
 +      WaypointSprite_SpawnFixed(string_null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE, '0 0 0');
 +      WaypointSprite_UpdateRule(self.sprite, self.team, SPRITERULE_TEAMPLAY);
 +      WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
 +      WaypointSprite_UpdateHealth(self.sprite, self.health);
 +      
 +      InitializeEntity(gen, ons_DelayedGeneratorSetup, INITPRIO_SETLOCATION);
 +}
  
 -              oself = self;
 -              self = self.owner;
 -              activator = self;
 -              SUB_UseTargets ();
 -              self = oself;
  
 -              self.owner.team = t;
 +// ===============
 +//  Round Handler
 +// ===============
  
 -              self.owner.waslinked = self.owner.islinked;
 +int total_generators;
 +void Onslaught_count_generators()
 +{
 +      entity e;
 +      total_generators = redowned = blueowned = yellowowned = pinkowned = 0;
 +      for(e = ons_worldgeneratorlist; e; e = e.ons_worldgeneratornext)
 +      {
 +              ++total_generators;
 +              redowned += (e.team == NUM_TEAM_1 && e.health > 0);
 +              blueowned += (e.team == NUM_TEAM_2 && e.health > 0);
 +              yellowowned += (e.team == NUM_TEAM_3 && e.health > 0);
 +              pinkowned += (e.team == NUM_TEAM_4 && e.health > 0);
        }
 +}
  
 -      if (self.punchangle.x > 0)
 +int Onslaught_GetWinnerTeam()
 +{
 +      int winner_team = 0;
 +      if(redowned > 0)
 +              winner_team = NUM_TEAM_1;
 +      if(blueowned > 0)
        {
 -              self.punchangle_x = self.punchangle.x - 60 * sys_frametime;
 -              if (self.punchangle.x < 0)
 -                      self.punchangle_x = 0;
 +              if(winner_team) return 0;
 +              winner_team = NUM_TEAM_2;
        }
 -      else if (self.punchangle.x < 0)
 +      if(yellowowned > 0)
        {
 -              self.punchangle_x = self.punchangle.x + 60 * sys_frametime;
 -              if (self.punchangle.x > 0)
 -                      self.punchangle_x = 0;
 +              if(winner_team) return 0;
 +              winner_team = NUM_TEAM_3;
        }
 -
 -      if (self.punchangle.y > 0)
 +      if(pinkowned > 0)
        {
 -              self.punchangle_y = self.punchangle.y - 60 * sys_frametime;
 -              if (self.punchangle.y < 0)
 -                      self.punchangle_y = 0;
 +              if(winner_team) return 0;
 +              winner_team = NUM_TEAM_4;
        }
 -      else if (self.punchangle.y < 0)
 +      if(winner_team)
 +              return winner_team;
 +      return -1; // no generators left?
 +}
 +
 +#define ONS_OWNED_GENERATORS() ((redowned > 0) + (blueowned > 0) + (yellowowned > 0) + (pinkowned > 0))
 +#define ONS_OWNED_GENERATORS_OK() (ONS_OWNED_GENERATORS() > 1)
 +bool Onslaught_CheckWinner()
 +{
 +      entity e;
 +      
 +      if ((autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60) || (round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0))
        {
 -              self.punchangle_y = self.punchangle.y + 60 * sys_frametime;
 -              if (self.punchangle.y > 0)
 -                      self.punchangle_y = 0;
 +              ons_stalemate = true;
 +
 +              if (!wpforenemy_announced)
 +              {
 +                      Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT);
 +                      sound(world, CH_INFO, "onslaught/generator_decay.wav", VOL_BASE, ATTEN_NONE);
 +
 +                      wpforenemy_announced = true;
 +              }
 +
 +              entity tmp_entity; // temporary entity
 +              float d;
 +              for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext) if(time >= tmp_entity.ons_overtime_damagedelay)
 +              {
 +                      // tmp_entity.max_health / 300 gives 5 minutes of overtime.
 +                      // control points reduce the overtime duration.
 +                      d = 1;
 +                      for(e = ons_worldcplist; e; e = e.ons_worldcpnext)
 +                      {
 +                              if(DIFF_TEAM(e, tmp_entity))
 +                              if(e.islinked)
 +                                      d = d + 1;
 +                      }
 +
 +                      if(autocvar_g_campaign && autocvar__campaign_testrun)
 +                              d = d * tmp_entity.max_health;
 +                      else
 +                              d = d * tmp_entity.max_health / max(30, 60 * autocvar_timelimit_suddendeath);
 +
 +                      Damage(tmp_entity, tmp_entity, tmp_entity, d, DEATH_HURTTRIGGER, tmp_entity.origin, '0 0 0');
 +                      
 +                      tmp_entity.sprite.SendFlags |= 16;
 +
 +                      tmp_entity.ons_overtime_damagedelay = time + 1;
 +              }
        }
 +      else { wpforenemy_announced = false; ons_stalemate = false; }
 +
 +      Onslaught_count_generators();
 +      
 +      if(ONS_OWNED_GENERATORS_OK())
 +              return 0;
  
 -      if (self.punchangle.z > 0)
 +      int winner_team = Onslaught_GetWinnerTeam();
 +
 +      if(winner_team > 0)
        {
 -              self.punchangle_z = self.punchangle.z - 60 * sys_frametime;
 -              if (self.punchangle.z < 0)
 -                      self.punchangle_z = 0;
 +              Send_Notification(NOTIF_ALL, world, MSG_CENTER, APP_TEAM_NUM_4(winner_team, CENTER_ROUND_TEAM_WIN_));
 +              Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(winner_team, INFO_ROUND_TEAM_WIN_));
 +              TeamScore_AddToTeam(winner_team, ST_ONS_CAPS, +1);
        }
 -      else if (self.punchangle.z < 0)
 +      else if(winner_team == -1)
        {
 -              self.punchangle_z = self.punchangle.z + 60 * sys_frametime;
 -              if (self.punchangle.z > 0)
 -                      self.punchangle_z = 0;
 +              Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_TIED);
 +              Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_TIED);
        }
 +      
 +      ons_stalemate = false;
  
 -      self.angles_x = self.punchangle.x;
 -      self.angles_y = self.punchangle.y + self.mangle.y;
 -      self.angles_z = self.punchangle.z;
 -      self.mangle_y = self.mangle.y + 45 * sys_frametime;
 -
 -      self.cp_bob_origin_z = 4 * PI * (1 - cos(self.cp_bob_spd));
 -      self.cp_bob_spd = self.cp_bob_spd + 1.875 * sys_frametime;
 -      if(self.cp_bob_dmg.z > 0)
 -              self.cp_bob_dmg_z = self.cp_bob_dmg.z - 3 * sys_frametime;
 -      else
 -              self.cp_bob_dmg_z = 0;
 -      setorigin(self,self.cp_origin + self.cp_bob_origin + self.cp_bob_dmg);
 -
 -      // damaged fx
 -      if(random() < 0.6 - self.health / self.max_health)
 +      play2all(sprintf("ctf/%s_capture.wav", Static_Team_ColorName_Lower(winner_team)));
 +      
 +      round_handler_Init(7, autocvar_g_onslaught_warmup, autocvar_g_onslaught_round_timelimit);
 +      
 +      FOR_EACH_PLAYER(e)
        {
 -              pointparticles(particleeffectnum("electricity_sparks"), self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1);
 +              e.ons_roundlost = true;
 +              e.player_blocked = true;
  
 -              if(random() > 0.8)
 -                      sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTEN_NORM);
 -              else if (random() > 0.5)
 -                      sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTEN_NORM);
 +              nades_Clear(e);
        }
 +
 +      return 1;
  }
  
 -void onslaught_controlpoint_icon_buildthink()
 +bool Onslaught_CheckPlayers()
  {
 -      entity oself;
 -      float a;
 +      return 1;
 +}
  
 -      self.nextthink = time + sys_frametime;
 +void Onslaught_RoundStart()
 +{
 +      entity tmp_entity;
 +      FOR_EACH_PLAYER(tmp_entity) { tmp_entity.player_blocked = false; }
  
 -      // only do this if there is power
 -      a = onslaught_controlpoint_can_be_linked(self.owner, self.owner.team);
 -      if(!a)
 -              return;
 +      for(tmp_entity = ons_worldcplist; tmp_entity; tmp_entity = tmp_entity.ons_worldcpnext)
 +              tmp_entity.sprite.SendFlags |= 16;
  
 -      self.health = self.health + self.count;
 +      for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
 +              tmp_entity.sprite.SendFlags |= 16;
 +}
  
 -      if (self.health >= self.max_health)
 -      {
 -              self.health = self.max_health;
 -              self.count = autocvar_g_onslaught_cp_regen * sys_frametime; // slow repair rate from now on
 -              self.think = onslaught_controlpoint_icon_think;
 -              sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTEN_NORM);
 -              bprint(Team_ColoredFullName(self.team), " captured ", self.owner.message, " control point\n");
 -              self.owner.iscaptured = true;
  
 -              WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
 -              WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
 +// ================
 +// Bot player logic
 +// ================
  
 -              onslaught_updatelinks();
 +// NOTE: LEGACY CODE, needs to be re-written!
  
 -              // Use targets now (somebody make sure this is in the right place..)
 -              oself = self;
 -              self = self.owner;
 -              activator = self;
 -              SUB_UseTargets ();
 -              self = oself;
 -              self.cp_origin = self.origin;
 -              self.cp_bob_origin = '0 0 0.1';
 -              self.cp_bob_spd = 0;
 +void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
 +{
 +      entity head;
 +      float t, c;
 +      int i;
 +      bool needarmor = false, needweapons = false;
 +
 +      // Needs armor/health?
 +      if(self.health<100)
 +              needarmor = true;
 +
 +      // Needs weapons?
 +      c = 0;
 +      for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
 +      {
 +              // Find weapon
 +              if(self.weapons & WepSet_FromWeapon(i))
 +              if(++c>=4)
 +                      break;
        }
 -      self.alpha = self.health / self.max_health;
 -      // colormod flash when shot
 -      self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
 -      if(self.owner.model != "models/onslaught/controlpoint_pad2.md3")
 -              setmodel(self.owner, "models/onslaught/controlpoint_pad2.md3");
 -      //setsize(self, '-32 -32 0', '32 32 8');
  
 -      if(random() < 0.9 - self.health / self.max_health)
 -              pointparticles(particleeffectnum("rage"), self.origin + 10 * randomvec(), '0 0 -1', 1);
 -}
 +      if(c<4)
 +              needweapons = true;
  
 +      if(!needweapons && !needarmor)
 +              return;
  
 +      ons_debug(strcat(self.netname, " needs weapons ", ftos(needweapons) , "\n"));
 +      ons_debug(strcat(self.netname, " needs armor ", ftos(needarmor) , "\n"));
  
 +      // See what is around
 +      head = findchainfloat(bot_pickup, true);
 +      while (head)
 +      {
 +              // gather health and armor only
 +              if (head.solid)
 +              if ( ((head.health || head.armorvalue) && needarmor) || (head.weapons && needweapons ) )
 +              if (vlen(head.origin - org) < sradius)
 +              {
 +                      t = head.bot_pickupevalfunc(self, head);
 +                      if (t > 0)
 +                              navigation_routerating(head, t * ratingscale, 500);
 +              }
 +              head = head.chain;
 +      }
 +}
  
 -void onslaught_controlpoint_touch()
 +void havocbot_role_ons_setrole(entity bot, int role)
  {
 -      entity e;
 -      float a;
 -      if (!IS_PLAYER(other))
 -              return;
 -      a = onslaught_controlpoint_attackable(self, other.team);
 -      if(a != 2 && a != 4)
 -              return;
 -      // we've verified that this player has a legitimate claim to this point,
 -      // so start building the captured point icon (which only captures this
 -      // point if it successfully builds without being destroyed first)
 -      self.goalentity = e = spawn();
 -      e.classname = "onslaught_controlpoint_icon";
 -      e.owner = self;
 -      e.max_health = autocvar_g_onslaught_cp_health;
 -      e.health = autocvar_g_onslaught_cp_buildhealth;
 -      e.solid = SOLID_BBOX;
 -      e.movetype = MOVETYPE_NONE;
 -      setmodel(e, "models/onslaught/controlpoint_icon.md3");
 -      setsize(e, '-32 -32 -32', '32 32 32');
 -      setorigin(e, self.origin + '0 0 96');
 -      e.takedamage = DAMAGE_AIM;
 -      e.bot_attack = true;
 -      e.event_damage = onslaught_controlpoint_icon_damage;
 -      e.team = other.team;
 -      e.colormap = 1024 + (e.team - 1) * 17;
 -      e.think = onslaught_controlpoint_icon_buildthink;
 -      e.nextthink = time + sys_frametime;
 -      e.count = (e.max_health - e.health) * sys_frametime / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
 -      sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTEN_NORM);
 -      self.team = e.team;
 -      self.colormap = e.colormap;
 -      WaypointSprite_UpdateBuildFinished(self.sprite, time + (e.max_health - e.health) / (e.count / sys_frametime));
 -      onslaught_updatelinks();
 +      ons_debug(strcat(bot.netname," switched to "));
 +      switch(role)
 +      {
 +              case HAVOCBOT_ONS_ROLE_DEFENSE:
 +                      ons_debug("defense");
 +                      bot.havocbot_role = havocbot_role_ons_defense;
 +                      bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_DEFENSE;
 +                      bot.havocbot_role_timeout = 0;
 +                      break;
 +              case HAVOCBOT_ONS_ROLE_ASSISTANT:
 +                      ons_debug("assistant");
 +                      bot.havocbot_role = havocbot_role_ons_assistant;
 +                      bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_ASSISTANT;
 +                      bot.havocbot_role_timeout = 0;
 +                      break;
 +              case HAVOCBOT_ONS_ROLE_OFFENSE:
 +                      ons_debug("offense");
 +                      bot.havocbot_role = havocbot_role_ons_offense;
 +                      bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_OFFENSE;
 +                      bot.havocbot_role_timeout = 0;
 +                      break;
 +      }
 +      ons_debug("\n");
  }
  
 -void onslaught_controlpoint_think()
 +int havocbot_ons_teamcount(entity bot, int role)
  {
 -      self.nextthink = time;
 -      CSQCMODEL_AUTOUPDATE();
 +      int c = 0;
 +      entity head;
 +
 +      FOR_EACH_PLAYER(head)
 +      if(SAME_TEAM(head, self))
 +      if(head.havocbot_role_flags & role)
 +              ++c;
 +
 +      return c;
  }
  
 -void onslaught_controlpoint_reset()
 +void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
  {
 -      if(self.goalentity && self.goalentity != world)
 -              remove(self.goalentity);
 -      self.goalentity = world;
 -      self.team = 0;
 -      self.colormap = 1024;
 -      self.iscaptured = false;
 -      self.islinked = false;
 -      self.isshielded = true;
 -      self.enemy.solid = SOLID_NOT;
 -      self.enemy.colormap = self.colormap;
 -      self.think = onslaught_controlpoint_think;
 -      self.enemy.think = func_null;
 -      self.nextthink = time; // don't like func_null :P
 -      setmodel(self, "models/onslaught/controlpoint_pad.md3");
 -      //setsize(self, '-32 -32 0', '32 32 8');
 +      entity cp, cp1, cp2, best, pl, wp;
 +      float radius, bestvalue;
 +      int c;
 +      bool found;
  
 -      WaypointSprite_UpdateMaxHealth(self.sprite, 0);
 +      // Filter control points
 +      for(cp2 = ons_worldcplist; cp2; cp2 = cp2.ons_worldcpnext)
 +      {
 +              cp2.wpcost = c = 0;
 +              cp2.wpconsidered = false;
  
 -      onslaught_updatelinks();
 +              if(cp2.isshielded)
 +                      continue;
  
 -      activator = self;
 -      SUB_UseTargets(); // to reset the structures, playerspawns etc.
 +              // Ignore owned controlpoints
 +              if(!(cp2.isgenneighbor[self.team] || cp2.iscpneighbor[self.team]))
 +                      continue;
  
 -      CSQCMODEL_AUTOUPDATE();
 +              // Count team mates interested in this control point
 +              // (easier and cleaner than keeping counters per cp and teams)
 +              FOR_EACH_PLAYER(pl)
 +              if(SAME_TEAM(pl, self))
 +              if(pl.havocbot_role_flags & HAVOCBOT_ONS_ROLE_OFFENSE)
 +              if(pl.havocbot_ons_target==cp2)
 +                      ++c;
 +
 +              // NOTE: probably decrease the cost of attackable control points
 +              cp2.wpcost = c;
 +              cp2.wpconsidered = true;
 +      }
 +
 +      // We'll consider only the best case
 +      bestvalue = 99999999999;
 +      cp = world;
 +      for(cp1 = ons_worldcplist; cp1; cp1 = cp1.ons_worldcpnext)
 +      {
 +              if (!cp1.wpconsidered)
 +                      continue;
 +
 +              if(cp1.wpcost<bestvalue)
 +              {
 +                      bestvalue = cp1.wpcost;
 +                      cp = cp1;
 +                      self.havocbot_ons_target = cp1;
 +              }
 +      }
 +
 +      if (!cp)
 +              return;
 +
 +      ons_debug(strcat(self.netname, " chose cp ranked ", ftos(bestvalue), "\n"));
 +
 +      if(cp.goalentity)
 +      {
 +              // Should be attacked
 +              // Rate waypoints near it
 +              found = false;
 +              best = world;
 +              bestvalue = 99999999999;
 +              for(radius=0; radius<1000 && !found; radius+=500)
 +              {
 +                      for(wp=findradius(cp.origin,radius); wp; wp=wp.chain)
 +                      {
 +                              if(!(wp.wpflags & WAYPOINTFLAG_GENERATED))
 +                              if(wp.classname=="waypoint")
 +                              if(checkpvs(wp.origin,cp))
 +                              {
 +                                      found = true;
 +                                      if(wp.cnt<bestvalue)
 +                                      {
 +                                              best = wp;
 +                                              bestvalue = wp.cnt;
 +                                      }
 +                              }
 +                      }
 +              }
 +
 +              if(best)
 +              {
 +                      navigation_routerating(best, ratingscale, 10000);
 +                      best.cnt += 1;
 +
 +                      self.havocbot_attack_time = 0;
 +                      if(checkpvs(self.view_ofs,cp))
 +                      if(checkpvs(self.view_ofs,best))
 +                              self.havocbot_attack_time = time + 2;
 +              }
 +              else
 +              {
 +                      navigation_routerating(cp, ratingscale, 10000);
 +              }
 +              ons_debug(strcat(self.netname, " found an attackable controlpoint at ", vtos(cp.origin) ,"\n"));
 +      }
 +      else
 +      {
 +              // Should be touched
 +              ons_debug(strcat(self.netname, " found a touchable controlpoint at ", vtos(cp.origin) ,"\n"));
 +              found = false;
 +
 +              // Look for auto generated waypoint
 +              if (!bot_waypoints_for_items)
 +              for (wp = findradius(cp.origin,100); wp; wp = wp.chain)
 +              {
 +                      if(wp.classname=="waypoint")
 +                      {
 +                              navigation_routerating(wp, ratingscale, 10000);
 +                              found = true;
 +                      }
 +              }
 +
 +              // Nothing found, rate the controlpoint itself
 +              if (!found)
 +                      navigation_routerating(cp, ratingscale, 10000);
 +      }
  }
  
 -/*QUAKED spawnfunc_onslaught_controlpoint (0 .5 .8) (-32 -32 0) (32 32 128)
 -  Control point. Be sure to give this enough clearance so that the shootable part has room to exist
 +bool havocbot_goalrating_ons_generator_attack(float ratingscale)
 +{
 +      entity g, wp, bestwp;
 +      bool found;
 +      int best;
  
 -  This should link to an spawnfunc_onslaught_controlpoint entity or spawnfunc_onslaught_generator entity.
 +      for(g = ons_worldgeneratorlist; g; g = g.ons_worldgeneratornext)
 +      {
 +              if(SAME_TEAM(g, self) || g.isshielded)
 +                      continue;
  
 -keys:
 -"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
 -"target" - target any entities that are tied to this control point, such as vehicles and buildable structure entities.
 -"message" - name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
 - */
 +              // Should be attacked
 +              // Rate waypoints near it
 +              found = false;
 +              bestwp = world;
 +              best = 99999999999;
  
 -void spawnfunc_onslaught_controlpoint()
 +              for(wp=findradius(g.origin,400); wp; wp=wp.chain)
 +              {
 +                      if(wp.classname=="waypoint")
 +                      if(checkpvs(wp.origin,g))
 +                      {
 +                              found = true;
 +                              if(wp.cnt<best)
 +                              {
 +                                      bestwp = wp;
 +                                      best = wp.cnt;
 +                              }
 +                      }
 +              }
 +
 +              if(bestwp)
 +              {
 +                      ons_debug("waypoints found around generator\n");
 +                      navigation_routerating(bestwp, ratingscale, 10000);
 +                      bestwp.cnt += 1;
 +
 +                      self.havocbot_attack_time = 0;
 +                      if(checkpvs(self.view_ofs,g))
 +                      if(checkpvs(self.view_ofs,bestwp))
 +                              self.havocbot_attack_time = time + 5;
 +
 +                      return true;
 +              }
 +              else
 +              {
 +                      ons_debug("generator found without waypoints around\n");
 +                      // if there aren't waypoints near the generator go straight to it
 +                      navigation_routerating(g, ratingscale, 10000);
 +                      self.havocbot_attack_time = 0;
 +                      return true;
 +              }
 +      }
 +      return false;
 +}
 +
 +void havocbot_role_ons_offense()
  {
 -      //entity e;
 -      if (!g_onslaught)
 +      if(self.deadflag != DEAD_NO)
        {
 -              remove(self);
 +              self.havocbot_attack_time = 0;
 +              havocbot_ons_reset_role(self);
                return;
        }
 -      precache_model("models/onslaught/controlpoint_pad.md3");
 -      precache_model("models/onslaught/controlpoint_pad2.md3");
 -      precache_model("models/onslaught/controlpoint_shield.md3");
 -      precache_model("models/onslaught/controlpoint_icon.md3");
 -      precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
 -      precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
 -      precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
 -      precache_model("models/onslaught/controlpoint_icon_gib1.md3");
 -      precache_model("models/onslaught/controlpoint_icon_gib2.md3");
 -      precache_model("models/onslaught/controlpoint_icon_gib4.md3");
 -      precache_sound("onslaught/controlpoint_build.wav");
 -      precache_sound("onslaught/controlpoint_built.wav");
 -      precache_sound("weapons/grenade_impact.wav");
 -      precache_sound("onslaught/damageblockedbyshield.wav");
 -      precache_sound("onslaught/controlpoint_underattack.wav");
 -      precache_sound("onslaught/ons_spark1.wav");
 -      precache_sound("onslaught/ons_spark2.wav");
  
 -      self.solid = SOLID_BBOX;
 -      self.movetype = MOVETYPE_NONE;
 -      setmodel(self, "models/onslaught/controlpoint_pad.md3");
 -      //setsize(self, '-32 -32 0', '32 32 8');
 -      if(!self.noalign)
 +      // Set the role timeout if necessary
 +      if (!self.havocbot_role_timeout)
 +              self.havocbot_role_timeout = time + 120;
 +
 +      if (time > self.havocbot_role_timeout)
        {
 -              setorigin(self, self.origin + '0 0 20');
 -              droptofloor();
 +              havocbot_ons_reset_role(self);
 +              return;
        }
 -      self.touch = onslaught_controlpoint_touch;
 -      self.team = 0;
 -      self.colormap = 1024;
 -      self.iscaptured = false;
 -      self.islinked = false;
 -      self.isshielded = true;
  
 -      // spawn shield model which indicates whether this can be damaged
 -      self.enemy = spawn();
 -      self.enemy.classname = "onslaught_controlpoint_shield";
 -      self.enemy.solid = SOLID_NOT;
 -      self.enemy.movetype = MOVETYPE_NONE;
 -      self.enemy.effects = EF_ADDITIVE;
 -      setmodel(self.enemy , "models/onslaught/controlpoint_shield.md3");
 +      if(self.havocbot_attack_time>time)
 +              return;
 +
 +      if (self.bot_strategytime < time)
 +      {
 +              navigation_goalrating_start();
 +              havocbot_goalrating_enemyplayers(20000, self.origin, 650);
 +              if(!havocbot_goalrating_ons_generator_attack(20000))
 +                      havocbot_goalrating_ons_controlpoints_attack(20000);
 +              havocbot_goalrating_ons_offenseitems(10000, self.origin, 10000);
 +              navigation_goalrating_end();
 +
 +              self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
 +      }
 +}
 +
 +void havocbot_role_ons_assistant()
 +{
 +      havocbot_ons_reset_role(self);
 +}
 +
 +void havocbot_role_ons_defense()
 +{
 +      havocbot_ons_reset_role(self);
 +}
  
 -      setattachment(self.enemy , self, "");
 -      //setsize(e, '-32 -32 0', '32 32 128');
 +void havocbot_ons_reset_role(entity bot)
 +{
 +      entity head;
 +      int c = 0;
  
 -      //setorigin(e, self.origin);
 -      self.enemy.colormap = self.colormap;
 +      if(self.deadflag != DEAD_NO)
 +              return;
  
 -      waypoint_spawnforitem(self);
 +      bot.havocbot_ons_target = world;
  
 -      self.think = onslaught_controlpoint_think;
 -      self.nextthink = time;
 +      // TODO: Defend control points or generator if necessary
  
 -      WaypointSprite_SpawnFixed(string_null, self.origin + '0 0 128', self, sprite, RADARICON_NONE, '0 0 0');
 -      WaypointSprite_UpdateRule(self.sprite, NUM_TEAM_2, SPRITERULE_TEAMPLAY);
 +      // if there is only me on the team switch to offense
 +      c = 0;
 +      FOR_EACH_PLAYER(head)
 +      if(SAME_TEAM(head, self))
 +              ++c;
  
 -      onslaught_updatelinks();
 +      if(c==1)
 +      {
 +              havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
 +              return;
 +      }
  
 -      self.reset = onslaught_controlpoint_reset;
 +      havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
 +}
  
 -      CSQCMODEL_AUTOINIT();
 +
 +/*
 + * Find control point or generator owned by the same team self which is nearest to pos
 + * if max_dist is positive, only control points within this range will be considered
 + */
 +entity ons_Nearest_ControlPoint(vector pos, float max_dist)
 +{
 +      entity tmp_entity, closest_target = world;
 +      tmp_entity = findchain(classname, "onslaught_controlpoint");
 +      while(tmp_entity)
 +      {
 +              if(SAME_TEAM(tmp_entity, self))
 +              if(tmp_entity.iscaptured)
 +              if(max_dist <= 0 || vlen(tmp_entity.origin - pos) <= max_dist)
 +              if(vlen(tmp_entity.origin - pos) <= vlen(closest_target.origin - pos) || closest_target == world)
 +                      closest_target = tmp_entity;
 +              tmp_entity = tmp_entity.chain;
 +      }
 +      tmp_entity = findchain(classname, "onslaught_generator");
 +      while(tmp_entity)
 +      {
 +              if(SAME_TEAM(tmp_entity, self))
 +              if(max_dist <= 0 || vlen(tmp_entity.origin - pos) < max_dist)
 +              if(vlen(tmp_entity.origin - pos) <= vlen(closest_target.origin - pos) || closest_target == world)
 +                      closest_target = tmp_entity;
 +              tmp_entity = tmp_entity.chain;
 +      }
 +      
 +      return closest_target;
  }
  
 -float onslaught_link_send(entity to, float sendflags)
 +/*
 + * Find control point or generator owned by the same team self which is nearest to pos
 + * if max_dist is positive, only control points within this range will be considered
 + * This function only check distances on the XY plane, disregarding Z
 + */
 +entity ons_Nearest_ControlPoint_2D(vector pos, float max_dist)
  {
 -      WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
 -      WriteByte(MSG_ENTITY, sendflags);
 -      if(sendflags & 1)
 +      entity tmp_entity, closest_target = world;
 +      vector delta;
 +      float smallest_distance = 0, distance;
 +      
 +      tmp_entity = findchain(classname, "onslaught_controlpoint");
 +      while(tmp_entity)
 +      {
 +              delta = tmp_entity.origin - pos;
 +              delta_z = 0;
 +              distance = vlen(delta);
 +              
 +              if(SAME_TEAM(tmp_entity, self))
 +              if(tmp_entity.iscaptured)
 +              if(max_dist <= 0 || distance <= max_dist)
 +              if(closest_target == world || distance <= smallest_distance )
 +              {
 +                      closest_target = tmp_entity;
 +                      smallest_distance = distance;
 +              }
 +              
 +              tmp_entity = tmp_entity.chain;
 +      }
 +      tmp_entity = findchain(classname, "onslaught_generator");
 +      while(tmp_entity)
 +      {
 +              delta = tmp_entity.origin - pos;
 +              delta_z = 0;
 +              distance = vlen(delta);
 +              
 +              if(SAME_TEAM(tmp_entity, self))
 +              if(max_dist <= 0 || distance <= max_dist)
 +              if(closest_target == world || distance <= smallest_distance )
 +              {
 +                      closest_target = tmp_entity;
 +                      smallest_distance = distance;
 +              }
 +              
 +              tmp_entity = tmp_entity.chain;
 +      }
 +      
 +      return closest_target;
 +}
 +/**
 + * find the number of control points and generators in the same team as self
 + */
 +int ons_Count_SelfControlPoints()
 +{
 +      entity tmp_entity;
 +      tmp_entity = findchain(classname, "onslaught_controlpoint");
 +      int n = 0;
 +      while(tmp_entity)
        {
 -              WriteCoord(MSG_ENTITY, self.goalentity.origin.x);
 -              WriteCoord(MSG_ENTITY, self.goalentity.origin.y);
 -              WriteCoord(MSG_ENTITY, self.goalentity.origin.z);
 +              if(SAME_TEAM(tmp_entity, self))
 +              if(tmp_entity.iscaptured)
 +                      n++;
 +              tmp_entity = tmp_entity.chain;
        }
 -      if(sendflags & 2)
 +      tmp_entity = findchain(classname, "onslaught_generator");
 +      while(tmp_entity)
        {
 -              WriteCoord(MSG_ENTITY, self.enemy.origin.x);
 -              WriteCoord(MSG_ENTITY, self.enemy.origin.y);
 -              WriteCoord(MSG_ENTITY, self.enemy.origin.z);
 +              if(SAME_TEAM(tmp_entity, self))
 +                      n++;
 +              tmp_entity = tmp_entity.chain;
        }
 -      if(sendflags & 4)
 +      return n;
 +}
 +
 +/**
 + * Teleport player to a random position near tele_target
 + * if tele_effects is true, teleport sound+particles are created
 + * return false on failure
 + */
 +bool ons_Teleport(entity player, entity tele_target, float range, bool tele_effects)
 +{
 +      if ( !tele_target )
 +              return false;
 +      
 +      int i;
 +      vector loc;
 +      float theta;
 +      for(i = 0; i < 16; ++i)
 +      {
 +              theta = random() * 2 * M_PI;
 +              loc_y = sin(theta);
 +              loc_x = cos(theta);
 +              loc_z = 0;
 +              loc *= random() * range;
 +              
 +              loc += tele_target.origin + '0 0 128';
 +              
 +              tracebox(loc, PL_MIN, PL_MAX, loc, MOVE_NORMAL, player);
 +              if(trace_fraction == 1.0 && !trace_startsolid)
 +              {
 +                      traceline(tele_target.origin, loc, MOVE_NOMONSTERS, tele_target); // double check to make sure we're not spawning outside the world
 +                      if(trace_fraction == 1.0 && !trace_startsolid)
 +                      {
 +                              if ( tele_effects )
 +                              {
 +                                      pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1);
 +                                      sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
 +                              }
 +                              setorigin(player, loc);
 +                              player.angles = '0 1 0' * ( theta * RAD2DEG + 180 );
 +                              makevectors(player.angles);
 +                              player.fixangle = true;
 +                              player.teleport_antispam = time + autocvar_g_onslaught_teleport_wait;
 +
 +                              if ( tele_effects )
 +                                      pointparticles(particleeffectnum("teleport"), player.origin + v_forward * 32, '0 0 0', 1);
 +                              return true;
 +                      }
 +              }
 +      }
 +      
 +      return false;
 +}
 +
 +// ==============
 +// Hook Functions
 +// ==============
 +
 +MUTATOR_HOOKFUNCTION(ons_ResetMap)
 +{
 +      FOR_EACH_PLAYER(self)
        {
 -              WriteByte(MSG_ENTITY, self.clientcolors); // which is goalentity's color + enemy's color * 16
 +              self.ons_roundlost = false;
 +              self.ons_deathloc = '0 0 0';
 +              PutClientInServer();
        }
 -      return true;
 +      return false;
  }
  
 -void onslaught_link_checkupdate()
 +MUTATOR_HOOKFUNCTION(ons_RemovePlayer)
  {
 -      // TODO check if the two sides have moved (currently they won't move anyway)
 -      float redpower, bluepower;
 +      self.ons_deathloc = '0 0 0';
 +      return false;
 +}
  
 -      redpower = bluepower = 0;
 -      if(self.goalentity.islinked)
 +MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
 +{
 +      if(!round_handler_IsRoundStarted())
 +      {
 +              self.player_blocked = true;
 +              return false;
 +      }
 +      
 +      entity l;
 +      for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
        {
 -              if(self.goalentity.team == NUM_TEAM_1)
 -                      redpower = 1;
 -              else if(self.goalentity.team == NUM_TEAM_2)
 -                      bluepower = 1;
 +              l.sprite.SendFlags |= 16;
        }
 -      if(self.enemy.islinked)
 +      for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
        {
 -              if(self.enemy.team == NUM_TEAM_1)
 -                      redpower = 2;
 -              else if(self.enemy.team == NUM_TEAM_2)
 -                      bluepower = 2;
 +              l.sprite.SendFlags |= 16;
        }
  
 -      float cc;
 -      if(redpower == 1 && bluepower == 2)
 -              cc = (NUM_TEAM_1 - 1) * 0x01 + (NUM_TEAM_2 - 1) * 0x10;
 -      else if(redpower == 2 && bluepower == 1)
 -              cc = (NUM_TEAM_1 - 1) * 0x10 + (NUM_TEAM_2 - 1) * 0x01;
 -      else if(redpower)
 -              cc = (NUM_TEAM_1 - 1) * 0x11;
 -      else if(bluepower)
 -              cc = (NUM_TEAM_2 - 1) * 0x11;
 -      else
 -              cc = 0;
 +      if(ons_stalemate) { Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT); }
  
 -      //print(etos(self), " rp=", ftos(redpower), " bp=", ftos(bluepower), " ");
 -      //print("cc=", ftos(cc), "\n");
 +      if ( autocvar_g_onslaught_spawn_choose )
 +      if ( self.ons_spawn_by )
 +      if ( ons_Teleport(self,self.ons_spawn_by,autocvar_g_onslaught_teleport_radius,false) )
 +      {
 +              self.ons_spawn_by = world;
 +              return false;
 +      }
 +      
 +      if(autocvar_g_onslaught_spawn_at_controlpoints)
 +      if(random() <= autocvar_g_onslaught_spawn_at_controlpoints_chance)
 +      {
 +              float random_target = autocvar_g_onslaught_spawn_at_controlpoints_random;
 +              entity tmp_entity, closest_target = world;
 +              vector spawn_loc = self.ons_deathloc;
 +              
 +              // new joining player or round reset, don't bother checking
 +              if(spawn_loc == '0 0 0') { return false; }
  
 -      if(cc != self.clientcolors)
 +              if(random_target) { RandomSelection_Init(); }
 +
 +              for(tmp_entity = ons_worldcplist; tmp_entity; tmp_entity = tmp_entity.ons_worldcpnext)
 +              {
 +                      if(SAME_TEAM(tmp_entity, self))
 +                      if(random_target)
 +                              RandomSelection_Add(tmp_entity, 0, string_null, 1, 1);
 +                      else if(vlen(tmp_entity.origin - spawn_loc) <= vlen(closest_target.origin - spawn_loc) || closest_target == world)
 +                              closest_target = tmp_entity;
 +              }
 +              
 +              if(random_target) { closest_target = RandomSelection_chosen_ent; }
 +              
 +              if(closest_target)
 +              {
 +                      float i;
 +                      vector loc;
 +                      for(i = 0; i < 10; ++i)
 +                      {
 +                              loc = closest_target.origin + '0 0 96';
 +                              loc += ('0 1 0' * random()) * 128;
 +                              tracebox(loc, PL_MIN, PL_MAX, loc, MOVE_NORMAL, self);
 +                              if(trace_fraction == 1.0 && !trace_startsolid)
 +                              {
 +                                      traceline(closest_target.origin, loc, MOVE_NOMONSTERS, closest_target); // double check to make sure we're not spawning outside the world
 +                                      if(trace_fraction == 1.0 && !trace_startsolid)
 +                                      {
 +                                              setorigin(self, loc);
 +                                              self.angles = normalize(loc - closest_target.origin) * RAD2DEG;
 +                                              return false;
 +                                      }
 +                              }
 +                      }
 +              }
 +      }
 +      
 +      if(autocvar_g_onslaught_spawn_at_generator)
 +      if(random() <= autocvar_g_onslaught_spawn_at_generator_chance)
        {
 -              self.clientcolors = cc;
 -              self.SendFlags |= 4;
 +              float random_target = autocvar_g_onslaught_spawn_at_generator_random;
 +              entity tmp_entity, closest_target = world;
 +              vector spawn_loc = self.ons_deathloc;
 +              
 +              // new joining player or round reset, don't bother checking
 +              if(spawn_loc == '0 0 0') { return false; }
 +              
 +              if(random_target) { RandomSelection_Init(); }
 +
 +              for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
 +              {
 +                      if(random_target)
 +                              RandomSelection_Add(tmp_entity, 0, string_null, 1, 1);
 +                      else
 +                      {
 +                              if(SAME_TEAM(tmp_entity, self))
 +                              if(vlen(tmp_entity.origin - spawn_loc) <= vlen(closest_target.origin - spawn_loc) || closest_target == world)
 +                                      closest_target = tmp_entity;
 +                      }
 +              }
 +              
 +              if(random_target) { closest_target = RandomSelection_chosen_ent; }
 +              
 +              if(closest_target)
 +              {
 +                      float i;
 +                      vector loc;
 +                      for(i = 0; i < 10; ++i)
 +                      {
 +                              loc = closest_target.origin + '0 0 128';
 +                              loc += ('0 1 0' * random()) * 256;
 +                              tracebox(loc, PL_MIN, PL_MAX, loc, MOVE_NORMAL, self);
 +                              if(trace_fraction == 1.0 && !trace_startsolid)
 +                              {
 +                                      traceline(closest_target.origin, loc, MOVE_NOMONSTERS, closest_target); // double check to make sure we're not spawning outside the world
 +                                      if(trace_fraction == 1.0 && !trace_startsolid)
 +                                      {
 +                                              setorigin(self, loc);
 +                                              self.angles = normalize(loc - closest_target.origin) * RAD2DEG;
 +                                              return false;
 +                                      }
 +                              }
 +                      }
 +              }
        }
  
 -      self.nextthink = time;
 +    return false;
  }
  
 -void onslaught_link_delayed()
 +MUTATOR_HOOKFUNCTION(ons_PlayerDies)
  {
 -      self.goalentity = find(world, targetname, self.target);
 -      self.enemy = find(world, targetname, self.target2);
 -      if (!self.goalentity)
 -              objerror("can not find target\n");
 -      if (!self.enemy)
 -              objerror("can not find target2\n");
 -      dprint(etos(self.goalentity), " linked with ", etos(self.enemy), "\n");
 -      self.SendFlags |= 3;
 -      self.think = onslaught_link_checkupdate;
 -      self.nextthink = time;
 +      frag_target.ons_deathloc = frag_target.origin;
 +      entity l;
 +      for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
 +      {
 +              l.sprite.SendFlags |= 16;
 +      }
 +      for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
 +      {
 +              l.sprite.SendFlags |= 16;
 +      }
 +      
 +      if ( autocvar_g_onslaught_spawn_choose )
 +      if ( ons_Count_SelfControlPoints() > 1 )
 +              stuffcmd(self, "qc_cmd_cl hud clickradar\n");
 +      
 +      return false;
  }
  
 -/*QUAKED spawnfunc_onslaught_link (0 .5 .8) (-16 -16 -16) (16 16 16)
 -  Link between control points.
 +MUTATOR_HOOKFUNCTION(ons_MonsterThink)
 +{
 +      entity e = find(world, targetname, self.target);
 +      if (e != world)
 +              self.team = e.team;
  
 -  This entity targets two different spawnfunc_onslaught_controlpoint or spawnfunc_onslaught_generator entities, and suppresses shielding on both if they are owned by different teams.
 +      return false;
 +}
  
 -keys:
 -"target" - first control point.
 -"target2" - second control point.
 - */
 -void spawnfunc_onslaught_link()
 +void ons_MonsterSpawn_Delayed()
  {
 -      if (!g_onslaught)
 +      entity e, own = self.owner;
 +      
 +      if(!own) { remove(self); return; }
 +      
 +      if(own.targetname)
        {
 -              remove(self);
 -              return;
 +              e = find(world, target, own.targetname);
 +              if(e != world)
 +              {
 +                      own.team = e.team;
 +                      
 +                      activator = e;
 +                      own.use();
 +              }
        }
 -      if (self.target == "" || self.target2 == "")
 -              objerror("target and target2 must be set\n");
 -      InitializeEntity(self, onslaught_link_delayed, INITPRIO_FINDTARGET);
 -      Net_LinkEntity(self, false, 0, onslaught_link_send);
 +      
 +      remove(self);
  }
  
 -MUTATOR_HOOKFUNCTION(ons_BuildMutatorsString)
 +MUTATOR_HOOKFUNCTION(ons_MonsterSpawn)
  {
 -      ret_string = strcat(ret_string, ":ONS");
 -      return 0;
 +      entity e = spawn();
 +      e.owner = self;
 +      InitializeEntity(e, ons_MonsterSpawn_Delayed, INITPRIO_FINDTARGET);
 +
 +      return false;
  }
  
 -MUTATOR_HOOKFUNCTION(ons_BuildMutatorsPrettyString)
 +void ons_TurretSpawn_Delayed()
  {
 -      ret_string = strcat(ret_string, ", Onslaught");
 -      return 0;
 +      entity e, own = self.owner;
 +
 +      if(!own) { remove(self); return; }
 +
 +      if(own.targetname)
 +      {
 +              e = find(world, target, own.targetname);
 +              if(e != world)
 +              {
 +                      own.team = e.team;
 +                      own.active = ACTIVE_NOT;
 +                      
 +                      activator = e;
 +                      own.use();
 +              }
 +      }
 +
 +      remove(self);
  }
  
 -MUTATOR_HOOKFUNCTION(ons_Spawn_Score)
 +MUTATOR_HOOKFUNCTION(ons_TurretSpawn)
  {
 +      entity e = spawn();
 +      e.owner = self;
 +      InitializeEntity(e, ons_TurretSpawn_Delayed, INITPRIO_FINDTARGET);
  
 -    /*
 -    float _neer_home = (random() > 0.5 ? true : false);
 +      return false;
 +}
  
 -      RandomSelection_Init();
 +MUTATOR_HOOKFUNCTION(ons_BotRoles)
 +{
 +      havocbot_ons_reset_role(self);
 +      return true;
 +}
  
 -      if(self.team == NUM_TEAM_1)
 -        RandomSelection_Add(ons_red_generator, 0, string_null, 1, 1);
 +MUTATOR_HOOKFUNCTION(ons_GetTeamCount)
 +{
 +      // onslaught is special
 +      entity tmp_entity;
 +      for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
 +      {
 +              switch(tmp_entity.team)
 +              {
 +                      case NUM_TEAM_1: c1 = 0; break;
 +                      case NUM_TEAM_2: c2 = 0; break;
 +                      case NUM_TEAM_3: c3 = 0; break;
 +                      case NUM_TEAM_4: c4 = 0; break;
 +              }
 +      }
  
 -      if(self.team == NUM_TEAM_2)
 -        RandomSelection_Add(ons_blue_generator, 0, string_null, 1, 1);
 +      return true;
 +}
  
 -      entity _cp = findchain(classname, "onslaught_controlpoint"):
 -      while _cp;
 -      {
 -          if(_cp.team == self.team)
 -            RandomSelection_Add(_cp, 0, string_null, 1, 1);
 +MUTATOR_HOOKFUNCTION(ons_SpectateCopy)
 +{
 +      self.ons_roundlost = other.ons_roundlost; // make spectators see it too
 +      return false;
 +}
  
 -              _cp = _cp.chain;
 +MUTATOR_HOOKFUNCTION(ons_SV_ParseClientCommand)
 +{
 +      if(MUTATOR_RETURNVALUE) // command was already handled?
 +              return false;
 +
 +      if ( cmd_name == "ons_spawn" )
 +      {
 +              vector pos = self.origin;
 +              if(cmd_argc > 1)
 +                      pos_x = stof(argv(1));
 +              if(cmd_argc > 2)
 +                      pos_y = stof(argv(2));
 +              if(cmd_argc > 3)
 +                      pos_z = stof(argv(3));
 +              
 +              if ( IS_PLAYER(self) )
 +              {
 +                      if ( !self.frozen )
 +                      {
 +                              entity source_point = ons_Nearest_ControlPoint(self.origin, autocvar_g_onslaught_teleport_radius);
 +                              
 +                              if ( !source_point && self.health > 0 )
 +                              {
 +                                      sprint(self, "\nYou need to be next to a control point\n");
 +                                      return 1;
 +                              }
 +                              
 +                              
 +                              entity closest_target = ons_Nearest_ControlPoint_2D(pos, autocvar_g_onslaught_click_radius);
 +                      
 +                              if ( closest_target == world )
 +                              {
 +                                      sprint(self, "\nNo control point found\n");
 +                                      return 1;
 +                              }
 +                              
 +                              if ( self.health <= 0 )
 +                              {
 +                                      self.ons_spawn_by = closest_target;
 +                                      self.respawn_flags = self.respawn_flags | RESPAWN_FORCE;
 +                              }
 +                              else
 +                              {
 +                                      if ( source_point == closest_target )
 +                                      {
 +                                              sprint(self, "\nTeleporting to the same point\n");
 +                                              return 1;
 +                                      }
 +                                      
 +                                      if ( !ons_Teleport(self,closest_target,autocvar_g_onslaught_teleport_radius,true) )
 +                                              sprint(self, "\nUnable to teleport there\n");
 +                              }
 +                              
 +                              return 1;
 +                      }
 +                      
 +                      sprint(self, "\nNo teleportation for you\n");
 +              }
 +              
 +              return 1;
        }
 +      return 0;
 +}
  
 -      if(RandomSelection_chosen_ent)
 +MUTATOR_HOOKFUNCTION(ons_PlayerUseKey)
 +{
 +      if(MUTATOR_RETURNVALUE || gameover) { return false; }
 +      
 +      if((time > self.teleport_antispam) && (self.deadflag == DEAD_NO) && !self.vehicle)
        {
 -              self.tur_head = RandomSelection_chosen_ent;
 -              spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_FOUND;
 +              entity source_point = ons_Nearest_ControlPoint(self.origin, autocvar_g_onslaught_teleport_radius);
 +              if ( source_point )
 +              {
 +                      stuffcmd(self, "qc_cmd_cl hud clickradar\n");
 +                      return true;
 +              }
        }
 -      else if(self.team == spawn_spot.team)
 -              spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM; // prefer same team, if we can't find a spawn near teammate
 +      
 +      return false;
 +}
  
 -    */
 +// ==========
 +// Spawnfuncs
 +// ==========
  
 -      return 0;
 -}
 +/*QUAKED spawnfunc_onslaught_link (0 .5 .8) (-16 -16 -16) (16 16 16)
 +  Link between control points.
  
 -MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
 +  This entity targets two different spawnfunc_onslaught_controlpoint or spawnfunc_onslaught_generator entities, and suppresses shielding on both if they are owned by different teams.
 +
 +keys:
 +"target" - first control point.
 +"target2" - second control point.
 + */
 +void spawnfunc_onslaught_link()
  {
 -    if(!autocvar_g_onslaught_spawn_at_controlpoints)
 -        return 0;
 +      if(!g_onslaught) { remove(self); return; }
 +
 +      if (self.target == "" || self.target2 == "")
 +              objerror("target and target2 must be set\n");
  
 -    if(random() < 0.5)  // 50/50 chane to use default spawnsystem.
 -        return 0;
 +      self.ons_worldlinknext = ons_worldlinklist; // link into ons_worldlinklist
 +      ons_worldlinklist = self;
  
 -    float _close_to_home = ((random() > 0.5) ? true : false);
 -    entity _best = world, _trg_gen = world;
 -    float _score, _best_score = MAX_SHOT_DISTANCE;
 +      InitializeEntity(self, ons_DelayedLinkSetup, INITPRIO_FINDTARGET);
 +      Net_LinkEntity(self, false, 0, ons_Link_Send);
 +}
  
 -      RandomSelection_Init();
 +/*QUAKED spawnfunc_onslaught_controlpoint (0 .5 .8) (-32 -32 0) (32 32 128)
 +  Control point. Be sure to give this enough clearance so that the shootable part has room to exist
  
 -      if(self.team == NUM_TEAM_1)
 -      {
 -          if(!_close_to_home)
 -            _trg_gen = ons_blue_generator;
 -        else
 -            _trg_gen  = ons_red_generator;
 -      }
 +  This should link to an spawnfunc_onslaught_controlpoint entity or spawnfunc_onslaught_generator entity.
  
 -      if(self.team == NUM_TEAM_2)
 -      {
 -          if(_close_to_home)
 -            _trg_gen = ons_blue_generator;
 -        else
 -            _trg_gen  = ons_red_generator;
 -      }
 +keys:
 +"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
 +"target" - target any entities that are tied to this control point, such as vehicles and buildable structure entities.
 +"message" - name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
 + */
  
 -      entity _cp = findchain(classname, "onslaught_controlpoint");
 -      while(_cp)
 -      {
 -          if(_cp.team == self.team)
 -        {
 -            _score = vlen(_trg_gen.origin - _cp.origin);
 -            if(_score < _best_score)
 -            {
 -                _best = _cp;
 -                _best_score = _score;
 -            }
 -        }
 -              _cp = _cp.chain;
 -      }
 +void spawnfunc_onslaught_controlpoint()
 +{
 +      if(!g_onslaught) { remove(self); return; }
 +      
 +      ons_ControlPoint_Setup(self);
 +}
  
 -    vector _loc;
 -    float i;
 -    if(_best)
 -    {
 -        for(i = 0; i < 10; ++i)
 -        {
 -            _loc = _best.origin + '0 0 96';
 -            _loc += ('0 1 0' * random()) * 128;
 -            tracebox(_loc, PL_MIN, PL_MAX, _loc, MOVE_NORMAL, self);
 -            if(trace_fraction == 1.0 && !trace_startsolid)
 -            {
 -                setorigin(self, _loc);
 -                self.angles = normalize(_loc - _best.origin) * RAD2DEG;
 -                return 0;
 -            }
 -        }
 -    }
 -    else
 -    {
 -        if(!autocvar_g_onslaught_spawn_at_generator)
 -            return 0;
 +/*QUAKED spawnfunc_onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
 +  Base generator.
  
 -        _trg_gen = ((self.team == NUM_TEAM_1) ? ons_red_generator : ons_blue_generator);
 +  spawnfunc_onslaught_link entities can target this.
  
 -        for(i = 0; i < 10; ++i)
 -        {
 -            _loc = _trg_gen.origin + '0 0 96';
 -            _loc += ('0 1 0' * random()) * 128;
 -            tracebox(_loc, PL_MIN, PL_MAX, _loc, MOVE_NORMAL, self);
 -            if(trace_fraction == 1.0 && !trace_startsolid)
 -            {
 -                setorigin(self, _loc);
 -                self.angles = normalize(_loc - _trg_gen.origin) * RAD2DEG;
 -                return 0;
 -            }
 -        }
 -    }
 +keys:
 +"team" - team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
 +"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
 + */
 +void spawnfunc_onslaught_generator()
 +{
 +      if(!g_onslaught) { remove(self); return; }
 +      if(!self.team) { objerror("team must be set"); }
  
 -    return 0;
 +      ons_GeneratorSetup(self);
  }
  
 -MUTATOR_HOOKFUNCTION(ons_MonsterThink)
 +
 +// scoreboard setup
 +void ons_ScoreRules()
  {
 -      entity e = find(world, targetname, self.target);
 -      if (e != world)
 -              self.team = e.team;
 +      CheckAllowedTeams(world);
 +      ScoreRules_basics(((c4>=0) ? 4 : (c3>=0) ? 3 : 2), SFL_SORT_PRIO_PRIMARY, 0, true);
 +      ScoreInfo_SetLabel_TeamScore  (ST_ONS_CAPS,     "destroyed", SFL_SORT_PRIO_PRIMARY);
 +      ScoreInfo_SetLabel_PlayerScore(SP_ONS_CAPS,     "caps",      SFL_SORT_PRIO_SECONDARY);
 +      ScoreInfo_SetLabel_PlayerScore(SP_ONS_TAKES,    "takes",     0);
 +      ScoreRules_basics_end();
 +}
  
 -      return false;
 +void ons_DelayedInit() // Do this check with a delay so we can wait for teams to be set up
 +{
 +      ons_ScoreRules();
 +      
 +      round_handler_Spawn(Onslaught_CheckPlayers, Onslaught_CheckWinner, Onslaught_RoundStart);
 +      round_handler_Init(5, autocvar_g_onslaught_warmup, autocvar_g_onslaught_round_timelimit);
  }
  
 -MUTATOR_HOOKFUNCTION(ons_MonsterSpawn)
 +void ons_Initialize()
  {
 -      entity e, ee = world;
 +      precache_sound("ctf/red_capture.wav");
 +      precache_sound("ctf/blue_capture.wav");
 +      precache_sound("ctf/yellow_capture.wav");
 +      precache_sound("ctf/pink_capture.wav");
  
 -      if(self.targetname)
 -      {
 -              e = find(world,target,self.targetname);
 -              if(e != world)
 -              {
 -                      self.team = e.team;
 -                      ee = e;
 -              }
 -      }
 +      ons_captureshield_force = autocvar_g_onslaught_shield_force;
  
 -      if(ee)
 -      {
 -        activator = ee;
 -        self.use();
 -    }
 +      addstat(STAT_ROUNDLOST, AS_INT, ons_roundlost);
  
 -      return false;
 +      InitializeEntity(world, ons_DelayedInit, INITPRIO_GAMETYPE);
  }
  
  MUTATOR_DEFINITION(gamemode_onslaught)
  {
 -      MUTATOR_HOOK(BuildMutatorsPrettyString, ons_BuildMutatorsPrettyString, CBC_ORDER_ANY);
 -      MUTATOR_HOOK(BuildMutatorsString, ons_BuildMutatorsString, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(reset_map_global, ons_ResetMap, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(MakePlayerObserver, ons_RemovePlayer, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(ClientDisconnect, ons_RemovePlayer, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerSpawn, ons_PlayerSpawn, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerDies, ons_PlayerDies, CBC_ORDER_ANY);
        MUTATOR_HOOK(MonsterMove, ons_MonsterThink, CBC_ORDER_ANY);
        MUTATOR_HOOK(MonsterSpawn, ons_MonsterSpawn, CBC_ORDER_ANY);
 -      //MUTATOR_HOOK(Spawn_Score, ons_Spawn_Score, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(TurretSpawn, ons_TurretSpawn, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(HavocBot_ChooseRole, ons_BotRoles, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(GetTeamCount, ons_GetTeamCount, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(SpectateCopy, ons_SpectateCopy, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(SV_ParseClientCommand, ons_SV_ParseClientCommand, CBC_ORDER_ANY);
 +      MUTATOR_HOOK(PlayerUseKey, ons_PlayerUseKey, CBC_ORDER_ANY);
  
        MUTATOR_ONADD
        {
                if(time > 1) // game loads at time 1
                        error("This is a game type and it cannot be added at runtime.");
 +              ons_Initialize();
 +      }
 +
 +      MUTATOR_ONROLLBACK_OR_REMOVE
 +      {
 +              // we actually cannot roll back ons_Initialize here
 +              // BUT: we don't need to! If this gets called, adding always
 +              // succeeds.
        }
  
        MUTATOR_ONREMOVE
                return -1;
        }
  
 -      return 0;
 +      return false;
  }
index 7cebb172da075349dfc926d01e69d13e48e85672,0000000000000000000000000000000000000000..c6c3d18145d4273d743d66bb02497f893c4ebf78
mode 100644,000000..100644
--- /dev/null
@@@ -1,93 -1,0 +1,93 @@@
- #define CPGEN_SPAWN_OFFSET ('0 0 1' * (PL_MAX_z - 13))
 +// these are needed since mutators are compiled last
 +
 +#ifdef SVQC
 +
 +.entity ons_toucher; // player who touched the control point
 +
 +// control point / generator constants
 +const float ONS_CP_THINKRATE = 0.2;
 +const float GEN_THINKRATE = 1;
++#define CPGEN_SPAWN_OFFSET ('0 0 1' * (PL_MAX_CONST.z - 13))
 +const vector CPGEN_WAYPOINT_OFFSET = ('0 0 128');
 +const vector CPICON_OFFSET = ('0 0 96');
 +
 +// list of generators on the map
 +entity ons_worldgeneratorlist;
 +.entity ons_worldgeneratornext;
 +.entity ons_stalegeneratornext;
 +
 +// list of control points on the map
 +entity ons_worldcplist;
 +.entity ons_worldcpnext;
 +.entity ons_stalecpnext;
 +
 +// list of links on the map
 +entity ons_worldlinklist;
 +.entity ons_worldlinknext;
 +.entity ons_stalelinknext;
 +
 +// definitions
 +.entity sprite;
 +.string target2;
 +.int iscaptured;
 +.int islinked;
 +.int isshielded;
 +.float lasthealth;
 +.int lastteam;
 +.int lastshielded;
 +.int lastcaptured;
 +
 +.bool waslinked;
 +
 +bool ons_stalemate;
 +
 +.float teleport_antispam;
 +
 +.bool ons_roundlost;
 +
 +// waypoint sprites
 +.entity bot_basewaypoint; // generator waypointsprite
 +
 +.bool isgenneighbor[17];
 +.bool iscpneighbor[17];
 +float ons_notification_time[17];
 +
 +.float ons_overtime_damagedelay;
 +
 +.vector ons_deathloc;
 +
 +.entity ons_spawn_by;
 +
 +// declarations for functions used outside gamemode_onslaught.qc
 +void ons_Generator_UpdateSprite(entity e);
 +void ons_ControlPoint_UpdateSprite(entity e);
 +bool ons_ControlPoint_Attackable(entity cp, int teamnumber);
 +
 +// CaptureShield: Prevent capturing or destroying control point/generator if it is not available yet
 +float ons_captureshield_force; // push force of the shield
 +
 +// bot player logic
 +const int HAVOCBOT_ONS_ROLE_NONE              = 0;
 +const int HAVOCBOT_ONS_ROLE_DEFENSE   = 2;
 +const int HAVOCBOT_ONS_ROLE_ASSISTANT         = 4;
 +const int HAVOCBOT_ONS_ROLE_OFFENSE   = 8;
 +
 +.entity havocbot_ons_target;
 +
 +.int havocbot_role_flags;
 +.float havocbot_attack_time;
 +
 +void havocbot_role_ons_defense();
 +void havocbot_role_ons_offense();
 +void havocbot_role_ons_assistant();
 +
 +void havocbot_ons_reset_role(entity bot);
 +void havocbot_goalrating_items(float ratingscale, vector org, float sradius);
 +void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradius);
 +
 +// score rule declarations
 +const int ST_ONS_CAPS = 1;
 +const int SP_ONS_CAPS = 4;
 +const int SP_ONS_TAKES = 6;
 +
 +#endif
diff --combined qcsrc/server/progs.src
index a496de32cb66d447fb3437504cb42efc9965528b,ab87642aaa5843e6f9b05150b6f80aa0ec198ab0..12a4f81820f7ace88dc8cd5f62325eb9ec4d403a
@@@ -8,73 -8,69 +8,70 @@@ sys-post.q
  
  anticheat.qc
  antilag.qc
- // assault.qc
  campaign.qc
  cheats.qc
  cl_client.qc
  cl_impulse.qc
- cl_physics.qc
  cl_player.qc
 +controlpoint.qc
  csqceffects.qc
- // ctf.qc
- // domination.qc
  ent_cs.qc
- func_breakable.qc
  g_casings.qc
  g_damage.qc
  g_hook.qc
+ // g_lights.qc // TODO: was never used
  g_models.qc
  g_subs.qc
  g_tetris.qc
- g_triggers.qc
  g_violence.qc
  g_world.qc
 +generator.qc
  ipban.qc
  item_key.qc
  mapvoting.qc
  miscfunctions.qc
- // mode_onslaught.qc
  movelib.qc
- // nexball.qc
+ // pathlib.qc // TODO: was never used. Seems to duplicate `pathlib/`
  playerdemo.qc
  portals.qc
  race.qc
  round_handler.qc
- // runematch.qc
  scores.qc
  scores_rules.qc
- secret.qc
  spawnpoints.qc
  steerlib.qc
  sv_main.qc
- target_music.qc
- target_spawn.qc
  teamplay.qc
  t_halflife.qc
  t_items.qc
- t_jumppads.qc
- t_plats.qc
  t_quake3.qc
  t_quake.qc
- t_swamp.qc
- t_teleporters.qc
  waypointsprites.qc
  
+ bot/aim.qc
  bot/bot.qc
+ bot/navigation.qc
+ bot/scripting.qc
+ bot/waypoints.qc
  
- command/banning.qc
- command/cmd.qc
- command/common.qc
- command/getreplies.qc
- command/radarmap.qc
- command/sv_cmd.qc
- command/vote.qc
+ bot/havocbot/havocbot.qc
+ bot/havocbot/role_keyhunt.qc
 -bot/havocbot/role_onslaught.qc
+ bot/havocbot/roles.qc
+ command/all.qc
  
  mutators/mutators_include.qc
  mutators/mutators.qc
  
+ pathlib/costs.qc
+ pathlib/expandnode.qc
+ pathlib/main.qc
+ pathlib/movenode.qc
+ pathlib/path_waypoint.qc
+ pathlib/utility.qc
+ vehicles/all.qc
  weapons/accuracy.qc
  weapons/common.qc
  weapons/csqcprojectile.qc // TODO
@@@ -90,22 -86,25 +87,25 @@@ weapons/weaponsystem.q
  ../common/buffs.qc
  ../common/campaign_file.qc
  ../common/campaign_setup.qc
- ../common/command/generic.qc
- ../common/command/markup.qc
- ../common/command/rpn.qc
  ../common/mapinfo.qc
- ../common/monsters/monsters.qc
+ ../common/monsters/all.qc
  ../common/monsters/spawn.qc
  ../common/monsters/sv_monsters.qc
+ ../common/movetypes/include.qc
  ../common/nades.qc
  ../common/net_notice.qc
  ../common/notifications.qc
+ ../common/physics.qc
  ../common/playerstats.qc
  ../common/test.qc
+ ../common/triggers/include.qc
  ../common/urllib.qc
  ../common/util.qc
+ ../common/items/all.qc
  ../common/weapons/config.qc
- ../common/weapons/weapons.qc // TODO
+ ../common/weapons/all.qc // TODO
  
  ../csqcmodellib/sv_model.qc
  
diff --combined qcsrc/server/teamplay.qc
index f2d88aa77c9535f5735db54336291c2f5b53a0cb,7bd44fec82401c29a41533a9b50f85b224406db1..cb03a31b46d7b83647d0f53929000368ba7968b7
@@@ -1,4 -1,19 +1,19 @@@
  #include "teamplay.qh"
+ #include "_all.qh"
+ #include "cl_client.qh"
+ #include "race.qh"
+ #include "scores.qh"
+ #include "scores_rules.qh"
+ #include "bot/bot.qh"
+ #include "command/vote.qh"
+ #include "mutators/mutators_include.qh"
+ #include "../common/deathtypes.qh"
+ #include "../common/teams.qh"
  
  void TeamchangeFrags(entity e)
  {
@@@ -146,7 -161,6 +161,7 @@@ void InitGameplayMode(
        if(g_onslaught)
        {
                ActivateTeamplay();
 +              fraglimit_override = autocvar_g_onslaught_point_limit;
                have_team_spawns = -1; // request team spawns
                MUTATOR_ADD(gamemode_onslaught);
        }
index f0f27d3c9795b4f27dc0f0fa1d98e399de9cedf3,d7b637d0ce03fcefaabe35d6fbce6a6441b3d997..6c714d1f3fb438c15245ca44c4f3cb23259755b5
@@@ -307,27 -307,12 +307,27 @@@ float WaypointSprite_SendEntity(entity 
                WriteCoord(MSG_ENTITY, self.fade_time);
                WriteCoord(MSG_ENTITY, self.teleport_time);
                WriteShort(MSG_ENTITY, self.fade_rate); // maxdist
 -              float f;
 -              f = 0;
 +              float f = 0;
                if(self.currentammo)
                        f |= 1; // hideable
                if(self.exteriormodeltoclient == to)
                        f |= 2; // my own
 +              if(g_onslaught)
 +              {
 +                      if(self.owner.classname == "onslaught_controlpoint")
 +                      {
 +                              entity wp_owner = self.owner;
 +                              entity e = WaypointSprite_getviewentity(to);
 +                              if(SAME_TEAM(e, wp_owner) && wp_owner.goalentity.health >= wp_owner.goalentity.max_health) { f |= 2; }
 +                              if(!ons_ControlPoint_Attackable(wp_owner, e.team)) { f |= 2; }
 +                      }
 +                      if(self.owner.classname == "onslaught_generator")
 +                      {
 +                              entity wp_owner = self.owner;
 +                              if(wp_owner.isshielded && wp_owner.health >= wp_owner.max_health) { f |= 2; }
 +                              if(wp_owner.health <= 0) { f |= 2; }
 +                      }
 +              }
                WriteByte(MSG_ENTITY, f);
        }
  
@@@ -389,11 -374,11 +389,11 @@@ entity WaypointSprite_Spawn
        wp.team = t;
        wp.owner = own;
        wp.currentammo = hideable;
-       if(own)
+       if (own)
        {
-               if(own.ownfield)
-                       remove(own.ownfield);
-               own.ownfield = wp;
+               if (own.(ownfield))
+                       remove(own.(ownfield));
+               own.(ownfield) = wp;
                wp.owned_by_field = ownfield;
        }
        wp.fade_rate = maxdistance;