Merge remote branch 'origin/master' into fruitiex/racefixes
authorFruitieX <rasse@rasse-laptop.(none)>
Tue, 26 Oct 2010 15:42:55 +0000 (18:42 +0300)
committerFruitieX <rasse@rasse-laptop.(none)>
Tue, 26 Oct 2010 15:42:55 +0000 (18:42 +0300)
13 files changed:
defaultXonotic.cfg
gfx/hud/default/player_blue.tga [new file with mode: 0644]
gfx/hud/default/player_red.tga [new file with mode: 0644]
qcsrc/client/View.qc
qcsrc/client/hud.qc
qcsrc/client/miscfunctions.qc
qcsrc/common/constants.qh
qcsrc/server/arena.qc
qcsrc/server/cl_client.qc
qcsrc/server/clientcommands.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_world.qc

index a5558f947c46a32597b932e46a6726bd11377047..0a959f207e70034da2d3b5d899caf8df8528d36b 100644 (file)
@@ -615,6 +615,8 @@ set g_arena_respawn_delay 0
 set g_arena_respawn_waves 0
 set g_ca_respawn_delay 0
 set g_ca_respawn_waves 0
+set g_ca_damage2score_multiplier 0.01
+set g_ca_round_timelimit 180
 set g_nexball_respawn_delay 0
 set g_nexball_respawn_waves 0
 set g_as_respawn_delay 0
diff --git a/gfx/hud/default/player_blue.tga b/gfx/hud/default/player_blue.tga
new file mode 100644 (file)
index 0000000..cf10bc5
Binary files /dev/null and b/gfx/hud/default/player_blue.tga differ
diff --git a/gfx/hud/default/player_red.tga b/gfx/hud/default/player_red.tga
new file mode 100644 (file)
index 0000000..aea0ed8
Binary files /dev/null and b/gfx/hud/default/player_red.tga differ
index 215aa524eb52fbf3d1fbb3b464e1abe84e4fdc68..5ac1f965e3a1d8714da30cd5ebdea66916917257 100644 (file)
@@ -950,11 +950,6 @@ void CSQC_UpdateView(float w, float h)
        // let's reset the view back to normal for the end
        R_SetView(VF_MIN, '0 0 0');
        R_SetView(VF_SIZE, '1 0 0' * w + '0 1 0' * h);
-
-       // be safe against triggerbots until everyone has the fixed engine
-       // this call is meant to overwrite the trace globals by something
-       // unsuspicious
-       traceline('0 0 0', '0 0 0', MOVE_WORLDONLY, world);
 }
 
 #define spider_h "gfx/vehicles/hud_bg.tga"
index d752235b418457fe9a7650f42ec49b989e989e01..b341f10515da597bbba1e90a3632e336f9a4c21b 100644 (file)
@@ -3908,6 +3908,37 @@ void HUD_VoteWindow(void)
 
 float mod_active; // is there any active mod icon?
 
