Merge branch 'master' into terencehill/welcome_dialog_translatable
authorterencehill <piuntn@gmail.com>
Fri, 8 Apr 2022 12:37:02 +0000 (14:37 +0200)
committerterencehill <piuntn@gmail.com>
Fri, 8 Apr 2022 12:37:02 +0000 (14:37 +0200)
19 files changed:
qcsrc/client/main.qc
qcsrc/common/mutators/mutator/hook/_mod.inc
qcsrc/common/mutators/mutator/hook/_mod.qh
qcsrc/common/mutators/mutator/hook/cl_hook.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/hook/cl_hook.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/hook/sv_hook.qc
qcsrc/common/mutators/mutator/instagib/sv_instagib.qc
qcsrc/common/mutators/mutator/melee_only/sv_melee_only.qc
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/offhand_blaster/_mod.inc
qcsrc/common/mutators/mutator/offhand_blaster/_mod.qh
qcsrc/common/mutators/mutator/offhand_blaster/cl_offhand_blaster.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/offhand_blaster/cl_offhand_blaster.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/offhand_blaster/sv_offhand_blaster.qc
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/server/client.qc
qcsrc/server/world.qc

index 8165f4cead3f76540654bef10b0eaf3bc713885c..1c7013a83406f4da3f2e093baba2178a654004b2 100644 (file)
@@ -1316,6 +1316,55 @@ NET_HANDLE(TE_CSQC_WEAPONCOMPLAIN, bool isNew)
        }
 }
 
+string translate_modifications(string s)
+{
+       return build_mutator_list(s);
+}
+
+string translate_weaponarena(string s)
+{
+       if (s == "") return s;
+       if (s == "All Weapons Arena") return _("All Weapons Arena");
+       if (s == "All Available Weapons Arena") return _("All Available Weapons Arena");
+       if (s == "Most Weapons Arena") return _("Most Weapons Arena");
+       if (s == "Most Available Weapons Arena") return _("Most Available Weapons Arena");
+       if (s == "Dev All Weapons Arena") return s; // development option, do not translate
+       if (s == "Dev All Available Weapons Arena") return s; // development option, do not translate
+       if (s == "No Weapons Arena") return _("No Weapons Arena");
+
+       int n = tokenizebyseparator(s, " & ");
+       string wpn_list = "";
+       for (int i = 0; i < n; i++)
+       {
+               Weapon wep = Weapon_from_name(argv(i));
+               if (wep == WEP_Null)
+                       LOG_INFO("^3Warning: ^7server sent an invalid weapon name\n");
+               wpn_list = cons_mid(wpn_list, " & ", wep.m_name);
+       }
+       if (wpn_list != "")
+               return sprintf(_("%s Arena"), wpn_list);
+       else
+               return _("No Weapons Arena");
+}
+
+string GetVersionMessage(string hostversion, bool version_mismatch, bool version_check)
+{
+       string xonotic_hostversion = strcat("Xonotic ", hostversion);
+       if (version_mismatch)
+       {
+               if(!version_check)
+                       return strcat(sprintf(_("This is %s"), xonotic_hostversion), "\n^3",
+                               _("Your client version is outdated."), "\n\n\n",
+                               _("### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###"), "\n\n\n",
+                               _("Please update!"));
+               else
+                       return strcat(sprintf(_("This is %s"), xonotic_hostversion), "\n^3",
+                               _("This server is using an outdated Xonotic version."), "\n\n\n",
+                               _("### THIS SERVER IS INCOMPATIBLE AND THUS YOU CANNOT JOIN ###"));
+       }
+       return sprintf(_("Welcome to %s"), xonotic_hostversion);
+}
+
 bool net_handle_ServerWelcome()
 {
        bool campaign = ReadByte();
@@ -1339,20 +1388,32 @@ bool net_handle_ServerWelcome()
 
        bool force_centerprint = ReadByte();
        string hostname = ReadString();
-       string ver = ReadString();
-       string modifications = ReadString();
+
+       string hostversion = ReadString();
+       bool version_mismatch = ReadByte();
+       bool version_check = ReadByte();
+       string ver = GetVersionMessage(hostversion, version_mismatch, version_check);
+
+       string modifications = translate_modifications(ReadString());
+       string weaponarena_list = translate_weaponarena(ReadString());
        string cache_mutatormsg = ReadString();
-       string mutator_msg = ReadString();
        string motd = ReadString();
 
        string msg = "";
        msg = strcat(msg, ver);
        msg = strcat(msg, "^8\n\n", strcat(_("Gametype:"), " ^1", MapInfo_Type_ToText(gametype)), "^8\n");
+
+       modifications = cons_mid(modifications, ", ", weaponarena_list);
        if(modifications != "")
                msg = strcat(msg, "^8\n", _("Active modifications:"), " ^3", modifications, "^8\n");
+
        if (cache_mutatormsg != "")
                msg = strcat(msg, "\n\n^8", _("Special gameplay tips:"), " ^7", cache_mutatormsg);
+       string mutator_msg = "";
+       MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg);
+       mutator_msg = M_ARGV(0, string);
        msg = strcat(msg, mutator_msg); // trust that the mutator will do proper formatting
