]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/monsters
authorMario <zacjardine@y7mail.com>
Sun, 9 Sep 2018 12:44:26 +0000 (22:44 +1000)
committerMario <zacjardine@y7mail.com>
Sun, 9 Sep 2018 12:44:26 +0000 (22:44 +1000)
36 files changed:
notifications.cfg
qcsrc/common/items/item/ammo.qh
qcsrc/common/items/item/armor.qh
qcsrc/common/items/item/health.qh
qcsrc/common/items/item/jetpack.qh
qcsrc/common/items/item/powerup.qh
qcsrc/common/minigames/sv_minigames.qc
qcsrc/common/mutators/mutator/buffs/all.inc
qcsrc/common/mutators/mutator/buffs/buffs.qc
qcsrc/common/mutators/mutator/buffs/buffs.qh
qcsrc/common/mutators/mutator/buffs/cl_buffs.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/instagib/items.qh
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh
qcsrc/common/notifications/all.inc
qcsrc/common/notifications/all.qh
qcsrc/common/physics/player.qc
qcsrc/common/turrets/cl_turrets.qc
qcsrc/common/turrets/sv_turrets.qc
qcsrc/common/viewloc.qc
qcsrc/server/autocvars.qh
qcsrc/server/client.qc
qcsrc/server/client.qh
qcsrc/server/clientkill.qc
qcsrc/server/command/cmd.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/player.qc
qcsrc/server/teamplay.qc
qcsrc/server/teamplay.qh
qcsrc/server/weapons/throwing.qc
qcsrc/server/weapons/throwing.qh
xonotic-client.cfg
xonotic-server.cfg

index 143b5c0e25d71a270007f14e8864b6a6ad99fd9d..dc50883e0df2b5b0bfcc10211b55cddc32b705df 100644 (file)
@@ -261,7 +261,7 @@ seta notification_INFO_POWERUP_STRENGTH "1" "0 = off, 1 = print to console, 2 =
 seta notification_INFO_QUIT_DISCONNECT "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_QUIT_KICK_IDLING "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_QUIT_KICK_SPECTATING "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
-seta notification_INFO_QUIT_SPECTATE "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_QUIT_SPECTATE "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_RACE_ABANDONED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_RACE_FAIL_RANKED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_RACE_FAIL_UNRANKED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
@@ -281,7 +281,7 @@ seta notification_INFO_SUPERSPEC_MISSING_UID "2" "0 = off, 1 = print to console,
 seta notification_INFO_SUPERWEAPON_PICKUP "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_TEAMCHANGE_LARGERTEAM "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_TEAMCHANGE_NOTALLOWED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