+// Clan Arena HUD modicons
+void HUD_Mod_CA(vector pos, vector mySize)
+{
+       mod_active = 1; // CA should never hide the mod icons panel
+       float redalive, bluealive;
+       redalive = getstati(STAT_REDALIVE);
+       bluealive = getstati(STAT_BLUEALIVE);
+
+       drawfont = hud_bigfont;
+       vector redpos, bluepos;
+       if(mySize_x > mySize_y)
+       {
+               redpos = pos;
+               bluepos = pos + eY * 0.5 * mySize_y;
+               drawpic_aspect_skin(redpos, "player_red.tga", 0.5 * mySize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring_aspect(redpos + eX * 0.5 * mySize_x, ftos(redalive), 0.5 * mySize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawpic_aspect_skin(bluepos, "player_blue.tga", 0.5 * mySize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring_aspect(bluepos + eX * 0.5 * mySize_x, ftos(bluealive), 0.5 * mySize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       }
+       else
+       {
+               redpos = pos;
+               bluepos = pos + eY * 0.5 * mySize_y;
+               drawpic_aspect_skin(redpos, "player_red.tga", eX * mySize_x + eY * 0.3 * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring_aspect(redpos + eY * 0.3 * mySize_y, ftos(redalive), eX * mySize_x + eY * 0.2 * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawpic_aspect_skin(bluepos, "player_blue.tga", eX * mySize_x + eY * 0.3 * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+               drawstring_aspect(bluepos + eY * 0.3 * mySize_y, ftos(bluealive), eX * mySize_x + eY * 0.2 * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+       }
+       drawfont = hud_font;
+}
+
 // CTF HUD modicon section
 float redflag_prevframe, blueflag_prevframe; // status during previous frame
 float redflag_prevstatus, blueflag_prevstatus; // last remembered status
@@ -4404,7 +4435,7 @@ void HUD_ModIcons(void)
        if(!autocvar_hud_panel_modicons && !autocvar__hud_configure)
                return;
 
-       if (gametype != GAME_KEYHUNT && gametype != GAME_CTF && gametype != GAME_NEXBALL && gametype != GAME_CTS && gametype != GAME_RACE && !autocvar__hud_configure)
+       if (gametype != GAME_KEYHUNT && gametype != GAME_CTF && gametype != GAME_NEXBALL && gametype != GAME_CTS && gametype != GAME_RACE && gametype != GAME_CA && !autocvar__hud_configure)
                return;
 
        active_panel = HUD_PANEL_MODICONS;
@@ -4441,6 +4472,8 @@ void HUD_ModIcons(void)
                HUD_Mod_NexBall(pos, mySize);
        else if(gametype == GAME_CTS || gametype == GAME_RACE)
                HUD_Mod_Race(pos, mySize);
+       else if(gametype == GAME_CA)
+               HUD_Mod_CA(pos, mySize);
 }
 
 // Draw pressed keys (#11)
index 5c377bffadb8ade59c381071def85021d3181ba8..049368c1636b07944ae7de43de10008dfbbd9da2 100644 (file)
@@ -627,28 +627,33 @@ void drawcolorcodedstring_aspect_expanding(vector pos, string text, vector sz, f
 }
 
 // this draws the triangles of a model DIRECTLY. Don't expect high performance, really...
-void PolyDrawModel(entity e)
+float PolyDrawModelSurface(entity e, float i_s)
 {
-       float i_s, i_t;
+       float i_t;
        float n_t;
        vector tri;
        string tex;
-       for(i_s = 0; ; ++i_s)
+       tex = getsurfacetexture(e, i_s);
+       if not(tex)
+               return 0; // this is beyond the last one
+       n_t = getsurfacenumtriangles(e, i_s);
+       for(i_t = 0; i_t < n_t; ++i_t)
        {
-               tex = getsurfacetexture(e, i_s);
-               if not(tex)
-                       break; // this is beyond the last one
-               n_t = getsurfacenumtriangles(e, i_s);
-               for(i_t = 0; i_t < n_t; ++i_t)
-               {
-                       tri = getsurfacetriangle(e, i_s, i_t);
-                       R_BeginPolygon(tex, 0);
-                       R_PolygonVertex(getsurfacepoint(e, i_s, tri_x), getsurfacepointattribute(e, i_s, tri_x, SPA_TEXCOORDS0), '1 1 1', 1);
-                       R_PolygonVertex(getsurfacepoint(e, i_s, tri_y), getsurfacepointattribute(e, i_s, tri_y, SPA_TEXCOORDS0), '1 1 1', 1);
-                       R_PolygonVertex(getsurfacepoint(e, i_s, tri_z), getsurfacepointattribute(e, i_s, tri_z, SPA_TEXCOORDS0), '1 1 1', 1);
-                       R_EndPolygon();
-               }
+               tri = getsurfacetriangle(e, i_s, i_t);
+               R_BeginPolygon(tex, 0);
+               R_PolygonVertex(getsurfacepoint(e, i_s, tri_x), getsurfacepointattribute(e, i_s, tri_x, SPA_TEXCOORDS0), '1 1 1', 1);
+               R_PolygonVertex(getsurfacepoint(e, i_s, tri_y), getsurfacepointattribute(e, i_s, tri_y, SPA_TEXCOORDS0), '1 1 1', 1);
+               R_PolygonVertex(getsurfacepoint(e, i_s, tri_z), getsurfacepointattribute(e, i_s, tri_z, SPA_TEXCOORDS0), '1 1 1', 1);
+               R_EndPolygon();
        }
+       return 1;
+}
+void PolyDrawModel(entity e)
+{
+       float i_s;
+       for(i_s = 0; ; ++i_s)
+               if(!PolyDrawModelSurface(e, i_s))
+                       break;
 }
 
 void DrawCircleClippedPic(vector centre, float radius, string pic, float f, vector rgb, float a, float drawflag)
index c1455af452b47b346f68e3066e17aaa49ebbf61e..4dd3bf76e369d0d44b6cbd88d34005704db5cc20 100644 (file)
@@ -310,6 +310,7 @@ const float STAT_SHOTORG = 46; // compressShotOrigin
 const float STAT_LEADLIMIT = 47;
 const float STAT_BULLETS_LOADED = 48;
 const float STAT_NEX_CHARGE = 49;
+const float STAT_HUD = 50;
 
 // see DP source, quakedef.h
 const float STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222;
@@ -320,7 +321,6 @@ const float CTF_STATE_ATTACK = 1;
 const float CTF_STATE_DEFEND = 2;
 const float CTF_STATE_COMMANDER = 3;
 
-const float STAT_HUD = 50;
 const float HUD_NORMAL = 0;
 const float HUD_SPIDERBOT = 10;
 const float HUD_WAKIZASHI = 11;
@@ -337,6 +337,10 @@ const float STAT_VEHICLESTAT_RELOAD1 = 64;
 const float STAT_VEHICLESTAT_AMMO2   = 65;
 const float STAT_VEHICLESTAT_RELOAD2 = 66;
 
+// mod stats (1xx)
+const float STAT_REDALIVE = 100;
+const float STAT_BLUEALIVE = 101;
+
 //const float STAT_SPIDERBOT_AIM     53 // compressShotOrigin
 //const float STAT_SPIDERBOT_TARGET  54 // compressShotOrigin
 
index ee4ce1b87ed9388ca2bf376f98a437866ef21bc3..046743151dbc02fd27dbd706a77d8065418397b6 100644 (file)
@@ -8,8 +8,8 @@ float arena_roundbased;
 entity spawnqueue_first;
 entity spawnqueue_last;
 entity champion;
+string champion_name;
 float warmup;
-float allowed_to_spawn;
 float ca_players;
 float required_ca_players;
 .float caplayer;
@@ -122,7 +122,7 @@ void reset_map(float dorespawn)
        if(g_keyhunt)
                kh_Controller_SetThink(cvar("g_balance_keyhunt_delay_round")+(game_starttime - time), "", kh_StartRound);
 
-       if(g_arena || g_ca)
+       if(g_arena)
        if(champion && champion.classname == "player" && player_count > 1)
                UpdateFrags(champion, +1);
 
@@ -195,11 +195,15 @@ void Arena_Warmup()
        if((!g_arena && !g_ca) || (g_arena && !arena_roundbased) || (time < game_starttime))
                return;
 
-       f = floor(warmup - time + 1);
+       f = ceil(warmup - time);
+       if(f > 0)
+               champion = world; // this is done because a if(champion) will not execute if champion = world
 
        allowed_to_spawn = 0;
 
-       if(g_ca && (ca_players < required_ca_players || inWarmupStage))
+       if(inWarmupStage)
+               allowed_to_spawn = 1;
+       if(ca_players < required_ca_players)
                allowed_to_spawn = 1;
 
        msg = NEWLINES;
@@ -208,7 +212,7 @@ void Arena_Warmup()
                if (g_ca)
                        allowed_to_spawn = 1;
                if(champion && g_arena)
-                       msg = strcat("The Champion is ", champion.netname, "^7\n");
+                       msg = strcat("The Champion is ", champion_name, "^7\n");
                        //centerprint(self, strcat(msg, "The Champion is ", champion.netname, "^7\n"));
 
                if(f != roundStartTime_prev) {
@@ -257,6 +261,9 @@ void Arena_Warmup()
 }
 
 float next_round;
+float stopalivecheck;
+float redalive, bluealive;
+.float redalive_stat, bluealive_stat;
 /**
  * This function finds out whether an arena round is over 1 player is left.
  * It determines the last player who's still alive and saves it's entity reference
@@ -266,6 +273,22 @@ float next_round;
  */
 void Spawnqueue_Check()
 {
+       if(g_ca) // we want to perform this before the return block below...
+       {
+               // this is STUPID to perform again, but has to be done so that we can give instant feedback when a round ends
+               // and so the code won't start searching for a champion using find() before all players are actually REMOVED
+               redalive = 0; bluealive = 0;
+               FOR_EACH_PLAYER(self) {
+                       if (self.team == COLOR_TEAM1 && self.health >= 1) redalive += 1;
+                       else if (self.team == COLOR_TEAM2 && self.health >= 1) bluealive += 1;
+               }
+               // as if the above stuff wasn't stupid enough, let's run it a third time! :D
+               // (so that we can send redalive/bluealive as a stat)
+               FOR_EACH_PLAYER(self) {
+                       self.redalive_stat = redalive;
+                       self.bluealive_stat = bluealive;
+               }
+       }
        if(time < warmup + 1 || inWarmupStage)
                return;
 
@@ -285,34 +308,43 @@ void Spawnqueue_Check()
                else if(ca_players < required_ca_players) {
                        FOR_EACH_PLAYER(self)
                                centerprint(self, strcat("^1Need at least 1 player in each team to play CA", "^7\n"));
-
-                       allowed_to_spawn = 1;
                        return;
                }
                else if(!next_round) {
                        if((redspawned && !bluespawned) || (bluespawned && !redspawned)) {
                                next_round = time + 5;
-
                                champion = find(world, classname, "player");
-                               string champion_team;
-                               if(champion.team == COLOR_TEAM1) {
-                                       champion_team = "^1Red team";
-                                       play2all("ctf/red_capture.wav");
-                               }
-                               else if(champion.team == COLOR_TEAM2) {
-                                       champion_team = "^4Blue team";
-                                       play2all("ctf/blue_capture.wav");
-                               }
-                               FOR_EACH_CLIENT(self) centerprint(self, strcat(champion_team, "^7 wins the round.", "^7\n"));
+                               if(champion_name)
+                                       strunzone(champion_name);
+                               champion_name = strzone(champion.netname);
                        }
-                       else if(!redspawned && !bluespawned) {
+                       else if((!redspawned && !bluespawned) || time - warmup > cvar("g_ca_round_timelimit")) {
                                FOR_EACH_CLIENT(self) centerprint(self, strcat("^7Round tied.", "^7\n"));
                                next_round = time + 5;
                        }
+
+               }
+               if(!stopalivecheck)
+               {
+                       if(redalive && !bluealive)
+                       {
+                               play2all("ctf/red_capture.wav");
+                               FOR_EACH_CLIENT(self) centerprint(self, "^1 RED ^7team wins the round.\n");
+                               TeamScore_AddToTeam(COLOR_TEAM1, ST_SCORE, +1);
+                               stopalivecheck = TRUE;
+                       }
+                       else if(bluealive && !redalive)
+                       {
+                               play2all("ctf/blue_capture.wav");
+                               FOR_EACH_CLIENT(self) centerprint(self, "^4 BLUE ^7team wins the round.\n");
+                               TeamScore_AddToTeam(COLOR_TEAM2, ST_SCORE, +1);
+                               stopalivecheck = TRUE;
+                       }
                }
 
                if((next_round && next_round < time))
                {
+                       stopalivecheck = FALSE;
                        next_round = 0;
                        reset_map(TRUE);
                }
index a5ec05c02fb6b75ac690f03a5b8663076d0e2e4d..76f81c8d7497080cc9ea3a3171631d42f824d859 100644 (file)
@@ -1305,7 +1305,12 @@ void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto
 
 void ClientKill (void)
 {
-       ClientKill_TeamChange(0);
+       if((g_arena || g_ca) && ((champion && champion.classname == "player" && player_count > 1) || player_count == 1)) // don't allow a kill in this case either
+       {
+               // do nothing
+       }
+       else
+               ClientKill_TeamChange(0);
 }
 
 void CTS_ClientKill_Think (void)
index a11ab82f9955577b47ebe4275e0aebc4b0fc207c..a92da718fe3583cdcd068c358f039adf2b2467ca 100644 (file)
@@ -432,7 +432,7 @@ void ReadyRestartForce()
 
        readyrestart_happened = 1;
        game_starttime = time;
-       if(!g_ca)
+       if(!g_ca && !g_arena)
                game_starttime += RESTART_COUNTDOWN;
        restart_mapalreadyrestarted = 0; //reset this var, needed when cvar sv_ready_restart_repeatable is in use
 
@@ -450,7 +450,7 @@ void ReadyRestartForce()
        }
 
        //initiate the restart-countdown-announcer entity
-       if(cvar("sv_ready_restart_after_countdown"))
+       if(cvar("sv_ready_restart_after_countdown") && !g_ca && !g_arena)
        {
                restartTimer = spawn();
                restartTimer.think = restartTimer_Think;
index 74e5d428f3a7cba8c0e7c14e4508796128f9a482..9295547c530f03e929d6310ffaa267628e43f955 100644 (file)
@@ -654,3 +654,5 @@ string deathmessage;
 .entity realowner;
 
 .float nex_charge;
+
+float allowed_to_spawn; // boolean variable used by the clan arena code to determine if a player can spawn (after the round has ended)
index c7336356cae0363a2a8e79a4bd8bff10775c82e8..ab0638387e472b6eeaf43830a065a388fd78a733 100644 (file)
@@ -753,6 +753,8 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                                                        if(deathtype & HITTYPE_HEADSHOT)
                                                                headshot = 1;
                                                }
+                                               if(g_ca)
+                                                       PlayerScore_Add(attacker, SP_SCORE, damage * cvar("g_ca_damage2score_multiplier"));
                                        }
                                }
                                else
index 053ed5124b134adc2d4d1837bef9b117bf1d4eb9..b761e97c7696a764d2a3fde35b4341089bc5d653 100644 (file)
@@ -440,6 +440,8 @@ void spawnfunc_worldspawn (void)
 
        compressShortVector_init();
 
+       allowed_to_spawn = TRUE;
+
        local entity head;
        head = nextent(world);
        maxclients = 0;
@@ -642,6 +644,11 @@ void spawnfunc_worldspawn (void)
 
        addstat(STAT_NEX_CHARGE, AS_FLOAT, nex_charge);
 
+       if(g_ca)
+       {
+               addstat(STAT_REDALIVE, AS_INT, redalive_stat);
+               addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
+       }
        // g_movementspeed hack
        addstat(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW, AS_FLOAT, stat_sv_airspeedlimit_nonqw);
        addstat(STAT_MOVEVARS_AIRACCEL_QW, AS_FLOAT, stat_sv_airaccel_qw);