+
        if (motd != "")
                msg = strcat(msg, "\n\n^8", _("MOTD:"), " ^7", motd);
 
index e5e68b6106fed48992f8d3d743eb9f087ac168c6..626c4cffa673fed98b3a14f972594068a0eaca51 100644 (file)
@@ -1,4 +1,7 @@
 // generated file; do not modify
+#ifdef CSQC
+    #include <common/mutators/mutator/hook/cl_hook.qc>
+#endif
 #ifdef SVQC
     #include <common/mutators/mutator/hook/sv_hook.qc>
 #endif
index 5a5d26e8172fd5ee077fc200e18a519b64acca0c..1216e36e8bacd8feb26deba268219a1c334c921d 100644 (file)
@@ -1,4 +1,7 @@
 // generated file; do not modify
+#ifdef CSQC
+    #include <common/mutators/mutator/hook/cl_hook.qh>
+#endif
 #ifdef SVQC
     #include <common/mutators/mutator/hook/sv_hook.qh>
 #endif
diff --git a/qcsrc/common/mutators/mutator/hook/cl_hook.qc b/qcsrc/common/mutators/mutator/hook/cl_hook.qc
new file mode 100644 (file)
index 0000000..be88853
--- /dev/null
@@ -0,0 +1,16 @@
+#include "cl_hook.qh"
+
+#ifdef CSQC
+REGISTER_MUTATOR(cl_hook, true);
+
+MUTATOR_HOOKFUNCTION(cl_hook, BuildGameplayTipsString)
+{
+       if (mut_is_active(MUT_GRAPPLING_HOOK))
+       {
+               string key = getcommandkey(_("off-hand hook"), "+hook");
+               M_ARGV(0, string) = strcat(M_ARGV(0, string),
+                       "\n\n", sprintf(_("^3grappling hook^8 is enabled, press ^3%s^8 to use it"), key), "\n");
+       }
+}
+
+#endif
diff --git a/qcsrc/common/mutators/mutator/hook/cl_hook.qh b/qcsrc/common/mutators/mutator/hook/cl_hook.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index c6a595363c3a272f64b4a4e0f89de37c7e94e9c6..94379cbb2828410315ee8312c1f42844a32dcdb1 100644 (file)
@@ -30,11 +30,6 @@ MUTATOR_HOOKFUNCTION(hook, BuildMutatorsPrettyString)
     M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Hook");
 }
 
