Commit the new clan arena mod, as well as make the unbalanced team nagger optional...
authorfruitiex <fruitiex@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Tue, 10 Nov 2009 21:28:20 +0000 (21:28 +0000)
committerfruitiex <fruitiex@f962a42d-fe04-0410-a3ab-8c8b0445ebaa>
Tue, 10 Nov 2009 21:28:20 +0000 (21:28 +0000)
git-svn-id: svn://svn.icculus.org/nexuiz/trunk@8267 f962a42d-fe04-0410-a3ab-8c8b0445ebaa

46 files changed:
data/balanceNexrun.cfg
data/defaultNexuiz.cfg
data/maps/aggressor.mapinfo
data/maps/aneurysm.mapinfo
data/maps/basement.mapinfo
data/maps/bleach.mapinfo
data/maps/darkzone.mapinfo
data/maps/desertfactory.mapinfo
data/maps/dieselpower.mapinfo
data/maps/downer.mapinfo
data/maps/eggandbacon.mapinfo
data/maps/evilspace.mapinfo
data/maps/farewell.mapinfo
data/maps/final_rage.mapinfo
data/maps/reslimed.mapinfo
data/maps/ruiner.mapinfo
data/maps/runningman.mapinfo
data/maps/runningman_1on1remix.mapinfo
data/maps/skyway.mapinfo
data/maps/slimepit.mapinfo
data/maps/soylent.mapinfo
data/maps/starship.mapinfo
data/maps/stormkeep.mapinfo
data/maps/stormkeep2.mapinfo
data/maps/strength.mapinfo
data/maps/toxic.mapinfo
data/maps/warfare.mapinfo
data/qcsrc/client/Main.qc
data/qcsrc/client/sbar.qc
data/qcsrc/common/constants.qh
data/qcsrc/common/mapinfo.qc
data/qcsrc/common/mapinfo.qh
data/qcsrc/common/util.qc
data/qcsrc/menu/nexuiz/dialog_multiplayer_create.c
data/qcsrc/menu/nexuiz/dialog_multiplayer_create_mapinfo.c
data/qcsrc/server/arena.qc
data/qcsrc/server/cl_client.qc
data/qcsrc/server/cl_player.qc
data/qcsrc/server/clientcommands.qc
data/qcsrc/server/constants.qh
data/qcsrc/server/defs.qh
data/qcsrc/server/g_damage.qc
data/qcsrc/server/g_world.qc
data/qcsrc/server/scores.qc
data/qcsrc/server/t_items.qc
data/qcsrc/server/teamplay.qc

index f630366..f50cc72 100644 (file)
@@ -159,7 +159,7 @@ set g_balance_fuel_limit 999
 // }}}
 
 // {{{ misc
-set g_balance_selfdamagepercent 1
+set g_balance_selfdamagepercent 0.75
 set g_balance_weaponswitchdelay 0.1
 set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
 set g_weaponratefactor 1 "weapon fire rate multiplier"
@@ -424,7 +424,7 @@ set g_balance_hagar_secondary_ammo 1
 //   {{{ rocketlauncher
 set g_balance_rocketlauncher_damage 90
 set g_balance_rocketlauncher_edgedamage 30
-set g_balance_rocketlauncher_force 400
+set g_balance_rocketlauncher_force 350
 set g_balance_rocketlauncher_radius 110
 set g_balance_rocketlauncher_speed 1000
 set g_balance_rocketlauncher_speedaccel 0
index 2b2c1aa..4864e02 100644 (file)
@@ -563,6 +563,8 @@ set g_tdm_team_spawns 0 "when 1, a map can define team spawnpoints for TDM"
 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"
+
 // dm
 set g_dm 1 "Deathmatch: killing any other player is one frag, player with most frags wins"
 set gamecfg 1  // "deathmatch"
index d0dc9c7..3ec63e5 100644 (file)
@@ -13,3 +13,4 @@ type arena 10 20
 type kh 1000 20 3
 type rc 20 5 10 20
 cdtrack 4
+type ca 10 20
index f56b610..139cc3d 100644 (file)
@@ -12,3 +12,4 @@ type arena 10 20
 type kh 1000 30 2
 type tdm 50 20 2
 cdtrack 6
+type ca 10 20
index 0d6aec4..6066ff8 100644 (file)
@@ -10,3 +10,4 @@ type rune 200 20
 type lms 9 20
 type arena 10 20
 cdtrack 4
+type ca 10 20
index 8c7af83..a01d0cb 100644 (file)
@@ -11,3 +11,4 @@ type rune 200 20
 type lms 9 20
 type kh 1000 20 3
 cdtrack 8
+type ca 10 20
index d155763..286a9f6 100644 (file)
@@ -10,3 +10,4 @@ type rune 200 20
 type lms 9 20
 type arena 10 20
 cdtrack 8
+type ca 10 20
index b95b83f..d1bb658 100644 (file)
@@ -8,3 +8,4 @@ type tdm 30 20 2
 type lms 9 20
 type arena 10 20
 type kh 1000 20 2