-seta notification_INFO_VERSION_BETA "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_VERSION_BETA "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_VERSION_OLD "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_VERSION_OUTDATED "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_WATERMARK "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
index 4c37464ad83c8de28d6a6f706d8f264ff26727f9..3249f07bca6caf6be0d76ae1b49ad4542c255c4c 100644 (file)
@@ -63,7 +63,7 @@ REGISTER_ITEM(Bullets, Bullets) {
     this.m_model    =   MDL_Bullets_ITEM;
 #endif
     this.netname    =   "bullets";
-    this.m_name     =   "bullets";
+    this.m_name     =   _("bullets");
     this.m_icon     =   "ammo_bullets";
 #ifdef SVQC
     this.m_botvalue =   1500;
@@ -93,7 +93,7 @@ REGISTER_ITEM(Cells, Ammo) {
     this.m_model    =   MDL_Cells_ITEM;
 #endif
     this.netname    =   "cells";
-    this.m_name     =   "cells";
+    this.m_name     =   _("cells");
     this.m_icon     =   "ammo_cells";
 #ifdef SVQC
     this.m_botvalue =   1500;
@@ -123,7 +123,7 @@ REGISTER_ITEM(Plasma, Ammo) {
     this.m_model    =   MDL_Plasma_ITEM;
 #endif
     this.netname    =   "plasma";
-    this.m_name     =   "plasma";
+    this.m_name     =   _("plasma");
     this.m_icon     =   "ammo_plasma";
 #ifdef SVQC
     this.m_botvalue =   1500;
@@ -153,7 +153,7 @@ REGISTER_ITEM(Rockets, Ammo) {
     this.m_model    =   MDL_Rockets_ITEM;
 #endif
     this.netname    =   "rockets";
-    this.m_name     =   "rockets";
+    this.m_name     =   _("rockets");
     this.m_icon     =   "ammo_rockets";
 #ifdef SVQC
     this.m_botvalue =   1500;
@@ -187,7 +187,7 @@ REGISTER_ITEM(Shells, Shells) {
     this.m_model    =   MDL_Shells_ITEM;
 #endif
     this.netname    =   "shells";
-    this.m_name     =   "shells";
+    this.m_name     =   _("shells");
     this.m_icon     =   "ammo_shells";
 #ifdef SVQC
     this.m_botvalue =   1000;
index ee39aa59242111771347d38005fe0d3c89113e4c..2ecd8355714c950f1089cc7d03bbcbc1c8a2850a 100644 (file)
@@ -39,7 +39,7 @@ REGISTER_ITEM(ArmorSmall, Armor) {
     this.m_sound                =   SND_ArmorSmall;
 #endif
     this.netname                =   "armor_small";
-    this.m_name                 =   "5 Armor";
+    this.m_name                 =   _("Small armor");
     this.m_icon                 =   "armor";
 #ifdef SVQC
     this.m_itemid               =   IT_ARMOR_SHARD;
@@ -77,7 +77,7 @@ REGISTER_ITEM(ArmorMedium, Armor) {
     this.m_sound                =   SND_ArmorMedium;
 #endif
     this.netname                =   "armor_medium";
-    this.m_name                 =   "25 Armor";
+    this.m_name                 =   _("Medium armor");
     this.m_icon                 =   "armor";
 #ifdef SVQC
     this.m_itemid               =   IT_ARMOR;
@@ -115,7 +115,7 @@ REGISTER_ITEM(ArmorBig, Armor) {
     this.m_sound                =   SND_ArmorBig;
 #endif
     this.netname                =   "armor_big";
-    this.m_name                 =   "50 Armor";
+    this.m_name                 =   _("Big armor");
     this.m_icon                 =   "armor";
     this.m_color                =   '0 1 0';
     this.m_waypoint             =   _("Big armor");
@@ -155,7 +155,7 @@ REGISTER_ITEM(ArmorMega, Armor) {
     this.m_sound                =   SND_ArmorMega;
 #endif
     this.netname                =   "armor_mega";
-    this.m_name                 =   "100 Armor";
+    this.m_name                 =   _("Mega armor");
     this.m_icon                 =   "item_large_armor";
     this.m_color                =   '0 1 0';
     this.m_waypoint             =   _("Mega armor");
index bf515fe4dd7f7c167d31c7f85b6eb3bc9e409fb3..e6a9dd9883589f13776384d823e207beae250357 100644 (file)
@@ -39,7 +39,7 @@ REGISTER_ITEM(HealthSmall, Health) {
     this.m_sound                =   SND_HealthSmall;
 #endif
     this.netname                =   "health_small";
-    this.m_name                 =   "5 Health";
+    this.m_name                 =   _("Small health");
     this.m_icon                 =   "health";
 #ifdef SVQC
     this.m_itemid               =   IT_5HP;
@@ -77,7 +77,7 @@ REGISTER_ITEM(HealthMedium, Health) {
     this.m_sound                =   SND_HealthMedium;
 #endif
     this.netname                =   "health_medium";
-    this.m_name                 =   "25 Health";
+    this.m_name                 =   _("Medium health");
     this.m_icon                 =   "health";
 #ifdef SVQC
     this.m_itemid               =   IT_25HP;
@@ -115,7 +115,7 @@ REGISTER_ITEM(HealthBig, Health) {
     this.m_sound                =   SND_HealthBig;
 #endif
     this.netname                =   "health_big";
-    this.m_name                 =   "50 Health";
+    this.m_name                 =   _("Big health");
     this.m_icon                 =   "health";
     this.m_color                =   '1 0 0';
     this.m_waypoint             =   _("Big health");
@@ -155,7 +155,7 @@ REGISTER_ITEM(HealthMega, Health) {
     this.m_sound                =   SND_HealthMega;
 #endif
     this.netname                =   "health_mega";
-    this.m_name                 =   "100 Health";
+    this.m_name                 =   _("Mega health");
     this.m_icon                 =   "item_mega_health";
     this.m_color                =   '1 0 0';
     this.m_waypoint             =   _("Mega health");
index 760033861a7db8377342bc6ff7dbd6bef1901b4b..24d040d56b403753c50f12f4ddcee7869a7f9cff 100644 (file)
@@ -35,7 +35,7 @@ REGISTER_ITEM(Jetpack, Powerup) {
     this.m_itemid               =   IT_JETPACK;
 #endif
     this.netname                =   "jetpack";
-    this.m_name                 =   "Jetpack";
+    this.m_name                 =   _("Jetpack");
     this.m_icon                 =   "jetpack";
     this.m_color                =   '0.5 0.5 0.5';
     this.m_waypoint             =   _("Jetpack");
@@ -68,7 +68,7 @@ REGISTER_ITEM(JetpackFuel, Ammo) {
     this.m_model    =   MDL_JetpackFuel_ITEM;
 #endif
     this.netname    =   "fuel";
-    this.m_name     =   "Fuel";
+    this.m_name     =   _("fuel");
     this.m_icon     =   "ammo_fuel";
 #ifdef SVQC
     this.m_botvalue =   2000;
@@ -93,7 +93,7 @@ REGISTER_ITEM(JetpackRegen, JetpackRegen) {
     this.m_model                =   MDL_JetpackRegen_ITEM;
 #endif
     this.netname                =   "fuel_regen";
-    this.m_name                 =   "Fuel regenerator";
+    this.m_name                 =   _("Fuel regenerator");
     this.m_icon                 =   "fuelregen";
     this.m_color                =   '1 0.5 0';
     this.m_waypoint             =   _("Fuel regen");
index 9de1235361787678286474044f004ddbc8e4c31c..43414b3d06f68af39afcb97f5eb0ebb7f2cf43ee 100644 (file)
@@ -40,7 +40,7 @@ REGISTER_ITEM(Strength, Powerup) {
     this.m_respawnsound     =   SND_STRENGTH_RESPAWN;
 #endif
     this.netname            =   "strength";
-    this.m_name             =   "Strength Powerup";
+    this.m_name             =   _("Strength");
     this.m_icon             =   "strength";
     this.m_color            =   '0 0 1';
     this.m_waypoint         =   _("Strength");
@@ -76,7 +76,7 @@ REGISTER_ITEM(Shield, Powerup) {
     this.m_respawnsound     =   SND_SHIELD_RESPAWN;
 #endif
     this.netname            =   "invincible";
-    this.m_name             =   "Shield";
+    this.m_name             =   _("Shield");
     this.m_icon             =   "shield";
     this.m_color            =   '1 0 1';
     this.m_waypoint         =   _("Shield");
index 5c6af26615dc5f71363dfb9286eab23da294a859..af74e6a5a6c601902c1da414b0a24d8d46f356b4 100644 (file)
@@ -9,7 +9,7 @@ void player_clear_minigame(entity player)
                set_movetype(player, MOVETYPE_WALK);
        else
                set_movetype(player, MOVETYPE_FLY_WORLDONLY);
-       player.team_forced = 0;
+       Player_SetForcedTeamIndex(player, TEAM_FORCE_DEFAULT);
 }
 
 void minigame_rmplayer(entity minigame_session, entity player)
@@ -150,7 +150,7 @@ int minigame_addplayer(entity minigame_session, entity player)
                        PutObserverInServer(player);
                }
                if ( autocvar_sv_minigames_observer == 2 )
-                       player.team_forced = -1;
+                       Player_SetForcedTeamIndex(player, TEAM_FORCE_SPECTATOR);
 
                minigame_resend(minigame_session);
        }
index 877d5c4eac2630e6a55caf1d4a541d7726a7d60a..0c9b8890189c7337f774db335c7555c5d40eaea2 100644 (file)
@@ -12,8 +12,8 @@ string Buff_UndeprecateName(string buffname)
 }
 
 REGISTER_BUFF(AMMO) {
-    this.m_prettyName = _("Ammo");
-    this.m_name = "ammo";
+    this.m_name = _("Ammo");
+    this.netname = "ammo";
     this.m_skin = 3;
     this.m_color = '0.76 1 0.1';
 }
@@ -21,8 +21,8 @@ BUFF_SPAWNFUNCS(ammo, BUFF_AMMO)
 BUFF_SPAWNFUNC_Q3TA_COMPAT(ammoregen, BUFF_AMMO)
 
 REGISTER_BUFF(RESISTANCE) {
-    this.m_prettyName = _("Resistance");
-    this.m_name = "resistance";
+    this.m_name = _("Resistance");
+    this.netname = "resistance";
     this.m_skin = 0;
     this.m_color = '0.36 1 0.07';
 }
@@ -30,8 +30,8 @@ BUFF_SPAWNFUNCS(resistance, BUFF_RESISTANCE)
 BUFF_SPAWNFUNC_Q3TA_COMPAT(resistance, BUFF_RESISTANCE)
 
 REGISTER_BUFF(SPEED) {
-    this.m_prettyName = _("Speed");
-    this.m_name = "speed";
+    this.m_name = _("Speed");
+    this.netname = "speed";
     this.m_skin = 9;
     this.m_color = '0.1 1 0.84';
 }
@@ -40,8 +40,8 @@ BUFF_SPAWNFUNC_Q3TA_COMPAT(haste, BUFF_SPEED)
 BUFF_SPAWNFUNC_Q3TA_COMPAT(scout, BUFF_SPEED)
 
 REGISTER_BUFF(MEDIC) {
-    this.m_prettyName = _("Medic");
-    this.m_name = "medic";
+    this.m_name = _("Medic");
+    this.netname = "medic";
     this.m_skin = 1;
     this.m_color = '1 0.12 0';
 }
@@ -51,40 +51,40 @@ BUFF_SPAWNFUNC_Q3TA_COMPAT(regen, BUFF_MEDIC)
 BUFF_SPAWNFUNC_Q3TA_COMPAT(revival, BUFF_MEDIC)
 
 REGISTER_BUFF(BASH) {
-    this.m_prettyName = _("Bash");
-    this.m_name = "bash";
+    this.m_name = _("Bash");
+    this.netname = "bash";
     this.m_skin = 5;
     this.m_color = '1 0.39 0';
 }
 BUFF_SPAWNFUNCS(bash, BUFF_BASH)
 
 REGISTER_BUFF(VAMPIRE) {
-    this.m_prettyName = _("Vampire");
-    this.m_name = "vampire";
+    this.m_name = _("Vampire");
+    this.netname = "vampire";
     this.m_skin = 2;
     this.m_color = '1 0 0.24';
 }
 BUFF_SPAWNFUNCS(vampire, BUFF_VAMPIRE)
 
 REGISTER_BUFF(DISABILITY) {
-    this.m_prettyName = _("Disability");
-    this.m_name = "disability";
+    this.m_name = _("Disability");
+    this.netname = "disability";
     this.m_skin = 7;
     this.m_color = '0.94 0.3 1';
 }
 BUFF_SPAWNFUNCS(disability, BUFF_DISABILITY)
 
 REGISTER_BUFF(VENGEANCE) {
-    this.m_prettyName = _("Vengeance");
-    this.m_name = "vengeance";
+    this.m_name = _("Vengeance");
+    this.netname = "vengeance";
     this.m_skin = 15;
     this.m_color = '1 0.23 0.61';
 }
 BUFF_SPAWNFUNCS(vengeance, BUFF_VENGEANCE)
 
 REGISTER_BUFF(JUMP) {
-    this.m_prettyName = _("Jump");
-    this.m_name = "jump";
+    this.m_name = _("Jump");
+    this.netname = "jump";
     this.m_skin = 10;
     this.m_color = '0.24 0.78 1';
 }
@@ -92,8 +92,8 @@ BUFF_SPAWNFUNCS(jump, BUFF_JUMP)
 BUFF_SPAWNFUNC_Q3TA_COMPAT(jumper, BUFF_JUMP)
 
 REGISTER_BUFF(INVISIBLE) {
-    this.m_prettyName = _("Invisible");
-    this.m_name = "invisible";
+    this.m_name = _("Invisible");
+    this.netname = "invisible";
     this.m_skin = 12;
     this.m_color = '0.5 0.5 1';
 }
@@ -101,40 +101,40 @@ BUFF_SPAWNFUNCS(invisible, BUFF_INVISIBLE)
 BUFF_SPAWNFUNC_Q3TA_COMPAT(invis, BUFF_INVISIBLE)
 
 REGISTER_BUFF(INFERNO) {
-    this.m_prettyName = _("Inferno");
-    this.m_name = "inferno";
+    this.m_name = _("Inferno");
+    this.netname = "inferno";
     this.m_skin = 16;
     this.m_color = '1 0.62 0';
 }
 BUFF_SPAWNFUNCS(inferno, BUFF_INFERNO)
 
 REGISTER_BUFF(SWAPPER) {
-    this.m_prettyName = _("Swapper");
-    this.m_name = "swapper";
+    this.m_name = _("Swapper");
+    this.netname = "swapper";
     this.m_skin = 17;
     this.m_color = '0.63 0.36 1';
 }
 BUFF_SPAWNFUNCS(swapper, BUFF_SWAPPER)
 
 REGISTER_BUFF(MAGNET) {
-    this.m_prettyName = _("Magnet");
-    this.m_name = "magnet";
+    this.m_name = _("Magnet");
+    this.netname = "magnet";
     this.m_skin = 18;
     this.m_color = '1 0.95 0.18';
 }
 BUFF_SPAWNFUNCS(magnet, BUFF_MAGNET)
 
 REGISTER_BUFF(LUCK) {
-    this.m_prettyName = _("Luck");
-    this.m_name = "luck";
+    this.m_name = _("Luck");
+    this.netname = "luck";
     this.m_skin = 19;
     this.m_color = '1 0.23 0.44';
 }
 BUFF_SPAWNFUNCS(luck, BUFF_LUCK)
 
 REGISTER_BUFF(FLIGHT) {
-    this.m_prettyName = _("Flight");
-    this.m_name = "flight";
+    this.m_name = _("Flight");
+    this.netname = "flight";
     this.m_skin = 11;
     this.m_color = '0.23 0.44 1';
 }
index 8ef69aad982f45e49e646d960143f2afb5900d09..4a5dcc82aaa1ded918115799619f366f321b3d87 100644 (file)
@@ -3,7 +3,7 @@
 string BUFF_NAME(int i)
 {
     Buff b = Buffs_from(i);
-    return strcat(rgb_to_hexcolor(b.m_color), b.m_prettyName);
+    return strcat(rgb_to_hexcolor(b.m_color), b.m_name);
 }
 
 entity buff_FirstFromFlags(int _buffs)
index 35005e7a8fea65285d869afd82a8f247da833f78..7d4e583675b812169ee16ebc076b57f3973ee7e3 100644 (file)
@@ -20,13 +20,13 @@ REGISTRY_CHECK(Buffs)
 CLASS(Buff, Pickup)
        /** bit index */
        ATTRIB(Buff, m_itemid, int, 0);
-       ATTRIB(Buff, m_name, string, "buff");
+       ATTRIB(Buff, netname, string, "buff");
        ATTRIB(Buff, m_color, vector, '1 1 1');
-       ATTRIB(Buff, m_prettyName, string, "Buff");
+       ATTRIB(Buff, m_name, string, "Buff");
        ATTRIB(Buff, m_skin, int, 0);
        ATTRIB(Buff, m_sprite, string, "");
        METHOD(Buff, display, void(entity this, void(string name, string icon) returns)) {
-               returns(this.m_prettyName, sprintf("/gfx/hud/%s/buff_%s", cvar_string("menu_skin"), this.m_name));
+               returns(this.m_name, sprintf("/gfx/hud/%s/buff_%s", cvar_string("menu_skin"), this.netname));
        }
 #ifdef SVQC
        METHOD(Buff, m_time, float(Buff this))
@@ -36,9 +36,8 @@ ENDCLASS(Buff)
 
 STATIC_INIT(REGISTER_BUFFS) {
     FOREACH(Buffs, true, {
-        it.netname = it.m_name; \
         it.m_itemid = BIT(it.m_id - 1); \
-        it.m_sprite = strzone(strcat("buff-", it.m_name)); \
+        it.m_sprite = strzone(strcat("buff-", it.netname)); \
     });
 }
 
index f751eecff091ff08e775bde798813d748fdb0b2f..790a10a86b8f16da4b5f0f0f65900d1813ca89a2 100644 (file)
@@ -5,7 +5,7 @@ MUTATOR_HOOKFUNCTION(cl_buffs, HUD_Powerups_add)
 {
     int allBuffs = STAT(BUFFS);
     FOREACH(Buffs, it.m_itemid & allBuffs, {
-               addPowerupItem(it.m_prettyName, strcat("buff_", it.m_name), it.m_color, bound(0, STAT(BUFF_TIME) - time, 99), 60);
+               addPowerupItem(it.m_name, strcat("buff_", it.netname), it.m_color, bound(0, STAT(BUFF_TIME) - time, 99), 60);
        });
 }
 MUTATOR_HOOKFUNCTION(cl_buffs, WP_Format)
@@ -16,8 +16,8 @@ MUTATOR_HOOKFUNCTION(cl_buffs, WP_Format)
     {
         Buff b = Buffs_from(this.wp_extra);
         M_ARGV(2, vector) = b.m_color;
-        M_ARGV(3, string) = b.m_prettyName;
-        M_ARGV(4, string) = strcat("buff_", b.m_name);
+        M_ARGV(3, string) = b.m_name;
+        M_ARGV(4, string) = strcat("buff_", b.netname);
         return true;
     }
 }
index 27f71b56c24ee02f88798ed51e214c15a5b05127..b7cdbf05b83c171ad278e61a3eb7e9c021ff78d6 100644 (file)
@@ -210,7 +210,7 @@ float buff_Available(entity buff)
                return false;
        if (buff == BUFF_VAMPIRE && cvar("g_vampire"))
                return false;
-       return cvar(strcat("g_buffs_", buff.m_name));
+       return cvar(strcat("g_buffs_", buff.netname));
 }
 
 .int buff_seencount;
index 3f8d087166353715a224acd0d7bbf4383cdb2154..42e3adbd73b74c6fa8eb1d23abfcde0c8e086145 100644 (file)
@@ -30,7 +30,7 @@ REGISTER_ITEM(VaporizerCells, Ammo) {
     this.m_sound                =   SND_VaporizerCells;
 #endif
     this.netname                =   "vaporizer_cells";
-    this.m_name                 =   "Vaporizer Ammo";
+    this.m_name                 =   _("Vaporizer ammo");
     this.m_icon                 =   "ammo_supercells";
 #ifdef SVQC
     this.m_botvalue             =   2000;
@@ -56,7 +56,7 @@ REGISTER_ITEM(ExtraLife, Powerup) {
     this.m_sound                =   SND_ExtraLife;
 #endif
     this.netname                =   "extralife";
-    this.m_name                 =   "Extra life";
+    this.m_name                 =   _("Extra life");
     this.m_icon                 =   "item_mega_health";
     this.m_color                =   '1 0 0';
     this.m_waypoint             =   _("Extra life");
@@ -88,7 +88,7 @@ REGISTER_ITEM(Invisibility, Powerup) {
     this.m_respawnsound     =   SND_STRENGTH_RESPAWN;
 #endif
     this.netname            =   "invisibility";
-    this.m_name             =   "Invisibility";
+    this.m_name             =   _("Invisibility");
     this.m_icon             =   "strength";
     this.m_color            =   '0 0 1';
     this.m_waypoint         =   _("Invisibility");
@@ -123,7 +123,7 @@ REGISTER_ITEM(Speed, Powerup) {
     this.m_respawnsound     =   SND_SHIELD_RESPAWN;
 #endif
     this.netname            =   "speed";
-    this.m_name             =   "Speed";
+    this.m_name             =   _("Speed");
     this.m_icon             =   "shield";
     this.m_color            =   '1 0 1';
     this.m_waypoint         =   _("Speed");
index 9bfa4862befc03fb6e9a7f8d9184787922b89e7c..e2190b66a26a9cef1c0efb477c51d53c7276422c 100644 (file)
@@ -52,6 +52,7 @@ int autocvar_g_waypointsprite_spam;
 float autocvar_g_waypointsprite_timealphaexponent;
 bool autocvar_g_waypointsprite_turrets = true;
 float autocvar_g_waypointsprite_turrets_maxdist = 5000;
+bool autocvar_g_waypointsprite_turrets_text = false;
 bool autocvar_g_waypointsprite_uppercase;
 bool autocvar_g_waypointsprite_text;
 float autocvar_g_waypointsprite_iconsize = 32;
index 62fe8300c2efe2461c4a520e3fe8ac44c8f1e0f9..b0e75e6cdfea7295257a57f5bc59664cfc336818 100644 (file)
     MSG_INFO_NOTIF(ITEM_BUFF_GOT,                           N_CONSOLE,  0, 1, "item_buffname", "",          "",     _("^BGYou got the %s^BG buff!"), "")
 
     MSG_INFO_NOTIF(ITEM_WEAPON_DONTHAVE,                    N_DISABLE,  0, 1, "item_wepname", "",                           "",     _("^BGYou do not have the ^F1%s"), "")
-    MSG_INFO_NOTIF(ITEM_WEAPON_DROP,                        N_DISABLE,  1, 1, "item_wepname item_wepammo", "",              "",     _("^BGYou dropped the ^F1%s^BG%s"), "")
+    MSG_INFO_NOTIF(ITEM_WEAPON_DROP,                        N_DISABLE,  0, 2, "item_wepname item_wepammo", "",              "",     _("^BGYou dropped the ^F1%s^BG%s"), "")
     MSG_INFO_NOTIF(ITEM_WEAPON_GOT,                         N_DISABLE,  0, 1, "item_wepname", "",                           "",     _("^BGYou got the ^F1%s"), "")
     MSG_INFO_NOTIF(ITEM_WEAPON_NOAMMO,                      N_DISABLE,  0, 1, "item_wepname", "",                           "",     _("^BGYou don't have enough ammo for the ^F1%s"), "")
     MSG_INFO_NOTIF(ITEM_WEAPON_PRIMORSEC,                   N_DISABLE,  0, 3, "item_wepname f2primsec f3primsec", "",       "",     _("^F1%s %s^BG is unable to fire, but its ^F1%s^BG can"), "")
     MSG_INFO_NOTIF(QUIT_KICK_IDLING,                        N_CHATCON,  1, 0, "s1", "",         "",             _("^BG%s^F3 was kicked for idling"), "")
     MSG_INFO_NOTIF(QUIT_KICK_SPECTATING,                    N_CONSOLE,  0, 0, "", "",           "",             _("^F2You were kicked from the server because you are a spectator and spectators aren't allowed at the moment."), "")
     MSG_INFO_NOTIF(QUIT_KICK_TEAMKILL,                      N_CHATCON,  1, 0, "s1", "",         "",             _("^BG%s^F3 was kicked for excessive teamkilling"), "")
-    MSG_INFO_NOTIF(QUIT_SPECTATE,                           N_CONSOLE,  1, 0, "s1", "",         "",             _("^BG%s^F3 is now spectating"), "")
+    MSG_INFO_NOTIF(QUIT_SPECTATE,                           N_CHATCON,  1, 0, "s1", "",         "",             _("^BG%s^F3 is now spectating"), "")
 
     MSG_INFO_NOTIF(RACE_ABANDONED,                          N_CONSOLE,  1, 0, "s1", "",                                                                     "",                         _("^BG%s^BG has abandoned the race"), "")
     MSG_INFO_NOTIF(RACE_FAIL_RANKED,                        N_CONSOLE,  1, 3, "s1 race_col f1ord race_col f3race_time race_diff", "s1 f3race_time",         "race_newfail",             _("^BG%s^BG couldn't break their %s%s^BG place record of %s%s %s"), "")
     MSG_INFO_NOTIF(TEAMCHANGE_LARGERTEAM,                   N_CONSOLE,  0, 0, "", "",           "",                     _("^BGYou cannot change to a larger team"), "")
     MSG_INFO_NOTIF(TEAMCHANGE_NOTALLOWED,                   N_CONSOLE,  0, 0, "", "",           "",                     _("^BGYou are not allowed to change teams"), "")
 
-    MSG_INFO_NOTIF(VERSION_BETA,                            N_CHATCON,  2, 0, "s1 s2", "",      "",                     _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s (beta)^BG, you have ^F2Xonotic %s"), "")
+    MSG_INFO_NOTIF(VERSION_BETA,                            N_CONSOLE,  2, 0, "s1 s2", "",      "",                     _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s (beta)^BG, you have ^F2Xonotic %s"), "")
     MSG_INFO_NOTIF(VERSION_OLD,                             N_CHATCON,  2, 0, "s1 s2", "",      "",                     _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s^BG, you have ^F2Xonotic %s"), "")
     MSG_INFO_NOTIF(VERSION_OUTDATED,                        N_CHATCON,  2, 0, "s1 s2", "",      "",                     _("^F4NOTE: ^F1Xonotic %s^BG is out, and you still have ^F2Xonotic %s^BG - get the update from ^F3http://www.xonotic.org/^BG!"), "")
 
     MSG_CENTER_NOTIF(ITEM_FUELREGEN_GOT,                N_ENABLE,    0, 0, "",                                   CPID_ITEM, "item_centime 0", _("^BGYou got the ^F1Fuel regenerator"), "")
     MSG_CENTER_NOTIF(ITEM_JETPACK_GOT,                  N_ENABLE,    0, 0, "",                                   CPID_ITEM, "item_centime 0", _("^BGYou got the ^F1Jetpack"), "")
     MSG_CENTER_NOTIF(ITEM_WEAPON_DONTHAVE,              N_ENABLE,    0, 1, "item_wepname",                       CPID_ITEM, "item_centime 0", _("^BGYou do not have the ^F1%s"), "")
-    MSG_CENTER_NOTIF(ITEM_WEAPON_DROP,                  N_ENABLE,    1, 1, "item_wepname item_wepammo",          CPID_ITEM, "item_centime 0", _("^BGYou dropped the ^F1%s^BG%s"), "")
+    MSG_CENTER_NOTIF(ITEM_WEAPON_DROP,                  N_ENABLE,    0, 2, "item_wepname item_wepammo",          CPID_ITEM, "item_centime 0", _("^BGYou dropped the ^F1%s^BG%s"), "")
     MSG_CENTER_NOTIF(ITEM_WEAPON_GOT,                   N_ENABLE,    0, 1, "item_wepname",                       CPID_ITEM, "item_centime 0", _("^BGYou got the ^F1%s"), "")
     MSG_CENTER_NOTIF(ITEM_WEAPON_NOAMMO,                N_ENABLE,    0, 1, "item_wepname",                       CPID_ITEM, "item_centime 0", _("^BGYou don't have enough ammo for the ^F1%s"), "")
     MSG_CENTER_NOTIF(ITEM_WEAPON_PRIMORSEC,             N_ENABLE,    0, 3, "item_wepname f2primsec f3primsec",   CPID_ITEM, "item_centime 0", _("^F1%s %s^BG is unable to fire, but its ^F1%s^BG can"), "")
index 7982ee01f73acfc3348bed12334f125d60af494e..6cbf91cc9b3fe185cb1b728b75dc8d273435e612 100644 (file)
@@ -6,6 +6,7 @@
 #include <common/teams.qh>
 #include <common/util.qh>
 #include <common/sounds/sound.qh>
+#include <common/weapons/all.qh>
 
 #ifdef CSQC
 #include <client/autocvars.qh>
@@ -370,7 +371,7 @@ float autocvar_notification_show_sprees_center_specialonly = true;
        spree_end: placed at the end of murder messages to show ending of sprees
        spree_lost: placed at the end of suicide messages to show losing of sprees
        item_wepname: return full name of a weapon from weaponid
-       item_wepammo: ammo display for weapon from string
+       item_wepammo: ammo display for weapon from f1 and f2
        item_centime: amount of time to display weapon message in centerprint
        item_buffname: return full name of a buff from buffid
        death_team: show the full name of the team a player is switching from
@@ -433,7 +434,7 @@ string BUFF_NAME(int i);
        ARG_CASE(ARG_CS_SV,     "item_wepname",  Weapons_from(f1).m_name) \
        ARG_CASE(ARG_CS_SV,     "item_buffname", BUFF_NAME(f1)) \
        ARG_CASE(ARG_CS_SV,     "f3buffname",    BUFF_NAME(f3)) \
-       ARG_CASE(ARG_CS_SV,     "item_wepammo",  (s1 != "" ? sprintf(_(" with %s"), s1) : "")) \
+       ARG_CASE(ARG_CS_SV,     "item_wepammo",  (f2 > 0 ? notif_arg_item_wepammo(f1, f2) : "")) \
        ARG_CASE(ARG_DC,        "item_centime",  ftos(autocvar_notification_item_centerprinttime)) \
        ARG_CASE(ARG_SV,        "death_team",    Team_ColoredFullName(f1)) \
        ARG_CASE(ARG_CS,        "death_team",    Team_ColoredFullName(f1 - 1)) \
@@ -624,6 +625,23 @@ string notif_arg_spree_inf(float type, string input, string player, float spree)
        return "";
 }
 
+string notif_arg_item_wepammo(float f1, float f2)
+{
+       string ammoitems = "";
+       Weapon wep = Weapons_from(f1);
+       switch (wep.ammo_type)
+       {
+               case RESOURCE_SHELLS:  ammoitems = ITEM_Shells.m_name;      break;
+               case RESOURCE_BULLETS: ammoitems = ITEM_Bullets.m_name;     break;
+               case RESOURCE_ROCKETS: ammoitems = ITEM_Rockets.m_name;     break;
+               case RESOURCE_CELLS:   ammoitems = ITEM_Cells.m_name;       break;
+               case RESOURCE_PLASMA:  ammoitems = ITEM_Plasma.m_name;      break;
+               case RESOURCE_FUEL:    ammoitems = ITEM_JetpackFuel.m_name; break;
+               default: return ""; // doesn't use ammo
+       }
+       return sprintf(_(" with %d %s"), f2, ammoitems);
+}
+
 
 // ====================================
 //  Initialization/Create Declarations
index f6ab29715a298c07a7bc9c317d0a69d4d9636298..572bee349f205ca81caac2d23d0ff6da1d839696 100644 (file)
@@ -119,6 +119,8 @@ void PM_ClientMovement_UpdateStatus(entity this)
                }
        }
        bool do_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
+       if(this.viewloc && !(this.viewloc.spawnflags & VIEWLOC_FREEMOVE) && PHYS_CS(this).movement.x < 0)
+               do_crouch = true;
        if (have_hook) {
                do_crouch = false;
        //} else if (this.waterlevel >= WATERLEVEL_SWIMMING) {
index ac68003a6cde83c1a6b652959af1f349240654e1..6cdda5103955a428443e1194c0711c310d692fe5 100644 (file)
@@ -176,7 +176,10 @@ void turret_draw2d(entity this)
        }
 
        o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
-       o = drawsprite_TextOrIcon(true, o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
+       if(autocvar_g_waypointsprite_turrets_text)
+       {
+               o = drawsprite_TextOrIcon(true, o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
+       }
        drawhealthbar(
                        o,
                        0,
index 27307d679511f8e55938c4515d4345816bb0bdec..8a88fb16874c0ba7b9f974f5389261091ad2ca7f 100644 (file)
@@ -716,7 +716,7 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl
        if(!checkpvs(e_target.origin, e_turret))
                return -1;
 
-       if(e_target.alpha <= 0.3)
+       if(e_target.alpha != 0 && e_target.alpha <= 0.3)
                return -1;
 
        if(MUTATOR_CALLHOOK(TurretValidateTarget, e_turret, e_target, validate_flags))
index f2dab7bfd22cd7c8620f3b69e7c10d9f37ece242..e1be43af0d41f9826993c9b9a7e1dceb247b9e16 100644 (file)
@@ -48,7 +48,7 @@ void viewloc_PlayerPhysics(entity this)
                        if(PHYS_CS(this).movement_x > 0) // right
                                this.angles_y = forward.y;
                }
-
+       #if 0
                //if(!PHYS_INPUT_BUTTON_CROUCH(this) && !IS_DUCKED(this))
                if(!(this.viewloc.spawnflags & VIEWLOC_FREEMOVE))
                {
@@ -65,6 +65,7 @@ void viewloc_PlayerPhysics(entity this)
                        //else { input_buttons &= ~16; this.flags &= ~FL_DUCKED; }
 #endif
                }
+       #endif
        }
 }
 
index 6fa7ca3af58f044dcc5331ddbeb4297d0ef2b197..7a2acf23badf4755b59656f339438c8da5c76813 100644 (file)
@@ -88,9 +88,6 @@ float autocvar_g_balance_powerup_strength_selfforce;
 //float autocvar_g_balance_powerup_strength_time;
 float autocvar_g_balance_superweapons_time;
 float autocvar_g_balance_selfdamagepercent;
-bool autocvar_g_balance_teams;
-bool autocvar_g_balance_teams_prevent_imbalance;
-//float autocvar_g_balance_teams_scorefactor;
 float autocvar_g_ballistics_density_corpse;
 float autocvar_g_ballistics_density_player;
 float autocvar_g_ballistics_mindistance;
@@ -109,7 +106,6 @@ bool autocvar_g_campaign;
 #define autocvar_g_campaign_forceteam cvar("g_campaign_forceteam")
 int autocvar_g_campaign_skill;
 int autocvar_g_casings;
-bool autocvar_g_changeteam_banned;
 float autocvar_g_chat_flood_burst;
 float autocvar_g_chat_flood_burst_team;
 float autocvar_g_chat_flood_burst_tell;
@@ -124,11 +120,7 @@ int autocvar_g_chat_nospectators;
 bool autocvar_g_chat_teamcolors;
 bool autocvar_g_chat_tellprivacy;
 bool autocvar_g_forced_respawn;
-string autocvar_g_forced_team_blue;
-string autocvar_g_forced_team_otherwise;
-string autocvar_g_forced_team_pink;
-string autocvar_g_forced_team_red;
-string autocvar_g_forced_team_yellow;
+string autocvar_g_forced_team_otherwise; // TODO: Move to teamplay.qc
 #define autocvar_g_friendlyfire cvar("g_friendlyfire")
 #define autocvar_g_friendlyfire_virtual cvar("g_friendlyfire_virtual")
 #define autocvar_g_friendlyfire_virtual_force cvar("g_friendlyfire_virtual_force")
@@ -366,8 +358,6 @@ bool autocvar_sv_vote_gamestart;
 string autocvar_sv_weaponstats_file;
 float autocvar_sv_gibhealth;
 float autocvar_sys_ticrate;
-bool autocvar_teamplay_lockonrestart;
-int autocvar_teamplay_mode;
 #define autocvar_timelimit cvar("timelimit")
 #define autocvar_timelimit_override cvar("timelimit_override")
 float autocvar_timelimit_increment;
index 85514bdf9e0b02c553e3def6a750ad84b5043e49..2418500efb121ebcd7ab57f0a633d4cc0a12c9c9 100644 (file)
@@ -285,25 +285,11 @@ void PutObserverInServer(entity this)
 
        WaypointSprite_PlayerDead(this);
 
-       if (mutator_returnvalue) {
-           // mutator prevents resetting teams+score
-       } else {
-               Player_SetTeamIndex(this, -1);
-               this.frags = FRAGS_SPECTATOR;
-        PlayerScore_Clear(this);  // clear scores when needed
-    }
-
        if (CS(this).killcount != FRAGS_SPECTATOR)
        {
-               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE, this.netname);
                if(!game_stopped)
                if(autocvar_g_chat_nospectators == 1 || (!warmup_stage && autocvar_g_chat_nospectators == 2))
                        Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_CHAT_NOSPECTATORS);
-
-               if(!CS(this).just_joined)
-                       LogTeamchange(this.playerid, -1, TEAM_CHANGE_SPECTATOR);
-               else
-                       CS(this).just_joined = false;
        }
 
        accuracy_resend(this);
@@ -346,7 +332,10 @@ void PutObserverInServer(entity this)
        this.strength_finished = 0;
        this.invincible_finished = 0;
        this.superweapons_finished = 0;
-       this.dphitcontentsmask = 0;
+       //this.dphitcontentsmask = 0;
+       this.dphitcontentsmask = DPCONTENTS_SOLID;
+       if (autocvar_g_playerclip_collisions)
+               this.dphitcontentsmask |= DPCONTENTS_PLAYERCLIP;
        this.pushltime = 0;
        this.istypefrag = 0;
        setthink(this, func_null);
@@ -388,6 +377,16 @@ void PutObserverInServer(entity this)
                if(axh.owner == this && axh != NULL && !wasfreed(axh))
                        delete(axh);
        }
+       
+       if (mutator_returnvalue)
+       {
+               // mutator prevents resetting teams+score
+       }
+       else
+       {
+               SetPlayerTeam(this, -1, TEAM_CHANGE_SPECTATOR);
+               this.frags = FRAGS_SPECTATOR;
+    }
 }
 
 int player_getspecies(entity this)
@@ -1070,38 +1069,7 @@ void ClientConnect(entity this)
 
        bot_clientconnect(this);
 
-       // identify the right forced team
-       if (autocvar_g_campaign)
-       {
-               if (IS_REAL_CLIENT(this)) // only players, not bots
-               {
-                       switch (autocvar_g_campaign_forceteam)
-                       {
-                               case 1: this.team_forced = NUM_TEAM_1; break;
-                               case 2: this.team_forced = NUM_TEAM_2; break;
-                               case 3: this.team_forced = NUM_TEAM_3; break;
-                               case 4: this.team_forced = NUM_TEAM_4; break;
-                               default: this.team_forced = 0;
-                       }
-               }
-       }
-       else if (PlayerInList(this, autocvar_g_forced_team_red))    this.team_forced = NUM_TEAM_1;
-       else if (PlayerInList(this, autocvar_g_forced_team_blue))   this.team_forced = NUM_TEAM_2;
-       else if (PlayerInList(this, autocvar_g_forced_team_yellow)) this.team_forced = NUM_TEAM_3;
-       else if (PlayerInList(this, autocvar_g_forced_team_pink))   this.team_forced = NUM_TEAM_4;
-       else switch (autocvar_g_forced_team_otherwise)
-       {
-               default: this.team_forced = 0; break;
-               case "red": this.team_forced = NUM_TEAM_1; break;
-               case "blue": this.team_forced = NUM_TEAM_2; break;
-               case "yellow": this.team_forced = NUM_TEAM_3; break;
-               case "pink": this.team_forced = NUM_TEAM_4; break;
-               case "spectate":
-               case "spectator":
-                       this.team_forced = -1;
-                       break;
-       }
-       if (!teamplay && this.team_forced > 0) this.team_forced = 0;
+       Player_DetermineForcedTeam(this);
 
        TRANSMUTE(Observer, this);
 
@@ -1647,7 +1615,7 @@ void GetPressedKeys(entity this)
        keys = BITSET(keys, KEY_LEFT,           CS(this).movement.y < 0);
 
        keys = BITSET(keys, KEY_JUMP,           PHYS_INPUT_BUTTON_JUMP(this));
-       keys = BITSET(keys, KEY_CROUCH,         PHYS_INPUT_BUTTON_CROUCH(this));
+       keys = BITSET(keys, KEY_CROUCH,         IS_DUCKED(this)); // workaround: player can't un-crouch until their path is clear, so we keep the button held here
        keys = BITSET(keys, KEY_ATCK,           PHYS_INPUT_BUTTON_ATCK(this));
        keys = BITSET(keys, KEY_ATCK2,          PHYS_INPUT_BUTTON_ATCK2(this));
        CS(this).pressedkeys = keys; // store for other users
@@ -1905,7 +1873,7 @@ void ShowRespawnCountdown(entity this)
 .bool team_selected;
 bool ShowTeamSelection(entity this)
 {
-       if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || this.team_selected || (CS(this).wasplayer && autocvar_g_changeteam_banned) || this.team_forced > 0)
+       if (!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || this.team_selected || (CS(this).wasplayer && autocvar_g_changeteam_banned) || Player_HasRealForcedTeam(this))
                return false;
        stuffcmd(this, "menu_showteamselect\n");
        return true;
@@ -1928,7 +1896,6 @@ void Join(entity this)
        if(IS_PLAYER(this))
        if(teamplay && this.team != -1)
        {
-               //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname);
        }
        else
                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_PLAY, this.netname);
@@ -1953,7 +1920,7 @@ int nJoinAllowed(entity this, entity ignore)
                        return 0;
        }
 
-       if(this && this.team_forced < 0)
+       if(this && (Player_GetForcedTeamIndex(this) == TEAM_FORCE_SPECTATOR))
                return 0; // forced spectators can never join
 
        // TODO simplify this
@@ -2505,7 +2472,7 @@ void PlayerPreThink (entity this)
                // don't do this in ClientConnect
                // many things can go wrong if a client is spawned as player on connection
                if (MUTATOR_CALLHOOK(AutoJoinOnConnection, this)
-                       || (!(autocvar_sv_spectate || autocvar_g_campaign || this.team_forced < 0)
+                       || (!(autocvar_sv_spectate || autocvar_g_campaign || (Player_GetForcedTeamIndex(this) == TEAM_FORCE_SPECTATOR))
                                && (!teamplay || autocvar_g_balance_teams)))
                {
                        campaign_bots_may_start = true;
index efb61a436d8db7021028b58c8b60424b6bdfb67a..099fac9f541f5ae71358f2fad6f2e0894a978e14 100644 (file)
@@ -226,6 +226,8 @@ METHOD(Client, m_unwind, bool(Client this))
     return false;
 }
 
+bool PlayerInList(entity player, string list);
+
 /// \brief Print the string to the client's chat.
 /// \param[in] client Client to print to.
 /// \param[in] text Text to print.
index 0bb761483b19bb8433c8bf968dad5fa3679b8f19..8d7293bb066214c1f5e47535be2ab93453f47c46 100644 (file)
@@ -22,7 +22,10 @@ void ClientKill_Now_TeamChange(entity this)
                PutObserverInServer(this);
        }
        else
-               SV_ChangeTeam(this, this.killindicator_teamchange - 1);
+       {
+               Player_SetTeamIndexChecked(this, Team_TeamToIndex(
+                       this.killindicator_teamchange));
+       }
        this.killindicator_teamchange = 0;
 }
 
index a5867dced827e3bcae9fb5f5151d14f063be81d5..915fea7ee0ca2ca02ffb14d9341d539b4b4a7d14 100644 (file)
@@ -121,7 +121,7 @@ void ClientCommand_clientversion(entity caller, int request, int argc)  // inter
                                        {
                                                // JoinBestTeam(caller, false, true);
                                        }
-                                       else if (teamplay && !autocvar_sv_spectate && !(caller.team_forced > 0))
+                                       else if (teamplay && !autocvar_sv_spectate && !(Player_GetForcedTeamIndex(caller) > 0))
                                        {
                                                TRANSMUTE(Observer, caller);  // really?
                                                stuffcmd(caller, "menu_showteamselect\n");
@@ -363,19 +363,7 @@ void ClientCommand_say_team(entity caller, int request, int argc, string command
                case CMD_REQUEST_COMMAND:
                {
                        if (argc >= 2)
-                       {
-                               string _classname = string_null;
-                               if (!IS_PLAYER(caller) && caller.caplayer)
-                               {
-                                       // CA: make work team chat for killed players
-                                       _classname = caller.classname;
-                                       caller.classname = STR_PLAYER;
-                               }
-
                                Say(caller, true, NULL, substring(command, argv_start_index(1), argv_end_index(-1) - argv_start_index(1)), 1);
-                               if (_classname)
-                                       caller.classname = _classname;
-                       }
                        return;  // never fall through to usage
                }
 
@@ -409,7 +397,7 @@ void ClientCommand_selectteam(entity caller, int request, int argc)
                                sprint(caller, "^7selectteam can only be used in teamgames\n");
                                return;
                        }
-                       if (caller.team_forced > 0)
+                       if (Player_GetForcedTeamIndex(caller) > 0)
                        {
                                sprint(caller, "^7selectteam can not be used as your team is forced\n");
                                return;
index c917874c358f5d345cd740fcffa194033f9f54c7..c3e5bf9015293c712bb59f4e1d05c6c71f626804 100644 (file)
@@ -1052,8 +1052,8 @@ void GameCommand_moveplayer(int request, int argc)
                                                        {
                                                                // set up
                                                                float team_id;
-                                                               float save = client.team_forced;
-                                                               client.team_forced = 0;
+                                                               int save = Player_GetForcedTeamIndex(client);
+                                                               Player_SetForcedTeamIndex(client, TEAM_FORCE_DEFAULT);
 
                                                                // find the team to move the player to
                                                                team_id = Team_ColorToTeam(destination);
@@ -1073,7 +1073,7 @@ void GameCommand_moveplayer(int request, int argc)
                                                                {
                                                                        balance = TeamBalance_CheckAllowedTeams(client);
                                                                }
-                                                               client.team_forced = save;
+                                                               Player_SetForcedTeamIndex(client, save);
 
                                                                // Check to see if the destination team is even available
                                                                switch (team_id)
@@ -1130,7 +1130,7 @@ void GameCommand_moveplayer(int request, int argc)
                                                                }
 
                                                                // If so, lets continue and finally move the player
-                                                               client.team_forced = 0;
+                                                               Player_SetForcedTeamIndex(client, TEAM_FORCE_DEFAULT);
                                                                if (MoveToTeam(client, Team_TeamToIndex(team_id), 6))
                                                                {
                                                                        successful = strcat(successful, (successful ? ", " : ""), playername(client, false));
@@ -1312,7 +1312,7 @@ void GameCommand_shuffleteams(int request)
                        }
 
                        FOREACH_CLIENT(IS_PLAYER(it) || it.caplayer, {
-                               if (it.team_forced) {
+                               if (Player_HasRealForcedTeam(it)) {
                                        // we could theoretically assign forced players to their teams
                                        // and shuffle the rest to fill the empty spots but in practise
                                        // either all players or none are gonna have forced teams
index 173c2d5caec0dbb7b62093a9240aa661938ad9f6..58111fb12bcfea9482a8d89b6d0dbceaf31ab42e 100644 (file)
@@ -351,8 +351,6 @@ const int ACTIVE_TOGGLE     = 3;
 
 //float serverflags;
 
-.int team_forced; // can be a team number to force a team, or 0 for default action, or -1 for forced spectator
-
 .bool player_blocked;
 
 .float revival_time; // time at which player was last revived
index a25ae5bec9f878d9ba5feca5a6bb2f7e7c55bae6..4964bf91e71014cea100bed1b76e5c784d8e91c4 100644 (file)
@@ -4,6 +4,7 @@
 #include "bot/api.qh"
 #include "g_hook.qh"
 #include <server/mutators/_mod.qh>
+#include "teamplay.qh"
 #include "scores.qh"
 #include "spawnpoints.qh"
 #include "../common/state.qh"
index ff62cd1674b3487185903df618d3198459817beb..2374b4869bc6c5415c08c319a162850ca9871440 100644 (file)
@@ -96,6 +96,8 @@ float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, f
 
 string NearestLocation(vector p);
 
+string AmmoNameFromWeaponentity(Weapon wep);
+
 void play2(entity e, string filename);
 
 string playername(entity p, bool team_colorize);
index 5d69c0aa1a4b88dde931bd63ec6f967dd525cdad..87005ad4bbf6c0476dab47635e1a34c8db616e04 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "../common/minigames/sv_minigames.qh"
 
+#include <common/gamemodes/_mod.qh>
+
 #include "../common/physics/player.qh"
 #include "../common/effects/qc/_mod.qh"
 #include "../common/mutators/mutator/waypoints/waypointsprites.qh"
@@ -551,8 +553,8 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                if(this.classname != "body")
                        Obituary (attacker, inflictor, this, deathtype, weaponentity);
 
-        // increment frag counter for used weapon type
-        Weapon w = DEATH_WEAPONOF(deathtype);
+               // increment frag counter for used weapon type
+               Weapon w = DEATH_WEAPONOF(deathtype);
                if(w != WEP_Null && accuracy_isgooddamage(attacker, this))
                        CS(attacker).accuracy.(accuracy_frags[w.m_id-1]) += 1;
 
@@ -686,13 +688,13 @@ bool PlayerHeal(entity targ, entity inflictor, float amount, float limit)
 int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol)
 {
        if (!teamsay && !privatesay && substring(msgin, 0, 1) == " ")
-        msgin = substring(msgin, 1, -1); // work around DP say bug (say_team does not have this!)
+               msgin = substring(msgin, 1, -1); // work around DP say bug (say_team does not have this!)
 
-    if(source)
+       if (source)
                msgin = formatmessage(source, msgin);
 
-    string colorstr;
-       if (!IS_PLAYER(source))
+       string colorstr;
+       if (!(IS_PLAYER(source) || source.caplayer))
                colorstr = "^0"; // black for spectators
        else if(teamplay)
                colorstr = Team_ColorCode(source.team);
@@ -705,10 +707,10 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
        if(game_stopped)
                teamsay = false;
 
-    if (!source) {
+       if (!source) {
                colorstr = "";
                teamsay = false;
-    }
+       }
 
        if(msgin != "")
                msgin = trigger_magicear_processmessage_forallears(source, teamsay, privatesay, msgin);
@@ -724,18 +726,17 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
        }
        */
 
-    string namestr = "";
-    if (source)
-        namestr = playername(source, autocvar_g_chat_teamcolors);
+       string namestr = "";
+       if (source)
+               namestr = playername(source, autocvar_g_chat_teamcolors);
 
-    string colorprefix = (strdecolorize(namestr) == namestr) ? "^3" : "^7";
+       string colorprefix = (strdecolorize(namestr) == namestr) ? "^3" : "^7";
 
-    string msgstr, cmsgstr;
-    string privatemsgprefix = string_null;
-    int privatemsgprefixlen = 0;
-       if (msgin == "") {
-        msgstr = cmsgstr = "";
-       } else {
+       string msgstr = "", cmsgstr = "";
+       string privatemsgprefix = string_null;
+       int privatemsgprefixlen = 0;
+       if (msgin != "")
+       {
                if(privatesay)
                {
                        msgstr = strcat("\{1}\{13}* ", colorprefix, namestr, "^3 tells you: ^7");
@@ -767,10 +768,10 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                                msgstr = strcat("\{1}^4* ", "^7", msgin);
                        }
                        else {
-                msgstr = "\{1}";
-                msgstr = strcat(msgstr, (namestr != "") ? strcat(colorprefix, namestr, "^7: ") : "^7");
-                msgstr = strcat(msgstr, msgin);
-            }
+                               msgstr = "\{1}";
+                               msgstr = strcat(msgstr, (namestr != "") ? strcat(colorprefix, namestr, "^7: ") : "^7");
+                               msgstr = strcat(msgstr, msgin);
+                       }
                        cmsgstr = "";
                }
                msgstr = strcat(strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
@@ -853,7 +854,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        source.(flood_field) = flood = 0;
        }
 
-    string sourcemsgstr, sourcecmsgstr;
+       string sourcemsgstr, sourcecmsgstr;
        if(flood == 2) // cannot happen for empty msgstr
        {
                if(autocvar_g_chat_flood_notify_flooder)
@@ -874,7 +875,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                sourcecmsgstr = cmsgstr;
        }
 
-       if (!privatesay && source && !IS_PLAYER(source))
+       if (!privatesay && source && !(IS_PLAYER(source) || source.caplayer))
        {
                if (!game_stopped)
                if (teamsay || (autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage))
@@ -888,7 +889,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
        if(privatesay)
                sourcemsgstr = strcat(privatemsgprefix, substring(sourcemsgstr, privatemsgprefixlen, -1));
 
-    int ret;
+       int ret;
        if(source && CS(source).muted)
        {
                // always fake the message
@@ -909,10 +910,10 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                ret = 1;
        }
 
-       if (privatesay && source && !IS_PLAYER(source))
+       if (privatesay && source && !(IS_PLAYER(source) || source.caplayer))
        {
                if (!game_stopped)
-               if ((privatesay && IS_PLAYER(privatesay)) && ((autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage)))
+               if ((privatesay && (IS_PLAYER(privatesay) || privatesay.caplayer)) && ((autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage)))
                        ret = -1; // just hide the message completely
        }
 
@@ -942,7 +943,9 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                {
                        sprint(source, sourcemsgstr);
                        dedicated_print(msgstr); // send to server console too
-                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && CS(it).active_minigame == CS(source).active_minigame && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), sprint(it, msgstr));
+                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && CS(it).active_minigame == CS(source).active_minigame && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               sprint(it, msgstr);
+                       });
                }
                else if(teamsay > 0) // team message, only sent to team mates
                {
@@ -950,7 +953,7 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                        dedicated_print(msgstr); // send to server console too
                        if(sourcecmsgstr != "")
                                centerprint(source, sourcecmsgstr);
-                       FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source && it.team == source.team && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                       FOREACH_CLIENT((IS_PLAYER(it) || it.caplayer) && IS_REAL_CLIENT(it) && it != source && it.team == source.team && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
                                sprint(it, msgstr);
                                if(cmsgstr != "")
                                        centerprint(it, cmsgstr);
@@ -960,17 +963,21 @@ int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodc
                {
                        sprint(source, sourcemsgstr);
                        dedicated_print(msgstr); // send to server console too
-                       FOREACH_CLIENT(!IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), sprint(it, msgstr));
+                       FOREACH_CLIENT(!(IS_PLAYER(it) || it.caplayer) && IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               sprint(it, msgstr);
+                       });
                }
                else
                {
-            if (source) {
-                sprint(source, sourcemsgstr);
-                dedicated_print(msgstr); // send to server console too
-                MX_Say(strcat(playername(source, true), "^7: ", msgin));
-            }
-            FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), sprint(it, msgstr));
-        }
+                       if (source) {
+                               sprint(source, sourcemsgstr);
+                               dedicated_print(msgstr); // send to server console too
+                               MX_Say(strcat(playername(source, true), "^7: ", msgin));
+                       }
+                       FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && !MUTATOR_CALLHOOK(ChatMessageTo, it, source), {
+                               sprint(it, msgstr);
+                       });
+               }
        }
 
        return ret;
index 2c41ae18bdfc77b22113f5f36f40df8cb5d7ba23..abc5df1d726a0e730e2c55402690112ad2cd9fc4 100644 (file)
@@ -28,6 +28,8 @@ enum
 /// \brief Indicates that the player is not allowed to join a team.
 const int TEAM_NOT_ALLOWED = -1;
 
+.float team_forced; // can be a team number to force a team, or 0 for default action, or -1 for forced spectator
+
 .int m_team_balance_state; ///< Holds the state of the team balance entity.
 .entity m_team_balance_team[NUM_TEAMS]; ///< ???
 
@@ -37,6 +39,11 @@ const int TEAM_NOT_ALLOWED = -1;
 .int m_num_players_alive; ///< Number of alive players in a team.
 .int m_num_control_points; ///< Number of control points owned by a team.
 
+string autocvar_g_forced_team_red;
+string autocvar_g_forced_team_blue;
+string autocvar_g_forced_team_yellow;
+string autocvar_g_forced_team_pink;
+
 entity g_team_entities[NUM_TEAMS]; ///< Holds global team entities.
 
 STATIC_INIT(g_team_entities)
@@ -204,22 +211,92 @@ bool SetPlayerTeam(entity player, int team_index, int type)
        {
                return false;
        }
-       LogTeamchange(player.playerid, player.team, type);
+       LogTeamChange(player.playerid, player.team, type);
        if (team_index != old_team_index)
        {
-               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(player.team,
-                       INFO_JOIN_PLAY_TEAM), player.netname);
+               PlayerScore_Clear(player);
+               if (team_index != -1)
+               {
+                       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(
+                               player.team, INFO_JOIN_PLAY_TEAM), player.netname);
+               }
+               else
+               {
+                       if (!CS(player).just_joined)
+                       {
+                               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE,
+                                       player.netname);
+                       }
+                       else
+                       {
+                               CS(player).just_joined = false;
+                       }
+               }
                KillPlayerForTeamChange(player);
+               if (!IS_BOT_CLIENT(player))
+               {
+                       TeamBalance_AutoBalanceBots();
+               }
        }
        return true;
 }
 
+void Player_SetTeamIndexChecked(entity player, int team_index)
+{
+       if (!teamplay)
+       {
+               return;
+       }
+       if (!Team_IsValidIndex(team_index))
+       {
+               return;
+       }
+       if ((autocvar_g_campaign) || (autocvar_g_changeteam_banned &&
+               CS(player).wasplayer))
+       {
+               Send_Notification(NOTIF_ONE, player, MSG_INFO,
+                       INFO_TEAMCHANGE_NOTALLOWED);
+               return;
+       }
+       entity balance = TeamBalance_CheckAllowedTeams(player);
+       if (team_index == 1 && !TeamBalance_IsTeamAllowedInternal(balance, 1))
+       {
+               team_index = 4;
+       }
+       if (team_index == 4 && !TeamBalance_IsTeamAllowedInternal(balance, 4))
+       {
+               team_index = 3;
+       }
+       if (team_index == 3 && !TeamBalance_IsTeamAllowedInternal(balance, 3))
+       {
+               team_index = 2;
+       }
+       if (team_index == 2 && !TeamBalance_IsTeamAllowedInternal(balance, 2))
+       {
+               team_index = 1;
+       }
+       // autocvar_g_balance_teams_prevent_imbalance only makes sense if autocvar_g_balance_teams is on, as it makes the team selection dialog pointless
+       if (autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance)
+       {
+               TeamBalance_GetTeamCounts(balance, player);
+               if ((Team_IndexToBit(team_index) & TeamBalance_FindBestTeams(balance,
+                       player, false)) == 0)
+               {
+                       Send_Notification(NOTIF_ONE, player, MSG_INFO,
+                               INFO_TEAMCHANGE_LARGERTEAM);
+                       TeamBalance_Destroy(balance);
+                       return;
+               }
+       }
+       TeamBalance_Destroy(balance);
+       SetPlayerTeam(player, team_index, TEAM_CHANGE_MANUAL);
+}
+
 bool MoveToTeam(entity client, int team_index, int type)
 {
        //PrintToChatAll(sprintf("MoveToTeam: %s, %f", client.netname, team_index));
        int lockteams_backup = lockteams;  // backup any team lock
        lockteams = 0;  // disable locked teams
-       PlayerScore_Clear(client);
        if (!SetPlayerTeam(client, team_index, type))
        {
                lockteams = lockteams_backup;  // restore the team lock
@@ -229,29 +306,150 @@ bool MoveToTeam(entity client, int team_index, int type)
        return true;
 }
 
-void KillPlayerForTeamChange(entity player)
+bool Player_HasRealForcedTeam(entity player)
 {
-       if (IS_DEAD(player))
+       return player.team_forced > TEAM_FORCE_DEFAULT;
+}
+
+int Player_GetForcedTeamIndex(entity player)
+{
+       return player.team_forced;
+}
+
+void Player_SetForcedTeamIndex(entity player, int team_index)
+{
+       switch (team_index)
        {
-               return;
+               case TEAM_FORCE_SPECTATOR:
+               case TEAM_FORCE_DEFAULT:
+               {
+                       player.team_forced = team_index;
+                       break;
+               }
+               default:
+               {
+                       if (!Team_IsValidIndex(team_index))
+                       {
+                               LOG_FATAL("Player_SetForcedTeamIndex: Invalid team index.");
+                       }
+                       else
+                       {
+                               player.team_forced = team_index;
+                               break;
+                       }
+               }
        }
-       if (MUTATOR_CALLHOOK(Player_ChangeTeamKill, player) == true)
+}
+
+void Player_DetermineForcedTeam(entity player)
+{
+       if (autocvar_g_campaign)
        {
-               return;
+               if (IS_REAL_CLIENT(player)) // only players, not bots
+               {
+                       if (Team_IsValidIndex(autocvar_g_campaign_forceteam))
+                       {
+                               player.team_forced = autocvar_g_campaign_forceteam;
+                       }
+                       else
+                       {
+                               player.team_forced = TEAM_FORCE_DEFAULT;
+                       }
+               }
+       }
+       else if (PlayerInList(player, autocvar_g_forced_team_red))
+       {
+               player.team_forced = 1;
+       }
+       else if (PlayerInList(player, autocvar_g_forced_team_blue))
+       {
+               player.team_forced = 2;
+       }
+       else if (PlayerInList(player, autocvar_g_forced_team_yellow))
+       {
+               player.team_forced = 3;
+       }
+       else if (PlayerInList(player, autocvar_g_forced_team_pink))
+       {
+               player.team_forced = 4;
+       }
+       else
+       {
+               switch (autocvar_g_forced_team_otherwise)
+               {
+                       case "red":
+                       {
+                               player.team_forced = 1;
+                               break;
+                       }
+                       case "blue":
+                       {
+                               player.team_forced = 2;
+                               break;
+                       }
+                       case "yellow":
+                       {
+                               player.team_forced = 3;
+                               break;
+                       }
+                       case "pink":
+                       {
+                               player.team_forced = 4;
+                               break;
+                       }
+                       case "spectate":
+                       case "spectator":
+                       {
+                               player.team_forced = TEAM_FORCE_SPECTATOR;
+                               break;
+                       }
+                       default:
+                       {
+                               player.team_forced = TEAM_FORCE_DEFAULT;
+                               break;
+                       }
+               }
+       }
+       if (!teamplay && Player_HasRealForcedTeam(player))
+       {
+               player.team_forced = TEAM_FORCE_DEFAULT;
        }
-       Damage(player, player, player, 100000, DEATH_TEAMCHANGE.m_id, DMG_NOWEP,
-               player.origin, '0 0 0');
 }
 
-void LogTeamchange(float player_id, float team_number, int type)
+void TeamBalance_JoinBestTeam(entity player)
 {
-       if(!autocvar_sv_eventlog)
+       //PrintToChatAll(sprintf("TeamBalance_JoinBestTeam: %s", player.netname));
+       if (!teamplay)
+       {
                return;
-
-       if(player_id < 1)
+       }
+       if (player.bot_forced_team)
+       {
                return;
-
-       GameLogEcho(strcat(":team:", ftos(player_id), ":", ftos(team_number), ":", ftos(type)));
+       }
+       entity balance = TeamBalance_CheckAllowedTeams(player);
+       if (Player_HasRealForcedTeam(player))
+       {
+               int forced_team_index = player.team_forced;
+               bool is_team_allowed = TeamBalance_IsTeamAllowedInternal(balance,
+                       forced_team_index);
+               TeamBalance_Destroy(balance);
+               if (!is_team_allowed)
+               {
+                       return;
+               }
+               if (!SetPlayerTeam(player, forced_team_index, TEAM_CHANGE_AUTO))
+               {
+                       return;
+               }
+               return;
+       }
+       int best_team_index = TeamBalance_FindBestTeam(balance, player, true);
+       TeamBalance_Destroy(balance);
+       if (!SetPlayerTeam(player, best_team_index, TEAM_CHANGE_AUTO))
+       {
+               return;
+       }
 }
 
 entity TeamBalance_CheckAllowedTeams(entity for_whom)
@@ -383,7 +581,7 @@ entity TeamBalance_CheckAllowedTeams(entity for_whom)
        // if player has a forced team, ONLY allow that one
        for (int i = 1; i <= NUM_TEAMS; ++i)
        {
-               if (for_whom.team_forced == Team_IndexToTeam(i) &&
+               if (for_whom.team_forced == i &&
                        TeamBalance_IsTeamAllowedInternal(balance, i))
                {
                        TeamBalance_BanTeamsExcept(balance, i);
@@ -483,13 +681,15 @@ void TeamBalance_GetTeamCounts(entity balance, entity ignore)
                                continue;
                        }
                        int team_num;
-                       if (IS_PLAYER(it) || it.caplayer)
+                       // TODO: Reconsider when the player is truly on the team.
+                       if (IS_CLIENT(it) || (it.caplayer))
                        {
                                team_num = it.team;
                        }
-                       else if (it.team_forced > 0)
+                       else if (Player_HasRealForcedTeam(it))
                        {
-                               team_num = it.team_forced; // reserve the spot
+                               // Do we really need this? Probably not.
+                               team_num = Team_IndexToTeam(it.team_forced); // reserve the spot
                        }
                        else
                        {
@@ -631,52 +831,6 @@ int TeamBalance_FindBestTeams(entity balance, entity player, bool use_score)
        return team_bits;
 }
 
-void TeamBalance_JoinBestTeam(entity this)
-{
-       //PrintToChatAll(sprintf("JoinBestTeam: %s", this.netname));
-       if (!teamplay)
-       {
-               return;
-       }
-       if (this.bot_forced_team)
-       {
-               return;
-       }
-       int old_team_index = Team_TeamToIndex(this.team);
-       entity balance = TeamBalance_CheckAllowedTeams(this);
-       if (this.team_forced > 0)
-       {
-               int forced_team_index = Team_TeamToIndex(this.team_forced);
-               bool is_team_allowed = TeamBalance_IsTeamAllowedInternal(balance,
-                       forced_team_index);
-               TeamBalance_Destroy(balance);
-               if (!is_team_allowed)
-               {
-                       return;
-               }
-               if (!SetPlayerTeam(this, forced_team_index, TEAM_CHANGE_AUTO))
-               {
-                       return;
-               }
-               if ((old_team_index != -1) && !IS_BOT_CLIENT(this))
-               {
-                       TeamBalance_AutoBalanceBots(forced_team_index, old_team_index);
-               }
-               return;
-       }
-       int best_team_index = TeamBalance_FindBestTeam(balance, this, true);
-       TeamBalance_Destroy(balance);
-       PlayerScore_Clear(this);
-       if (!SetPlayerTeam(this, best_team_index, TEAM_CHANGE_AUTO))
-       {
-               return;
-       }
-       if ((old_team_index != -1) && !IS_BOT_CLIENT(this))
-       {
-               TeamBalance_AutoBalanceBots(best_team_index, old_team_index);
-       }
-}
-
 int TeamBalance_CompareTeams(entity balance, int team_index_a, int team_index_b,
        entity player, bool use_score)
 {
@@ -708,74 +862,172 @@ int TeamBalance_CompareTeams(entity balance, int team_index_a, int team_index_b,
        return TeamBalance_CompareTeamsInternal(team_a, team_b, player, use_score);
 }
 
-void TeamBalance_AutoBalanceBots(int source_team_index,
-       int destination_team_index)
+void TeamBalance_AutoBalanceBots()
 {
-       if (!Team_IsValidIndex(source_team_index))
-       {
-               LOG_WARNF("TeamBalance_AutoBalanceBots: "
-                       "Source team index is invalid: %f", source_team_index);
-               return;
-       }
-       if (!Team_IsValidIndex(destination_team_index))
-       {
-               LOG_WARNF("TeamBalance_AutoBalanceBots: "
-                       "Destination team index is invalid: %f", destination_team_index);
-               return;
-       }
        if (!autocvar_g_balance_teams ||
                !autocvar_g_balance_teams_prevent_imbalance)
        {
                return;
        }
+       //PrintToChatAll("TeamBalance_AutoBalanceBots");
        entity balance = TeamBalance_CheckAllowedTeams(NULL);
        TeamBalance_GetTeamCounts(balance, NULL);
-       entity source_team = TeamBalance_GetTeamFromIndex(balance,
-               source_team_index);
-       entity destination_team = TeamBalance_GetTeamFromIndex(balance,
-               destination_team_index);
-       if ((source_team.m_num_bots == 0) || (source_team.m_num_players <=
-               destination_team.m_num_players))
+       int smallest_team_index = 0;
+       int smallest_team_player_count = 0;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
        {
-               TeamBalance_Destroy(balance);
-               return;
+               entity team_ = TeamBalance_GetTeamFromIndex(balance, i);
+               if (!TeamBalanceTeam_IsAllowed(team_))
+               {
+                       continue;
+               }
+               int player_count = TeamBalanceTeam_GetNumberOfPlayers(team_);
+               if (smallest_team_index == 0)
+               {
+                       smallest_team_index = i;
+                       smallest_team_player_count = player_count;
+               }
+               else if (player_count < smallest_team_player_count)
+               {
+                       smallest_team_index = i;
+                       smallest_team_player_count = player_count;
+               }
+       }
+       //PrintToChatAll(sprintf("Smallest team: %f", smallest_team_index));
+       //PrintToChatAll(sprintf("Smallest team players: %f", smallest_team_player_count));
+       entity switchable_bot = NULL;
+       int teams = BITS(NUM_TEAMS);
+       while (teams != 0)
+       {
+               int largest_team_index = TeamBalance_GetLargestTeamIndex(balance,
+                       teams);
+               if (smallest_team_index == largest_team_index)
+               {
+                       TeamBalance_Destroy(balance);
+                       return;
+               }
+               entity largest_team = TeamBalance_GetTeamFromIndex(balance,
+                       largest_team_index);
+               int largest_team_player_count = TeamBalanceTeam_GetNumberOfPlayers(
+                       largest_team);
+               if (largest_team_player_count - smallest_team_player_count < 2)
+               {
+                       TeamBalance_Destroy(balance);
+                       return;
+               }
+               //PrintToChatAll(sprintf("Largest team: %f", largest_team_index));
+               //PrintToChatAll(sprintf("Largest team players: %f", largest_team_player_count));
+               switchable_bot = TeamBalance_GetPlayerForTeamSwitch(largest_team_index,
+                       smallest_team_index, true);
+               if (switchable_bot != NULL)
+               {
+                       break;
+               }
+               teams &= ~Team_IndexToBit(largest_team_index);
        }
        TeamBalance_Destroy(balance);
-       entity lowest_bot = NULL;
+       if (switchable_bot == NULL)
+       {
+               //PrintToChatAll("No bot found after searching through all the teams");
+               return;
+       }
+       SetPlayerTeam(switchable_bot, smallest_team_index, TEAM_CHANGE_AUTO);
+}
+
+int TeamBalance_GetLargestTeamIndex(entity balance, int teams)
+{
+       int largest_team_index = 0;
+       int largest_team_player_count = 0;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               if (!(Team_IndexToBit(i) & teams))
+               {
+                       continue;
+               }
+               entity team_ = TeamBalance_GetTeamFromIndex(balance, i);
+               if (!TeamBalanceTeam_IsAllowed(team_))
+               {
+                       continue;
+               }
+               int player_count = TeamBalanceTeam_GetNumberOfPlayers(team_);
+               if (largest_team_index == 0)
+               {
+                       largest_team_index = i;
+                       largest_team_player_count = player_count;
+               }
+               else if (player_count > largest_team_player_count)
+               {
+                       largest_team_index = i;
+                       largest_team_player_count = player_count;
+               }
+       }
+       return largest_team_index;
+}
+
+entity TeamBalance_GetPlayerForTeamSwitch(int source_team_index,
+       int destination_team_index, bool is_bot)
+{
        if (MUTATOR_CALLHOOK(TeamBalance_GetPlayerForTeamSwitch, source_team_index,
-               destination_team_index, true))
+               destination_team_index, is_bot))
        {
-               lowest_bot = M_ARGV(3, entity);
+               return M_ARGV(3, entity);
        }
-       else
+       entity lowest_player = NULL;
+       float lowest_score = FLOAT_MAX;
+       FOREACH_CLIENT(Entity_GetTeamIndex(it) == source_team_index,
        {
-               float lowest_score = FLOAT_MAX;
-               FOREACH_CLIENT(IS_BOT_CLIENT(it) && (Entity_GetTeamIndex(it) ==
-                       source_team_index),
+               if (IS_BOT_CLIENT(it) != is_bot)
                {
-                       float temp_score = PlayerScore_Get(it, SP_SCORE);
-                       if (temp_score >= lowest_score)
-                       {
-                               continue;
-                       }
-                       balance = TeamBalance_CheckAllowedTeams(it);
-                       if (TeamBalance_IsTeamAllowed(balance, destination_team_index))
-                       {
-                               lowest_bot = it;
-                               lowest_score = temp_score;
-                       }
-                       TeamBalance_Destroy(balance);
-               });
+                       continue;
+               }
+               float temp_score = PlayerScore_Get(it, SP_SCORE);
+               if (temp_score >= lowest_score)
+               {
+                       continue;
+               }
+               //PrintToChatAll(sprintf(
+               //      "Found %s with lowest score, checking allowed teams", it.netname));
+               entity balance = TeamBalance_CheckAllowedTeams(it);
+               if (TeamBalance_IsTeamAllowed(balance, source_team_index))
+               {
+                       //PrintToChatAll("Allowed");
+                       lowest_player = it;
+                       lowest_score = temp_score;
+               }
+               else
+               {
+                       //PrintToChatAll("Not allowed");
+               }
+               TeamBalance_Destroy(balance);
+       });
+       return lowest_player;
+}
+
+void LogTeamChange(float player_id, float team_number, int type)
+{
+       if (!autocvar_sv_eventlog)
+       {
+               return;
+       }
+       if (player_id < 1)
+       {
+               return;
        }
-       if (lowest_bot == NULL)
+       GameLogEcho(sprintf(":team:%f:%f:%f", player_id, team_number, type));
+}
+
+void KillPlayerForTeamChange(entity player)
+{
+       if (IS_DEAD(player))
        {
                return;
        }
-       if (!Player_SetTeamIndex(lowest_bot, destination_team_index))
+       if (MUTATOR_CALLHOOK(Player_ChangeTeamKill, player) == true)
        {
                return;
        }
-       KillPlayerForTeamChange(lowest_bot);
+       Damage(player, player, player, 100000, DEATH_TEAMCHANGE.m_id, DMG_NOWEP,
+               player.origin, '0 0 0');
 }
 
 bool TeamBalance_IsTeamAllowedInternal(entity balance, int index)
@@ -866,101 +1118,24 @@ int TeamBalance_CompareTeamsInternal(entity team_a, entity team_b,
        return TEAMS_COMPARE_EQUAL;
 }
 
-// Called when the player connects or when they change their color with "color"
-// command.
-void SV_ChangeTeam(entity this, float _color)
+void SV_ChangeTeam(entity player, int new_color)
 {
-       //PrintToChatAll(sprintf("SV_ChangeTeam: %s, %f", this.netname, _color));
-
-       // in normal deathmatch we can just apply the color and we're done
-       if(!teamplay)
-               SetPlayerColors(this, _color);
-
-       if(!IS_CLIENT(this))
-       {
-               // since this is an engine function, and gamecode doesn't have any calls earlier than this, do the connecting message here
-               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_CONNECTING, this.netname);
-               return;
-       }
-
-       if(!teamplay)
-               return;
-
-       int source_color, destination_color;
-       int source_team_index, destination_team_index;
-
-       source_color = this.clientcolors & 0x0F;
-       destination_color = _color & 0x0F;
-
-       source_team_index = Team_TeamToIndex(source_color + 1);
-       destination_team_index = Team_TeamToIndex(destination_color + 1);
-
-       if (destination_team_index == -1)
-       {
-               return;
-       }
-
-       entity balance = TeamBalance_CheckAllowedTeams(this);
-
-       if (destination_team_index == 1 && !TeamBalance_IsTeamAllowedInternal(
-               balance, 1))
-       {
-               destination_team_index = 4;
-       }
-       if (destination_team_index == 4 && !TeamBalance_IsTeamAllowedInternal(
-               balance, 4))
-       {
-               destination_team_index = 3;
-       }
-       if (destination_team_index == 3 && !TeamBalance_IsTeamAllowedInternal(
-               balance, 3))
-       {
-               destination_team_index = 2;
-       }
-       if (destination_team_index == 2 && !TeamBalance_IsTeamAllowedInternal(
-               balance, 2))
-       {
-               destination_team_index = 1;
-       }
-
-       // not changing teams
-       if (source_color == destination_color)
-       {
-               SetPlayerTeam(this, destination_team_index, TEAM_CHANGE_MANUAL);
-               TeamBalance_Destroy(balance);
-               return;
-       }
-
-       if((autocvar_g_campaign) || (autocvar_g_changeteam_banned && CS(this).wasplayer)) {
-               Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_TEAMCHANGE_NOTALLOWED);
-               return; // changing teams is not allowed
-       }
-
-       // autocvar_g_balance_teams_prevent_imbalance only makes sense if autocvar_g_balance_teams is on, as it makes the team selection dialog pointless
-       if (autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance)
-       {
-               TeamBalance_GetTeamCounts(balance, this);
-               if ((Team_IndexToBit(destination_team_index) &
-                       TeamBalance_FindBestTeams(balance, this, false)) == 0)
-               {
-                       Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_TEAMCHANGE_LARGERTEAM);
-                       TeamBalance_Destroy(balance);
-                       return;
-               }
-       }
-       TeamBalance_Destroy(balance);
-       if (IS_PLAYER(this) && source_team_index != destination_team_index)
+       if (!teamplay)
        {
-               // reduce frags during a team change
-               PlayerScore_Clear(this);
+               SetPlayerColors(player, new_color);
        }
