]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'terencehill/scoreboard_update' into 'master'
authorMario <zacjardine@y7mail.com>
Sun, 11 Sep 2016 11:22:15 +0000 (11:22 +0000)
committerMario <zacjardine@y7mail.com>
Sun, 11 Sep 2016 11:22:15 +0000 (11:22 +0000)
Scoreboard update

Scoreboard:
* limit size of player names and relative column; scoreboard width is now based on this value
* limit scoreboard height and therefore number of players displayed in the scoreboard, display remaining players with primary scores in the last row
* compact spectator list by displaying multiple spectator names per row
* display an empty scoreboard in the beginning in DM too

Rankings:
* limit name size and if there's enough room split rankings into more columns
* center text vertically and add padding to both sides of each column

See merge request !366

24 files changed:
defaultXonotic.cfg
qcsrc/client/autocvars.qh
qcsrc/client/hud/panel/modicons.qc
qcsrc/client/mutators/events.qh
qcsrc/client/view.qc
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/gamemodes/gamemode/onslaught/cl_generator.qc
qcsrc/common/gamemodes/gamemode/onslaught/onslaught.qc
qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc
qcsrc/common/minigames/minigame/snake.qc
qcsrc/server/autocvars.qh
qcsrc/server/mutators/events.qh
qcsrc/server/mutators/mutator/gamemode_assault.qc
qcsrc/server/mutators/mutator/gamemode_ca.qc
qcsrc/server/mutators/mutator/gamemode_ctf.qc
qcsrc/server/mutators/mutator/gamemode_domination.qc
qcsrc/server/mutators/mutator/gamemode_freezetag.qc
qcsrc/server/mutators/mutator/gamemode_invasion.qc
qcsrc/server/mutators/mutator/gamemode_keyhunt.qc
qcsrc/server/mutators/mutator/gamemode_keyhunt.qh
qcsrc/server/mutators/mutator/gamemode_race.qc
qcsrc/server/mutators/mutator/gamemode_tdm.qc
qcsrc/server/teamplay.qc
qcsrc/server/weapons/tracing.qc

index 538e3549fc5cc41ca4d8bebb03226129243a0f4a..892921f3af09076fa5543b5329c18f42d83e50e3 100644 (file)
@@ -1091,6 +1091,7 @@ set g_showweaponspawns 1 "1: display waypoints for weapon spawns found on the ma
 set g_ballistics_mindistance 2 // enable ballistics starting from 2 qu
 set g_ballistics_density_player 0.50 // players are 2x as easy to pass as walls
 set g_ballistics_density_corpse 0.10 // corpses are 10x as easy to pass as walls
+set g_ballistics_penetrate_clips 0 "allow ballistics to pass through weapon clips"
 
 set cl_stripcolorcodes 0       "experimental feature (notes: strips ALL color codes from messages!)"
 
index 9cbbcb5f7ee61f2207ed7a691ba88438397b9d80..8e2c722e8f374ec8baee0f4a0204ad1f296fcc04 100644 (file)
@@ -412,8 +412,6 @@ float autocvar_cl_hitsound_max_pitch = 1.5;
 float autocvar_cl_hitsound_nom_damage = 25;
 float autocvar_cl_hitsound_antispam_time;
 int autocvar_cl_eventchase_death = 1;
-vector autocvar_cl_eventchase_generator_viewoffset = '0 0 80';
-float autocvar_cl_eventchase_generator_distance = 400;
 float autocvar_cl_eventchase_distance = 140;
 float autocvar_cl_eventchase_speed = 1.3;
 vector autocvar_cl_eventchase_maxs = '12 12 8';