+type ca 10 20
index 6db2543..01b8334 100644 (file)
@@ -11,3 +11,4 @@ type rune 200 20
 type lms 9 20
 type kh 1000 20 3
 cdtrack 15
+type ca 10 20
index 137b47a..9f214c0 100644 (file)
@@ -11,3 +11,4 @@ type rune 200 20
 type lms 9 20
 type arena 10 20
 cdtrack 8
+type ca 10 20
index bf90e01..f4c6cca 100644 (file)
@@ -9,3 +9,4 @@ type dm 30 20
 type lms 16 20
 type arena 10 20
 type ctf 300 20
+type ca 10 20
index 9953aaf..376f8b1 100644 (file)
@@ -8,3 +8,4 @@ type dm 30 20
 type lms 9 20
 type arena 10 20
 cdtrack 7
+type ca 10 20
index aae9675..33b9f2b 100644 (file)
@@ -11,3 +11,4 @@ type lms 9 20
 type arena 10 20
 cdtrack 5
 size -1536 -832 -576 896 1152 768
+type ca 10 20
index 8c0a022..8e513c0 100644 (file)
@@ -11,3 +11,4 @@ type rune 200 20
 type lms 9 20
 type arena 10 20
 cdtrack 7
+type ca 10 20
index badcf6c..3093d00 100644 (file)
@@ -10,3 +10,4 @@ type dom 200 20
 type rune 200 20
 type lms 9 20
 cdtrack 4
+type ca 10 20
index 43ac8af..7781165 100644 (file)
@@ -12,3 +12,4 @@ type arena 10 20
 cdtrack 11
 clientsettemp_for_type all r_shadow_glossexponent 96
 clientsettemp_for_type all r_shadow_glossintensity 2
+type ca 10 20
index 9caf57e..2979501 100644 (file)
@@ -11,3 +11,4 @@ type rune 200 20
 type lms 9 20
 type arena 10 20
 cdtrack 2
+type ca 10 20
index 0dcc54c..56195c2 100644 (file)
@@ -12,3 +12,4 @@ type lms 9 20
 type arena 10 20
 type kh 1000 20 3
 cdtrack 2
+type ca 10 20
index 8d219ae..20ad5e0 100644 (file)
@@ -11,3 +11,4 @@ type lms 9 20
 type arena 10 20
 type kh 1000 20 3
 cdtrack 9
+type ca 10 20
index 005dab2..9a0c796 100644 (file)
@@ -10,3 +10,4 @@ type rune 200 20
 type lms 9 20
 type arena 10 20
 cdtrack 4
+type ca 10 20
index d81773c..bd588ae 100644 (file)
@@ -11,3 +11,4 @@ type rune 200 20
 type lms 9 20
 type arena 10 20
 cdtrack 14
+type ca 10 20
index ea5e179..7c2d2a6 100644 (file)
@@ -10,3 +10,4 @@ type rune 200 20
 type lms 9 20
 type arena 10 20
 cdtrack 16
+type ca 10 20
index eccf2e4..2304133 100644 (file)
@@ -13,3 +13,4 @@ type arena 10 20
 type kh 1000 20 3
 type tdm 50 20 2
 cdtrack 6
+type ca 10 20
index 3a826de..670425c 100644 (file)
@@ -12,3 +12,4 @@ type arena 10 20
 type kh 1000 20 3
 type tdm 50 20 2
 cdtrack 6
+type ca 10 20
index cdbae1e..6ef14e6 100644 (file)
@@ -11,3 +11,4 @@ type lms 9 20
 type arena 10 20
 type tdm 50 20 2
 cdtrack 5
+type ca 10 20
index dedfeba..3d3b3de 100644 (file)
@@ -11,3 +11,4 @@ type rune 200 20
 type lms 9 20
 type arena 10 20
 cdtrack 3
+type ca 10 20
index 8b3668e..1cc3ef6 100644 (file)
@@ -11,3 +11,4 @@ type tdm 50 20 2
 type lms 9 20
 type arena 10 20
 cdtrack 6
+type ca 10 20
index a47da34..e8e1410 100644 (file)
@@ -1050,6 +1050,11 @@ void Net_ReadSpawn()
        current_viewzoom = 0.6;
 }
 
+void Net_TeamNagger()
+{
+       teamnagger = 1;
+}
+
 // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
 // You must ALWAYS first acquire the temporary ID, which is sent as a byte.
 // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
@@ -1088,6 +1093,10 @@ float CSQC_Parse_TempEntity()
                        Net_ReadNexgunBeamParticle();
                        bHandled = true;
                        break;
+               case TE_CSQC_TEAMNAGGER:
+                       Net_TeamNagger();
+                       bHandled = true;
+                       break;
         case TE_CSQC_LIGHTNINGARC:
             Net_ReadLightningarc();
             bHandled = true;