-       if (!SetPlayerTeam(this, destination_team_index, TEAM_CHANGE_MANUAL))
+       // TODO: Should we really bother with this?
+       if(!IS_CLIENT(player))
        {
+               // since this is an engine function, and gamecode doesn't have any calls earlier than this, do the connecting message here
+               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_CONNECTING,
+                       player.netname);
                return;
        }
-       if (source_team_index == -1)
+       if (!teamplay)
        {
                return;
        }
-       TeamBalance_AutoBalanceBots(destination_team_index, source_team_index);
+       Player_SetTeamIndexChecked(player, Team_TeamToIndex((new_color & 0x0F) +
+               1));
 }
index 776a80d329cf91d5917f1af4e1ba7275eb18a731..33f9d02d7e6b01da87c6dd86e6217b3ab546aa95 100644 (file)
@@ -1,5 +1,13 @@
 #pragma once
 
+int autocvar_teamplay_mode;
+
+bool autocvar_g_changeteam_banned;
+bool autocvar_teamplay_lockonrestart;
+
+bool autocvar_g_balance_teams;
+bool autocvar_g_balance_teams_prevent_imbalance;
+
 bool lockteams;
 
 // ========================== Global teams API ================================
@@ -83,13 +91,25 @@ void SetPlayerColors(entity player, float _color);
 /// \return True if team switch was successful, false otherwise.
 bool Player_SetTeamIndex(entity player, int index);
 