-MUTATOR_HOOKFUNCTION(hook, BuildGameplayTipsString)
-{
-    M_ARGV(0, string) = strcat(M_ARGV(0, string), "\n\n^3grappling hook^8 is enabled, press 'e' (+hook) to use it\n");
-}
-
 MUTATOR_HOOKFUNCTION(hook, SetStartItems)
 {
     if(autocvar_g_grappling_hook_useammo)
index 2abb0b5967483dcf11383b5b417bd367f89a6c29..2131228ebf2e47a13a7676b0e09d5c9fad16caac 100644 (file)
@@ -453,7 +453,7 @@ MUTATOR_HOOKFUNCTION(mutator_instagib, BuildMutatorsString)
 
 MUTATOR_HOOKFUNCTION(mutator_instagib, BuildMutatorsPrettyString)
 {
-       M_ARGV(0, string) = strcat(M_ARGV(0, string), ", instagib");
+       M_ARGV(0, string) = strcat(M_ARGV(0, string), ", InstaGib");
 }
 
 MUTATOR_HOOKFUNCTION(mutator_instagib, SetModname)
index 2596770daa57be0c2b595873d79f18ecb40ee66f..ec031730e5ee60e1b94e642bec059657f53644db 100644 (file)
@@ -48,5 +48,5 @@ MUTATOR_HOOKFUNCTION(melee_only, BuildMutatorsString)
 
 MUTATOR_HOOKFUNCTION(melee_only, BuildMutatorsPrettyString)
 {
-       M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Melee Only Arena");
+       M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Melee only Arena");
 }
index 7a00bd686b5b122b4b481e42fced7119becc67ce..5ea4cb49cfb9a4d4deb6802d8bf8e82d1cad3491 100644 (file)
@@ -117,6 +117,17 @@ MUTATOR_HOOKFUNCTION(cl_nades, EditProjectile)
        else
                proj.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY;
 }
+
+MUTATOR_HOOKFUNCTION(cl_nades, BuildGameplayTipsString)
+{
+       if (mut_is_active(MUT_NADES))
+       {
+               string key = getcommandkey(_("drop weapon / throw nade"), "dropweapon");
+               M_ARGV(0, string) = strcat(M_ARGV(0, string),
+                       "\n\n", sprintf(_("^3nades^8 are enabled, press ^3%s^8 to use them"), key), "\n");
+       }
+}
+
 bool Projectile_isnade(int p)
 {
        return Nade_FromProjectile(p) != NADE_TYPE_Null;
@@ -1564,14 +1575,14 @@ MUTATOR_HOOKFUNCTION(nades, SpectateCopy)
        STAT(VEIL_ORB_ALPHA, client) = STAT(VEIL_ORB_ALPHA, spectatee);
 }
 
-MUTATOR_HOOKFUNCTION(nades, BuildMutatorsString)
+MUTATOR_HOOKFUNCTION(nades, BuildMutatorsPrettyString)
 {
-       M_ARGV(0, string) = strcat(M_ARGV(0, string), ":Nades");
+       M_ARGV(0, string) = strcat(M_ARGV(0, string), "Nades");
 }
 
-MUTATOR_HOOKFUNCTION(nades, BuildGameplayTipsString)
+MUTATOR_HOOKFUNCTION(nades, BuildMutatorsString)
 {
-       M_ARGV(0, string) = strcat(M_ARGV(0, string), "\n\n^3nades^8 are enabled, press 'g' (dropweapon) to use them\n");
+       M_ARGV(0, string) = strcat(M_ARGV(0, string), ":Nades");
 }
 
 #endif
index 41bb01e55eeaee272278e8ede77ab4f8c05be397..0a555570d1d6f6b83db21e4ee1275425cfde8542 100644 (file)
@@ -1,4 +1,7 @@
 // generated file; do not modify
+#ifdef CSQC
+    #include <common/mutators/mutator/offhand_blaster/cl_offhand_blaster.qc>
+#endif
 #ifdef SVQC
     #include <common/mutators/mutator/offhand_blaster/sv_offhand_blaster.qc>
 #endif
index 5e11096a532644d671eb7bd409b0519e08d3c3bd..2c4587f417b2e1e3820e3f4b1facd22e55b1d772 100644 (file)
@@ -1,4 +1,7 @@
 // generated file; do not modify
+#ifdef CSQC
+    #include <common/mutators/mutator/offhand_blaster/cl_offhand_blaster.qh>
+#endif
 #ifdef SVQC
     #include <common/mutators/mutator/offhand_blaster/sv_offhand_blaster.qh>
 #endif
