]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'terencehill/chat_maximized_scrollable' into 'master'
authorterencehill <piuntn@gmail.com>
Sat, 5 Feb 2022 11:06:03 +0000 (11:06 +0000)
committerterencehill <piuntn@gmail.com>
Sat, 5 Feb 2022 11:06:03 +0000 (11:06 +0000)
Allow scrolling the maximized chat history by pressing mouse wheel up/down

See merge request xonotic/xonotic-data.pk3dir!974

34 files changed:
.tx/merge-base
common.pt_BR.po
common.tr.po
gamemodes-server.cfg
qcsrc/common/constants.qh
qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc
qcsrc/common/playerstats.qc
qcsrc/lib/urllib.qh
qcsrc/menu/xonotic/_mod.inc
qcsrc/menu/xonotic/_mod.qh
qcsrc/menu/xonotic/credits.qc
qcsrc/menu/xonotic/dialog_firstrun.qc
qcsrc/menu/xonotic/dialog_firstrun.qh
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qh
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qc [new file with mode: 0644]
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qh [new file with mode: 0644]
qcsrc/menu/xonotic/dialog_multiplayer_join_termsofservice.qc [new file with mode: 0644]
qcsrc/menu/xonotic/dialog_multiplayer_join_termsofservice.qh [new file with mode: 0644]
qcsrc/menu/xonotic/dialog_termsofservice.qc [new file with mode: 0644]
qcsrc/menu/xonotic/dialog_termsofservice.qh [new file with mode: 0644]
qcsrc/menu/xonotic/mainwindow.qc
qcsrc/menu/xonotic/mainwindow.qh
qcsrc/menu/xonotic/playerlist.qc
qcsrc/menu/xonotic/serverlist.qc
qcsrc/menu/xonotic/textbox.qc [new file with mode: 0644]
qcsrc/menu/xonotic/textbox.qh [new file with mode: 0644]
qcsrc/menu/xonotic/util.qc
qcsrc/menu/xonotic/util.qh
qcsrc/server/bot/default/bot.qc
qcsrc/server/scores.qc
qcsrc/server/world.qc
qcsrc/server/world.qh
xonotic-client.cfg

index 24b03de2faad32d3f01f1dcb389550ad164237e1..7044dd87b04a0380ba634bd2d1c530c034172967 100644 (file)
@@ -1 +1 @@
-Fri Jan 28 07:23:07 CET 2022
+Fri Feb  4 07:23:04 CET 2022
index 7abebc98bc398ac569237234fba653b04e9031f3..d45c32c099610dde23b87f022e9c92a46b887d48 100644 (file)
@@ -9,7 +9,7 @@
 # NotThatPrivate Yes <henriqueferreira2009@gmail.com>, 2015
 # Ricardo Manuel da Cruz Coelho da Silva <ricardo.mccs@gmail.com>, 2015
 # Rui <xymarior@yandex.com>, 2018
-# yy0zz, 2021
+# yy0zz, 2021-2022
 # yy0zz, 2021
 # zerowhy . <anymailz@tutanota.com>, 2021
 msgid ""
@@ -17,7 +17,7 @@ msgstr ""
 "Project-Id-Version: Xonotic\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2021-11-28 07:22+0100\n"
-"PO-Revision-Date: 2021-12-27 13:05+0000\n"
+"PO-Revision-Date: 2022-02-03 17:10+0000\n"
 "Last-Translator: yy0zz\n"
 "Language-Team: Portuguese (Brazil) (http://www.transifex.com/team-xonotic/"
 "xonotic/language/pt_BR/)\n"
@@ -10172,7 +10172,7 @@ msgstr "Dezembro"
 #: qcsrc/menu/xonotic/statslist.qc:46
 #, no-c-format
 msgid "DATE^%m %d, %Y"
-msgstr "DATA ^%m %d, %Y"
+msgstr "%d de %m de %Y"
 
 #: qcsrc/menu/xonotic/statslist.qc:97
 msgid "Joined:"
index 16a0da7e33a14170d58fd67270630db152b502c8..71ce6aa20ea709cb57da9249354b8bd7d57ade45 100644 (file)
@@ -4,6 +4,8 @@
 #
 # Translators:
 # Abdurrahman AKKUŞ <a.rahmanakkus@hotmail.com>, 2019
+# Ahmet, 2022
+# Ahmet, 2022
 # Big Brother <tanakinci2002@gmail.com>, 2021
 # Çağlar Turalı <caglarturali@gmail.com>, 2018
 # Demiray Muhterem <mdemiray@msn.com>, 2018
@@ -17,8 +19,8 @@ msgstr ""
 "Project-Id-Version: Xonotic\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2021-11-28 07:22+0100\n"
-"PO-Revision-Date: 2021-11-28 06:22+0000\n"
-"Last-Translator: divVerent <divVerent@xonotic.org>\n"
+"PO-Revision-Date: 2022-01-30 12:01+0000\n"
+"Last-Translator: Ahmet\n"
 "Language-Team: Turkish (http://www.transifex.com/team-xonotic/xonotic/"
 "language/tr/)\n"
 "Language: tr\n"
@@ -998,7 +1000,7 @@ msgstr "^2+%s %s"
 #: qcsrc/client/hud/panel/scoreboard.qc:1925
 #, c-format
 msgid "^7Map: ^2%s"
-msgstr ""
+msgstr "^7Harita: ^2%s"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:2079
 #, c-format
@@ -4649,11 +4651,11 @@ msgstr ""
 
 #: qcsrc/common/turrets/turret/machinegun.qh:13
 msgid "Machinegun Turret"
-msgstr ""
+msgstr "Makineli Tüfek Kulesi"
 
 #: qcsrc/common/turrets/turret/machinegun_weapon.qh:7
 msgid "Machinegun"
-msgstr ""
+msgstr "Makineli Tüfek"
 
 #: qcsrc/common/turrets/turret/mlrs.qh:13
 msgid "MLRS Turret"
@@ -4673,11 +4675,11 @@ msgstr ""
 
 #: qcsrc/common/turrets/turret/plasma.qh:13
 msgid "Plasma Cannon"
-msgstr ""
+msgstr "Plazma Topu"
 
 #: qcsrc/common/turrets/turret/plasma_dual.qh:8
 msgid "Dual plasma"
-msgstr ""
+msgstr "Çift plazma"
 
 #: qcsrc/common/turrets/turret/plasma_dual.qh:20
 msgid "Dual Plasma Cannon"
index 09c84f0f85a79cd552eb1e912c8046d9c452c8d5..1d2a0d70a945168d319ccda9b4e1a08dcb8675a2 100644 (file)
@@ -445,7 +445,8 @@ set g_keyhunt_team_spawns 0 "when 1, players spawn from the team spawnpoints of
 set g_lms 0 "Last Man Standing: everyone starts with a certain amount of lives, and the survivor wins"
 set g_lms_lives_override -1
 set g_lms_extra_lives 0
-set g_lms_regenerate 0
+set g_lms_regenerate 0 "health and/or armor regeneration, according to g_balance_health_regen and g_balance_armor_regen"
+set g_lms_rot 0 "health and/or armor rotting, according to g_balance_health_rot and g_balance_armor_rot"
 set g_lms_last_join 3  "if g_lms_join_anytime is 0, new players can only join if the worst active player has (fraglimit - g_lms_last_join) or more lives; in other words, new players can no longer join once the worst player loses more than g_lms_last_join lives"
 set g_lms_join_anytime 1       "1: new players can join, but get same amount of lives as the worst player; 0: new players can only join if the worst active player has (fraglimit - g_lms_last_join) or more lives"
 set g_lms_items 0 "enables items to spawn, weaponarena still disables weapons and ammo (to force all items to spawn, use g_pickup_items 1 instead)"