index 2a12e81c25e140db54908ee2bc4710aabe7d2f5b..c3310b25a13b8189711c8ccecf7e3957b4b17c5c 100644 (file)
@@ -16,27 +16,11 @@ void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int
        vector color = '0 0 0';
        switch(i)
        {
-               case 0:
-                       stat = STAT(REDALIVE);
-                       pic = "player_red.tga";
-                       color = '1 0 0';
-                       break;
-               case 1:
-                       stat = STAT(BLUEALIVE);
-                       pic = "player_blue.tga";
-                       color = '0 0 1';
-                       break;
-               case 2:
-                       stat = STAT(YELLOWALIVE);
-                       pic = "player_yellow.tga";
-                       color = '1 1 0';
-                       break;
+               case 0: stat = STAT(REDALIVE); pic = "player_red"; color = '1 0 0'; break;
+               case 1: stat = STAT(BLUEALIVE); pic = "player_blue"; color = '0 0 1'; break;
+               case 2: stat = STAT(YELLOWALIVE); pic = "player_yellow"; color = '1 1 0'; break;
                default:
-               case 3:
-                       stat = STAT(PINKALIVE);
-                       pic = "player_pink.tga";
-                       color = '1 0 1';
-                       break;
+               case 3: stat = STAT(PINKALIVE); pic = "player_pink"; color = '1 0 1'; break;
        }
 
        if(mySize.x/mySize.y > aspect_ratio)
@@ -654,29 +638,15 @@ void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, in
        vector color = '0 0 0';
        switch(i)
        {
-               case 0:
-                       stat = STAT(DOM_PPS_RED);
-                       pic = "dom_icon_red";
-                       color = '1 0 0';
-                       break;
-               case 1:
-                       stat = STAT(DOM_PPS_BLUE);
-                       pic = "dom_icon_blue";
-                       color = '0 0 1';
-                       break;
-               case 2:
-                       stat = STAT(DOM_PPS_YELLOW);
-                       pic = "dom_icon_yellow";
-                       color = '1 1 0';
-                       break;
+               case 0: stat = STAT(DOM_PPS_RED); pic = "dom_icon_red"; color = '1 0 0'; break;
+               case 1: stat = STAT(DOM_PPS_BLUE); pic = "dom_icon_blue"; color = '0 0 1'; break;
+               case 2: stat = STAT(DOM_PPS_YELLOW); pic = "dom_icon_yellow"; color = '1 1 0'; break;
                default:
-               case 3:
-                       stat = STAT(DOM_PPS_PINK);
-                       pic = "dom_icon_pink";
-                       color = '1 0 1';
-                       break;
+               case 3: stat = STAT(DOM_PPS_PINK); pic = "dom_icon_pink"; color = '1 0 1'; break;
        }
-       float pps_ratio = stat / STAT(DOM_TOTAL_PPS);
+       float pps_ratio = 0;
+       if(STAT(DOM_TOTAL_PPS))
+               pps_ratio = stat / STAT(DOM_TOTAL_PPS);
 
        if(mySize.x/mySize.y > aspect_ratio)
        {
index a852fdbe472437e96c4ffbbf9a2f5bd498f2335a..1792183f1ccd6e5f5d7da6f9ca3ef1969b175397 100644 (file)
@@ -88,6 +88,15 @@ MUTATOR_HOOKABLE(GetModelParams, EV_GetModelParams);
        /**/
 MUTATOR_HOOKABLE(WantEventchase, EV_WantEventchase);
 
+/** allow customizing 3rd person mode effect */
+#define EV_CustomizeEventchase(i, o) \
+       /** entity id */ i(entity, MUTATOR_ARGV_0_entity) \
+       /* current_view_origin_override */ o(vector, MUTATOR_ARGV_0_vector) \
+       /* view_offset_override */ o(vector, MUTATOR_ARGV_1_vector) \
+       /* chase_distance_override */ o(float, MUTATOR_ARGV_0_float) \
+       /**/
+MUTATOR_HOOKABLE(CustomizeEventchase, EV_CustomizeEventchase);
+
 #define EV_AnnouncerOption(i, o) \
        /** announcer string */  i(string, MUTATOR_ARGV_0_string) \
        /** announcer string */ o(string, MUTATOR_ARGV_0_string) \
index e5f8b6a580969ee76a0687fd19aee735a756afa1..3134a24ed28fed2c9b917d4d279b31053dee9b46 100644 (file)
@@ -1490,8 +1490,6 @@ void CSQC_UpdateView(entity this, float w, float h)
                        cvar_set("chase_active", "0");
 
                float vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
-               float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && STAT(ROUNDLOST));
-               entity gen = NULL;
 
                float vehicle_viewdist = 0;
                vector vehicle_viewofs = '0 0 0';