+enum
+{
+       TEAM_CHANGE_AUTO = 2, ///< The team was selected by autobalance.
+       TEAM_CHANGE_MANUAL = 3, ///< Player has manually selected their team.
+       TEAM_CHANGE_SPECTATOR = 4 ///< Player is joining spectators. //TODO: Remove?
+};
+
 /// \brief Sets the team of the player.
 /// \param[in,out] player Player to adjust.
 /// \param[in] team_index Index of the team to set.
-/// \param[in] type ???
+/// \param[in] type Type of the team change. See TEAM_CHANGE constants.
 /// \return True if team switch was successful, false otherwise.
 bool SetPlayerTeam(entity player, int team_index, int type);
 
+/// \brief Sets the team of the player with all sanity checks.
+/// \param[in,out] player Player to adjust.
+/// \param[in] team_index Index of the team to set.
+void Player_SetTeamIndexChecked(entity player, int team_index);
+
 /// \brief Moves player to the specified team.
 /// \param[in,out] client Client to move.
 /// \param[in] team_index Index of the team.
@@ -97,21 +117,39 @@ bool SetPlayerTeam(entity player, int team_index, int type);
 /// \return True on success, false otherwise.
 bool MoveToTeam(entity client, int team_index, int type);
 
-/// \brief Kills player as a result of team change.
-/// \param[in,out] player Player to kill.
-void KillPlayerForTeamChange(entity player);
-
 enum
 {
-       TEAM_CHANGE_AUTO = 2,
-       TEAM_CHANGE_MANUAL = 3,
-       TEAM_CHANGE_SPECTATOR = 4
+       TEAM_FORCE_SPECTATOR = -1, ///< Force the player to spectator team.
+       TEAM_FORCE_DEFAULT = 0 ///< Don't force any team.
 };
 