diff --git a/qcsrc/common/mutators/mutator/offhand_blaster/cl_offhand_blaster.qc b/qcsrc/common/mutators/mutator/offhand_blaster/cl_offhand_blaster.qc
new file mode 100644 (file)
index 0000000..f6b15ae
--- /dev/null
@@ -0,0 +1,13 @@
+#include "cl_offhand_blaster.qh"
+
+REGISTER_MUTATOR(cl_offhand_blaster, true);
+
+MUTATOR_HOOKFUNCTION(cl_offhand_blaster, BuildGameplayTipsString)
+{
+       if (mut_is_active(MUT_OFFHAND_BLASTER))
+       {
+               string key = getcommandkey(_("off-hand hook"), "+hook");
+               M_ARGV(0, string) = strcat(M_ARGV(0, string),
+                       "\n\n", sprintf(_("^3offhand blaster^8 is enabled, press ^3%s^8 to use it"), key), "\n");
+       }
+}
diff --git a/qcsrc/common/mutators/mutator/offhand_blaster/cl_offhand_blaster.qh b/qcsrc/common/mutators/mutator/offhand_blaster/cl_offhand_blaster.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
index fbffa8a439cd241d5977bde45d876661fdcb9c7e..931ab1ad9991f517cde5ab95e56f5f4dd53a9db7 100644 (file)
@@ -14,11 +14,6 @@ MUTATOR_HOOKFUNCTION(offhand_blaster, BuildMutatorsPrettyString)
        M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Offhand blaster");
 }
 
-MUTATOR_HOOKFUNCTION(offhand_blaster, BuildGameplayTipsString)
-{
-    M_ARGV(0, string) = strcat(M_ARGV(0, string), "\n\n^3offhand blaster^8 is enabled, press 'e' (+hook) to use it\n");
-}
-
 MUTATOR_HOOKFUNCTION(offhand_blaster, PlayerSpawn)
 {
        entity player = M_ARGV(0, entity);
index 469ab50d8c809bc4d52d6d4d27e3cc70693b7722..1dc444b3ec3181e8012bfcb9182416d996cd7512 100644 (file)
@@ -210,6 +210,70 @@ string draw_UseSkinFor(string pic)
        else
                return strcat(draw_currentSkin, "/", pic);
 }