@@ -1506,18 +1504,18 @@ void CSQC_UpdateView(entity this, float w, float h)
                        }
                }
 
-               if(ons_roundlost) // TODO: move this junk to a client mutator for onslaught (possible using the WantEventchase hook)
+               if(WantEventchase(this))
                {
-                       IL_EACH(g_onsgenerators, it.health <= 0,
+                       vector current_view_origin_override = '0 0 0';
+                       vector view_offset_override = '0 0 0';
+                       float chase_distance_override = 0;
+                       bool custom_eventchase = MUTATOR_CALLHOOK(CustomizeEventchase, this);
+                       if(custom_eventchase)
                        {
-                               gen = it;
-                               break;
-                       });
-                       if(!gen)
-                               ons_roundlost = false; // don't enforce the 3rd person camera if there is no dead generator to show
-               }
-               if(WantEventchase(this) || (!autocvar_cl_orthoview && ons_roundlost))
-               {
+                               current_view_origin_override = M_ARGV(0, vector);
+                               view_offset_override = M_ARGV(1, vector);
+                               chase_distance_override = M_ARGV(0, float);
+                       }
                        eventchase_running = true;
 
                        entity local_player = ((csqcplayer) ? csqcplayer : CSQCModel_server2csqc(player_localentnum - 1));
@@ -1526,7 +1524,8 @@ void CSQC_UpdateView(entity this, float w, float h)
 
                        // make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.)
                        vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
-                       if(ons_roundlost) { current_view_origin = gen.origin; }
+                       if (custom_eventchase)
+                               current_view_origin = current_view_origin_override;
 
                        // detect maximum viewoffset and use it
                        vector view_offset = autocvar_cl_eventchase_viewoffset;
@@ -1537,7 +1536,8 @@ void CSQC_UpdateView(entity this, float w, float h)
                                else
                                        view_offset = autocvar_cl_eventchase_vehicle_viewoffset;
                        }
-                       if(ons_roundlost) { view_offset = autocvar_cl_eventchase_generator_viewoffset; }
+                       if (custom_eventchase)
+                               view_offset = view_offset_override;
 
                        if(view_offset)
                        {
@@ -1560,7 +1560,8 @@ void CSQC_UpdateView(entity this, float w, float h)
                                else
                                        chase_distance = autocvar_cl_eventchase_vehicle_distance;
                        }
-                       if(ons_roundlost) { chase_distance = autocvar_cl_eventchase_generator_distance; }
+                       if (custom_eventchase)
+                               chase_distance = chase_distance_override;
 
                        if(autocvar_cl_eventchase_speed && eventchase_current_distance < chase_distance)
                                eventchase_current_distance += autocvar_cl_eventchase_speed * (chase_distance - eventchase_current_distance) * frametime; // slow down the further we get
index 0054fd63607b1523c5b729382e1fe52c593da6d9..1d2555e95e9c9750dd5ef146f2356bad7bf40286 100644 (file)
@@ -1086,7 +1086,7 @@ MUTATOR_HOOKFUNCTION(nb, ItemTouch)
        return MUT_ITEMTOUCH_CONTINUE;
 }
 