-void LogTeamchange(float player_id, float team_number, int type);
+/// \brief Returns whether player has real forced team. Spectator team is
+/// ignored.
+/// \param[in] player Player to check.
+/// \return True if player has real forced team, false otherwise.
+bool Player_HasRealForcedTeam(entity player);
+
+/// \brief Returns the index of the forced team of the given player.
+/// \param[in] player Player to check.
+/// \return Index of the forced team.
+int Player_GetForcedTeamIndex(entity player);
+
+/// \brief Sets the index of the forced team of the given player.
+/// \param[in,out] player Player to adjust.
+/// \param[in] team_index Index of the team to set.
+void Player_SetForcedTeamIndex(entity player, int team_index);
+
+/// \brief Determines the forced team of the player using current global config.
+/// \param[in,out] player Player to adjust.
+void Player_DetermineForcedTeam(entity player);
 
 // ========================= Team balance API =================================
 
+/// \brief Assigns the given player to a team that will make the game most
+/// balanced.
+/// \param[in,out] player Player to assign.
+void TeamBalance_JoinBestTeam(entity player);
+
 /// \brief Checks whether the player can join teams according to global
 /// configuration and mutator settings.
 /// \param[in] for_whom Player to check for. Pass NULL for global rules.
@@ -174,8 +212,6 @@ int TeamBalance_FindBestTeam(entity balance, entity player, bool ignore_player);
 /// function.
 int TeamBalance_FindBestTeams(entity balance, entity player, bool use_score);
 