+
+void mut_set_active(int mut)
+{
+       if (mut >= 24)
+               active_mutators[1] |= BIT(mut - 24);
+       else
+               active_mutators[0] |= BIT(mut);
+}
+
+bool mut_is_active(int mut)
+{
+       if (mut >= 24)
+               return (active_mutators[1] & (BIT(mut - 24)));
+       else
+               return (active_mutators[0] & BIT(mut));
+}
+
+// if s == "" (MENUQC) builds the mutator list for the Mutators dialog based on local cvar values
+// otherwise (CSQC) translates the mutator list (s) that client has received from server
+// NOTE: this function merges MENUQC and CSQC code in order to avoid duplicating and separating strings
+string build_mutator_list(string s)
+{
+       int i = -1, n = 0; // allow only 1 iteration in the following for loop if (s == "")
+       if (s != "")
+       {
+               i = 0;
+               n = tokenizebyseparator(s, ", ");
+       }
+       string s2 = "";
+       for (string arg = ""; i < n; i++)
+       {
+               if (i >= 0) arg = argv(i);
+               // cond is the condition for showing the mutator enabled in the menu
+               #define X(name, translated_name, mut, cond) \
+                       if(arg == name || (!n && (cond))) { s2 = cons_mid(s2, ", ", translated_name); mut_set_active(mut); }
+               X("Dodging"                   , _("Dodging")                   , MUT_DODGING                   , cvar("g_dodging"))
+               X("InstaGib"                  , _("InstaGib")                  , MUT_INSTAGIB                  , cvar("g_instagib"))
+               X("New Toys"                  , _("New Toys")                  , MUT_NEW_TOYS                  , cvar("g_new_toys"))
+               X("NIX"                       , _("NIX")                       , MUT_NIX                       , cvar("g_nix"))
+               X("Rocket Flying"             , _("Rocket Flying")             , MUT_ROCKET_FLYING             , cvar("g_rocket_flying"))
+               X("Invincible Projectiles"    , _("Invincible Projectiles")    , MUT_INVINCIBLE_PROJECTILES    , cvar("g_invincible_projectiles"))
+               X("Low gravity"               , _("Low gravity")               , MUT_GRAVITY                   , cvar("sv_gravity") < stof(cvar_defstring("sv_gravity")))
+               X("Cloaked"                   , _("Cloaked")                   , MUT_CLOAKED                   , cvar("g_cloaked"))
+               X("Hook"                      , _("Hook")                      , MUT_GRAPPLING_HOOK            , cvar("g_grappling_hook"))
+               X("Midair"                    , _("Midair")                    , MUT_MIDAIR                    , cvar("g_midair"))
+               X("Melee only Arena"          , _("Melee only Arena")          , MUT_MELEE_ONLY                , cvar("g_melee_only"))
+               X("Vampire"                   , _("Vampire")                   , MUT_VAMPIRE                   , cvar("g_vampire"))
+               X("Piñata"                    , _("Piñata")                    , MUT_PINATA                    , cvar("g_pinata"))
+               X("Weapons stay"              , _("Weapons stay")              , MUT_WEAPON_STAY               , cvar("g_weapon_stay"))
+               X("Blood loss"                , _("Blood loss")                , MUT_BLOODLOSS                 , cvar("g_bloodloss") > 0)
+               X("Jetpack"                   , _("Jetpack")                   , MUT_JETPACK                   , cvar("g_jetpack"))
+               X("Buffs"                     , _("Buffs")                     , MUT_BUFFS                     , cvar("g_buffs") > 0)
+               X("Overkill"                  , _("Overkill")                  , MUT_OVERKILL                  , cvar("g_overkill"))
+               X("No powerups"               , _("No powerups")               , MUT_NO_POWERUPS               , cvar("g_powerups") == 0)
+               X("Powerups"                  , _("Powerups")                  , MUT_POWERUPS                  , cvar("g_powerups") > 0)
+               X("Touch explode"             , _("Touch explode")             , MUT_TOUCHEXPLODE              , cvar("g_touchexplode") > 0)
+               X("Wall jumping"              , _("Wall jumping")              , MUT_WALLJUMP                  , cvar("g_walljump"))
+               X("No start weapons"          , _("No start weapons")          , MUT_NO_START_WEAPONS          , cvar_string("g_weaponarena") == "0" && cvar("g_balance_blaster_weaponstartoverride") == 0)
+               X("Nades"                     , _("Nades")                     , MUT_NADES                     , cvar("g_nades"))
+               X("Offhand blaster"           , _("Offhand blaster")           , MUT_OFFHAND_BLASTER           , cvar("g_offhand_blaster"))
+               #undef X
+       }
+       return s2;
+}
 #endif
 
 void wordwrap_cb(string s, float l, void(string) callback)
index 1334f5ec35c392d41be44559cade95dc561931c7..3ca09994ac3be97da0b957c4c512138255b832bd 100644 (file)
@@ -44,6 +44,40 @@ void wordwrap_cb(string s, float l, void(string) callback);
 #ifndef SVQC
 string draw_currentSkin;
 string draw_UseSkinFor(string pic);