index 2c43d12d98ec3a178ef470fa0d09b962938e078e..feaa9f8651ea47e3251ae867f5c88a335718edc0 100644 (file)
@@ -7,14 +7,15 @@ const int FRAGS_PLAYER_OUT_OF_GAME = -616;
 ///////////////////////////
 // cvar constants
 
-const int CVAR_SAVE = 1;
-const int CVAR_NOTIFY = 2;
-const int CVAR_READONLY = 4;
+const int CVAR_SAVE = BIT(0);
+const int CVAR_NOTIFY = BIT(1);
+const int CVAR_READONLY = BIT(2);
 
 // server flags
-const int SERVERFLAG_ALLOW_FULLBRIGHT = 1;
-const int SERVERFLAG_TEAMPLAY = 2;
-const int SERVERFLAG_PLAYERSTATS = 4;
+const int SERVERFLAG_ALLOW_FULLBRIGHT = BIT(0);
+const int SERVERFLAG_TEAMPLAY = BIT(1);
+const int SERVERFLAG_PLAYERSTATS = BIT(2);
+const int SERVERFLAG_PLAYERSTATS_CUSTOM = BIT(3);
 
 const int SPECIES_HUMAN = 0;
 const int SPECIES_ROBOT_SOLID = 1;
index c8cc0e6e565751b75aa3919ffeb4b4ddf3095f51..ffc7768e24cecbbab341ad9f2cc59d8ed605bb0e 100644 (file)
@@ -11,6 +11,7 @@ bool autocvar_g_lms_join_anytime;
 int autocvar_g_lms_last_join;
 bool autocvar_g_lms_items;
 bool autocvar_g_lms_regenerate;
+bool autocvar_g_lms_rot;
 
 // main functions
 int LMS_NewPlayerLives()