-void TeamBalance_JoinBestTeam(entity this);
-
 /// \brief Describes the result of comparing teams.
 enum
 {
@@ -198,13 +234,33 @@ int TeamBalance_CompareTeams(entity balance, int team_index_a, int team_index_b,
        entity player, bool use_score);
 
 /// \brief Switches a bot from one team to another if teams are not balanced.
-/// \param[in] source_team_index Index of the team to switch from.
+void TeamBalance_AutoBalanceBots();
+
+/// \brief Returns the index of the team with most players that is contained in
+/// the given bitmask of teams.
+/// \param[in] balance Team balance entity.
+/// \param[in] teams Bitmask of teams to search in.
+/// \return Index of the team with most players.
+int TeamBalance_GetLargestTeamIndex(entity balance, int teams);
+
+/// \brief Returns the player who is the most suitable for switching between
+/// the given teams.
+/// \param[in] source_team_index Index of the team to search in.
 /// \param[in] destination_team_index Index of the team to switch to.
-void TeamBalance_AutoBalanceBots(int source_team_index,
-       int destination_team_index);
+/// \param[in] is_bot True to search for bot, false for human.
+/// \return Player who is the most suitable for switching between the given
+/// teams or NULL if not found.
+entity TeamBalance_GetPlayerForTeamSwitch(int source_team_index,
+       int destination_team_index, bool is_bot);
 
 // ============================ Internal API ==================================
 
+void LogTeamChange(float player_id, float team_number, int type);
+
+/// \brief Kills player as a result of team change.
+/// \param[in,out] player Player to kill.
+void KillPlayerForTeamChange(entity player);
+
 /// \brief Returns whether the team change to the specified team is allowed.
 /// \param[in] balance Team balance entity.
 /// \param[in] index Index of the team.
@@ -262,3 +318,9 @@ int TeamBalanceTeam_GetNumberOfBots(entity team_ent);
 /// function.
 int TeamBalance_CompareTeamsInternal(entity team_a, entity team_index_b,
        entity player, bool use_score);
+
+/// \brief Called when the player connects or when they change their color with
+/// the "color" command.
+/// \param[in,out] player Player that requested a new color.
+/// \param[in] new_color Requested color.
+void SV_ChangeTeam(entity player, int new_color);
index 462af14d8e0ca151f366f9daa611f1caf3c00cc7..9aaabb05bfafa8075ea63466e89ab0996ffe53b5 100644 (file)
@@ -33,11 +33,9 @@ void thrown_wep_think(entity this)
                SUB_VanishOrRemove(this);
 }
 
-// returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity)
+// returns amount of ammo used, or -1 for failure, or 0 for no ammo count
+float W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity)
 {
-       float thisammo;
-       string s;
        Weapon info = Weapons_from(wpn);
        int ammotype = info.ammo_type;
 
@@ -84,7 +82,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
 
        weapon_defaultspawnfunc(wep, info);
        if(startitem_failed)
-               return string_null;
+               return -1;
        setthink(wep, thrown_wep_think);
        wep.savenextthink = wep.nextthink;
        wep.nextthink = min(wep.nextthink, time + 0.5);
@@ -93,12 +91,10 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
        //wa = W_AmmoItemCode(wpn);
        if(ammotype == RESOURCE_NONE)
        {
-               return "";
+               return 0;
        }
        else
        {
-               s = "";
-
                if(doreduce && g_weapon_stay == 2)
                {
                        // if our weapon is loaded, give its load back to the player
@@ -121,23 +117,13 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                        }
 
                        float ownderammo = GetResourceAmount(own, ammotype);
-                       thisammo = min(ownderammo, GetResourceAmount(wep, ammotype));
+                       float thisammo = min(ownderammo, GetResourceAmount(wep, ammotype));
                        SetResourceAmount(wep, ammotype, thisammo);
                        SetResourceAmount(own, ammotype, ownderammo - thisammo);
 
-                       switch (ammotype)
-                       {
-                               case RESOURCE_SHELLS:  s = sprintf("%s and %d shells", s, thisammo);  break;
-                               case RESOURCE_BULLETS: s = sprintf("%s and %d nails", s, thisammo);   break;
-                               case RESOURCE_ROCKETS: s = sprintf("%s and %d rockets", s, thisammo); break;
-                               case RESOURCE_CELLS:   s = sprintf("%s and %d cells", s, thisammo);   break;
-                               case RESOURCE_PLASMA:  s = sprintf("%s and %d plasma", s, thisammo);  break;
-                               case RESOURCE_FUEL:    s = sprintf("%s and %d fuel", s, thisammo);    break;
-                       }
-
-                       s = substring(s, 5, -1);
+                       return thisammo;
                }
-               return s;
+               return 0;
        }
 }
 