-MUTATOR_HOOKFUNCTION(nb, GetTeamCount)
+MUTATOR_HOOKFUNCTION(nb, CheckAllowedTeams)
 {
        M_ARGV(1, string) = "nexball_team";
        return true;
index cbba9a9aaa87bc23d183b18b224f9fd508d91080..ac7a066ab17032c3fb0ae3733bdd8ead99c686c8 100644 (file)
@@ -14,6 +14,7 @@ void ons_generator_ray_draw(entity this)
 
        if(this.count > 10)
        {
+               IL_REMOVE(g_drawables, this);
                delete(this);
                return;
        }
@@ -149,7 +150,10 @@ void generator_construct(entity this, bool isnew)
        this.classname = "onslaught_generator";
 
        if(isnew)
+       {
                IL_PUSH(g_onsgenerators, this);
+               IL_PUSH(g_drawables, this);
+       }
 
        setorigin(this, this.origin);
        setmodel(this, MDL_ONS_GEN);
index 36926b754b0bcb8f0c92b4f1c734d8391c3cafc6..a30dd7d07e1c2da7b91a20edf9478d4a15e8e0d4 100644 (file)
@@ -1 +1,46 @@
 #include "onslaught.qh"
+
+#ifdef CSQC
+
+REGISTER_MUTATOR(cl_ons, true);
+
+float ons_roundlost;
+vector generator_origin;
+vector autocvar_cl_eventchase_generator_viewoffset = '0 0 80';
+float autocvar_cl_eventchase_generator_distance = 400;
+MUTATOR_HOOKFUNCTION(cl_ons, WantEventchase)
+{
+       ons_roundlost = STAT(ROUNDLOST);
+       entity gen = NULL;
+       if(ons_roundlost)
+       {
+               IL_EACH(g_onsgenerators, it.health <= 0,
+               {
+                       gen = it;
+                       break;
+               });
+               if(!gen)
+                       ons_roundlost = false; // don't enforce the 3rd person camera if there is no dead generator to show
+       }
+
+       if(ons_roundlost)
+       {
+               generator_origin = gen.origin;
+               return true;
+       }
+       return false;
+}
+
+MUTATOR_HOOKFUNCTION(cl_ons, CustomizeEventchase)
+{
+       if(ons_roundlost)
+       {
+               M_ARGV(0, vector) = generator_origin;
+               M_ARGV(1, vector) = autocvar_cl_eventchase_generator_viewoffset;
+               M_ARGV(0, float) = autocvar_cl_eventchase_generator_distance;
+               return true;
+       }
+       return false;
+}
+
+#endif
index 8e60bc30897a4ac897ea19c594630b68987989a3..d6606a370b74e6cc08fdd9a898e2f6a5a12d5766 100644 (file)
@@ -827,7 +827,7 @@ void ons_GeneratorDamage(entity this, entity inflictor, entity attacker, float d
        {
                if (this.isshielded)
                {
-                       // this is protected by a shield, so ignore the damage
+                       // generator is protected by a shield, so ignore the damage
                        if (time > this.pain_finished)
                                if (IS_PLAYER(attacker))
                                {
@@ -1871,7 +1871,7 @@ MUTATOR_HOOKFUNCTION(ons, HavocBot_ChooseRole)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(ons, GetTeamCount)
+MUTATOR_HOOKFUNCTION(ons, CheckAllowedTeams)
 {
        // onslaught is special
        for(entity tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
index cd45ed96d6662cada5cdf4d9f669ded4a4e1e61d..c15ecd463b94f4e8da29e7e745fd5bc87fef3de7 100644 (file)
@@ -675,16 +675,15 @@ void snake_hud_board(vector pos, vector mySize)
 void snake_hud_status(vector pos, vector mySize)
 {
        HUD_Panel_DrawBg();
-       vector ts;
-       ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
+       vector ts = minigame_drawstring_wrapped(mySize.x, pos, active_minigame.descriptor.message,
                hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
-       ts_y += hud_fontsize_y;
-       pos_y += ts_y;
-       mySize_y -= ts_y;
+       ts.y += hud_fontsize.y;
+       pos.y += ts.y;
+       mySize.y -= ts.y;
 
        vector player_fontsize = hud_fontsize * 1.75;
-       ts_y = ( mySize_y - SNAKE_TEAMS*player_fontsize_y ) / SNAKE_TEAMS;
-       ts_x = mySize_x;
+       ts.y = player_fontsize.y + (mySize.y - SNAKE_TEAMS * player_fontsize.y) / SNAKE_TEAMS;
+       ts.x = mySize_x;
        vector mypos;
 
        entity e;
@@ -692,22 +691,26 @@ void snake_hud_status(vector pos, vector mySize)
        {
                if ( e.classname == "minigame_player" )
                {
-                       mypos = pos;
-                       mypos_y  += (e.team-1) * (player_fontsize_y + ts_y);
+                       mypos = pos + eY * (e.team - 1) * ts.y;
 
-                       drawfill(mypos, ts, snake_teamcolor(e.team), 0.25, DRAWFLAG_ADDITIVE);
+                       if (e == minigame_self)
+                       {
+                               const vector hl_size = '1 1 0';
+                               drawfill(mypos + hl_size, ts - 2 * hl_size, snake_teamcolor(e.team), 0.25 * panel_fg_alpha, DRAWFLAG_ADDITIVE);
+                               drawborderlines(hl_size.x, mypos + hl_size, ts - 2 * hl_size, snake_teamcolor(e.team), panel_fg_alpha, DRAWFLAG_NORMAL);
+                       }
+                       else
+                               drawfill(mypos, ts, snake_teamcolor(e.team), 0.25 * panel_fg_alpha, DRAWFLAG_ADDITIVE);
 
-                       minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
-                               entcs_GetName(e.minigame_playerslot-1),
+                       minigame_drawcolorcodedstring_trunc(mySize.x - hud_fontsize.x * 0.5, mypos + eX * hud_fontsize.x * 0.25,
+                               entcs_GetName(e.minigame_playerslot - 1),
                                player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
 
-                       drawstring(mypos+eY*player_fontsize_y,ftos(e.snake_score),'48 48 0' * (SNAKE_TEAMS * 0.1),
-                                          '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-                       drawstring(mypos+(eY*player_fontsize_y) + (eX*player_fontsize_x),strcat("1UP: ", ftos(active_minigame.snake_lives[e.team])),'48 48 0' * (SNAKE_TEAMS * 0.1),
-                                                        '1 0.44 0.54', panel_fg_alpha, DRAWFLAG_NORMAL);
-
-                       if ( e == minigame_self )
-                               drawborderlines(1, mypos, ts, snake_teamcolor(e.team), 1, DRAWFLAG_NORMAL);
+                       mypos.y += player_fontsize.y;
+                       drawstring_aspect(mypos, ftos(e.snake_score), ts - eY * player_fontsize.y - eX * ts.x * (3 / 4),
+                                                               '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+                       drawstring_aspect(mypos + eX * ts.x * (1 / 4), strcat("1UP: ", ftos(active_minigame.snake_lives[e.team])), ts - eY * player_fontsize.y - eX * ts.x * (1 / 4),
+                                                               '1 0.44 0.54', panel_fg_alpha, DRAWFLAG_NORMAL);
                }
        }
 }
index a1bb5fb958d5da0cdf69d86759fc9b48bfe7de82..6faddf4dde63d51399a626be342967caf0def555 100644 (file)
@@ -92,6 +92,7 @@ float autocvar_g_balance_teams_scorefactor;
 float autocvar_g_ballistics_density_corpse;
 float autocvar_g_ballistics_density_player;
 float autocvar_g_ballistics_mindistance;
+bool autocvar_g_ballistics_penetrate_clips;
 float autocvar_g_ban_default_bantime;
 float autocvar_g_ban_default_masksize;
 float autocvar_g_ban_sync_interval;
index c8c3415561248834da720ca1858b64c26c8469b0..3743c6b94978977769c9112e30a024e4d912b86a 100644 (file)
@@ -98,14 +98,14 @@ MUTATOR_HOOKABLE(GiveFragsForKill, EV_GiveFragsForKill);
 /** called when the match ends */
 MUTATOR_HOOKABLE(MatchEnd, EV_NO_ARGS);
 
-/** should adjust number to contain the team count */
-#define EV_GetTeamCount(i, o) \
-    /** number of teams    */ i(float, MUTATOR_ARGV_0_float) \
+/** allows adjusting allowed teams */
+#define EV_CheckAllowedTeams(i, o) \
+    /** mask of teams      */ i(float, MUTATOR_ARGV_0_float) \
     /**/                      o(float, MUTATOR_ARGV_0_float) \
     /** team entity name   */ i(string, MUTATOR_ARGV_1_string) \
     /**/                      o(string, MUTATOR_ARGV_1_string) \
     /**/
-MUTATOR_HOOKABLE(GetTeamCount, EV_GetTeamCount);
+MUTATOR_HOOKABLE(CheckAllowedTeams, EV_CheckAllowedTeams);
 
 /** copies variables for spectating "spectatee" to "this" */
 #define EV_SpectateCopy(i, o) \
index f4566a9ca667b305a759e05fcf96edf9dc7c6e4c..10a8f644f89c7e2389c4c879ede4db57e485eef2 100644 (file)
@@ -562,7 +562,7 @@ MUTATOR_HOOKFUNCTION(as, PlayHitsound)
        return (frag_victim.classname == "func_assault_destructible");
 }
 
-MUTATOR_HOOKFUNCTION(as, GetTeamCount)
+MUTATOR_HOOKFUNCTION(as, CheckAllowedTeams)
 {
        // assault always has 2 teams
        c1 = c2 = 0;
index 84f668bab5f9954db2cb331a8adef632fa894746..ebfcd9540282d99f853c94cbb6c0f5d94ca75d04 100644 (file)
@@ -226,7 +226,7 @@ MUTATOR_HOOKFUNCTION(ca, reset_map_global)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(ca, GetTeamCount, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(ca, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = ca_teams;
 }
index 56ee04d5dafe61135f3c2acc1fb6b6bed70fd5ac..0a3c622a9b0a3575f2d73c570e2866505362ec60 100644 (file)
@@ -2369,7 +2369,7 @@ MUTATOR_HOOKFUNCTION(ctf, HavocBot_ChooseRole)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(ctf, GetTeamCount)
+MUTATOR_HOOKFUNCTION(ctf, CheckAllowedTeams)
 {
        //M_ARGV(0, float) = ctf_teams;
        M_ARGV(1, string) = "ctf_team";
index abcae5ada5dffb2db2381386b8a9d0a23627d5b4..eb94e4f263f75a57b21b0e0a1cb8b5b52d197fd5 100644 (file)
@@ -411,7 +411,7 @@ void havocbot_role_dom(entity this)
        }
 }
 
-MUTATOR_HOOKFUNCTION(dom, GetTeamCount)
+MUTATOR_HOOKFUNCTION(dom, CheckAllowedTeams)
 {
        // fallback?
        M_ARGV(0, float) = domination_teams;
index cd7372699004bd93fe18e482e69d552e5b24f27d..0143760872504e1fbc6a143714b6bc2e5eba47fb 100644 (file)
@@ -553,7 +553,7 @@ MUTATOR_HOOKFUNCTION(ft, HavocBot_ChooseRole)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(ft, GetTeamCount, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(ft, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = freezetag_teams;
 }
index 2a1b35956b0bce2b42d6b6156629acf93c751683..515148c1bbdc06625c5b8161892785ac42014686 100644 (file)
@@ -412,7 +412,7 @@ MUTATOR_HOOKFUNCTION(inv, AllowMobSpawning)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(inv, GetTeamCount, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(inv, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = invasion_teams;
 }
index f299c7d07eb5178df28a7da98f72911ae4124195..781609a9106cf977ed9d5e3a68dccb0592fc1684 100644 (file)
@@ -40,7 +40,7 @@ const vector KH_KEY_MIN = '-10 -10 -46';
 const vector KH_KEY_MAX = '10 10 3';
 const float KH_KEY_BRIGHTNESS = 2;
 
-float kh_no_radar_circles;
+bool kh_no_radar_circles;
 
 // kh_state
 //     bits  0- 4: team of key 1, or 0 for no such key, or 30 for dropped, or 31 for self
@@ -81,6 +81,8 @@ float kh_interferemsg_time, kh_interferemsg_team;
 
 float kh_key_dropped, kh_key_carried;
 
+int kh_Key_AllOwnedByWhichTeam();
+
 const float ST_KH_CAPS = 1;
 void kh_ScoreRules(int teams)
 {
@@ -782,14 +784,11 @@ void kh_Key_Spawn(entity initial_owner, float _angle, float i)  // runs every ti
 }
 
 // -1 when no team completely owns all keys yet
-float kh_Key_AllOwnedByWhichTeam()  // constantly called. check to see if all the keys are owned by the same team
+int kh_Key_AllOwnedByWhichTeam()  // constantly called. check to see if all the keys are owned by the same team
 {
        entity key;
-       float teem;
-       float keys;
-
-       teem = -1;
-       keys = NumTeams(kh_teams);
+       int teem = -1;
+       int keys = NumTeams(kh_teams);
        FOR_EACH_KH_KEY(key)
        {
                if(!key.owner)
@@ -855,24 +854,23 @@ void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
        }
 }
 
-float kh_CheckPlayers(float num)
+int kh_GetMissingTeams()
 {
-       if(num < NumTeams(kh_teams))
+       int missing_teams = 0;
+       for(int i = 0; i < NumTeams(kh_teams); ++i)
        {
-               float t_team = kh_Team_ByID(num);
-               float players = 0;
+               int teem = kh_Team_ByID(i);
+               int players = 0;
                FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
-                       if(!IS_DEAD(it) && !PHYS_INPUT_BUTTON_CHAT(it) && it.team == t_team)
+                       if(!IS_DEAD(it) && !PHYS_INPUT_BUTTON_CHAT(it) && it.team == teem)
                                ++players;
                ));
-
-               if (!players) { return t_team; }
+               if (!players)
+                       missing_teams |= pow(2, i);
        }
-       return 0;
+       return missing_teams;
 }
 
-#define KH_READY_TEAMS() (!p1 + !p2 + ((NumTeams(kh_teams) >= 3) ? !p3 : p3) + ((NumTeams(kh_teams) >= 4) ? !p4 : p4))
-#define KH_READY_TEAMS_OK() (KH_READY_TEAMS() == NumTeams(kh_teams))
 void kh_WaitForPlayers()  // delay start of the round until enough players are present
 {
        if(time < game_starttime)
@@ -881,9 +879,9 @@ void kh_WaitForPlayers()  // delay start of the round until enough players are p
                return;
        }
 
-       static float prev_missing_teams_mask;
-       float p1 = kh_CheckPlayers(0), p2 = kh_CheckPlayers(1), p3 = kh_CheckPlayers(2), p4 = kh_CheckPlayers(3);
-       if(KH_READY_TEAMS_OK())
+       static int prev_missing_teams_mask;
+       int missing_teams_mask = kh_GetMissingTeams();
+       if(!missing_teams_mask)
        {
                if(prev_missing_teams_mask > 0)
                        Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_MISSING_TEAMS);
@@ -901,15 +899,6 @@ void kh_WaitForPlayers()  // delay start of the round until enough players are p
                }
                else
                {
-                       int missing_teams_mask = 0;
-                       if(kh_teams & BIT(0))
-                               missing_teams_mask += boolean(p1) * 1;
-                       if(kh_teams & BIT(1))
-                               missing_teams_mask += boolean(p2) * 2;
-                       if(kh_teams & BIT(2))
-                               missing_teams_mask += boolean(p3) * 4;
-                       if(kh_teams & BIT(3))
-                               missing_teams_mask += boolean(p4) * 8;
                        if(prev_missing_teams_mask != missing_teams_mask)
                        {
                                Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_MISSING_TEAMS, missing_teams_mask);
@@ -930,7 +919,7 @@ void kh_EnableTrackingDevice()  // runs after each round
 
 void kh_StartRound()  // runs at the start of each round
 {
-       float i, players, teem;
+       int i, players, teem;
 
        if(time < game_starttime)
        {
@@ -938,8 +927,7 @@ void kh_StartRound()  // runs at the start of each round
                return;
        }
 
-       float p1 = kh_CheckPlayers(0), p2 = kh_CheckPlayers(1), p3 = kh_CheckPlayers(2), p4 = kh_CheckPlayers(3);
-       if(!KH_READY_TEAMS_OK())
+       if(kh_GetMissingTeams())
        {
                kh_Controller_SetThink(1, kh_WaitForPlayers);
                return;
@@ -1285,7 +1273,7 @@ MUTATOR_HOOKFUNCTION(kh, MatchEnd)
        kh_finalize();
 }
 
-MUTATOR_HOOKFUNCTION(kh, GetTeamCount, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(kh, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = kh_teams;
 }
index 9a98df98fda007eee44fc3e982da116b8a3584d2..d0fb5f95bc2ff0c455a96da9900932b586e75e8f 100644 (file)
@@ -42,9 +42,8 @@ REGISTER_MUTATOR(kh, false)
 // ALL OF THESE should be removed in the future, as other code should not have to care
 
 // used by bots:
-float kh_tracking_enabled;
+bool kh_tracking_enabled;
 .entity kh_next;
-float kh_Key_AllOwnedByWhichTeam();
 
 USING(kh_Think_t, void());
 void kh_StartRound();
index b791a69dce9830cc42b45743501dce63bbc80ff1..abe6b846e73fb714e4f132bef49ff7df0d89cd4d 100644 (file)
@@ -343,7 +343,7 @@ MUTATOR_HOOKFUNCTION(rc, ForbidPlayerScore_Clear)
                return true; // in qualifying, you don't lose score by observing
 }
 
-MUTATOR_HOOKFUNCTION(rc, GetTeamCount, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(rc, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = race_teams;
 }
index d906c1988c247c6bf4f4353da149d31006e5e192..101f57fcc4d6efb96ecd5d2ed5157b0065c29060 100644 (file)
@@ -57,7 +57,7 @@ void tdm_DelayedInit(entity this)
        }
 }
 
-MUTATOR_HOOKFUNCTION(tdm, GetTeamCount, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(tdm, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(1, string) = "tdm_team";
        return true;
index de7f2f992617320717d079bd86ea8c8c68f91ed6..6ccb7d408186a2c473c4860bd7a210860e9deea2 100644 (file)
@@ -216,23 +216,23 @@ void SetPlayerTeam(entity pl, float t, float s, float noprint)
 // set c1...c4 to show what teams are allowed
 void CheckAllowedTeams (entity for_whom)
 {
-       int dm = 0;
+       int teams_mask = 0;
 
        c1 = c2 = c3 = c4 = -1;
        cb1 = cb2 = cb3 = cb4 = 0;
 
        string teament_name = string_null;
 
-       bool mutator_returnvalue = MUTATOR_CALLHOOK(GetTeamCount, dm, teament_name);
-       dm = M_ARGV(0, float);
+       bool mutator_returnvalue = MUTATOR_CALLHOOK(CheckAllowedTeams, teams_mask, teament_name);
+       teams_mask = M_ARGV(0, float);
        teament_name = M_ARGV(1, string);
 
        if(!mutator_returnvalue)
        {
-               if(dm & BIT(0)) c1 = 0;
-               if(dm & BIT(1)) c2 = 0;
-               if(dm & BIT(2)) c3 = 0;
-               if(dm & BIT(3)) c4 = 0;
+               if(teams_mask & BIT(0)) c1 = 0;
+               if(teams_mask & BIT(1)) c2 = 0;
+               if(teams_mask & BIT(2)) c3 = 0;
+               if(teams_mask & BIT(3)) c4 = 0;
        }
 
        // find out what teams are allowed if necessary
index 176b69e6b6c9e5f720f2dfc09fb9af13367c1ff8..051a725480088097d1bf0803b4a2e014834b06d7 100644 (file)
@@ -445,7 +445,7 @@ void fireBullet(entity this, vector start, vector dir, float spread, float max_s
                        }
                }
 
-               if (is_weapclip)
+               if (is_weapclip && !autocvar_g_ballistics_penetrate_clips)
                        break;
 
                // go through solid!