@@ -54,7 +55,7 @@ int WinningCondition_LMS()
                {
                        // two or more active players - continue with the game
 
-                       if (autocvar_g_campaign)
+                       if (autocvar_g_campaign && campaign_bots_may_start)
                        {
                                FOREACH_CLIENT(IS_REAL_CLIENT(it), {
                                        float pl_lives = GameRules_scoring_add(it, LMS_LIVES, 0);
@@ -358,9 +359,11 @@ MUTATOR_HOOKFUNCTION(lms, PlayerPreThink)
 
 MUTATOR_HOOKFUNCTION(lms, PlayerRegen)
 {
-       if(autocvar_g_lms_regenerate)
-               return false;
-       return true;
+       if(!autocvar_g_lms_regenerate)
+               M_ARGV(2, float) = 0;
+       if(!autocvar_g_lms_rot)
+               M_ARGV(3, float) = 0;
+       return (!autocvar_g_lms_regenerate && !autocvar_g_lms_rot);
 }
 
 MUTATOR_HOOKFUNCTION(lms, ForbidThrowCurrentWeapon)
index 3d0ca1ee6d6154f731f4eff2884522d7b5091552..e3b1e8461c77e796ff70ddf98f5f8903ea3406cb 100644 (file)
@@ -268,6 +268,10 @@ void PlayerStats_GameReport_Init() // initiated before InitGameplayMode so that
                PlayerStats_GameReport_DelayMapVote = true;
 
                serverflags |= SERVERFLAG_PLAYERSTATS;
+               if(autocvar_g_playerstats_gamereport_uri != cvar_defstring("g_playerstats_gamereport_uri"))
+               {
+                       serverflags |= SERVERFLAG_PLAYERSTATS_CUSTOM;
+               }
 
                PlayerStats_GameReport_AddEvent(PLAYERSTATS_ALIVETIME);
                PlayerStats_GameReport_AddEvent(PLAYERSTATS_AVGLATENCY);
index 8918ca0a2a695df6ade44e96df9837b271adc3a4..639b5db73e0615f6caa49b1cc494892faf38ab0f 100644 (file)
@@ -7,6 +7,7 @@ const int URI_GET_IPBAN_END = 16;
 const int URI_GET_CURL = 17;
 const int URI_GET_CURL_END = 32;
 const int URI_GET_UPDATENOTIFICATION = 33;
+const int URI_GET_TOS = 34;
 const int URI_GET_URLLIB = 128;
 const int URI_GET_URLLIB_END = 191;
 
index 0f9a960c92f657e0dc00ba00ff1ea3a26bdb10bd..1c09f35866a80a4178f06c39f94a7c77573d0431 100644 (file)
@@ -49,6 +49,8 @@
 #include <menu/xonotic/dialog_multiplayer_create_mutators.qc>
 #include <menu/xonotic/dialog_multiplayer_join.qc>
 #include <menu/xonotic/dialog_multiplayer_join_serverinfo.qc>
+#include <menu/xonotic/dialog_multiplayer_join_serverinfotab.qc>
+#include <menu/xonotic/dialog_multiplayer_join_termsofservice.qc>
 #include <menu/xonotic/dialog_multiplayer_media.qc>
 #include <menu/xonotic/dialog_multiplayer_media_demo.qc>
 #include <menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc>
@@ -82,6 +84,7 @@
 #include <menu/xonotic/dialog_singleplayer.qc>
 #include <menu/xonotic/dialog_singleplayer_winner.qc>
 #include <menu/xonotic/dialog_teamselect.qc>
+#include <menu/xonotic/dialog_termsofservice.qc>
 #include <menu/xonotic/dialog_uid2name.qc>
 #include <menu/xonotic/gametypelist.qc>
 #include <menu/xonotic/hudskinlist.qc>
 #include <menu/xonotic/statslist.qc>
 #include <menu/xonotic/tab.qc>
 #include <menu/xonotic/tabcontroller.qc>
+#include <menu/xonotic/textbox.qc>
 #include <menu/xonotic/textlabel.qc>
 #include <menu/xonotic/textslider.qc>
 #include <menu/xonotic/util.qc>
index 2bb4ccead24a71d6df581c6db654e49acd47cb7e..7c3ab9059b5fa6f57c1208f40f9a840d920b2a6d 100644 (file)
@@ -49,6 +49,8 @@
 #include <menu/xonotic/dialog_multiplayer_create_mutators.qh>
 #include <menu/xonotic/dialog_multiplayer_join.qh>
 #include <menu/xonotic/dialog_multiplayer_join_serverinfo.qh>
+#include <menu/xonotic/dialog_multiplayer_join_serverinfotab.qh>
+#include <menu/xonotic/dialog_multiplayer_join_termsofservice.qh>
 #include <menu/xonotic/dialog_multiplayer_media.qh>
 #include <menu/xonotic/dialog_multiplayer_media_demo.qh>
 #include <menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qh>
@@ -82,6 +84,7 @@
 #include <menu/xonotic/dialog_singleplayer.qh>
 #include <menu/xonotic/dialog_singleplayer_winner.qh>
 #include <menu/xonotic/dialog_teamselect.qh>
+#include <menu/xonotic/dialog_termsofservice.qh>
 #include <menu/xonotic/dialog_uid2name.qh>
 #include <menu/xonotic/gametypelist.qh>
 #include <menu/xonotic/hudskinlist.qh>
 #include <menu/xonotic/statslist.qh>
 #include <menu/xonotic/tab.qh>
 #include <menu/xonotic/tabcontroller.qh>
+#include <menu/xonotic/textbox.qh>
 #include <menu/xonotic/textlabel.qh>
 #include <menu/xonotic/textslider.qh>
 #include <menu/xonotic/util.qh>
index 423974e44b1f32fc36bf44671b49677eb4cd9947..7d096a90ad35d8d0ecb98d9d5f19cb98e14d7eaa 100644 (file)
@@ -24,6 +24,9 @@
                PERSON(packer) \
                PERSON(Severin "sev" Meyer) \
                PERSON(SpiKe) \
+               PERSON(Thomas "illwieckz" Debesse) \
+               PERSON(Victor "LegendGuard" Jaume) \
+               PERSON(z411) \
        NL() \
        NL() \
        FUNCTION(_("Website")) \
@@ -96,6 +99,8 @@
                PERSON(Rudolf "divVerent" Polzer) \
                PERSON(Samual "Ares" Lenks) \
                PERSON(TimePath) \
+               PERSON(Victor "LegendGuard" Jaume) \
+               PERSON(z411) \
                PERSON(Zac "Mario" Jardine) \
        NL() \
        FUNCTION(_("Marketing / PR")) \
index 6dc1cfcc09c0415baaaefc702e5e65cbf24ad4b2..c45256c525621e59e2eeb901d6efd3dcca8c1e7e 100644 (file)
@@ -8,6 +8,11 @@
 #include "charmap.qh"
 #include "commandbutton.qh"
 
+bool XonoticFirstRunDialog_shouldShow()
+{
+    return cvar_string("_cl_name") == cvar_defstring("_cl_name");
+}
+
 float CheckFirstRunButton(entity me)
 {
        if(cvar_string("_cl_name") != cvar_defstring("_cl_name"))
index 51a56bb6aa66a7e3d9b1411d5351015a1904c11f..8952f009eaecc91fd01347856e5d0aec860346c0 100644 (file)
@@ -3,6 +3,7 @@
 #include "rootdialog.qh"
 CLASS(XonoticFirstRunDialog, XonoticRootDialog)
        METHOD(XonoticFirstRunDialog, fill, void(entity));
+       METHOD(XonoticFirstRunDialog, shouldShow, bool());
        ATTRIB(XonoticFirstRunDialog, title, string, _("Welcome"));
        ATTRIB(XonoticFirstRunDialog, color, vector, SKINCOLOR_DIALOG_FIRSTRUN);
        ATTRIB(XonoticFirstRunDialog, intendedWidth, float, 0.7);
index cf542f39c8f47d0d6120c6ef1e56336a07676e90..f9ea1ef33e8ff2cc5fb139190dbd48eb80ec493d 100644 (file)
@@ -1,11 +1,15 @@
 #include "dialog_multiplayer_join_serverinfo.qh"
 #include <common/mapinfo.qh>
 
+#include "tabcontroller.qh"
 #include "serverlist.qh"
 #include "playerlist.qh"
 #include "inputbox.qh"
 #include "textlabel.qh"
 #include "button.qh"
+#include "dialog_multiplayer_join_serverinfotab.qh"
+#include "dialog_multiplayer_join_termsofservice.qh"
+
 
 void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
 {
@@ -36,10 +40,10 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
        //  Now, fill in the strings
        // ==========================
        me.currentServerName = strzone(gethostcachestring(SLIST_FIELD_NAME, i));
-       me.nameLabel.setText(me.nameLabel, me.currentServerName);
+       me.infoTab.nameLabel.setText(me.infoTab.nameLabel, me.currentServerName);
 
        me.currentServerCName = strzone(gethostcachestring(SLIST_FIELD_CNAME, i));
-       me.cnameLabel.setText(me.cnameLabel, me.currentServerCName);
+       me.infoTab.cnameLabel.setText(me.infoTab.cnameLabel, me.currentServerCName);
 
        pure_available = false;
        pure_violations = -1;
@@ -56,6 +60,7 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
        freeslots = -1;
        sflags = -1;
        modname = "";
+       bool ToSSpecified = false;
        for(int j = 2; j < m; ++j)
        {
                if(argv(j) == "")
@@ -68,11 +73,37 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
                        pure_violations = stof(v);
                }
                else if(k == "S")
+               {
                        freeslots = stof(v);
+               }
                else if(k == "F")
+               {
                        sflags = stof(v);
+               }
                else if(k == "M")
+               {
                        modname = v;
+               }
+               else if(k == "T")
+               {
+                       ToSSpecified = true;
+                       string downloadurl = v;
+                       LOG_INFOF("SERVERTOS DOWNLOADURL: %s", downloadurl);
+                       if (downloadurl == "INVALID")
+                       {
+                               me.ToSTab.textBox.setText(me.ToSTab.textBox, _("No Terms of Service specified"));
+                       }
+                       else
+                       {
+                               downloadurl = strreplace("|", ":", downloadurl);
+                               me.ToSTab.loadToS(me.ToSTab, downloadurl);
+                       }
+               }
+       }
+
+       if (!ToSSpecified)
+       {
+               me.ToSTab.textBox.setText(me.ToSTab.textBox, _("No Terms of Service specified"));
        }
 
 #ifdef COMPAT_NO_MOD_IS_XONOTIC
@@ -88,39 +119,39 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
        if(j) { typestr = MapInfo_Type_ToText(j); } // only set it if we actually found it
 
        me.currentServerType = strzone(typestr);
-       me.typeLabel.setText(me.typeLabel, me.currentServerType);
+       me.infoTab.typeLabel.setText(me.infoTab.typeLabel, me.currentServerType);
 
        me.currentServerMap = strzone(gethostcachestring(SLIST_FIELD_MAP, i));
-       me.mapLabel.setText(me.mapLabel, me.currentServerMap);
+       me.infoTab.mapLabel.setText(me.infoTab.mapLabel, me.currentServerMap);
 
        me.currentServerPlayers = strzone(gethostcachestring(SLIST_FIELD_PLAYERS, i));
-       me.rawPlayerList.setPlayerList(me.rawPlayerList, me.currentServerPlayers);
+       me.infoTab.rawPlayerList.setPlayerList(me.infoTab.rawPlayerList, me.currentServerPlayers);
 
        numh = gethostcachenumber(SLIST_FIELD_NUMHUMANS, i);
        maxp = gethostcachenumber(SLIST_FIELD_MAXPLAYERS, i);
        numb = gethostcachenumber(SLIST_FIELD_NUMBOTS, i);
        me.currentServerNumPlayers = strzone(sprintf("%d/%d", numh, maxp));
-       me.numPlayersLabel.setText(me.numPlayersLabel, me.currentServerNumPlayers);
+       me.infoTab.numPlayersLabel.setText(me.infoTab.numPlayersLabel, me.currentServerNumPlayers);
 
        s = ftos(numb);
        me.currentServerNumBots = strzone(s);
-       me.numBotsLabel.setText(me.numBotsLabel, me.currentServerNumBots);
+       me.infoTab.numBotsLabel.setText(me.infoTab.numBotsLabel, me.currentServerNumBots);
 
        if(freeslots < 0) { freeslots = maxp - numh - numb; }
        s = ftos(freeslots);
        me.currentServerNumFreeSlots = strzone(s);
-       me.numFreeSlotsLabel.setText(me.numFreeSlotsLabel, me.currentServerNumFreeSlots);
+       me.infoTab.numFreeSlotsLabel.setText(me.infoTab.numFreeSlotsLabel, me.currentServerNumFreeSlots);
 
        me.currentServerMod = ((modname == "Xonotic") ? ZCTX(_("MOD^Default")) : modname);
        me.currentServerMod = strzone(me.currentServerMod);
-       me.modLabel.setText(me.modLabel, me.currentServerMod);
+       me.infoTab.modLabel.setText(me.infoTab.modLabel, me.currentServerMod);
 
        me.currentServerVersion = strzone(versionstr);
-       me.versionLabel.setText(me.versionLabel, me.currentServerVersion);
+       me.infoTab.versionLabel.setText(me.infoTab.versionLabel, me.currentServerVersion);
 
        me.currentServerPure = ((!pure_available) ? _("N/A") : (pure_violations == 0) ? _("Official") : sprintf(_("%d modified"), pure_violations));
        me.currentServerPure = strzone(me.currentServerPure);
-       me.pureLabel.setText(me.pureLabel, me.currentServerPure);
+       me.infoTab.pureLabel.setText(me.infoTab.pureLabel, me.currentServerPure);
 
        s = crypto_getencryptlevel(me.currentServerCName);
        if(s == "")
@@ -157,101 +188,34 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
                                me.currentServerEncrypt = _("Required (will encrypt)");
                        break;
        }
-       me.encryptLabel.setText(me.encryptLabel, me.currentServerEncrypt);
-       setZonedTooltip(me.encryptLabel, _("Use the `crypto_aeslevel` cvar to change your preferences"), string_null);
+       me.infoTab.encryptLabel.setText(me.infoTab.encryptLabel, me.currentServerEncrypt);
+       setZonedTooltip(me.infoTab.encryptLabel, _("Use the `crypto_aeslevel` cvar to change your preferences"), string_null);
 
        s = crypto_getidfp(me.currentServerCName);
        if (!s) { s = _("N/A"); }
        me.currentServerID = strzone(s);
-       me.idLabel.setText(me.idLabel, me.currentServerID);
+       me.infoTab.idLabel.setText(me.infoTab.idLabel, me.currentServerID);
 
        s = crypto_getkeyfp(me.currentServerCName);
        if (!s) { s = _("N/A"); }
        me.currentServerKey = strzone(s);
-       me.keyLabel.setText(me.keyLabel, me.currentServerKey);
+       me.infoTab.keyLabel.setText(me.infoTab.keyLabel, me.currentServerKey);
+
+       me.currentServerStatsStatus = ((sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS)) ? ((sflags & SERVERFLAG_PLAYERSTATS_CUSTOM) ? _("custom stats server") : _("stats enabled")) : _("stats disabled"));
+       me.currentServerStatsStatus = strzone(me.currentServerStatsStatus);
+       me.infoTab.statsLabel.setText(me.infoTab.statsLabel, me.currentServerStatsStatus);
 }
 
 void XonoticServerInfoDialog_fill(entity me)
 {
-       entity e;
+       entity mc, e;
+       mc = makeXonoticTabController(me.rows - 2);
        me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Hostname:")));
-               me.TD(me, 1, 4.6, e = makeXonoticTextLabel(0.5, ""));
-               e.colorL = SKINCOLOR_SERVERINFO_NAME;
-               e.allowCut = 1;
-               me.nameLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Address:")));
-               me.TD(me, 1, 4.6, e = makeXonoticTextLabel(0.5, ""));
-               e.colorL = SKINCOLOR_SERVERINFO_IP;
-               e.allowCut = 1;
-               me.cnameLabel = e;
+               me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Status"), me.infoTab = makeXonoticServerInfoTab()));
+               me.TD(me, 1, 1, e = mc.makeTabButton(mc, _("Terms of Service"), me.ToSTab = makeXonoticServerToSTab()));
 
        me.TR(me);
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Gametype:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.typeLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Map:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.mapLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Mod:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.modLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Version:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.versionLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Settings:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.pureLabel = e;
-
-       me.TR(me);
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Players:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.numPlayersLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Bots:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.numBotsLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Free slots:")));
-               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
-               e.allowCut = 1;
-               me.numFreeSlotsLabel = e;
-
-       me.gotoRC(me, me.rows - 5, 0);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Encryption:")));
-               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
-                       e.allowCut = 1;
-                       me.encryptLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("ID:")));
-               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
-                       e.allowCut = 1;
-                       me.keyLabel = e;
-       me.TR(me);
-               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Key:")));
-               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
-                       e.allowCut = 1;
-                       me.idLabel = e;
-
-       me.gotoRC(me, 2, 2.2); me.setFirstColumn(me, me.currentColumn);
-               me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Players:")));
-       me.TR(me);
-               me.TD(me, me.rows - 8, 4, e = makeXonoticPlayerList());
-                       me.rawPlayerList = e;
+               me.TD(me, me.rows - 2, me.columns, mc);
 
        me.gotoRC(me, me.rows - 1, 0);
                me.TD(me, 1, me.columns/2, e = makeXonoticButton(_("Close"), '0 0 0'));
@@ -270,3 +234,4 @@ void Join_Click(entity btn, entity me)
 {
        localcmd("connect ", me.currentServerCName, "\n");
 }
+
index 68f5ab8ca0c08cc95084715202fbb9ec5e442f36..30a5453dd111253030786aa1a6f473a0cae2d1d1 100644 (file)
@@ -2,44 +2,33 @@
 
 #include "dialog.qh"
 CLASS(XonoticServerInfoDialog, XonoticDialog)
-       METHOD(XonoticServerInfoDialog, fill, void(entity));
        METHOD(XonoticServerInfoDialog, loadServerInfo, void(entity, float));
-       ATTRIB(XonoticServerInfoDialog, title, string, _("Server Information"));
-       ATTRIB(XonoticServerInfoDialog, color, vector, SKINCOLOR_DIALOG_SERVERINFO);
-       ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.8);
-       ATTRIB(XonoticServerInfoDialog, rows, float, 18);
-       ATTRIB(XonoticServerInfoDialog, columns, float, 6.2);
+       METHOD(XonoticServerInfoDialog, fill, void(entity));
+       ATTRIB(XonoticServerInfoDialog, title, string, _("Server Info"));
+       ATTRIB(XonoticServerInfoDialog, color, vector, SKINCOLOR_DIALOG_MULTIPLAYER);
+       ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.96);
+       ATTRIB(XonoticServerInfoDialog, rows, float, 19);
+       ATTRIB(XonoticServerInfoDialog, columns, float, 2);
+       ATTRIB(XonoticServerInfoDialog, infoTab, entity);
+       ATTRIB(XonoticServerInfoDialog, ToSTab, entity);
 