+
+// NOTE they aren't all registered mutators, e.g. jetpack, low gravity
+// TODO add missing "mutators"
+const int MUT_DODGING = 0;
+const int MUT_INSTAGIB = 1;
+const int MUT_NEW_TOYS = 2;
+const int MUT_NIX = 3;
+const int MUT_ROCKET_FLYING = 4;
+const int MUT_INVINCIBLE_PROJECTILES = 5;
+const int MUT_GRAVITY = 6;
+const int MUT_CLOAKED = 7;
+const int MUT_GRAPPLING_HOOK = 8;
+const int MUT_MIDAIR = 9;
+const int MUT_MELEE_ONLY = 10;
+const int MUT_VAMPIRE = 11;
+const int MUT_PINATA = 12;
+const int MUT_WEAPON_STAY = 13;
+const int MUT_BLOODLOSS = 14;
+const int MUT_JETPACK = 15;
+const int MUT_BUFFS = 16;
+const int MUT_OVERKILL = 17;
+const int MUT_NO_POWERUPS = 18;
+const int MUT_POWERUPS = 19;
+const int MUT_TOUCHEXPLODE = 20;
+const int MUT_WALLJUMP = 21;
+const int MUT_NO_START_WEAPONS = 22;
+const int MUT_NADES = 23;
+const int MUT_OFFHAND_BLASTER = 24;
+
+const int MUT_MAX = 47;
+
+int active_mutators[2];
+bool mut_is_active(int mut);
+string build_mutator_list(string s);
 #endif
 
 // iterative depth-first search, with fields that go "up", "down left" and "right" in a tree
index 7473e8e8da66619524e0abdfefd2592f6fb85c36..564ffc5ae578e37bea3e8ddf63adc35c39b4522c 100644 (file)
@@ -22,12 +22,13 @@ string WeaponArenaString()
        string s;
        float n;
        s = cvar_string("g_weaponarena");
-       if(s == "0")
-               return "";
-       if(s == "all" || s == "1")
-               return _("All Weapons Arena");
-       if(s == "most")
-               return _("Most Weapons Arena");
+       if(s == "0" || s == "") return "";
+       if(s == "all" || s == "1") return _("All Weapons Arena");
+       if(s == "all_available") return _("All Available Weapons Arena");
+       if(s == "most") return _("Most Weapons Arena");
+       if(s == "most_available") return _("Most Available Weapons Arena");
+       if(s == "devall") return "Dev All Weapons Arena"; // development option, do not translate
+       if(s == "devall_available") return "Dev All Available Weapons Arena"; // development option, do not translate
        if(s == weaponarenastring_cvar)
                return weaponarenastring;
 
@@ -43,7 +44,10 @@ string WeaponArenaString()
                        s = cons_mid(s, " & ", wep.m_name);
                }
        }
-       s = sprintf(_("%s Arena"), s);
+       if (s != "")
+               s = sprintf(_("%s Arena"), s);
+       else
+               s = _("No Weapons Arena");
 
        strcpy(weaponarenastring, s);
 
@@ -52,55 +56,9 @@ string WeaponArenaString()
 
 string XonoticMutatorsDialog_toString(entity me)
 {
-       string s = "";
-       if(cvar("g_dodging"))
-               s = cons_mid(s, ", ", _("Dodging"));
-       if(cvar("g_instagib"))
-               s = cons_mid(s, ", ", _("InstaGib"));
-       if(cvar("g_new_toys"))
-               s = cons_mid(s, ", ", _("New Toys"));
-       if(cvar("g_nix"))
-               s = cons_mid(s, ", ", _("NIX"));
-       if(cvar("g_rocket_flying"))
-               s = cons_mid(s, ", ", _("Rocket Flying"));
-       if(cvar("g_invincible_projectiles"))
-               s = cons_mid(s, ", ", _("Invincible Projectiles"));
+       string s = build_mutator_list("");
        if(cvar_string("g_weaponarena") != "0")
                s = cons_mid(s, ", ", WeaponArenaString());
-       else if(cvar("g_balance_blaster_weaponstartoverride") == 0)
-               s = cons_mid(s, ", ", _("No start weapons"));
-       if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity")))
-               s = cons_mid(s, ", ", _("Low gravity"));
-       if(cvar("g_cloaked"))
-               s = cons_mid(s, ", ", _("Cloaked"));
-       if(cvar("g_grappling_hook"))
-               s = cons_mid(s, ", ", _("Hook"));
-       if(cvar("g_midair"))
-               s = cons_mid(s, ", ", _("Midair"));
-       if(cvar("g_melee_only"))
-               s = cons_mid(s, ", ", _("Melee only"));
-       if(cvar("g_vampire"))
-               s = cons_mid(s, ", ", _("Vampire"));
-       if(cvar("g_pinata"))
-               s = cons_mid(s, ", ", _("Piñata"));
-       if(cvar("g_weapon_stay"))
-               s = cons_mid(s, ", ", _("Weapons stay"));
-       if(cvar("g_bloodloss") > 0)
-               s = cons_mid(s, ", ", _("Blood loss"));
-       if(cvar("g_jetpack"))
-               s = cons_mid(s, ", ", _("Jetpack"));
-       if(cvar("g_buffs") > 0)
-               s = cons_mid(s, ", ", _("Buffs"));
-       if(cvar("g_overkill"))
-               s = cons_mid(s, ", ", _("Overkill"));
-       if(cvar("g_powerups") == 0)
-               s = cons_mid(s, ", ", _("No powerups"));
-       if(cvar("g_powerups") > 0)
-               s = cons_mid(s, ", ", _("Powerups"));
-       if(cvar("g_touchexplode") > 0)
-               s = cons_mid(s, ", ", _("Touch explode"));
-       if(cvar("g_walljump"))
-               s = cons_mid(s, ", ", _("Wall jumping"));
        if(s == "")
                return ZCTX(_("MUT^None"));
        else
index a5f508851b00876304e486f92f9fcb9634d6f438..097cafda03813137afac5c0c28f57fe0c6841c8d 100644 (file)
@@ -1018,21 +1018,6 @@ void ClientPreConnect(entity this)
 }
 #endif
 