index 5e4ea28..83bbe75 100644 (file)
@@ -1,6 +1,8 @@
 void drawstringright(vector, string, vector, vector, float, float);
 void drawstringcenter(vector, string, vector, vector, float, float);
 
+float teamnagger;
+
 float weapon_hits[WEP_COUNT];
 float weapon_fired[WEP_COUNT];
 float weapon_number;
@@ -2598,7 +2600,7 @@ void Sbar_Draw (void)
                        o = Sbar_DrawNoteLine(o, s);
                }
        }
-       if(teamplay && !intermission && !spectatee_status)
+       if(teamplay && !intermission && !spectatee_status && gametype != GAME_CA && teamnagger)
        {
                entity tm;
                float ts_min, ts_max;
index f4d554c..4e9fe23 100644 (file)
@@ -38,6 +38,7 @@ const float GAME_ONSLAUGHT    = 10;
 const float GAME_RACE  = 11;
 const float GAME_NEXBALL = 12;
 const float GAME_CTS = 13;
+const float GAME_CA            = 14;
 
 const float AS_STRING          = 1;
 const float AS_INT             = 2;
@@ -50,6 +51,7 @@ const float TE_CSQC_SPAWN = 102;
 const float TE_CSQC_ZCURVEPARTICLES = 103;
 const float TE_CSQC_NEXGUNBEAMPARTICLE = 104;
 const float TE_CSQC_LIGHTNINGARC = 105;
+const float TE_CSQC_TEAMNAGGER = 106;
 
 const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
 const float RACE_NET_CHECKPOINT_CLEAR = 1;
index c6fa792..a438bcf 100644 (file)
@@ -405,8 +405,10 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
                MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_RUNEMATCH;       // Rune always works
                MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_LMS;             // LMS always works
 
-               if(spawnpoints >= 8  && diameter > 4096)
+               if(spawnpoints >= 8  && diameter > 4096) {
                        MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_TEAM_DEATHMATCH;
+                       MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_CA;
+               }
                if(                     diameter < 4096)
                        MapInfo_Map_supportedGametypes |= MAPINFO_TYPE_ARENA;
                if(spawnpoints >= 12 && diameter > 5120)
@@ -525,6 +527,7 @@ float MapInfo_Type_FromString(string t)
        else if(t == "rune")    return MAPINFO_TYPE_RUNEMATCH;
        else if(t == "lms")     return MAPINFO_TYPE_LMS;
        else if(t == "arena")   return MAPINFO_TYPE_ARENA;
+       else if(t == "ca")      return MAPINFO_TYPE_CA;
        else if(t == "kh")      return MAPINFO_TYPE_KEYHUNT;
        else if(t == "as")      return MAPINFO_TYPE_ASSAULT;
        else if(t == "ons")     return MAPINFO_TYPE_ONSLAUGHT;
@@ -699,6 +702,7 @@ float MapInfo_Get_ByName(string pFilename, float pAllowGenerate, float pGametype
                if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_RUNEMATCH)       fputs(fh, "type rune 200 20\n");
                if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_LMS)             fputs(fh, "type lms 9 20\n");
                if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_ARENA)           fputs(fh, "type arena 10 20\n");
+               if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_CA)              fputs(fh, "type ca 10 20\n");
                if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_KEYHUNT)         fputs(fh, "type kh 1000 20 3\n");
                if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_ASSAULT)         fputs(fh, "type as 20\n");
                if(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_RACE)            fputs(fh, "type rc 20 5 7 15\n");
@@ -966,6 +970,8 @@ float MapInfo_CurrentGametype()
                return MAPINFO_TYPE_LMS;
        else if(cvar("g_arena"))
                return MAPINFO_TYPE_ARENA;
+       else if(cvar("g_ca"))
+               return MAPINFO_TYPE_CA; 
        else if(cvar("g_keyhunt"))
                return MAPINFO_TYPE_KEYHUNT;
        else if(cvar("g_onslaught"))
@@ -1010,6 +1016,7 @@ string MapInfo_GetGameTypeCvar(float t)
                case MAPINFO_TYPE_RUNEMATCH: return "g_runematch";
                case MAPINFO_TYPE_LMS: return "g_lms";
                case MAPINFO_TYPE_ARENA: return "g_arena";
+               case MAPINFO_TYPE_CA: return "g_ca";
                case MAPINFO_TYPE_KEYHUNT: return "g_kh";
                case MAPINFO_TYPE_ASSAULT: return "g_assault";
                case MAPINFO_TYPE_ONSLAUGHT: return "g_onslaught";
@@ -1030,6 +1037,7 @@ void MapInfo_SwitchGameType(float t)
        cvar_set("g_runematch",  (t == MAPINFO_TYPE_RUNEMATCH)       ? "1" : "0");
        cvar_set("g_lms",        (t == MAPINFO_TYPE_LMS)             ? "1" : "0");
        cvar_set("g_arena",      (t == MAPINFO_TYPE_ARENA)           ? "1" : "0");