-       ATTRIB(XonoticServerInfoDialog, currentServerName, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerCName, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerType, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerMap, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerPlayers, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerNumPlayers, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerNumBots, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerNumFreeSlots, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerMod, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerVersion, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerKey, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerID, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerEncrypt, string);
-       ATTRIB(XonoticServerInfoDialog, currentServerPure, string);
+       ATTRIB(XonoticServerInfoTab, currentServerName, string);
+       ATTRIB(XonoticServerInfoTab, currentServerCName, string);
+       ATTRIB(XonoticServerInfoTab, currentServerType, string);
+       ATTRIB(XonoticServerInfoTab, currentServerMap, string);
+       ATTRIB(XonoticServerInfoTab, currentServerPlayers, string);
+       ATTRIB(XonoticServerInfoTab, currentServerNumPlayers, string);
+       ATTRIB(XonoticServerInfoTab, currentServerNumBots, string);
+       ATTRIB(XonoticServerInfoTab, currentServerNumFreeSlots, string);
+       ATTRIB(XonoticServerInfoTab, currentServerMod, string);
+       ATTRIB(XonoticServerInfoTab, currentServerVersion, string);
+       ATTRIB(XonoticServerInfoTab, currentServerKey, string);
+       ATTRIB(XonoticServerInfoTab, currentServerID, string);
+       ATTRIB(XonoticServerInfoTab, currentServerEncrypt, string);
+       ATTRIB(XonoticServerInfoTab, currentServerPure, string);
+       ATTRIB(XonoticServerInfoTab, currentServerStatsStatus, string);
 
-       ATTRIB(XonoticServerInfoDialog, nameLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, cnameLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, typeLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, mapLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, rawPlayerList, entity);
-       ATTRIB(XonoticServerInfoDialog, numPlayersLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, numBotsLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, numFreeSlotsLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, modLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, versionLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, keyLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, idLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, encryptLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, canConnectLabel, entity);
-       ATTRIB(XonoticServerInfoDialog, pureLabel, entity);
 ENDCLASS(XonoticServerInfoDialog)
 
 void Join_Click(entity btn, entity me);