-string GetClientVersionMessage(entity this)
-{
-       if (CS(this).version_mismatch) {
-               if(CS(this).version < autocvar_gameversion) {
-                       return strcat("This is Xonotic ", autocvar_g_xonoticversion,
-                               "\n^3Your client version is outdated.\n\n\n### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###\n\n\nPlease update!!!^8");
-               } else {
-                       return strcat("This is Xonotic ", autocvar_g_xonoticversion,
-                               "\n^3This server is using an outdated Xonotic version.\n\n\n ### THIS SERVER IS INCOMPATIBLE AND THUS YOU CANNOT JOIN ###.^8");
-               }
-       } else {
-               return strcat("Welcome to Xonotic ", autocvar_g_xonoticversion);
-       }
-}
-
 void SendWelcomemessage(entity this, bool force_centerprint)
 {
        msg_entity = this;
@@ -1040,6 +1025,9 @@ void SendWelcomemessage(entity this, bool force_centerprint)
        SendWelcomemessage_msg_type(this, force_centerprint, MSG_ONE);
 }
 
+// NOTE csqc uses the active mutators list sent by this function
+// to understand which mutators are enabled
+// also note that they aren't all registered mutators, e.g. jetpack, low gravity
 void SendWelcomemessage_msg_type(entity this, bool force_centerprint, int msg_type)
 {
        WriteByte(msg_type, boolean(autocvar_g_campaign));
@@ -1052,30 +1040,27 @@ void SendWelcomemessage_msg_type(entity this, bool force_centerprint, int msg_ty
        }
        WriteByte(msg_type, force_centerprint);
        WriteString(msg_type, autocvar_hostname);
-       WriteString(msg_type, GetClientVersionMessage(this));
+       WriteString(msg_type, autocvar_g_xonoticversion);
+       WriteByte(msg_type, CS(this).version_mismatch);
+       WriteByte(msg_type, (CS(this).version < autocvar_gameversion));
 
        MUTATOR_CALLHOOK(BuildMutatorsPrettyString, "");
        string modifications = M_ARGV(0, string);
 
-       if(g_weaponarena)
-       {
-               if(g_weaponarena_random)
-                       modifications = strcat(modifications, ", ", ftos(g_weaponarena_random), " of ", g_weaponarena_list, " Arena");
-               else
-                       modifications = strcat(modifications, ", ", g_weaponarena_list, " Arena");
-       }
-       else if(cvar("g_balance_blaster_weaponstartoverride") == 0)
+       if (!g_weaponarena && cvar("g_balance_blaster_weaponstartoverride") == 0)
                modifications = strcat(modifications, ", No start weapons");
        if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity")))
                modifications = strcat(modifications, ", Low gravity");
        if(g_weapon_stay && !g_cts)
                modifications = strcat(modifications, ", Weapons stay");
        if(autocvar_g_jetpack)
-               modifications = strcat(modifications, ", Jet pack");
+               modifications = strcat(modifications, ", Jetpack");
        modifications = substring(modifications, 2, strlen(modifications) - 2);
 
        WriteString(msg_type, modifications);
 
+       WriteString(msg_type, g_weaponarena_list);
+
        if(cache_lastmutatormsg != autocvar_g_mutatormsg)
        {
                strcpy(cache_lastmutatormsg, autocvar_g_mutatormsg);
@@ -1084,11 +1069,6 @@ void SendWelcomemessage_msg_type(entity this, bool force_centerprint, int msg_ty
 
        WriteString(msg_type, cache_mutatormsg);
 
-       string mutator_msg = "";
-       MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg);
-       mutator_msg = M_ARGV(0, string);
-
-       WriteString(msg_type, mutator_msg); // trust that the mutator will do proper formatting
        WriteString(msg_type, strreplace("\\n", "\n", autocvar_sv_motd));
 }
 
index 5801fae88a3eb2fbd06d091e81bed09b779c38d4..9d4678ffd4814a04aed3a0185828e36dfbf8026a 100644 (file)
@@ -1884,25 +1884,25 @@ void readplayerstartcvars()
        else if (s == "all" || s == "1")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "All Weapons";
+               g_weaponarena_list = "All Weapons Arena";
                g_weaponarena_weapons = weapons_all();
        }
        else if (s == "devall")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "Dev All Weapons";
