Merge branch 'master' into terencehill/quickmenu
authorMario <zacjardine@y7mail.com>
Sun, 30 Aug 2015 04:32:07 +0000 (14:32 +1000)
committerMario <zacjardine@y7mail.com>
Sun, 30 Aug 2015 04:32:07 +0000 (14:32 +1000)
# Conflicts:
# qcsrc/client/command/cl_cmd.qc

1  2 
qcsrc/client/command/cl_cmd.qc
qcsrc/client/hud.qc
qcsrc/client/hud_config.qc
qcsrc/client/main.qc
qcsrc/client/scoreboard.qc
qcsrc/client/view.qc
qcsrc/server/command/cmd.qc

@@@ -53,22 -53,22 +53,22 @@@ void LocalCommand_blurtest(int request
                        blurtest_time1 = time + stof(argv(1));
                        blurtest_radius = stof(argv(2));
                        blurtest_power = stof(argv(3));
-                       print("Enabled blurtest\n");
+                       LOG_INFO("Enabled blurtest\n");
                        return;
                }
  
                default:
                case CMD_REQUEST_USAGE:
                {
-                       print("\nUsage:^3 cl_cmd blurtest\n");
-                       print("  No arguments required.\n");
+                       LOG_INFO("\nUsage:^3 cl_cmd blurtest\n");
+                       LOG_INFO("  No arguments required.\n");
                        return;
                }
        }
        #else
        if(request)
        {
-               print("Blurtest is not enabled on this client.\n");
+               LOG_INFO("Blurtest is not enabled on this client.\n");
                return;
        }
        #endif
@@@ -82,7 -82,7 +82,7 @@@ void LocalCommand_boxparticles(int requ
                {
                        if (argc == 9)
                        {
-                               int effect = particleeffectnum(argv(1));
+                               int effect = _particleeffectnum(argv(1));
                                if (effect >= 0)
                                {
                                        int index = stoi(argv(2));
                }
  
                default:
-                       print("Incorrect parameters for ^2boxparticles^7\n");
+                       LOG_INFO("Incorrect parameters for ^2boxparticles^7\n");
                case CMD_REQUEST_USAGE:
                {
-                       print("\nUsage:^3 lv_cmd boxparticles effectname own org_from org_to, dir_from, dir_to, countmultiplier, flags\n");
-                       print("  'effectname' is the name of a particle effect in effectinfo.txt\n");
-                       print("  'own' is the entity number of the owner (negative for csqc ent, positive for svqc ent)\n");
-                       print("  'org_from' is the starting origin of the box\n");
-                       print("  'org_to' is the ending origin of the box\n");
-                       print("  'dir_from' is the minimum velocity\n");
-                       print("  'dir_to' is the maximum velocity\n");
-                       print("  'countmultiplier' defines a multiplier for the particle count (affects count only, not countabsolute or trailspacing)\n");
-                       print("  'flags' can contain:\n");
-                       print("    1 to respect globals particles_alphamin, particles_alphamax (set right before via prvm_globalset client)\n");
-                       print("    2 to respect globals particles_colormin, particles_colormax (set right before via prvm_globalset client)\n");
-                       print("    4 to respect globals particles_fade (set right before via prvm_globalset client)\n");
-                       print("    128 to draw a trail, not a box\n");
+                       LOG_INFO("\nUsage:^3 lv_cmd boxparticles effectname own org_from org_to, dir_from, dir_to, countmultiplier, flags\n");
+                       LOG_INFO("  'effectname' is the name of a particle effect in effectinfo.txt\n");
+                       LOG_INFO("  'own' is the entity number of the owner (negative for csqc ent, positive for svqc ent)\n");
+                       LOG_INFO("  'org_from' is the starting origin of the box\n");
+                       LOG_INFO("  'org_to' is the ending origin of the box\n");
+                       LOG_INFO("  'dir_from' is the minimum velocity\n");
+                       LOG_INFO("  'dir_to' is the maximum velocity\n");
+                       LOG_INFO("  'countmultiplier' defines a multiplier for the particle count (affects count only, not countabsolute or trailspacing)\n");
+                       LOG_INFO("  'flags' can contain:\n");
+                       LOG_INFO("    1 to respect globals particles_alphamin, particles_alphamax (set right before via prvm_globalset client)\n");
+                       LOG_INFO("    2 to respect globals particles_colormin, particles_colormax (set right before via prvm_globalset client)\n");
+                       LOG_INFO("    4 to respect globals particles_fade (set right before via prvm_globalset client)\n");
+                       LOG_INFO("    128 to draw a trail, not a box\n");
                        return;
                }
        }
@@@ -142,13 -142,13 +142,13 @@@ void LocalCommand_create_scrshot_ent(in
                                fputs(fh, strcat("\"angles\" \"", strcat(ftos(view_angles.x), " ", ftos(view_angles.y), " ", ftos(view_angles.z)), "\"\n"));
                                fputs(fh, "}\n");
  
-                               print("Completed screenshot entity dump in ^2data/data/", MapInfo_Map_bspname, "_scrshot_ent.txt^7.\n");
+                               LOG_INFO("Completed screenshot entity dump in ^2data/data/", MapInfo_Map_bspname, "_scrshot_ent.txt^7.\n");
  
                                fclose(fh);
                        }
                        else
                        {
-                               print("^1Error: ^7Could not dump to file!\n");
+                               LOG_INFO("^1Error: ^7Could not dump to file!\n");
                        }
                        return;
                }
                default:
                case CMD_REQUEST_USAGE:
                {
-                       print("\nUsage:^3 cl_cmd create_scrshot_ent\n");
-                       print("  No arguments required.\n");
+                       LOG_INFO("\nUsage:^3 cl_cmd create_scrshot_ent\n");
+                       LOG_INFO("  No arguments required.\n");
                        return;
                }
        }
@@@ -186,8 -186,8 +186,8 @@@ void LocalCommand_debugmodel(int reques
                default:
                case CMD_REQUEST_USAGE:
                {
-                       print("\nUsage:^3 cl_cmd debugmodel model\n");
-                       print("  Where 'model' is a string of the model name to use for the debug model.\n");
+                       LOG_INFO("\nUsage:^3 cl_cmd debugmodel model\n");
+                       LOG_INFO("  Where 'model' is a string of the model name to use for the debug model.\n");
                        return;
                }
        }
@@@ -230,11 -230,11 +230,11 @@@ void LocalCommand_handlevote(int reques
                }
  
                default:
-                       print("Incorrect parameters for ^2handlevote^7\n");
+                       LOG_INFO("Incorrect parameters for ^2handlevote^7\n");
                case CMD_REQUEST_USAGE:
                {
-                       print("\nUsage:^3 cl_cmd handlevote vote\n");
-                       print("  Where 'vote' is the selection for either the current poll or uid2name.\n");
+                       LOG_INFO("\nUsage:^3 cl_cmd handlevote vote\n");
+                       LOG_INFO("  Where 'vote' is the selection for either the current poll or uid2name.\n");
                        return;
                }
        }
@@@ -254,15 -254,6 +254,15 @@@ void LocalCommand_hud(int request, int 
                                        return;
                                }
  
 +                              case "quickmenu":
 +                              {
 +                                      if(QuickMenu_IsOpened())
 +                                              QuickMenu_Close();
 +                                      else
 +                                              QuickMenu_Open(argv(2), argv(3)); // mode, submenu
 +                                      return;
 +                              }
 +
                                case "minigame":
                                {
                                        if(HUD_MinigameMenu_IsOpened())
                }
  
                default:
-                       print("Incorrect parameters for ^2hud^7\n");
+                       LOG_INFO("Incorrect parameters for ^2hud^7\n");
                case CMD_REQUEST_USAGE:
                {
-                       print("\nUsage:^3 cl_cmd hud action [configname | radartoggle | layout]\n");
-                       print("  Where 'action' is the command to complete,\n");
-                       print("  'configname' is the name to save to for \"save\" action,\n");
-                       print("  'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action,\n");
-                       print("  and 'layout' is how to organize the scoreboard columns for the set action.\n");
-                       print("  quickmenu [[default | file | \"\"] submenu]\n");
-                       print("    Called without options (or with "") loads either the default quickmenu or a quickmenu file if hud_panel_quickmenu_file is set to a valid filename.\n");
-                       print("    Submenu option allows to open quickmenu directly in a submenu, it requires to specify 'default', 'file' or '\"\"' option.\n");
-                       print("  Full list of commands here: \"configure, quickmenu, minigame, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"\n");
+                       LOG_INFO("\nUsage:^3 cl_cmd hud action [configname | radartoggle | layout]\n");
+                       LOG_INFO("  Where 'action' is the command to complete,\n");
+                       LOG_INFO("  'configname' is the name to save to for \"save\" action,\n");
+                       LOG_INFO("  'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action,\n");
+                       LOG_INFO("  and 'layout' is how to organize the scoreboard columns for the set action.\n");
++                      LOG_INFO("  quickmenu [[default | file | \"\"] submenu]\n");
++                      LOG_INFO("    Called without options (or with "") loads either the default quickmenu or a quickmenu file if hud_panel_quickmenu_file is set to a valid filename.\n");
++                      LOG_INFO("    Submenu option allows to open quickmenu directly in a submenu, it requires to specify 'default', 'file' or '\"\"' option.\n");
+                       LOG_INFO("  Full list of commands here: \"configure, minigame, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"\n");
                        return;
                }
        }
@@@ -346,11 -334,11 +346,11 @@@ void LocalCommand_localprint(int reques
                }
  
                default:
-                       print("Incorrect parameters for ^2localprint^7\n");
+                       LOG_INFO("Incorrect parameters for ^2localprint^7\n");
                case CMD_REQUEST_USAGE:
                {
-                       print("\nUsage:^3 cl_cmd localprint \"message\"\n");
-                       print("  'message' is the centerprint message to send to yourself.\n");
+                       LOG_INFO("\nUsage:^3 cl_cmd localprint \"message\"\n");
+                       LOG_INFO("  'message' is the centerprint message to send to yourself.\n");
                        return;
                }
        }
@@@ -370,11 -358,11 +370,11 @@@ void LocalCommand_mv_download(int reque
                }
  
                default:
-                       print("Incorrect parameters for ^2mv_download^7\n");
+                       LOG_INFO("Incorrect parameters for ^2mv_download^7\n");
                case CMD_REQUEST_USAGE:
                {
-                       print("\nUsage:^3 cl_cmd mv_download mapid\n");
-                       print("  Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.\n");
+                       LOG_INFO("\nUsage:^3 cl_cmd mv_download mapid\n");
+                       LOG_INFO("  Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.\n");
                        return;
                }
        }
@@@ -389,17 -377,17 +389,17 @@@ void LocalCommand_find(int request, in
                        entity client;
  
                        for(client = world; (client = find(client, classname, argv(1))); )
-                               print(etos(client), "\n");
+                               LOG_INFO(etos(client), "\n");
  
                        return;
                }
  
                default:
-                       print("Incorrect parameters for ^2find^7\n");
+                       LOG_INFO("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");
+                       LOG_INFO("\nUsage:^3 cl_cmd find classname\n");
+                       LOG_INFO("  Where 'classname' is the classname to search for.\n");
                        return;
                }
        }
@@@ -429,11 -417,11 +429,11 @@@ void LocalCommand_sendcvar(int request
                }
  
                default:
-                       print("Incorrect parameters for ^2sendcvar^7\n");
+                       LOG_INFO("Incorrect parameters for ^2sendcvar^7\n");
                case CMD_REQUEST_USAGE:
                {
-                       print("\nUsage:^3 cl_cmd sendcvar <cvar>\n");
-                       print("  Where 'cvar' is the cvar plus arguments to send to the server.\n");
+                       LOG_INFO("\nUsage:^3 cl_cmd sendcvar <cvar>\n");
+                       LOG_INFO("  Where 'cvar' is the cvar plus arguments to send to the server.\n");
                        return;
                }
        }