+
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qc b/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qc
new file mode 100644 (file)
index 0000000..5b2dc05
--- /dev/null
@@ -0,0 +1,107 @@
+#include "dialog_multiplayer_join_serverinfo.qh"
+#include "dialog_multiplayer_join_serverinfotab.qh"
+#include <common/mapinfo.qh>
+
+#include "serverlist.qh"
+#include "playerlist.qh"
+#include "inputbox.qh"
+#include "textlabel.qh"
+#include "button.qh"
+
+
+entity makeXonoticServerInfoTab()
+{
+       entity me;
+       me = NEW(XonoticServerInfoTab);
+       me.configureDialog(me);
+       return me;
+}
+
+void XonoticServerInfoTab_fill(entity me)
+{
+       entity e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Hostname:")));
+               me.TD(me, 1, 4.6, e = makeXonoticTextLabel(0.5, ""));
+               e.colorL = SKINCOLOR_SERVERINFO_NAME;
+               e.allowCut = 1;
+               me.nameLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Address:")));
+               me.TD(me, 1, 4.6, e = makeXonoticTextLabel(0.5, ""));
+               e.colorL = SKINCOLOR_SERVERINFO_IP;
+               e.allowCut = 1;
+               me.cnameLabel = e;
+
+       me.TR(me);
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Gametype:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.typeLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Map:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.mapLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Mod:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.modLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Version:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.versionLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Settings:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.pureLabel = e;
+
+       me.TR(me);
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Players:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.numPlayersLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Bots:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.numBotsLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Free slots:")));
+               me.TD(me, 1, 1.2, e = makeXonoticTextLabel(0, ""));
+               e.allowCut = 1;
+               me.numFreeSlotsLabel = e;
+
+       me.gotoRC(me, me.rows - 5, 0);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Encryption:")));
+               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
+                       e.allowCut = 1;
+                       me.encryptLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("ID:")));
+               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
+                       e.allowCut = 1;
+                       me.keyLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Key:")));
+               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
+                       e.allowCut = 1;
+                       me.idLabel = e;
+       me.TR(me);
+               me.TD(me, 1, 0.8, e = makeXonoticTextLabel(0, _("Stats:")));
+               me.TD(me, 1, 5.4, e = makeXonoticTextLabel(0, ""));
+                       e.allowCut = 1;
+                       me.statsLabel = e;
+
+       me.gotoRC(me, 2, 2.2); me.setFirstColumn(me, me.currentColumn);
+               me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Players:")));
+       me.TR(me);
+               me.TD(me, me.rows - 8, 4, e = makeXonoticPlayerList());
+                       me.rawPlayerList = e;
+}
+
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qh b/qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfotab.qh
new file mode 100644 (file)
index 0000000..ed3515f
--- /dev/null
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "tab.qh"
+CLASS(XonoticServerInfoTab, XonoticTab)
+       METHOD(XonoticServerInfoTab, fill, void(entity));
+       ATTRIB(XonoticServerInfoTab, title, string, _("Server Information"));
+       ATTRIB(XonoticServerInfoTab, color, vector, SKINCOLOR_DIALOG_SERVERINFO);
+       ATTRIB(XonoticServerInfoTab, intendedWidth, float, 0.8);
+       ATTRIB(XonoticServerInfoTab, rows, float, 17);
+       ATTRIB(XonoticServerInfoTab, columns, float, 6.2);
+
+       ATTRIB(XonoticServerInfoTab, nameLabel, entity);
+       ATTRIB(XonoticServerInfoTab, cnameLabel, entity);
+       ATTRIB(XonoticServerInfoTab, typeLabel, entity);
+       ATTRIB(XonoticServerInfoTab, mapLabel, entity);
+       ATTRIB(XonoticServerInfoTab, rawPlayerList, entity);
+       ATTRIB(XonoticServerInfoTab, numPlayersLabel, entity);
+       ATTRIB(XonoticServerInfoTab, numBotsLabel, entity);
+       ATTRIB(XonoticServerInfoTab, numFreeSlotsLabel, entity);
+       ATTRIB(XonoticServerInfoTab, modLabel, entity);
+       ATTRIB(XonoticServerInfoTab, versionLabel, entity);
+       ATTRIB(XonoticServerInfoTab, keyLabel, entity);
+       ATTRIB(XonoticServerInfoTab, idLabel, entity);
+       ATTRIB(XonoticServerInfoTab, encryptLabel, entity);
+       ATTRIB(XonoticServerInfoTab, canConnectLabel, entity);
+       ATTRIB(XonoticServerInfoTab, pureLabel, entity);
+       ATTRIB(XonoticServerInfoTab, statsLabel, entity);
+ENDCLASS(XonoticServerInfoTab)
+entity makeXonoticServerInfoTab();
+
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_join_termsofservice.qc b/qcsrc/menu/xonotic/dialog_multiplayer_join_termsofservice.qc
new file mode 100644 (file)
index 0000000..81d0897
--- /dev/null
@@ -0,0 +1,62 @@
+#include "dialog_multiplayer_join_termsofservice.qh"
+
+#include "textbox.qh"
+#include <lib/urllib.qh>
+
+
+entity makeXonoticServerToSTab()
+{
+       entity me;
+       me = NEW(XonoticServerToSTab);
+       me.configureDialog(me);
+       return me;
+}
+
+void XonoticServerToSTab_loadToS(entity me, string downloadurl)
+{
+       url_single_fopen(downloadurl, FILE_READ, AdditionalServerInfo_OnGet, me);
+}
+
+void XonoticServerToSTab_fill(entity me)
+{
+       entity e;
+       me.TR(me);
+       me.TD(me, me.rows, me.columns, e = makeXonoticTextBox());
+       me.textBox = e;
+}
+
+void AdditionalServerInfo_OnGet(entity fh, entity me, int status)
+{
+       switch (status) {
+               case URL_READY_CLOSED:
+               {
+                       break;
+               }
+               case URL_READY_ERROR:
+               {
+                       me.text = strzone("Error reading ToS");
+                       me.textBox.setText(me.textBox, me.text);
+                       break;
+               }
+               case URL_READY_CANREAD:
+               {
+                       strfree(me.text);
+                       string temp = "";
+                       for (string s; (s = url_fgets(fh)); )
+                       {
+                               if (temp != "")
+                                       temp = strcat(temp, "\n", s);
+                               else
+                                       temp = s;
+                       }
+                       url_fclose(fh);
+                       me.text = strzone(temp);
+                       me.textBox.setText(me.textBox, me.text);
+                       break;
+               }
+               default:
+               {
+                       break;
+               }
+       }
+}
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_join_termsofservice.qh b/qcsrc/menu/xonotic/dialog_multiplayer_join_termsofservice.qh
new file mode 100644 (file)
index 0000000..ebc2d86
--- /dev/null
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "tab.qh"
+CLASS(XonoticServerToSTab, XonoticTab)
+       METHOD(XonoticServerToSTab, fill, void(entity));
+       METHOD(XonoticServerToSTab, loadToS, void(entity, string));
+       ATTRIB(XonoticServerToSTab, title, string, _("Terms of Service"));
+       ATTRIB(XonoticServerToSTab, color, vector, SKINCOLOR_DIALOG_SERVERINFO);
+       ATTRIB(XonoticServerToSTab, intendedWidth, float, 0.8);
+       ATTRIB(XonoticServerToSTab, rows, float, 17);
+       ATTRIB(XonoticServerToSTab, columns, float, 6.2);
+
+       ATTRIB(XonoticServerToSTab, text, string);
+       ATTRIB(XonoticServerToSTab, textBox, entity);
+ENDCLASS(XonoticServerToSTab)
+entity makeXonoticServerToSTab();
+
+void AdditionalServerInfo_OnGet(entity fh, entity pass, int status);
diff --git a/qcsrc/menu/xonotic/dialog_termsofservice.qc b/qcsrc/menu/xonotic/dialog_termsofservice.qc
new file mode 100644 (file)
index 0000000..39ffaa4
--- /dev/null
@@ -0,0 +1,102 @@
+#include "dialog_termsofservice.qh"
+
+#include "../menu.qh"
+#include "mainwindow.qh"
+#include "dialog_firstrun.qh"
+#include "textbox.qh"
+#include "textlabel.qh"
+#include "button.qh"
+#include "util.qh"
+
+void Close_Clicked(entity btn, entity me)
+{
+       LOG_INFOF("Accepted ToS version %d", _Nex_ExtResponseSystem_NewToS);
+       cvar_set("_termsofservice_accepted", ftos(_Nex_ExtResponseSystem_NewToS));
+       localcmd("saveconfig\n");
+       if (main.firstRunDialog.shouldShow())
+               main.firstDraw = true;
+       Dialog_Close(btn, me);
+}
+
+void DontAccept_Clicked(entity btn, entity me)
+{
+       localcmd("quit\n");
+}
+
+void XonoticToSDialog_loadXonoticToS(entity me)
+{
+       url_single_fopen(termsofservice_url, FILE_READ, XonoticToS_OnGet, me);
+}
+
+void XonoticToS_OnGet(entity fh, entity me, int status)
+{
+       switch (status) {
+               case URL_READY_CLOSED:
+               {
+                       break;
+               }
+               case URL_READY_ERROR:
+               {
+                       me.text = strzone("Error reading ToS");
+                       me.textBox.setText(me.textBox, me.text);
+                       break;
+               }
+               case URL_READY_CANREAD:
+               {
+                       strfree(me.text);
+                       string temp = "";
+                       for (string s; (s = url_fgets(fh)); )
+                       {
+                               if (temp != "")
+                                       temp = strcat(temp, "\n", s);
+                               else
+                                       temp = s;
+                       }
+                       url_fclose(fh);
+                       me.text = strzone(temp);
+                       me.textBox.setText(me.textBox, me.text);
+                       break;
+               }
+               default:
+               {
+                       break;
+               }
+       }
+}
+
+bool XonoticToSDialog_shouldShow()
+{
+       return (_Nex_ExtResponseSystem_NewToS && _Nex_ExtResponseSystem_NewToS > autocvar__termsofservice_accepted);
+}
+
+void XonoticToSDialog_fill(entity me)
+{
+       entity e;
+       string subtitle;
+
+       if (autocvar__termsofservice_accepted > 0)
+               subtitle = _("Terms of Service have been updated. Please read them before continuing:");
+       else
+               subtitle = _("Welcome to Xonotic! Please read the following Terms of Service:");
+
+       me.TR(me);
+               me.TD(me, 1, 5, e = makeXonoticTextLabel(0, subtitle));
+               e.allowWrap = 1;
+
+       me.TR(me);
+       me.TR(me);
+               me.TD(me, me.rows - 4, me.columns, me.textBox = makeXonoticTextBox());
+               me.loadXonoticToS(me);
+
+       me.TR(me);
+       me.gotoRC(me, me.rows - 1, 0);
+
+               me.TD(me, 1, me.columns/2, e = makeXonoticButton(_("Accept"), '0 1 0'));
+               e.onClick = Close_Clicked;
+               e.onClickEntity = me;
+
+               me.TD(me, 1, me.columns/2, e = makeXonoticButton(_("Don't accept (quit the game)"), '1 0 0'));
+               e.onClick = DontAccept_Clicked;
+               e.onClickEntity = me;
+}
+
diff --git a/qcsrc/menu/xonotic/dialog_termsofservice.qh b/qcsrc/menu/xonotic/dialog_termsofservice.qh
new file mode 100644 (file)
index 0000000..9231f30
--- /dev/null
@@ -0,0 +1,24 @@
+#pragma once
+
+int autocvar__termsofservice_accepted;
+const string termsofservice_url = "http://update.xonotic.org/tos.txt";
+
+#include "rootdialog.qh"
+CLASS(XonoticToSDialog, XonoticRootDialog)
+       METHOD(XonoticToSDialog, shouldShow, bool());
+       METHOD(XonoticToSDialog, fill, void(entity));
+       METHOD(XonoticToSDialog, loadXonoticToS, void(entity));
+       ATTRIB(XonoticToSDialog, title, string, _("Terms of Service"));
+       ATTRIB(XonoticToSDialog, color, vector, SKINCOLOR_DIALOG_FIRSTRUN);
+       ATTRIB(XonoticToSDialog, intendedWidth, float, 0.8);
+       ATTRIB(XonoticToSDialog, rows, float, 16);
+       ATTRIB(XonoticToSDialog, columns, float, 6.2);
+       ATTRIB(XonoticToSDialog, name, string, "TermsOfService");
+
+       ATTRIB(XonoticToSDialog, text, string);
+       ATTRIB(XonoticToSDialog, textBox, entity);
+
+       ATTRIB(XonoticToSDialog, closable, float, 0);
+ENDCLASS(XonoticToSDialog)
+
+void XonoticToS_OnGet(entity fh, entity me, int status);
index 89a61fb0d89d2fff669177c4245b5c738d0aad4c..4aa974835a58da15959f2d79e5b7be34d9324e0d 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "nexposee.qh"
 #include "inputbox.qh"