+       cvar_set("g_ca",         (t == MAPINFO_TYPE_CA)              ? "1" : "0");
        cvar_set("g_keyhunt",    (t == MAPINFO_TYPE_KEYHUNT)         ? "1" : "0");
        cvar_set("g_assault",    (t == MAPINFO_TYPE_ASSAULT)         ? "1" : "0");
        cvar_set("g_onslaught",  (t == MAPINFO_TYPE_ONSLAUGHT)       ? "1" : "0");
index 7c06a98..a8cd7a2 100644 (file)
@@ -11,7 +11,8 @@ float MAPINFO_TYPE_ARENA                      = 512;
 float MAPINFO_TYPE_KEYHUNT                     = 1024;
 float MAPINFO_TYPE_NEXBALL          = 2048;
 float MAPINFO_TYPE_CTS              = 4096;
-float MAPINFO_TYPE_ALL              = 65535; // this has to include all above bits
+float MAPINFO_TYPE_CA                          = 8192;
+float MAPINFO_TYPE_ALL              = 16383; // this has to include all above bits
 
 float MAPINFO_FEATURE_WEAPONS       = 1; // not defined for minstagib-only maps
 
index dcae85e..b2ad966 100644 (file)
@@ -462,6 +462,7 @@ string GametypeNameFromType(float g)
        else if (g == GAME_RUNEMATCH) return "rune";
        else if (g == GAME_LMS) return "lms";
        else if (g == GAME_ARENA) return "arena";
+       else if (g == GAME_CA) return "ca";
        else if (g == GAME_KEYHUNT) return "kh";
        else if (g == GAME_ONSLAUGHT) return "ons";
        else if (g == GAME_ASSAULT) return "as";
index 768228d..65f4c1d 100644 (file)
@@ -51,6 +51,8 @@ void fillNexuizServerCreateTab(entity me)
                        if(e.checked) e0 = NULL;
                me.TD(me, 1, me.columns / n, e = makeNexuizGametypeButton(1, "g_ctf", "CTF"));
                        if(e.checked) e0 = NULL;
+               me.TD(me, 1, me.columns / n, e = makeNexuizGametypeButton(1, "g_ca", "CA"));
+                       if(e.checked) e0 = NULL;
                me.TD(me, 1, me.columns / n, e = makeNexuizGametypeButton(1, "g_domination", "Domination"));
                        if(e.checked) e0 = NULL;
                me.TD(me, 1, me.columns / n, e = makeNexuizGametypeButton(1, "g_keyhunt", "Key Hunt"));
index 845962d..6f3f506 100644 (file)
@@ -22,6 +22,7 @@ CLASS(NexuizMapInfoDialog) EXTENDS(NexuizDialog)
        ATTRIB(NexuizMapInfoDialog, typeDominationLabel, entity, NULL)
        ATTRIB(NexuizMapInfoDialog, typeKeyHuntLabel, entity, NULL)
        ATTRIB(NexuizMapInfoDialog, typeCTFLabel, entity, NULL)
+       ATTRIB(NexuizMapInfoDialog, typeCALabel, entity, NULL)
        ATTRIB(NexuizMapInfoDialog, typeAssaultLabel, entity, NULL)
        ATTRIB(NexuizMapInfoDialog, typeOnslaughtLabel, entity, NULL)
        ATTRIB(NexuizMapInfoDialog, typeRaceLabel, entity, NULL)
@@ -76,6 +77,7 @@ void loadMapInfoNexuizMapInfoDialog(entity me, float i, entity mlb)
        me.typeRuneLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_RUNEMATCH);
        me.typeKeyHuntLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_KEYHUNT);
        me.typeCTFLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_CTF);
+       me.typeCALabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_CA);
        me.typeAssaultLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_ASSAULT);
        me.typeOnslaughtLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_ONSLAUGHT);
        me.typeRaceLabel.disabled = !(MapInfo_Map_supportedGametypes & MAPINFO_TYPE_RACE);
@@ -132,6 +134,8 @@ void fillNexuizMapInfoDialog(entity me)
                        me.typeKeyHuntLabel = e;
                me.TD(me, 1, wgt, e = makeNexuizTextLabel(0, "CTF"));
                        me.typeCTFLabel = e;
+               me.TD(me, 1, wgt, e = makeNexuizTextLabel(0, "CA"));
+                       me.typeCALabel = e;
                me.TD(me, 1, wgt, e = makeNexuizTextLabel(0, "Assault"));
                        me.typeAssaultLabel = e;
                me.TD(me, 1, wgt, e = makeNexuizTextLabel(0, "Onslaught"));
index 9d96a51..bdb918c 100644 (file)
@@ -9,6 +9,9 @@ entity spawnqueue_first;
 entity spawnqueue_last;
 entity champion;
 float warmup;
+float allowed_to_spawn;
+float player_cnt;
+.float caplayer;
 
 void PutObserverInServer();
 void PutClientInServer();
@@ -29,10 +32,13 @@ void reset_map(float dorespawn)
        entity oldself;
        oldself = self;
 