@@ -175,10 +161,10 @@ void W_ThrowWeapon(entity this, .entity weaponentity, vector velo, vector delta,
        STAT(WEAPONS, this) &= ~set;
 
        W_SwitchWeapon_Force(this, w_getbestweapon(this, weaponentity), weaponentity);
-       string a = W_ThrowNewWeapon(this, w.m_id, doreduce, this.origin + delta, velo, weaponentity);
+       float a = W_ThrowNewWeapon(this, w.m_id, doreduce, this.origin + delta, velo, weaponentity);
 
-       if(!a) return;
-       Send_Notification(NOTIF_ONE, this, MSG_MULTI, ITEM_WEAPON_DROP, a, w.m_id);
+       if(a < 0) return;
+       Send_Notification(NOTIF_ONE, this, MSG_MULTI, ITEM_WEAPON_DROP, w.m_id, a);
 }
 
 void SpawnThrownWeapon(entity this, vector org, Weapon wep, .entity weaponentity)
index 9ea5e5cb8e442c930f628f47f1e93ff29ef150de..20732753e4fe66f11c1fdd802df01eda300fc658 100644 (file)
@@ -6,8 +6,8 @@
 .float savenextthink;
 void thrown_wep_think(entity this);
 
-// returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity);
+// returns amount of ammo used, or -1 for failure, or 0 for no ammo count
+float W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo, .entity weaponentity);
 
 bool W_IsWeaponThrowable(entity this, int w);
 
index 548616908e06c893763a09fa3ea99ed248162a6c..32f08fc948bbdf7852ab7ba17f18fca721cd5522 100644 (file)
@@ -390,6 +390,7 @@ set g_waypointsprite_spam 0 "Debugging feature. Set to 10 and load courtfun in r
 set g_waypointsprite_timealphaexponent 1
 seta g_waypointsprite_turrets 1 "disable turret waypoints"
 seta g_waypointsprite_turrets_maxdist 5000 "max distance for turret waypoints"
+seta g_waypointsprite_turrets_text 0 "show the turret's name in the waypoint"
 seta g_waypointsprite_uppercase 1
 seta g_waypointsprite_text 0 "Always show text instead of icons, setting this to 0 will still use text if the icon is unavailable"
 seta g_waypointsprite_iconsize 32
index 4898cb6afcae4c7e3aac4726d479fab8c3645536..efba68a908c55b9c6451b08f62e2a83db9432f5f 100644 (file)
@@ -258,9 +258,7 @@ set g_teamdamage_resetspeed 20      "for teamplay_mode 4: how fast player's team
 
 set g_balance_teams 1  "automatically balance out players entering instead of asking them for their preferred team"
 set g_balance_teams_prevent_imbalance  1       "prevent players from changing to larger teams"
-set g_balance_teams_scorefactor 0.25 "at the end of the game, take score into account instead of team size by this amount (beware: values over 0.5 mean that a x:0 score imbalance will cause ALL new players to prefer the losing team at the end, despite numbers)"
 set g_changeteam_banned 0      "not allowed to change team"
-set g_changeteam_fragtransfer 0        "% of frags you get to keep when you change teams (rounded down)"
 
 set sv_teamnagger 1 "enable a nag message when the teams are unbalanced"