+#include "dialog_termsofservice.qh"
 #include "dialog_firstrun.qh"
 #include "dialog_hudsetup_exit.qh"
 #include "dialog_hudpanel_notification.qh"
@@ -58,10 +59,13 @@ void MainWindow_draw(entity me)
 {
        SUPER(MainWindow).draw(me);
 
-       if(me.dialogToShow)
-       {
-               DialogOpenButton_Click_withCoords(NULL, me.dialogToShow, '0 0 0', eX * conwidth + eY * conheight);
-               me.dialogToShow = NULL;
+       if (me.firstDraw) {
+               if (me.ToSDialog.shouldShow())
+                       DialogOpenButton_Click_withCoords(NULL, me.ToSDialog, '0 0 0', eX * conwidth + eY * conheight);
+               else if(me.firstRunDialog.shouldShow())
+                       DialogOpenButton_Click_withCoords(NULL, me.firstRunDialog, '0 0 0', eX * conwidth + eY * conheight);
+               
+               me.firstDraw = false;
        }
 
        //-------------------------------------
@@ -104,6 +108,11 @@ void MainWindow_configureMainWindow(entity me)
 {
        entity n, i;
 
+       // terms of service dialog
+       me.ToSDialog = i = NEW(XonoticToSDialog);
+       i.configureDialog(i);
+       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+
        // dialog run upon startup
        me.firstRunDialog = i = NEW(XonoticFirstRunDialog);
        i.configureDialog(i);
@@ -281,7 +290,7 @@ void MainWindow_configureMainWindow(entity me)
 
        // main dialogs/windows
        me.mainNexposee = n = NEW(XonoticNexposee);
-       
+
        /*
                if(checkextension("DP_GECKO_SUPPORT"))
                {
@@ -291,7 +300,7 @@ void MainWindow_configureMainWindow(entity me)
                        n.setNexposee(n, i, '0.1 0.1 0', SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
                }
        */
-       
+
                i = NEW(XonoticSingleplayerDialog);
                i.configureDialog(i);
                n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
@@ -332,7 +341,4 @@ void MainWindow_configureMainWindow(entity me)
 
        me.initializeDialog(me, n);
        me.disconnectDialogVisibility = 1;
-
-       if(cvar_string("_cl_name") == cvar_defstring("_cl_name"))
-               me.dialogToShow = me.firstRunDialog;
 }
index 1e8afa4a39b1b3344ee7c4990247cdec9acd120e..82e126a9f0f41025c7cf7c7ae725d0d51020abe4 100644 (file)
@@ -5,6 +5,7 @@
 CLASS(MainWindow, ModalController)
        METHOD(MainWindow, configureMainWindow, void(entity));
        METHOD(MainWindow, draw, void(entity));
+       ATTRIB(MainWindow, ToSDialog, entity);
        ATTRIB(MainWindow, firstRunDialog, entity);
        ATTRIB(MainWindow, advancedDialog, entity);
        ATTRIB(MainWindow, mutatorsDialog, entity);
@@ -20,7 +21,7 @@ CLASS(MainWindow, ModalController)
        ATTRIB(MainWindow, languageWarningDialog, entity);
        ATTRIB(MainWindow, mainNexposee, entity);
        ATTRIB(MainWindow, fadedAlpha, float, SKINALPHA_BEHIND);
-       ATTRIB(MainWindow, dialogToShow, entity);
+       ATTRIB(MainWindow, firstDraw, bool, true);
        ATTRIB(MainWindow, demostartconfirmDialog, entity);
        ATTRIB(MainWindow, demotimeconfirmDialog, entity);
        ATTRIB(MainWindow, resetDialog, entity);
index e90eef23d3a11d2c63a2aa33798f49522508a396..1edc5b8400c8cc6347f5916125ebc34c850e5e0d 100644 (file)
@@ -2,11 +2,11 @@
 
 .float realUpperMargin2;
 
-const float PLAYERPARM_SCORE = 0;
-const float PLAYERPARM_PING = 1;
-const float PLAYERPARM_TEAM = 2;
-const float PLAYERPARM_NAME = 3;
-const float PLAYERPARM_COUNT = 4;
+const int PLAYERPARM_SCORE = 0;
+const int PLAYERPARM_PING = 1;
+const int PLAYERPARM_TEAM = 2;
+const int PLAYERPARM_NAME = 3;
+const int PLAYERPARM_COUNT = 4;
 
 entity makeXonoticPlayerList()
 {
@@ -33,7 +33,7 @@ void XonoticPlayerList_setPlayerList(entity me, string plist)
                s = bufstr_get(buf, i * PLAYERPARM_COUNT + PLAYERPARM_NAME);
                n = tokenize_console(s);
 
-               if(n == 4)
+               if(n == PLAYERPARM_COUNT)
                {
                        bufstr_set(buf, i * PLAYERPARM_COUNT + PLAYERPARM_SCORE, argv(0)); // -666
                        bufstr_set(buf, i * PLAYERPARM_COUNT + PLAYERPARM_PING,  argv(1)); // 100
index e20a13a8ee58a95ca3fe06b899a2d87409375ef5..7d5d21e30df9c2653f448cced6b08c18d141fb43 100644 (file)
@@ -1036,7 +1036,12 @@ void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool is
 
        // Stats
        if(sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS))
-               draw_Picture(iconPos, "icon_stats1", iconSize, '1 1 1', 1);
+       {
+               if (sflags & SERVERFLAG_PLAYERSTATS_CUSTOM)
+                       draw_Picture(iconPos, "icon_mod_", iconSize, '1 1 1', 1); // TODO: custom stats server icon
+               else
+                       draw_Picture(iconPos, "icon_stats1", iconSize, '1 1 1', 1);
+       }
 
        if(isFocused && me.mouseOverIcons && !me.tooltip)
        {
@@ -1048,7 +1053,7 @@ void XonoticServerList_drawListBoxItem(entity me, int i, vector absSize, bool is
                if(pure_available)
                        t = strcat(t, sprintf(" (%s)", (pure) ? _("official settings") : _("modified settings")));
                t = strcat(t, ", ");
-               t = strcat(t, ((sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS)) ? _("stats enabled") : _("stats disabled")));
+               t = strcat(t, ((sflags >= 0 && (sflags & SERVERFLAG_PLAYERSTATS)) ? ((sflags & SERVERFLAG_PLAYERSTATS_CUSTOM) ? _("custom stats server") : _("stats enabled")) : _("stats disabled")));
                setZonedTooltip(me, t, string_null);
        }
        // --------------
diff --git a/qcsrc/menu/xonotic/textbox.qc b/qcsrc/menu/xonotic/textbox.qc
new file mode 100644 (file)
index 0000000..1027d0c
--- /dev/null
@@ -0,0 +1,90 @@
+#include "textbox.qh"
+#include "../item/label.qh"
+
+entity makeXonoticTextBox()
+{
+       entity me;
+       me = NEW(XonoticTextBox);
+       me.configureXonoticListBox(me);
+       return me;
+}
+
+void XonoticTextBox_destroy(entity me)
+{
+       if (me.stringList >= 0)
+       {
+               buf_del(me.stringList);
+               me.stringList = -1;
+       }
+}
+
+void XonoticTextBox_setText(entity me, string text)
+{
+       if (me.stringList >= 0)
+       {
+               buf_del(me.stringList);
+               me.stringList = -1;
+       }
+
+       int buf;
+       int line = 0;
+
+       string t;
+
+       buf = buf_create();
+       for (int i = 0, n = tokenizebyseparator(text, "\n"); i < n; ++i)
+       {
+               t = substring(argv(i), 0, -1);
+               getWrappedLine_remaining = t;
+               while (getWrappedLine_remaining)
+               {
+                       t = getWrappedLine(1, me.realFontSize, draw_TextWidth_WithColors);
+                       bufstr_set(buf, line, t);
+                       line++;
+               }
+       }
+
+       me.stringList = buf;
+       me.nItems = line+1;
+}
+
+string XonoticTextBox_getTextBoxLine(entity me, int i)
+{
+       if (me.stringList >= 0)
+       {
+               return bufstr_get(me.stringList, i);
+       }
+       return string_null;
+}
+
+// mostly copied from playerlist
+// FIXME: is this really needed
+void XonoticTextBox_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+       me.itemAbsSize = '0 0 0';
+       SUPER(XonoticTextBox).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
+
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
+       string temp = string_null;
+       for (int i = 0; i < me.nItems; ++i)
+       {
+               if (!temp)
+               {
+                       temp = me.getTextBoxLine(me, i);
+               }
+               else
+               {
+                       temp = strcat(temp, "\n", me.getTextBoxLine(me, i));
+               }
+       }
+       me.setText(me, temp);
+}
+
+void XonoticTextBox_drawListBoxItem(entity me, int i, vector absSize, bool isSelected, bool isFocused)
+{
+       string s = me.getTextBoxLine(me, i);
+       draw_Text(vec2(0, 0), s, me.realFontSize, me.colorL, me.alpha, true);
+}
diff --git a/qcsrc/menu/xonotic/textbox.qh b/qcsrc/menu/xonotic/textbox.qh
new file mode 100644 (file)
index 0000000..b274816
--- /dev/null
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "listbox.qh"
+
+// slightly hacky multiline textbox with scrollbar
+CLASS(XonoticTextBox, XonoticListBox)
+       METHOD(XonoticTextBox, destroy, void(entity));
+       ATTRIB(XonoticTextBox, rowsPerItem, float, 1);
+       METHOD(XonoticTextBox, resizeNotify, void(entity, vector, vector, vector, vector));
+       METHOD(XonoticTextBox, drawListBoxItem, void(entity, int, vector, bool, bool));
+       ATTRIB(XonoticTextBox, allowFocusSound, float, 0);
+       ATTRIB(XonoticTextBox, alpha, float, SKINALPHA_TEXT);
+       ATTRIB(XonoticTextBox, fontSize, float, SKINFONTSIZE_NORMAL);
+       ATTRIB(XonoticTextBox, realFontSize, vector, '0 0 0');
+       ATTRIB(XonoticTextBox, itemAbsSize, vector, '0 0 0');
+       METHOD(XonoticTextBox, setText, void(entity, string));
+       METHOD(XonoticTextBox, getTextBoxLine, string(entity, int));
+       ATTRIB(XonoticTextBox, nItems, int, 0);
+       ATTRIB(XonoticTextBox, stringList, int, -1);
+       ATTRIB(XonoticTextBox, selectionDoesntMatter, bool, true);
+ENDCLASS(XonoticTextBox)
+entity makeXonoticTextBox();
+
index e77049d200153e9c2f15fb0ca097edd1c1649fe3..06139566d85ad6a50c30af6d3f09d19a3eca418d 100644 (file)
@@ -352,6 +352,7 @@ void UpdateNotification_URI_Get_Callback(float id, float status, string data)
        string s;
 
        string un_version = "";
+       string un_tosversion = "";
        string un_download = "";
        string un_url = "";
        string un_bannedservers = "";
@@ -372,6 +373,11 @@ void UpdateNotification_URI_Get_Callback(float id, float status, string data)
                                un_version = s;
                                break;
                        }
+                       case "T":
+                       {
+                               un_tosversion = s;
+                               break;
+                       }
                        case "C":
                        {
                                un_compatexpire = s;
@@ -431,6 +437,12 @@ void UpdateNotification_URI_Get_Callback(float id, float status, string data)
                        }
                }
        }
