Merge remote branch 'refs/remotes/origin/fruitiex/ca_nodmg_after_round'
authorRudolf Polzer <divverent@alientrap.org>
Sun, 24 Oct 2010 12:14:49 +0000 (14:14 +0200)
committerRudolf Polzer <divverent@alientrap.org>
Sun, 24 Oct 2010 12:14:49 +0000 (14:14 +0200)
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/hud.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 3ac447e864691b3229548c392f10a53241b31fbe..0ba520e135aefda888f97c0f42965804ecceb915 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 357f8a0e3502a726436461bc9163bf0b861e459f..7ce1a202d6c9991b5e4d70e11e57796f8e496a98 100644 (file)
@@ -3859,6 +3859,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
@@ -4355,7 +4386,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;
@@ -4392,6 +4423,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 6f0eccfafb8af72f94a556ad5709a0554c0ccfab..b4b92ff8bd2e72cc41cc07b01bf8a339eb9e1006 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 df6c8d4b2a3f41e0793e271d8aae9a9b54512692..bb2b753b84369a3d87907d307885b0e44b94bcbf 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 DoTeamChange(float destteam)
index a9fd886bfe9c331e34b7651faf4c4bca063703c5..b705e9c09ce18a1877a3e9889e2130c06a53daa9 100644 (file)
@@ -430,7 +430,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
 
@@ -448,7 +448,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 d1d86ed79a19703ceb266b0f5d8bf40e6836d7d2..745a6e0b2a5e148be15ba87a3e3da7079d4d2f86 100644 (file)
@@ -651,3 +651,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 08329a29d7e61a76a2f1e3097b307a93fa0fff78..6260d7e86d8f08a404afd3228908f70bdce1e774 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);