+               g_weaponarena_list = "Dev All Weapons Arena";
                g_weaponarena_weapons = weapons_devall();
        }
        else if (s == "most")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "Most Weapons";
+               g_weaponarena_list = "Most Weapons Arena";
                g_weaponarena_weapons = weapons_most();
        }
        else if (s == "all_available")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "All Available Weapons";
+               g_weaponarena_list = "All Available Weapons Arena";
 
                // this needs to run after weaponsInMapAll is initialized
                InitializeEntity(NULL, weaponarena_available_all_update, INITPRIO_FINDTARGET);
@@ -1910,7 +1910,7 @@ void readplayerstartcvars()
        else if (s == "devall_available")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "Dev All Available Weapons";
+               g_weaponarena_list = "Dev All Available Weapons Arena";
 
                // this needs to run after weaponsInMapAll is initialized
                InitializeEntity(NULL, weaponarena_available_devall_update, INITPRIO_FINDTARGET);
@@ -1918,7 +1918,7 @@ void readplayerstartcvars()
        else if (s == "most_available")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "Most Available Weapons";
+               g_weaponarena_list = "Most Available Weapons Arena";
 
                // this needs to run after weaponsInMapAll is initialized
                InitializeEntity(NULL, weaponarena_available_most_update, INITPRIO_FINDTARGET);
@@ -1926,7 +1926,7 @@ void readplayerstartcvars()
        else if (s == "none")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "No Weapons";
+               g_weaponarena_list = "No Weapons Arena";
        }
        else
        {
@@ -1940,10 +1940,13 @@ void readplayerstartcvars()
                        if(wep != WEP_Null)
                        {
                                g_weaponarena_weapons |= (wep.m_wepset);
-                               g_weaponarena_list = strcat(g_weaponarena_list, wep.m_name, " & ");
+                               g_weaponarena_list = strcat(g_weaponarena_list, wep.netname, " & ");
                        }
                }
-               g_weaponarena_list = strzone(substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3));
+               if (g_weaponarena_list != "") // remove trailing " & "
+                       g_weaponarena_list = substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3);
+               else // no valid weapon found
+                       g_weaponarena_list = "No Weapons Arena";
        }
 
        if (g_weaponarena)
@@ -1951,6 +1954,7 @@ void readplayerstartcvars()
                g_weapon_stay = 0; // incompatible
                start_weapons = g_weaponarena_weapons;
                start_items |= IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS;
+               g_weaponarena_list = strzone(g_weaponarena_list);
        }
        else
        {