@@@ -484,7 -472,7 +484,7 @@@ void LocalCommand_(int request
  void LocalCommand_macro_help()
  {
        #define CLIENT_COMMAND(name,function,description) \
-               { if(strtolower(description) != "") { print("  ^2", name, "^7: ", description, "\n"); } }
+               { if(strtolower(description) != "") { LOG_INFO("  ^2", name, "^7: ", description, "\n"); } }
  
        CLIENT_COMMANDS(0, 0);
        #undef CLIENT_COMMAND
@@@ -544,14 -532,14 +544,14 @@@ void GameCommand(string command
        {
                if(argc == 1)
                {
-                       print("\nClient console commands:\n");
+                       LOG_INFO("\nClient console commands:\n");
                        LocalCommand_macro_help();
  
-                       print("\nGeneric commands shared by all programs:\n");
+                       LOG_INFO("\nGeneric commands shared by all programs:\n");
                        GenericCommand_macro_help();
  
-                       print("\nUsage:^3 cl_cmd COMMAND...^7, where possible commands are listed above.\n");
-                       print("For help about a specific command, type cl_cmd help COMMAND\n");
+                       LOG_INFO("\nUsage:^3 cl_cmd COMMAND...^7, where possible commands are listed above.\n");
+                       LOG_INFO("For help about a specific command, type cl_cmd help COMMAND\n");
  
                        return;
                }
        ) return;
  
        // nothing above caught the command, must be invalid
-       print(((command != "") ? strcat("Unknown client command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try cl_cmd help.\n");
+       LOG_INFO(((command != "") ? strcat("Unknown client command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try cl_cmd help.\n");
  
        return;
  }
diff --combined qcsrc/client/hud.qc
@@@ -2731,7 -2731,7 +2731,7 @@@ void HUD_Vote(void
                {
                        vote_yescount = 0;
                        vote_nocount = 0;
-                       print(_("^1You must answer before entering hud configure mode\n"));
+                       LOG_INFO(_("^1You must answer before entering hud configure mode\n"));
                        cvar_set("_hud_configure", "0");
                }
                if(vote_called_vote)
@@@ -4674,12 -4674,6 +4674,12 @@@ void HUD_CenterPrint (void
  //
  #include "../common/minigames/cl_minigames_hud.qc"
  
 +
 +// QuickMenu (#23)
 +//
 +#include "quickmenu.qc"
 +
 +
  /*
  ==================
  Main HUD system
@@@ -4817,7 -4811,7 +4817,7 @@@ void HUD_Main (void
                        }
                }
                if (warning)
-                       dprint("Automatically fixed wrong/missing panel numbers in _hud_panelorder\n");
+                       LOG_TRACE("Automatically fixed wrong/missing panel numbers in _hud_panelorder\n");
  
                cvar_set("_hud_panelorder", s);
                if(hud_panelorder_prev)
                HUD_Panel_Draw(HUD_PANEL(RADAR));
        if(autocvar__con_chat_maximized)
                HUD_Panel_Draw(HUD_PANEL(CHAT));
 +      if(hud_panel_quickmenu)
 +              HUD_Panel_Draw(HUD_PANEL(QUICKMENU));
  
        HUD_Configure_PostDraw();
  
@@@ -209,19 -209,17 +209,19 @@@ void HUD_Panel_ExportCfg(string cfgname
                                        HUD_Write_PanelCvar_q("_text");
                                        HUD_Write_PanelCvar_q("_ratio");
                                        HUD_Write_PanelCvar_q("_dynamicsize");
 +                              case HUD_PANEL_QUICKMENU:
 +                                      HUD_Write_PanelCvar_q("_align");
                                        break;
                        }
                        HUD_Write("\n");
                }
                HUD_Write("menu_sync\n"); // force the menu to reread the cvars, so that the dialogs are updated
  
-               printf(_("^2Successfully exported to %s! (Note: It's saved in data/data/)\n"), filename);
+               LOG_INFOF(_("^2Successfully exported to %s! (Note: It's saved in data/data/)\n"), filename);
                fclose(fh);
        }
        else
-               printf(_("^1Couldn't write to %s\n"), filename);
+               LOG_INFOF(_("^1Couldn't write to %s\n"), filename);
  }
  
  void HUD_Configure_Exit_Force()
diff --combined qcsrc/client/main.qc
@@@ -87,10 -87,10 +87,10 @@@ string forcefog
  void ConsoleCommand_macro_init();
  void CSQC_Init(void)
  {
 -      prvm_language = cvar_string("prvm_language");
 +      prvm_language = strzone(cvar_string("prvm_language"));
  
  #ifdef WATERMARK
-       dprintf("^4CSQC Build information: ^1%s\n", WATERMARK);
+       LOG_TRACEF("^4CSQC Build information: ^1%s\n", WATERMARK);
  #endif
  
        int i;
        CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
        CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
        CALL_ACCUMULATED_FUNCTION(RegisterHUD_Panels);
-       CALL_ACCUMULATED_FUNCTION(RegisterEffects);
  
        initialize_minigames();
  
@@@ -245,7 -244,7 +244,7 @@@ float SetTeam(entity o, int Team
                        default:
                                if(GetTeam(Team, false) == world)
                                {
-                                       dprintf("trying to switch to unsupported team %d\n", Team);
+                                       LOG_TRACEF("trying to switch to unsupported team %d\n", Team);
                                        Team = NUM_SPECTATOR;
                                }
                                break;
                        default:
                                if(GetTeam(Team, false) == world)
                                {
-                                       dprintf("trying to switch to unsupported team %d\n", Team);
+                                       LOG_TRACEF("trying to switch to unsupported team %d\n", Team);
                                        Team = NUM_SPECTATOR;
                                }
                                break;
@@@ -369,9 -368,6 +368,9 @@@ float CSQC_InputEvent(float bInputType
        if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary))
                return true;
  
 +      if (QuickMenu_InputEvent(bInputType, nPrimary, nSecondary))
 +              return true;
 +
        if ( HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary) )
                return true;
  
@@@ -460,7 -456,7 +459,7 @@@ void Ent_ReadPlayerScore(
        if(!isNew && n != self.sv_entnum)
        {
                //print("A CSQC entity changed its owner!\n");
-               printf("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname);
+               LOG_INFOF("A CSQC entity changed its owner! (edict: %d, classname: %s)\n", num_for_edict(self), self.classname);
                isNew = true;
                Ent_Remove();
                self.enttype = ENT_CLIENT_SCORES;
@@@ -730,14 -726,14 +729,14 @@@ void Ent_ReadSpawnPoint(float is_new) /
                        {
                                switch(teamnum)
                                {
-                                       case NUM_TEAM_1: self.cnt = particleeffectnum("spawn_point_red"); break;
-                                       case NUM_TEAM_2: self.cnt = particleeffectnum("spawn_point_blue"); break;
-                                       case NUM_TEAM_3: self.cnt = particleeffectnum("spawn_point_yellow"); break;
-                                       case NUM_TEAM_4: self.cnt = particleeffectnum("spawn_point_pink"); break;
-                                       default: self.cnt = particleeffectnum("spawn_point_neutral"); break;
+                                       case NUM_TEAM_1: self.cnt = particleeffectnum(EFFECT_SPAWNPOINT_RED); break;
+                                       case NUM_TEAM_2: self.cnt = particleeffectnum(EFFECT_SPAWNPOINT_BLUE); break;
+                                       case NUM_TEAM_3: self.cnt = particleeffectnum(EFFECT_SPAWNPOINT_YELLOW); break;
+                                       case NUM_TEAM_4: self.cnt = particleeffectnum(EFFECT_SPAWNPOINT_PINK); break;
+                                       default: self.cnt = particleeffectnum(EFFECT_SPAWNPOINT_NEUTRAL); break;
                                }
                        }
-                       else { self.cnt = particleeffectnum("spawn_point_neutral"); }
+                       else { self.cnt = particleeffectnum(EFFECT_SPAWNPOINT_NEUTRAL); }
  
                        self.draw = Spawn_Draw;
                }
@@@ -767,11 -763,11 +766,11 @@@ void Ent_ReadSpawnEvent(float is_new
                        {
                                switch(teamnum)
                                {
-                                       case NUM_TEAM_1: pointparticles(particleeffectnum("spawn_event_red"), self.origin, '0 0 0', 1); break;
-                                       case NUM_TEAM_2: pointparticles(particleeffectnum("spawn_event_blue"), self.origin, '0 0 0', 1); break;
-                                       case NUM_TEAM_3: pointparticles(particleeffectnum("spawn_event_yellow"), self.origin, '0 0 0', 1); break;
-                                       case NUM_TEAM_4: pointparticles(particleeffectnum("spawn_event_pink"), self.origin, '0 0 0', 1); break;
-                                       default: pointparticles(particleeffectnum("spawn_event_neutral"), self.origin, '0 0 0', 1); break;
+                                       case NUM_TEAM_1: pointparticles(particleeffectnum(EFFECT_SPAWN_RED), self.origin, '0 0 0', 1); break;
+                                       case NUM_TEAM_2: pointparticles(particleeffectnum(EFFECT_SPAWN_BLUE), self.origin, '0 0 0', 1); break;
+                                       case NUM_TEAM_3: pointparticles(particleeffectnum(EFFECT_SPAWN_YELLOW), self.origin, '0 0 0', 1); break;
+                                       case NUM_TEAM_4: pointparticles(particleeffectnum(EFFECT_SPAWN_PINK), self.origin, '0 0 0', 1); break;
+                                       default: pointparticles(particleeffectnum(EFFECT_SPAWN_NEUTRAL), self.origin, '0 0 0', 1); break;
                                }
                        }
                        if(autocvar_cl_spawn_event_sound)
@@@ -809,7 -805,7 +808,7 @@@ void CSQC_Ent_Update(float bIsNewEntity
        t = ReadByte();
  
        if(autocvar_developer_csqcentities)
-               printf("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t);
+               LOG_INFOF("CSQC_Ent_Update(%d) with self=%i self.entnum=%d self.enttype=%d t=%d\n", bIsNewEntity, self, self.entnum, self.enttype, t);
  
        // set up the "time" global for received entities to be correct for interpolation purposes
        savetime = time;
                if(t != self.enttype || bIsNewEntity)
                {
                        //print("A CSQC entity changed its type!\n");
-                       printf("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t);
+                       LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)\n", num_for_edict(self), self.entnum, self.enttype, t);
                        Ent_Remove();
                        clearentity(self);
                        bIsNewEntity = 1;
        {
                if(!bIsNewEntity)
                {
-                       printf("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t);
+                       LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)\n", num_for_edict(self), self.entnum, t);
                        bIsNewEntity = 1;
                }
        }
@@@ -947,11 -943,11 +946,11 @@@ void Ent_Remove(
  void CSQC_Ent_Remove()
  {
        if(autocvar_developer_csqcentities)
-               printf("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype);
+               LOG_INFOF("CSQC_Ent_Remove() with self=%i self.entnum=%d self.enttype=%d\n", self, self.entnum, self.enttype);
  
        if(wasfreed(self))
        {
-               print("WARNING: CSQC_Ent_Remove called for already removed entity. Packet loss?\n");
+               LOG_INFO("WARNING: CSQC_Ent_Remove called for already removed entity. Packet loss?\n");
                return;
        }
        if(self.enttype)
@@@ -972,7 -968,7 +971,7 @@@ void Gamemode_Init(
  void CSQC_Parse_StuffCmd(string strMessage)
  {
        if(autocvar_developer_csqcentities)
-               printf("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage);
+               LOG_INFOF("CSQC_Parse_StuffCmd(\"%s\")\n", strMessage);
  
        localcmd(strMessage);
  }
  void CSQC_Parse_Print(string strMessage)
  {
        if(autocvar_developer_csqcentities)
-               printf("CSQC_Parse_Print(\"%s\")\n", strMessage);
+               LOG_INFOF("CSQC_Parse_Print(\"%s\")\n", strMessage);
  
-       print(ColorTranslateRGB(strMessage));
+       LOG_INFO(ColorTranslateRGB(strMessage));
  }
  
  // CSQC_Parse_CenterPrint : Provides the centerprint_hud string in the first parameter that the server provided.
  void CSQC_Parse_CenterPrint(string strMessage)
  {
        if(autocvar_developer_csqcentities)
-               printf("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage);
+               LOG_INFOF("CSQC_Parse_CenterPrint(\"%s\")\n", strMessage);
  
        centerprint_hud(strMessage);
  }
@@@ -1278,7 -1274,7 +1277,7 @@@ float CSQC_Parse_TempEntity(
        int nTEID = ReadByte();
  
        if (autocvar_developer_csqcentities)
-               printf("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
+               LOG_INFOF("CSQC_Parse_TempEntity() with nTEID=%d\n", nTEID);
  
        switch (nTEID)
        {
@@@ -245,68 -245,68 +245,68 @@@ void HUD_UpdateTeamPos(entity Team
  
  void Cmd_HUD_Help()
  {
-       print(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
-       print(_("^3|---------------------------------------------------------------|\n"));
-       print(_("Usage:\n"));
-       print(_("^2scoreboard_columns_set default\n"));
-       print(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
-       print(_("The following field names are recognized (case insensitive):\n"));
-       print(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
-       print(_("^3name^7 or ^3nick^7             Name of a player\n"));
-       print(_("^3ping^7                     Ping time\n"));
-       print(_("^3pl^7                       Packet loss\n"));
-       print(_("^3kills^7                    Number of kills\n"));
-       print(_("^3deaths^7                   Number of deaths\n"));
-       print(_("^3suicides^7                 Number of suicides\n"));
-       print(_("^3frags^7                    kills - suicides\n"));
-       print(_("^3kd^7                       The kill-death ratio\n"));
-       print(_("^3sum^7                      frags - deaths\n"));
-       print(_("^3caps^7                     How often a flag (CTF) or a key (KeyHunt) was captured\n"));
-       print(_("^3pickups^7                  How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
-       print(_("^3captime^7                  Time of fastest cap (CTF)\n"));
-       print(_("^3fckills^7                  Number of flag carrier kills\n"));
-       print(_("^3returns^7                  Number of flag returns\n"));
-       print(_("^3drops^7                    Number of flag drops\n"));
-       print(_("^3lives^7                    Number of lives (LMS)\n"));
-       print(_("^3rank^7                     Player rank\n"));
-       print(_("^3pushes^7                   Number of players pushed into void\n"));
-       print(_("^3destroyed^7                Number of keys destroyed by pushing them into void\n"));
-       print(_("^3kckills^7                  Number of keys carrier kills\n"));
-       print(_("^3losses^7                   Number of times a key was lost\n"));
-       print(_("^3laps^7                     Number of laps finished (race/cts)\n"));
-       print(_("^3time^7                     Total time raced (race/cts)\n"));
-       print(_("^3fastest^7                  Time of fastest lap (race/cts)\n"));
-       print(_("^3ticks^7                    Number of ticks (DOM)\n"));
-       print(_("^3takes^7                    Number of domination points taken (DOM)\n"));
-       print(_("^3bckills^7                  Number of ball carrier kills\n"));
-       print(_("^3bctime^7                   Total amount of time holding the ball in Keepaway\n"));
-       print(_("^3score^7                    Total score\n\n"));
-       print(_("Before a field you can put a + or - sign, then a comma separated list\n"
+       LOG_INFO(_("You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"));
+       LOG_INFO(_("^3|---------------------------------------------------------------|\n"));
+       LOG_INFO(_("Usage:\n"));
+       LOG_INFO(_("^2scoreboard_columns_set default\n"));
+       LOG_INFO(_("^2scoreboard_columns_set ^7field1 field2 ...\n"));
+       LOG_INFO(_("The following field names are recognized (case insensitive):\n"));
+       LOG_INFO(_("You can use a ^3|^7 to start the right-aligned fields.\n\n"));
+       LOG_INFO(_("^3name^7 or ^3nick^7             Name of a player\n"));
+       LOG_INFO(_("^3ping^7                     Ping time\n"));
+       LOG_INFO(_("^3pl^7                       Packet loss\n"));
+       LOG_INFO(_("^3kills^7                    Number of kills\n"));
+       LOG_INFO(_("^3deaths^7                   Number of deaths\n"));
+       LOG_INFO(_("^3suicides^7                 Number of suicides\n"));
+       LOG_INFO(_("^3frags^7                    kills - suicides\n"));
+       LOG_INFO(_("^3kd^7                       The kill-death ratio\n"));
+       LOG_INFO(_("^3sum^7                      frags - deaths\n"));
+       LOG_INFO(_("^3caps^7                     How often a flag (CTF) or a key (KeyHunt) was captured\n"));
+       LOG_INFO(_("^3pickups^7                  How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up\n"));
+       LOG_INFO(_("^3captime^7                  Time of fastest cap (CTF)\n"));
+       LOG_INFO(_("^3fckills^7                  Number of flag carrier kills\n"));
+       LOG_INFO(_("^3returns^7                  Number of flag returns\n"));
+       LOG_INFO(_("^3drops^7                    Number of flag drops\n"));
+       LOG_INFO(_("^3lives^7                    Number of lives (LMS)\n"));
+       LOG_INFO(_("^3rank^7                     Player rank\n"));
+       LOG_INFO(_("^3pushes^7                   Number of players pushed into void\n"));
+       LOG_INFO(_("^3destroyed^7                Number of keys destroyed by pushing them into void\n"));
+       LOG_INFO(_("^3kckills^7                  Number of keys carrier kills\n"));
+       LOG_INFO(_("^3losses^7                   Number of times a key was lost\n"));
+       LOG_INFO(_("^3laps^7                     Number of laps finished (race/cts)\n"));
+       LOG_INFO(_("^3time^7                     Total time raced (race/cts)\n"));
+       LOG_INFO(_("^3fastest^7                  Time of fastest lap (race/cts)\n"));
+       LOG_INFO(_("^3ticks^7                    Number of ticks (DOM)\n"));
+       LOG_INFO(_("^3takes^7                    Number of domination points taken (DOM)\n"));
+       LOG_INFO(_("^3bckills^7                  Number of ball carrier kills\n"));
+       LOG_INFO(_("^3bctime^7                   Total amount of time holding the ball in Keepaway\n"));
+       LOG_INFO(_("^3score^7                    Total score\n\n"));
+       LOG_INFO(_("Before a field you can put a + or - sign, then a comma separated list\n"
                "of game types, then a slash, to make the field show up only in these\n"
                "or in all but these game types. You can also specify 'all' as a\n"
                "field to show all fields available for the current game mode.\n\n"));
  
-       print(_("The special game type names 'teams' and 'noteams' can be used to\n"
+       LOG_INFO(_("The special game type names 'teams' and 'noteams' can be used to\n"
                "include/exclude ALL teams/noteams game modes.\n\n"));
  
-       print(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
-       print(_("will display name, ping and pl aligned to the left, and the fields\n"
+       LOG_INFO(_("Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4\n"));
+       LOG_INFO(_("will display name, ping and pl aligned to the left, and the fields\n"
                "right of the vertical bar aligned to the right.\n"));
-       print(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
+       LOG_INFO(_("'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
                "other gamemodes except DM.\n"));
  }
  
  #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" */ \
+ "-teams,rc,lms/kills +ft,tdm/kills -teams,lms/deaths +ft,tdm/deaths -teams,lms,rc,ka/suicides +ft,tdm/suicides -rc,dm,tdm,ka,ft/frags " /* tdm already has this in "score" */ \
  "+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 " \
+ "?+rc/laps ?+rc/time ?+rc/fastest " \
  "+as/objectives +nb/faults +nb/goals +ka/pickups +ka/bckills +ka/bctime +ft/revivals " \
- "-lms,race,nb/score"
+ "-lms,rc,nb/score"
  
  void Cmd_HUD_SetFields(float argc)
  {
                hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], false, hud_fontsize);
                str = strtolower(str);
  
-               if(str == "ping") {
-                       hud_field[hud_num_fields] = SP_PING;
-               } else if(str == "pl") {
-                       hud_field[hud_num_fields] = SP_PL;
-               } else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
-                       hud_field[hud_num_fields] = SP_KDRATIO;
-               } else if(str == "sum" || str == "diff" || str == "k-d") {
-                       hud_field[hud_num_fields] = SP_SUM;
-               } else if(str == "name" || str == "nick") {
-                       hud_field[hud_num_fields] = SP_NAME;
-                       have_name = 1;
-               } else if(str == "|") {
-                       hud_field[hud_num_fields] = SP_SEPARATOR;
-                       have_separator = 1;
-               } else {
-                       for(j = 0; j < MAX_SCORE; ++j)
-                               if(str == strtolower(scores_label[j]))
-                                       goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
- :notfound
-                       if(str == "frags")
-                       {
-                               j = SP_FRAGS;
-                       }
-                       else
+               switch(str)
+               {
+                       case "ping": hud_field[hud_num_fields] = SP_PING; break;
+                       case "pl": hud_field[hud_num_fields] = SP_PL; break;
+                       case "pl": hud_field[hud_num_fields] = SP_PL; break;
+                       case "kd": case "kdr": case "kdratio": case "k/d": hud_field[hud_num_fields] = SP_KDRATIO; break;
+                       case "sum": case "diff": case "k-d": hud_field[hud_num_fields] = SP_SUM; break;
+                       case "name": case "nick": hud_field[hud_num_fields] = SP_NAME; have_name = true; break;
+                       case "|": hud_field[hud_num_fields] = SP_SEPARATOR; have_separator = true; break;
+                       default:
                        {
-                               if (!nocomplain)
-                                       printf("^1Error:^7 Unknown score field: '%s'\n", str);
-                               continue;
-                       }
+                               for(j = 0; j < MAX_SCORE; ++j)
+                                       if(str == strtolower(scores_label[j]))
+                                               goto found; // sorry, but otherwise fteqcc -O3 miscompiles this and warns about "unreachable code"
+ :notfound
+                               if(str == "frags")
+                                       j = SP_FRAGS;
+                               else
+                               {
+                                       if(!nocomplain)
+                                               LOG_INFOF("^1Error:^7 Unknown score field: '%s'\n", str);
+                                       continue;
+                               }
  :found
-                       hud_field[hud_num_fields] = j;
-                       if(j == ps_primary)
-                               have_primary = 1;
-                       if(j == ps_secondary)
-                               have_secondary = 1;
+                               hud_field[hud_num_fields] = j;
+                               if(j == ps_primary)
+                                       have_primary = 1;
+                               if(j == ps_secondary)
+                                       have_secondary = 1;
+                       }
                }
                ++hud_num_fields;
                if(hud_num_fields >= MAX_HUD_FIELDS)
                        hud_title[0] = strzone(TranslateScoresLabel("name"));
                        hud_field[0] = SP_NAME;
                        ++hud_num_fields;
-                       print("fixed missing field 'name'\n");
+                       LOG_INFO("fixed missing field 'name'\n");
  
                        if(!have_separator)
                        {
                                hud_field[1] = SP_SEPARATOR;
                                hud_size[1] = stringwidth("|", false, hud_fontsize);
                                ++hud_num_fields;
-                               print("fixed missing field '|'\n");
+                               LOG_INFO("fixed missing field '|'\n");
                        }
                }
                else if(!have_separator)
                        hud_size[hud_num_fields] = stringwidth("|", false, hud_fontsize);
                        hud_field[hud_num_fields] = SP_SEPARATOR;
                        ++hud_num_fields;
-                       print("fixed missing field '|'\n");
+                       LOG_INFO("fixed missing field '|'\n");
                }
                if(!have_secondary)
                {
                        hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], false, hud_fontsize);
                        hud_field[hud_num_fields] = ps_secondary;
                        ++hud_num_fields;
-                       printf("fixed missing field '%s'\n", scores_label[ps_secondary]);
+                       LOG_INFOF("fixed missing field '%s'\n", scores_label[ps_secondary]);
                }
                if(!have_primary)
                {
                        hud_size[hud_num_fields] = stringwidth(hud_title[hud_num_fields], false, hud_fontsize);
                        hud_field[hud_num_fields] = ps_primary;
                        ++hud_num_fields;
-                       printf("fixed missing field '%s'\n", scores_label[ps_primary]);
+                       LOG_INFOF("fixed missing field '%s'\n", scores_label[ps_primary]);
                }
        }
  
@@@ -959,8 -956,6 +956,8 @@@ vector HUD_Scoreboard_MakeTable(vector 
  float HUD_WouldDrawScoreboard() {
        if (autocvar__hud_configure)
                return 0;
 +      else if (QuickMenu_IsOpened())
 +              return 0;
        else if (HUD_Radar_Clickable())
                return 0;
        else if (scoreboard_showscores)
diff --combined qcsrc/client/view.qc
@@@ -131,6 -131,7 +131,7 @@@ vector GetCurrentFov(float fov
  
        zoomdir = button_zoom;
        if(hud == HUD_NORMAL)
+       if(switchweapon == activeweapon)
        if((activeweapon == WEP_VORTEX.m_id && vortex_scope) || (activeweapon == WEP_RIFLE.m_id && rifle_scope)) // do NOT use switchweapon here
                zoomdir += button_attack2;
        if(spectatee_status > 0 || isdemo())
@@@ -437,6 -438,8 +438,8 @@@ bool WantEventchase(
        {
                if(hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0))
                        return true;
+               if(MUTATOR_CALLHOOK(WantEventchase, self))
+                       return true;
                if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WepSet_FromWeapon(WEP_PORTO.m_id)))
                        return true;
                if(autocvar_cl_eventchase_death && (getstati(STAT_HEALTH) <= 0))
  
  vector damage_blurpostprocess, content_blurpostprocess;
  
- float checkfail[16];
  float unaccounted_damage = 0;
  void UpdateDamage()
  {
        if (damage_dealt_time != damage_dealt_time_prev)
        {
                unaccounted_damage += unaccounted_damage_new;
-               dprint("dmg total: ", ftos(unaccounted_damage), " (+", ftos(unaccounted_damage_new), ")", "\n");
+               LOG_TRACE("dmg total: ", ftos(unaccounted_damage), " (+", ftos(unaccounted_damage_new), ")", "\n");
        }
        damage_dealt_time_prev = damage_dealt_time;
  
@@@ -511,7 -512,7 +512,7 @@@ void UpdateHitsound(
                                pitch_shift = mirror_value + (mirror_value - pitch_shift);
                        }
  
-                       dprint("dmg total (dmg): ", ftos(unaccounted_damage), " , pitch shift: ", ftos(pitch_shift), "\n");
+                       LOG_TRACE("dmg total (dmg): ", ftos(unaccounted_damage), " , pitch shift: ", ftos(pitch_shift), "\n");
  
                        // todo: avoid very long and very short sounds from wave stretching using different sound files? seems unnecessary
                        // todo: normalize sound pressure levels? seems unnecessary
@@@ -1005,6 -1006,14 +1006,14 @@@ void UpdateCrosshair(
        }
  }
  
+ bool ov_enabled;
+ float oldr_nearclip;
+ float oldr_farclip_base;
+ float oldr_farclip_world;
+ float oldr_novis;
+ float oldr_useportalculling;
+ float oldr_useinfinitefarclip;
  const int BUTTON_3 = 4;
  const int BUTTON_4 = 8;
  float cl_notice_run();
@@@ -1047,22 -1056,6 +1056,6 @@@ void CSQC_UpdateView(float w, float h
        button_attack2 = (input_buttons & BUTTON_3);
        button_zoom = (input_buttons & BUTTON_4);
  
- #define CHECKFAIL_ASSERT(flag,func,parm,val) do {                                                                   \
-       float checkfailv = (func)(parm);                                                                                \
-       if (checkfailv != (val)) {                                                                                      \
-               if (!checkfail[(flag)])                                                                                     \
-               localcmd(sprintf("\ncmd checkfail %s %s %d %d\n", #func, parm, val, checkfailv));                           \
-               checkfail[(flag)] = 1;                                                                                      \
-       }                                                                                                               \
- } while(0)
-       CHECKFAIL_ASSERT(0, cvar_type, "\{100}\{105}\{118}\{48}\{95}\{101}\{118}\{97}\{100}\{101}", 0);
-       CHECKFAIL_ASSERT(1, cvar_type, "\{97}\{97}\{95}\{101}\{110}\{97}\{98}\{108}\{101}", 0);
-       CHECKFAIL_ASSERT(2, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{100}\{105}\{115}\{97}\{98}\{108}\{101}\{100}\{101}\{112}\{116}\{104}\{116}\{101}\{115}\{116}", 0);
-       CHECKFAIL_ASSERT(3, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{111}\{118}\{101}\{114}\{100}\{114}\{97}\{119}", 0);
-       CHECKFAIL_ASSERT(4, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{108}\{105}\{103}\{104}\{116}", 0);
-       CHECKFAIL_ASSERT(5, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{115}\{104}\{97}\{100}\{111}\{119}\{118}\{111}\{108}\{117}\{109}\{101}\{115}", 0);
-       CHECKFAIL_ASSERT(6, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{111}\{118}\{101}\{114}\{100}\{114}\{97}\{119}", 0);
        vf_size = getpropertyvec(VF_SIZE);
        vf_min = getpropertyvec(VF_MIN);
        vid_width = vf_size.x;
        }
  
        // do lockview after event chase camera so that it still applies whenever necessary.
 -      if(autocvar_cl_lockview || (!autocvar_hud_cursormode && (autocvar__hud_configure && spectatee_status <= 0 || intermission > 1)))
 +      if(autocvar_cl_lockview || (!autocvar_hud_cursormode && (autocvar__hud_configure && spectatee_status <= 0 || intermission > 1 || QuickMenu_IsOpened())))
        {
                setproperty(VF_ORIGIN, freeze_org);
                setproperty(VF_ANGLES, freeze_ang);
                if((dist = vlen(vec3(ov_worldmax.x, ov_worldmin.y, ov_worldmax.z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
                if((dist = vlen(vec3(ov_worldmax.x, ov_worldmax.y, ov_worldmax.z) - ov_org)) > ov_furthest) { ov_furthest = dist; }
  
+               if(!ov_enabled)
+               {
+                       oldr_nearclip = cvar("r_nearclip");
+                       oldr_farclip_base = cvar("r_farclip_base");
+                       oldr_farclip_world = cvar("r_farclip_world");
+                       oldr_novis = cvar("r_novis");
+                       oldr_useportalculling = cvar("r_useportalculling");
+                       oldr_useinfinitefarclip = cvar("r_useinfinitefarclip");
+               }
                cvar_settemp("r_nearclip", ftos(ov_nearest));
                cvar_settemp("r_farclip_base", ftos(ov_furthest));
                cvar_settemp("r_farclip_world", "0");
                setproperty(VF_ORIGIN, ov_org);
                setproperty(VF_ANGLES, '90 0 0');
  
+               ov_enabled = true;
                #if 0
-               printf("OrthoView: org = %s, angles = %s, distance = %f, nearest = %f, furthest = %f\n",
+               LOG_INFOF("OrthoView: org = %s, angles = %s, distance = %f, nearest = %f, furthest = %f\n",
                        vtos(ov_org),
                        vtos(getpropertyvec(VF_ANGLES)),
                        ov_distance,
                        ov_furthest);
                #endif
        }
+       else
+       {
+               if(ov_enabled)
+               {
+                       cvar_set("r_nearclip", ftos(oldr_nearclip));
+                       cvar_set("r_farclip_base", ftos(oldr_farclip_base));
+                       cvar_set("r_farclip_world", ftos(oldr_farclip_world));
+                       cvar_set("r_novis", ftos(oldr_novis));
+                       cvar_set("r_useportalculling", ftos(oldr_useportalculling));
+                       cvar_set("r_useinfinitefarclip", ftos(oldr_useinfinitefarclip));
+               }
+               ov_enabled = false;
+       }
  
        // Render the Scene
        view_origin = getpropertyvec(VF_ORIGIN);
                HUD_Panel_Mouse();
        else if ( HUD_MinigameMenu_IsOpened() || minigame_isactive() )
                HUD_Minigame_Mouse();
 +      else if(QuickMenu_IsOpened())
 +              QuickMenu_Mouse();
        else
                HUD_Radar_Mouse();
  
@@@ -93,7 -93,7 +93,7 @@@ void ClientCommand_checkfail(float requ
        {
                case CMD_REQUEST_COMMAND:
                {
-                       printf("CHECKFAIL: %s (%s) epically failed check %s\n", self.netname, self.netaddress, substring(command, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)));
+                       LOG_INFOF("CHECKFAIL: %s (%s) epically failed check %s\n", self.netname, self.netaddress, substring(command, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)));
                        self.checkfail = 1;
                        return; // never fall through to usage
                }
@@@ -220,163 -220,6 +220,6 @@@ void ClientCommand_join(float request
        }
  }
  
- void ClientCommand_mobedit(float request, float argc)
- {
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       if(argv(1) && argv(2))
-                       {
-                               makevectors(self.v_angle);
-                               WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 100, MOVE_NORMAL, self);
-                               if(!autocvar_g_monsters_edit) { sprint(self, "Monster property editing is not enabled.\n"); return; }
-                               if(IS_MONSTER(trace_ent))
-                               {
-                                       if(trace_ent.realowner != self) { sprint(self, "That monster does not belong to you.\n"); return; }
-                                       switch(argv(1))
-                                       {
-                                               case "skin":
-                                               {
-                                                       if(trace_ent.monsterid != MON_MAGE.monsterid)
-                                                               trace_ent.skin = stof(argv(2));
-                                                       return;
-                                               }
-                                               case "movetarget":
-                                               {
-                                                       trace_ent.monster_moveflags = stof(argv(2));
-                                                       return;
-                                               }
-                                       }
-                               }
-                       }
-               }
-               default:
-                       sprint(self, "Incorrect parameters for ^2mobedit^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       sprint(self, "\nUsage:^3 cmd mobedit [argument]\n");
-                       sprint(self, "  Where 'argument' can be skin or movetarget.\n");
-                       sprint(self, "  Aim at your monster to edit its properties.\n");
-                       return;
-               }
-       }
- }
- void ClientCommand_mobkill(float request)
- {
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       makevectors(self.v_angle);
-                       WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 100, MOVE_NORMAL, self);
-                       if(IS_MONSTER(trace_ent))
-                       {
-                               if(trace_ent.realowner != self)
-                               {
-                                       sprint(self, "That monster does not belong to you.\n");
-                                       return;
-                               }
-                               sprint(self, strcat("Your pet '", trace_ent.monster_name, "' has been brutally mutilated.\n"));
-                               Damage (trace_ent, world, world, trace_ent.health + trace_ent.max_health + 200, DEATH_KILL, trace_ent.origin, '0 0 0');
-                               return;
-                       }
-               }
-               default:
-                       sprint(self, "Incorrect parameters for ^2mobkill^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       sprint(self, "\nUsage:^3 cmd mobkill\n");
-                       sprint(self, "  Aim at your monster to kill it.\n");
-                       return;
-               }
-       }
- }
- void ClientCommand_mobspawn(float request, float argc)
- {
-       switch(request)
-       {
-               case CMD_REQUEST_COMMAND:
-               {
-                       entity e;
-                       string tospawn;
-                       float moveflag, monstercount = 0;
-                       moveflag = (argv(2) ? stof(argv(2)) : 1); // follow owner if not defined
-                       tospawn = strtolower(argv(1));
-                       if(tospawn == "list")
-                       {
-                               sprint(self, monsterlist_reply);
-                               return;
-                       }
-                       FOR_EACH_MONSTER(e)
-                       {
-                               if(e.realowner == self)
-                                       ++monstercount;
-                       }
-                       if(autocvar_g_monsters_max <= 0 || autocvar_g_monsters_max_perplayer <= 0) { sprint(self, "Monster spawning is disabled.\n"); return; }
-                       else if(!IS_PLAYER(self)) { sprint(self, "You can't spawn monsters while spectating.\n"); return; }
-                       else if(MUTATOR_CALLHOOK(AllowMobSpawning)) { sprint(self, "Monster spawning is currently disabled by a mutator.\n"); return; }
-                       else if(!autocvar_g_monsters) { Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_MONSTERS_DISABLED); return; }
-                       else if(self.vehicle) { sprint(self, "You can't spawn monsters while driving a vehicle.\n"); return; }
-                       else if(self.frozen) { sprint(self, "You can't spawn monsters while frozen.\n"); return; }
-                       else if(autocvar_g_campaign) { sprint(self, "You can't spawn monsters in campaign mode.\n"); return; }
-                       else if(self.deadflag != DEAD_NO) { sprint(self, "You can't spawn monsters while dead.\n"); return; }
-                       else if(monstercount >= autocvar_g_monsters_max_perplayer) { sprint(self, "You have spawned too many monsters, kill some before trying to spawn any more.\n"); return; }
-                       else if(totalspawned >= autocvar_g_monsters_max) { sprint(self, "The global maximum monster count has been reached, kill some before trying to spawn any more.\n"); return; }
-                       else if(tospawn != "")
-                       {
-                               float found = 0, i;
-                               entity mon;
-                               for(i = MON_FIRST; i <= MON_LAST; ++i)
-                               {
-                                       mon = get_monsterinfo(i);
-                                       if(mon.netname == tospawn)
-                                       {
-                                               found = true;
-                                               break;
-                                       }
-                               }
-                               if(found || tospawn == "random")
-                               {
-                                       totalspawned += 1;
-                                       makevectors(self.v_angle);
-                                       WarpZone_TraceBox (CENTER_OR_VIEWOFS(self), PL_MIN, PL_MAX, CENTER_OR_VIEWOFS(self) + v_forward * 150, true, self);
-                                       //WarpZone_TraceLine(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 150, MOVE_NORMAL, self);
-                                       e = spawnmonster(tospawn, 0, self, self, trace_endpos, false, false, moveflag);
-                                       sprint(self, strcat("Spawned ", e.monster_name, "\n"));
-                                       return;
-                               }
-                       }
-               }
-               default:
-                       sprint(self, "Incorrect parameters for ^2mobspawn^7\n");
-               case CMD_REQUEST_USAGE:
-               {
-                       sprint(self, "\nUsage:^3 cmd mobspawn <random> <monster> [movetype]\n");
-                       sprint(self, "  See 'cmd mobspawn list' for available monsters.\n");
-                       sprint(self, "  Argument 'random' spawns a random monster.\n");
-                       sprint(self, "  Monster will follow the owner if second argument is not defined.\n");
-                       return;
-               }
-       }
- }
  void ClientCommand_physics(float request, float argc)
  {
        switch(request)
@@@ -717,18 -560,7 +560,18 @@@ void ClientCommand_tell(float request, 
                                {
                                        if(tell_to != self) // and we're allowed to send to them :D
                                        {
 -                                              Say(self, false, tell_to, substring(command, argv_start_index(next_token), argv_end_index(-1) - argv_start_index(next_token)), true);
 +                                              // workaround for argv indexes indexing ascii chars instead of utf8 chars
 +                                              // In this case when the player name contains utf8 chars
 +                                              // the message gets partially trimmed in the beginning.
 +                                              // Potentially this bug affects any substring call that uses
 +                                              // argv_start_index and argv_end_index.
 +
 +                                              string utf8_enable_save = cvar_string("utf8_enable");
 +                                              cvar_set("utf8_enable", "0");
 +                                              string msg = substring(command, argv_start_index(next_token), argv_end_index(-1) - argv_start_index(next_token));
 +                                              cvar_set("utf8_enable", utf8_enable_save);
 +
 +                                              Say(self, false, tell_to, msg, true);
                                                return;
                                        }
                                        else { print_to(self, "You can't ^2tell^7 a message to yourself."); return; }
@@@ -817,9 -649,6 +660,6 @@@ void ClientCommand_(float request
        CLIENT_COMMAND("clientversion", ClientCommand_clientversion(request, arguments), "Release version of the game") \
        CLIENT_COMMAND("mv_getpicture", ClientCommand_mv_getpicture(request, arguments), "Retrieve mapshot picture from the server") \
        CLIENT_COMMAND("join", ClientCommand_join(request), "Become a player in the game") \
-       CLIENT_COMMAND("mobedit", ClientCommand_mobedit(request, arguments), "Edit your monster's properties") \
-       CLIENT_COMMAND("mobkill", ClientCommand_mobkill(request), "Kills your monster") \
-       CLIENT_COMMAND("mobspawn", ClientCommand_mobspawn(request, arguments), "Spawn monsters infront of yourself") \
        CLIENT_COMMAND("physics", ClientCommand_physics(request, arguments), "Change physics set") \
        CLIENT_COMMAND("ready", ClientCommand_ready(request), "Qualify as ready to end warmup stage (or restart server if allowed)") \
        CLIENT_COMMAND("say", ClientCommand_say(request, arguments, command), "Print a message to chat to all players") \