+       
+       if(un_tosversion != "")
+       {
+               _Nex_ExtResponseSystem_NewToS = stof(un_tosversion);
+               LOG_INFOF("Latest ToS version is %d", _Nex_ExtResponseSystem_NewToS);
+       }
 
        if(un_bannedservers != "")
        {
@@ -582,6 +594,7 @@ void preMenuDraw()
                draw_CenterText(mid - 1 * line, l1, fs, '1 0 0', 1, 0);
                draw_CenterText(mid - 0 * line, l2, fs, '0 0 1', 1, 0);
        }
+
        if (!campaign_name_previous)
                campaign_name_previous = strzone(strcat(campaign_name, "x")); // force unequal
        if(campaign_name == campaign_name_previous)
index f5bd636d81f98c1b481b0919776ed2051d5fddaf..9e90c77764d020715c4b6bc94ad71deeee6f19aa 100644 (file)
@@ -47,5 +47,6 @@ string _Nex_ExtResponseSystem_PromotedServers;
 float _Nex_ExtResponseSystem_PromotedServersNeedsRefresh;
 string _Nex_ExtResponseSystem_RecommendedServers;
 float _Nex_ExtResponseSystem_RecommendedServersNeedsRefresh;
+float _Nex_ExtResponseSystem_NewToS;
 
 void CheckSendCvars(entity me, string cvarnamestring);