-       if(g_arena)
+       if(g_arena || g_ca)
        if(cvar("g_arena_warmup"))
                warmup = time + cvar("g_arena_warmup");
 
+       if(g_ca)
+               allowed_to_spawn = 1;
+
        lms_lowest_lives = 999;
        lms_next_place = player_count;
 
@@ -81,6 +87,10 @@ void reset_map(float dorespawn)
                                else
                                        PutObserverInServer();
                        }
+                       else if(g_ca && self.caplayer) {
+                               self.classname = "player";
+                               PutClientInServer();
+                       }
                        else
                        {
                                /*
@@ -111,8 +121,8 @@ 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)
-       if(champion)
+       if(g_arena || g_ca)
+       if(champion && champion.classname == "player" && player_cnt > 1)
                UpdateFrags(champion, +1);
 
        self = oldself;
@@ -175,50 +185,73 @@ void Spawnqueue_Mark(entity e)
  * 
  * Called in PlayerPostThink()
  */
+float roundStartTime_prev; // prevent networkspam
 void Arena_Warmup()
 {
        float f;
        string msg;
 
-       if(!g_arena || !arena_roundbased || (time < game_starttime))
+       if((!g_arena && !g_ca) || !arena_roundbased || (time < game_starttime))
                return;
 
-       f = rint(warmup - time);
+       f = floor(warmup - time + 1);
+
+       allowed_to_spawn = 0;
+
+       if(g_ca && player_cnt < 2)
+               allowed_to_spawn = 1;
 
        msg = NEWLINES;
-       if(time < warmup && self.spawned)
+       if(time < warmup)
        {
-               if(champion)
-                       msg = strcat(msg, "The Champion is ", champion.netname, "^7\n");
+               if (g_ca)
+                       allowed_to_spawn = 1;
+               if(champion && !(g_ca))
+                       centerprint(self, strcat(msg, "The Champion is ", champion.netname, "^7\n"));
+
+               if(f != roundStartTime_prev) {
+                       centerprint(self, strcat("Round will start in ", ftos(f),"\n"));
+                       roundStartTime_prev = f;
+                       if(f == 5)
+                               play2all("announcer/robotic/prepareforbattle.wav");
+                       else if(f == 3)
+                               play2all("announcer/robotic/3.wav");
+                       else if(f == 2)
+                               play2all("announcer/robotic/2.wav");
+                       else if(f == 1)
+                               play2all("announcer/robotic/1.wav");
+               }
 
-               if(f)
-                       msg = strcat(msg, "Round will start in ", ftos(f),"\n");
-               else
-               {
+               if (!g_ca) {
                        if(self.spawned)
-                               msg = strcat(msg, "^1Fight!\n");
+                               self.movetype = MOVETYPE_NONE;
+
+                       self.velocity = '0 0 0';
+                       self.avelocity = '0 0 0';
+                       self.movement = '0 0 0';
+                       //self.fixangle = TRUE;
                }
+       }
 
-               centerprint(self, msg);
+       else if((!g_ca && self.movetype == MOVETYPE_NONE) || ((g_ca && f > -1 && f != roundStartTime_prev)))
+       {
+               if(self.classname == "player")
+                       self.movetype = MOVETYPE_WALK;
+               centerprint(self, "^1Fight!\n");        
+               roundStartTime_prev = f;
+               play2all("announcer/robotic/begin.wav");
 
-               if(self.spawned)
-                       self.movetype = MOVETYPE_NONE;
+               player_cnt = 0;
 
-               self.velocity = '0 0 0';
-               self.avelocity = '0 0 0';
-               self.movement = '0 0 0';
-               //self.fixangle = TRUE;
-       }
-       else if(self.movetype == MOVETYPE_NONE)
-       {
-               self.movetype = MOVETYPE_WALK;
-               centerprint(self, "\n");
+               FOR_EACH_CLIENT(self) {
+                       if (self.classname == "player") {
+                               player_cnt += 1;
+                       }
+               }               
        }
-
 }
 
 float next_round;
-
 /**
  * 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
@@ -231,34 +264,83 @@ void Spawnqueue_Check()
        if(time < warmup + 1)
                return;
 
-       //extend next_round if it isn't set yet and only 1 player is spawned
-       if(!next_round)
-       if(numspawned < 2)
-               next_round = time + 3;
+       if(g_ca) {
+               // check the amount of spawned players in each team
+               float redspawned, bluespawned;
+               FOR_EACH_CLIENT(self) {
+                       if (self.classname == "player") {
+                               if (self.team == COLOR_TEAM1) redspawned += 1;
+                               else if (self.team == COLOR_TEAM2) bluespawned += 1;
+                       }
+               }
 
-       if(!arena_roundbased || (next_round && next_round < time && player_count > 1))
-       {
-               next_round = 0;
+               if(player_cnt < 2 && (redspawned && bluespawned)) {
+                       reset_map(TRUE);
+               }
+               else if(player_cnt < 2) {
+                       FOR_EACH_CLIENT(self) 
+                       if(self.classname == "player")
+                               centerprint(self, strcat("^1Need at least 2 players to play CA", "^7\n"));
 
-               if(arena_roundbased)
+                       allowed_to_spawn = 1;
+                       return;
+               }
+               else if(!next_round)
+                       if((redspawned && bluespawned == 0) || (bluespawned && redspawned == 0)) {
+                               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"));   
+                       else if(!redspawned && !bluespawned) {
+                               FOR_EACH_CLIENT(self) centerprint(self, strcat("^7Round tied.", "^7\n"));
+                               next_round = time + 5;
+                       }
+               }
+
+               if((next_round && next_round < time))
                {
-                       champion = find(world, classname, "player");
-                       while(champion && champion.deadflag)
-                               champion = find(champion, classname, "player");
+                       next_round = 0;
                        reset_map(TRUE);
                }
+       } else { // arena
+               //extend next_round if it isn't set yet and only 1 player is spawned
+               if(!next_round)
+               if(numspawned < 2)
+                       next_round = time + 3;
 
-               while(numspawned < maxspawned && spawnqueue_first)
+               if(!arena_roundbased || (next_round && next_round < time && player_count > 1))
                {
-                       self = spawnqueue_first;
+                       next_round = 0;
 
-                       bprint ("^4", self.netname, "^4 is the next challenger\n");
+                       if(arena_roundbased)
+                       {
+                               champion = find(world, classname, "player");
+                               while(champion && champion.deadflag)
+                                       champion = find(champion, classname, "player");
+                               reset_map(TRUE);
+                       }
 
-                       Spawnqueue_Remove(self);
-                       Spawnqueue_Mark(self);
+                       while(numspawned < maxspawned && spawnqueue_first)
+                       {
+                               self = spawnqueue_first;
 
-                       self.classname = "player";
-                       PutClientInServer();
+                               bprint ("^4", self.netname, "^4 is the next challenger\n");
+
+                               Spawnqueue_Remove(self);
+                               Spawnqueue_Mark(self);
+
+                               self.classname = "player";
+                               PutClientInServer();
+                       }
                }
        }
 }
index 7d9d077..da1e834 100644 (file)
@@ -1,5 +1,10 @@
 void race_send_recordtime(float t, float msg);
 
+void send_CSQC_teamnagger() {
+       WriteByte(0, SVC_TEMPENTITY);
+       WriteByte(0, TE_CSQC_TEAMNAGGER);
+}
+
 float ClientData_Send(entity to, float sf)
 {
        if(to != self.owner)
@@ -316,7 +321,7 @@ entity SelectSpawnPoint (float anypoint)
                // there is 50/50 chance of choosing a random spot or the furthest spot
                // (this means that roughly every other spawn will be furthest, so you
                // usually won't get fragged at spawn twice in a row)
-               if (arena_roundbased)
+               if (arena_roundbased && !g_ca)
                {
                        firstspot_new = Spawn_FilterOutBadSpots(firstspot, playerlist, 800, teamcheck);
                        if(firstspot_new)
@@ -638,7 +643,11 @@ void PutObserverInServer (void)
        if(sv_loddistance1)
                SetCustomizer(self, Client_customizeentityforclient, Client_uncustomizeentityforclient);
 
-       self.team = -1;
+       if(g_ca) {
+               // do nothing
+       }
+       else
+               self.team = -1;
 
        if(g_arena)
        {
@@ -785,14 +794,14 @@ void PutClientInServer (void)
                        self.classname = "observer";
        }
 
-       if(g_arena)
+       if(g_arena || (g_ca && !allowed_to_spawn))
        if(!self.spawned)
                self.classname = "observer";
 
        if(gameover)
                self.classname = "observer";
 
-       if(self.classname == "player") {
+       if(self.classname == "player" && (!g_ca || (g_ca && allowed_to_spawn))) {
                entity spot, oldself;
                float j;
 
@@ -936,6 +945,9 @@ void PutClientInServer (void)
                        Spawnqueue_Mark(self);
                }
 
+               else if(g_ca)
+                       self.caplayer = 1;
+
                self.event_damage = PlayerDamage;
 
                self.bot_attack = TRUE;
@@ -993,7 +1005,7 @@ void PutClientInServer (void)
                                SUB_UseTargets();
                        activator = world;
                self = oldself;
-       } else if(self.classname == "observer") {
+       } else if(self.classname == "observer" || (g_ca && !allowed_to_spawn)) {
                PutObserverInServer ();
        }
 
@@ -1406,10 +1418,11 @@ void ClientConnect (void)
 
        stuffcmd(self, strcat("set gametype ", ftos(game), "\n"));
 
-       if(g_arena)
+       if(g_arena || g_ca)
        {
                self.classname = "observer";
-               Spawnqueue_Insert(self);
+               if(g_arena)
+                       Spawnqueue_Insert(self);
        }
        /*else if(g_ctf)
        {
@@ -1473,6 +1486,8 @@ void ClientConnect (void)
                speedaward_alltimebest_holder = db_get(ServerProgsDB, strcat(GetMapname(), rr, "speed/netname"));
                race_send_speedaward_alltimebest(MSG_ONE);
        }
+       else if(cvar("sv_teamnagger"))
+               send_CSQC_teamnagger();
 }
 
 /*
@@ -2140,7 +2155,10 @@ void LeaveSpectatorMode()
                                centerprint(self,""); // clear MOTD
                        return;
                } else {
-                       stuffcmd(self,"menu_showteamselect\n");
+                       if (g_ca && self.caplayer) {
+                       }       // do nothing
+                       else
+                               stuffcmd(self,"menu_showteamselect\n");
                        return;
                }
        }
@@ -2430,7 +2448,7 @@ void PlayerPreThink (void)
                                if(frametime)
                                        player_anim();
                                button_pressed = (self.BUTTON_ATCK || self.BUTTON_JUMP || self.BUTTON_ATCK2 || self.BUTTON_HOOK || self.BUTTON_USE);
-                               force_respawn = (g_lms || cvar("g_forced_respawn"));
+                               force_respawn = (g_lms || (g_ca) || cvar("g_forced_respawn"));
                                if (self.deadflag == DEAD_DYING)
                                {
                                        if(force_respawn)
index 5870832..457f5da 100644 (file)
@@ -475,8 +475,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
        else
                Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
 
-       if(g_arena)
-       if(numspawned < 2)
+       if(g_arena && numspawned < 2)
                return;
 
        if (!g_minstagib)
index 3b3eb2e..5f0bfd1 100644 (file)
@@ -257,6 +257,8 @@ void SV_ParseClientCommand(string s) {
                        kh_Key_DropAll(self, TRUE);
                        WaypointSprite_PlayerDead();
                        self.classname = "observer";
+                       if(g_ca)
+                               self.caplayer = 0;
                        if(blockSpectators)
                                sprint(self, strcat("^7You have to become a player within the next ", ftos(cvar("g_maxplayers_spectator_blocktime")), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n"));
                        PutClientInServer();
@@ -269,6 +271,8 @@ void SV_ParseClientCommand(string s) {
                {
                        if(isJoinAllowed()) {
                                self.classname = "player";
+                               if(g_ca)
+                                       self.caplayer = 1;
                                PlayerScore_Clear(self);
                                bprint ("^4", self.netname, "^4 is playing now\n");
                                PutClientInServer();
@@ -813,7 +817,8 @@ void ReadyRestartForce()
 void ReadyRestart()
 {
        // no arena, assault support yet...
-       if(g_arena | g_assault | gameover | intermission_running | race_completing)
+       // TODO: CA support
+       if(g_arena | g_ca | g_assault | gameover | intermission_running | race_completing)
                localcmd("restart\n");
        else
                localcmd("\nsv_hook_gamerestart;");
index e1460f8..867e3b8 100644 (file)
@@ -1,4 +1,4 @@
-string CVAR_CHECK_DEFAULT = "9ede7a7edae0b7ae4c8b7e6517293a6a";
+string CVAR_CHECK_DEFAULT = "489314f0011ead8255994194a02ab81a";
 string CVAR_CHECK_BALANCE = "729b07b9caa8a86c08841a0f4275e97d";
 
 float  FALSE                                   = 0;
index e4986a6..eb1e682 100644 (file)
@@ -17,7 +17,7 @@ float require_spawnfunc_prefix; // if this float exists, only functions with spa
 
 float ctf_score_value(string parameter);
 
-float g_dm, g_domination, g_ctf, g_tdm, g_keyhunt, g_onslaught, g_assault, g_arena, g_lms, g_runematch, g_race, g_nexball, g_cts;
+float g_dm, g_domination, g_ctf, g_tdm, g_keyhunt, g_onslaught, g_assault, g_arena, g_ca, g_lms, g_runematch, g_race, g_nexball, g_cts;
 float g_cloaked, g_footsteps, g_jump_grunt, g_grappling_hook, g_laserguided_missile, g_midair, g_minstagib, g_nixnex, g_nixnex_with_laser, g_pinata, g_norecoil, g_vampire, g_minstagib_invis_alpha, g_bloodloss;
 float g_warmup_limit;
 float g_warmup_allguns;
index f1d9279..bbbf914 100644 (file)
@@ -121,7 +121,7 @@ void GiveFrags (entity attacker, entity targ, float f)
 
        PlayerScore_Add(targ, SP_DEATHS, 1);
 
-       if(g_arena)
+       if(g_arena || g_ca)
                if(cvar("g_arena_roundbased"))
                        return;
 
index 7c4bc39..7687b9a 100644 (file)
@@ -243,6 +243,7 @@ void cvar_changes_init()
                BADCVAR("timelimit");
                BADCVAR("fraglimit");
                BADCVAR("g_arena");
+               BADCVAR("g_ca");
                BADCVAR("g_assault");
                BADCVAR("g_ctf");
                BADCVAR("g_dm");
@@ -1205,7 +1206,7 @@ void DumpStats(float final)
                {
                        s = strcat(":player:see-labels:", GetPlayerScoreString(other, 0), ":");
                        s = strcat(s, ftos(rint(time - other.jointime)), ":");
-                       if(other.classname == "player" || g_arena || g_lms)
+                       if(other.classname == "player" || g_arena || g_ca || g_lms)
                                s = strcat(s, ftos(other.team), ":");
                        else
                                s = strcat(s, "spectator:");
@@ -1702,7 +1703,7 @@ float WinningCondition_Scores(float limit, float leadlimit)
        if(WinningConditionHelper_zeroisworst)
                leadlimit = 0; // not supported in this mode
 
-       if(g_dm || g_tdm || g_arena || (g_race && !g_race_qualifying) || g_nexball)
+       if(g_dm || g_tdm || g_arena || g_ca || (g_race && !g_race_qualifying) || g_nexball)
        // these modes always score in increments of 1, thus this makes sense
        {
                if(leaderfrags != WinningConditionHelper_topscore)
index 90c2f57..30adf39 100644 (file)
@@ -246,7 +246,7 @@ void PlayerScore_Clear(entity player)
        if(teamscores_entities_count)
                return;
        if(g_lms) return;
-       if(g_arena) return;
+       if(g_arena || g_ca) return;
        if(g_race && !g_race_qualifying) return;
 
        sk = player.scorekeeper;
@@ -496,12 +496,12 @@ void WinningConditionHelper()
                                s = strcat(s, ":human");
                        else
                                s = strcat(s, ":bot");
-                       if(p.classname != "player" && !g_arena && !g_lms)
+                       if(p.classname != "player" && !g_arena && !g_ca && !g_lms)
                                s = strcat(s, ":spectator");
                }
                else
                {
-                       if(p.classname == "player" || g_arena || g_lms)
+                       if(p.classname == "player" || g_arena || g_ca || g_lms)
                                s = GetPlayerScoreString(p, 2);
                        else
                                s = "-666";
index 1f30ca7..a1b22b2 100644 (file)
@@ -1270,7 +1270,7 @@ void spawnfunc_item_health_mega (void) {
        if(!cvar("g_powerup_superhealth"))
                return;
 
-       if(g_arena && !cvar("g_arena_powerups"))
+       if((g_arena || g_ca) && !cvar("g_arena_powerups"))
                return;
 
        if(g_minstagib) {
@@ -1295,7 +1295,7 @@ void spawnfunc_item_strength (void) {
        if(!cvar("g_powerup_strength"))
                return;
 
-       if(g_arena && !cvar("g_arena_powerups"))
+       if((g_arena || g_ca) && !cvar("g_arena_powerups"))
                return;
 
        if(g_minstagib) {
@@ -1311,7 +1311,7 @@ void spawnfunc_item_invincible (void) {
        if(!cvar("g_powerup_shield"))
                return;
 
-       if(g_arena && !cvar("g_arena_powerups"))
+       if((g_arena || g_ca) && !cvar("g_arena_powerups"))
                return;
 
        if(g_minstagib) {
index 387a6b2..c20e3a4 100644 (file)
@@ -93,6 +93,7 @@ void WriteGameCvars()
        cvar_set("g_runematch", ftos(g_runematch));
        cvar_set("g_lms", ftos(g_lms));
        cvar_set("g_arena", ftos(g_arena));
+       cvar_set("g_ca", ftos(g_ca));
        cvar_set("g_keyhunt", ftos(g_keyhunt));
        cvar_set("g_assault", ftos(g_assault));
        cvar_set("g_onslaught", ftos(g_onslaught));
@@ -118,6 +119,7 @@ void ReadGameCvars()
                found += (g_runematch = (!found && (prev != GAME_RUNEMATCH) && cvar("g_runematch")));
                found += (g_lms = (!found && (prev != GAME_LMS) && cvar("g_lms")));
                found += (g_arena = (!found && (prev != GAME_ARENA) && cvar("g_arena")));
+               found += (g_ca = (!found && (prev != GAME_CA) && cvar("g_ca")));
                found += (g_keyhunt = (!found && (prev != GAME_KEYHUNT) && cvar("g_keyhunt")));
                found += (g_assault = (!found && (prev != GAME_ASSAULT) && cvar("g_assault")));
                found += (g_onslaught = (!found && (prev != GAME_ONSLAUGHT) && cvar("g_onslaught")));
@@ -282,10 +284,12 @@ void InitGameplayMode()
                ScoreRules_lms();
        }
 
-       if(g_arena)
+       if(g_arena || g_ca)
        {
                game = GAME_ARENA;
                gamemode_name = "Arena";
+               if(g_ca)
+                       ActivateTeamplay();
                fraglimit_override = cvar("g_arena_point_limit");
                leadlimit_override = cvar("g_arena_point_leadlimit");
                maxspawned = cvar("g_arena_maxspawned");