index 59ff81df94678b5f744c0da45e617019e56416a7..f487ca4c9fd75fcc0c38b755aecb882d89aa84cf 100644 (file)
@@ -536,11 +536,8 @@ void bot_removenewest()
 
 void autoskill(float factor)
 {
-       float bestbot;
-       float bestplayer;
-
-       bestbot = -1;
-       bestplayer = -1;
+       int bestbot = -1;
+       int bestplayer = -1;
        FOREACH_CLIENT(IS_PLAYER(it), {
                if(IS_REAL_CLIENT(it))
                        bestplayer = max(bestplayer, it.totalfrags - it.totalfrags_lastcheck);
@@ -548,37 +545,37 @@ void autoskill(float factor)
                        bestbot = max(bestbot, it.totalfrags - it.totalfrags_lastcheck);
        });
 
-       LOG_DEBUG("autoskill: best player got ", ftos(bestplayer), ", ");
-       LOG_DEBUG("best bot got ", ftos(bestbot), "; ");
+       string msg = strcat("autoskill: best player got ", ftos(bestplayer), ", ""best bot got ", ftos(bestbot), "; ");
        if(bestbot < 0 || bestplayer < 0)
        {
-               LOG_DEBUG("not doing anything");
+               msg = strcat(msg, "not doing anything");
                // don't return, let it reset all counters below
        }
        else if(bestbot <= bestplayer * factor - 2)
        {
                if(autocvar_skill < 17)
                {
-                       LOG_DEBUG("2 frags difference, increasing skill");
+                       msg = strcat(msg, "2 frags difference, increasing skill");
                        cvar_set("skill", ftos(autocvar_skill + 1));
-                       bprint("^2SKILL UP!^7 Now at level ", ftos(autocvar_skill), "\n");
+                       bprint("^2BOT SKILL UP!^7 Now at level ", ftos(autocvar_skill), "\n");
                }
        }
        else if(bestbot >= bestplayer * factor + 2)
        {
                if(autocvar_skill > 0)
                {
-                       LOG_DEBUG("2 frags difference, decreasing skill");
+                       msg = strcat(msg, "2 frags difference, decreasing skill");
                        cvar_set("skill", ftos(autocvar_skill - 1));
-                       bprint("^1SKILL DOWN!^7 Now at level ", ftos(autocvar_skill), "\n");
+                       bprint("^1BOT SKILL DOWN!^7 Now at level ", ftos(autocvar_skill), "\n");
                }
        }
        else
        {
-               LOG_DEBUG("not doing anything");
+               msg = strcat(msg, "not doing anything");
                return;
                // don't reset counters, wait for them to accumulate
        }
+       LOG_DEBUG(msg);
 
        FOREACH_CLIENT(IS_PLAYER(it), { it.totalfrags_lastcheck = it.totalfrags; });
 }
index 7e1bfd1e560dc0b12f7286048aee1bd8c0b837d7..07c400f5d3bf31337449629435cfe5f1dc5949c7 100644 (file)
@@ -434,6 +434,7 @@ void WinningConditionHelper(entity this)
        s = strcat(s, ":P", ftos(cvar_purechanges_count));
        s = strcat(s, ":S", ftos(nJoinAllowed(this, NULL)));
        s = strcat(s, ":F", ftos(serverflags));
+       s = strcat(s, ":T", sv_termsofservice_url_escaped);
        s = strcat(s, ":M", modname);
        s = strcat(s, "::", GetPlayerScoreString(NULL, (fullstatus ? 1 : 2)));
 
index e2a44d2c8b71e29d28a02138543ea4faf0f3f44a..51093d51b512abb12fc687c7b391ee0fea9b28db 100644 (file)
@@ -689,6 +689,15 @@ spawnfunc(worldspawn)
 {
        server_is_dedicated = boolean(stof(cvar_defstring("is_dedicated")));
 
+       if (autocvar_sv_termsofservice_url && autocvar_sv_termsofservice_url != "")
+       {
+               strcpy(sv_termsofservice_url_escaped, strreplace(":", "|", autocvar_sv_termsofservice_url));
+       }
+       else
+       {
+               strcpy(sv_termsofservice_url_escaped, "INVALID");
+       }
+
        bool wantrestart = false;
        {
                if (!server_is_dedicated)
@@ -2430,6 +2439,8 @@ void Shutdown()
 
                WeaponStats_Shutdown();
                MapInfo_Shutdown();
+
+               strfree(sv_termsofservice_url_escaped);
        }
        else if(world_initialized == 0)
        {
index 3f6b9b6d22d676abd06947c077560d28e6924307..299c88535446724e3819fc5f90c67ac07efe0693 100644 (file)
@@ -47,6 +47,10 @@ string gamemode_name;
 
 string record_type;
 
+string autocvar_sv_termsofservice_url;
+// only escape the terms of service url on map change
+string sv_termsofservice_url_escaped;
+
 string clientstuff;
 
 string matchid;
index 8ade6794e6b0a958ff69113a2e429de520233ebb..c5777051871e81e8e8c6fce4f8fc7fff04835ab6 100644 (file)
@@ -842,6 +842,9 @@ seta cl_allow_uid2name -1 "-1 = ask if the player wants to disable/enable this f
 seta cl_allow_uidtracking 1 "-1 = ask if the player wants to disable/enable this feature, 0 = disable, 1 = enable uid tracking (allows associating your data with your player ID)"
 seta cl_allow_uidranking 1 "0 = disable, 1 = enable uid ranking (allows statistics like elo to rank you in leaderboards)"
 
+// terms of service
+seta _termsofservice_accepted 0
+
 // polygonoffset for submodel SUCKS SUCKS SUCKS (only a hack for quake1, we don't need that)
 r_polygonoffset_submodel_offset 0
 r_polygonoffset_submodel_factor 0