// allow fullbright
set sv_allow_fullbright 0 "when set, clients may use r_fullbright on this server without getting a night vision effect overlay"
+// auto-teams (team selection by player ID)
+// any player not listed is forced to spectate
+set g_forced_team_red "" "list of player IDs for red team"
+set g_forced_team_blue "" "list of player IDs for blue team"
+set g_forced_team_yellow "" "list of player IDs for yellow team"
+set g_forced_team_pink "" "list of player IDs for pink team"
+set g_forced_team_otherwise "default" "action if a non listed player joins (can be default for default action, spectate for forcing to spectate, or red, blue, yellow, pink)"
+
// other config files
exec balanceXonotic.cfg
exec ctfscoring-ai.cfg
stretchfactor 0.1
-
-// crylink linkjoin effect
+// crylink joinexplode effect
// decal
-// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("crylink_linkjoin"), org2, '0 0 0', 1)
-effect crylink_linkjoin
+// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("crylink_joinexplode"), org2, '0 0 0', 1)
+effect crylink_joinexplode
countabsolute 1
type decal
tex 47 47
-size 8 8
+size 24 24
alpha 256 256 0
originjitter 12 12 12
-//lightradius 60
-//lightradiusfade 300
+//lightradius 200
+//lightradiusfade 800
//lightcolor 3.2 0.4 4
// purple flare effect
-effect crylink_linkjoin
+effect crylink_joinexplode
countabsolute 1
type static
tex 39 39
color 0x504060 0x504060
-size 8 8
+size 24 24
alpha 256 256 512
// purple sparks
-effect crylink_linkjoin
-count 10
+effect crylink_joinexplode
+count 40
type spark
tex 41 41
color 0xA040C0 0xA040C0
bounce 2
-size 1 2
+size 6 6
alpha 256 256 1024
-velocityjitter 256 256 256
+velocityjitter 512 512 512
// purple splash
-effect crylink_linkjoin
+effect crylink_joinexplode
count 1.5
type static
color 0xE070FF 0xE070FF
-size 8 8
+size 16 16
alpha 256 256 512
-velocityjitter 8 8 8
+velocityjitter 32 32 32
// purple splash
-effect crylink_linkjoin
-count 1.5
+effect crylink_joinexplode
+count 3
type static
color 0xE070FF 0xE070FF
-size 8 8
+size 16 16
alpha 256 256 1024
-velocityjitter 32 32 32
-
-
+velocityjitter 256 256 256
*/
}
+float PlayerInIDList(entity p, string idlist)
+{
+ float n, i;
+ string s;
+
+ // NOTE: we do NOT check crypto_keyfp here, an unsigned ID is fine too for this
+ if not(p.crypto_idfp)
+ return 0;
+
+ // this function allows abbreviated player IDs too!
+ n = tokenize_console(idlist);
+ for(i = 0; i < n; ++i)
+ {
+ s = argv(i);
+ if(s == substring(p.crypto_idfp, 0, strlen(s)))
+ return 1;
+ }
+
+ return 0;
+}
+
/*
=============
ClientConnect
//if(g_domination)
// dom_player_join_team(self);
+ // identify the right forced team
+ if(PlayerInIDList(self, cvar_string("g_forced_team_red")))
+ self.team_forced = COLOR_TEAM1;
+ else if(PlayerInIDList(self, cvar_string("g_forced_team_blue")))
+ self.team_forced = COLOR_TEAM2;
+ else if(PlayerInIDList(self, cvar_string("g_forced_team_yellow")))
+ self.team_forced = COLOR_TEAM3;
+ else if(PlayerInIDList(self, cvar_string("g_forced_team_pink")))
+ self.team_forced = COLOR_TEAM4;
+ else if(cvar_string("g_forced_team_otherwise") == "red")
+ self.team_forced = COLOR_TEAM1;
+ else if(cvar_string("g_forced_team_otherwise") == "blue")
+ self.team_forced = COLOR_TEAM2;
+ else if(cvar_string("g_forced_team_otherwise") == "yellow")
+ self.team_forced = COLOR_TEAM3;
+ else if(cvar_string("g_forced_team_otherwise") == "pink")
+ self.team_forced = COLOR_TEAM4;
+ else if(cvar_string("g_forced_team_otherwise") == "spectate")
+ self.team_forced = -1;
+ else if(cvar_string("g_forced_team_otherwise") == "spectator")
+ self.team_forced = -1;
+ else
+ self.team_forced = 0;
+
+ if(!teams_matter)
+ if(self.team_forced > 0)
+ self.team_forced = 0;
+
JoinBestTeam(self, FALSE, FALSE); // if the team number is valid, keep it
- if((cvar("sv_spectate") == 1 && !g_lms) || cvar("g_campaign")) {
+ if((cvar("sv_spectate") == 1 && !g_lms) || cvar("g_campaign") || self.team_forced < 0) {
self.classname = "observer";
} else {
if(teams_matter)
void LeaveSpectatorMode()
{
if(isJoinAllowed()) {
- if(!teams_matter || cvar("g_campaign") || cvar("g_balance_teams") || (self.wasplayer && cvar("g_changeteam_banned"))) {
+ if(!teams_matter || cvar("g_campaign") || cvar("g_balance_teams") || (self.wasplayer && cvar("g_changeteam_banned")) || self.team_forced > 0) {
self.classname = "player";
if(cvar("g_campaign") || cvar("g_balance_teams") || cvar("g_balance_teams_force"))
* @return bool TRUE if the player is allowed to join, false otherwise
*/
float isJoinAllowed() {
+ if(self.team_forced < 0)
+ return FALSE; // forced spectators can never join
+
if (!cvar("g_maxplayers"))
return TRUE;
if(ww)
W_SwitchWeapon_Force(pl, ww);
}
+.float prevdryfire;
float weapon_prepareattack_checkammo(float secondary)
{
if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
return FALSE;
- if(self.weapon == self.switchweapon) // only play once BEFORE starting to switch weapons
+ if(self.weapon == self.switchweapon && time - self.prevdryfire > 1) // only play once BEFORE starting to switch weapons
+ {
sound (self, CHAN_AUTO, "weapons/dryfire.wav", VOL_BASE, ATTN_NORM);
+ self.prevdryfire = time;
+ }
W_SwitchToOtherWeapon(self);
return FALSE;
PutClientInServer();
} else if(cvar("g_campaign") || cvar("g_balance_teams") || cvar("g_balance_teams_force")) {
//JoinBestTeam(self, FALSE, TRUE);
- } else if(teams_matter && !cvar("sv_spectate")) {
+ } else if(teams_matter && !cvar("sv_spectate") && !(self.team_forced > 0)) {
self.classname = "observer";
stuffcmd(self,"menu_showteamselect\n");
}
if not(self.flags & FL_CLIENT)
return;
if( !teams_matter ) {
- sprint( self, "selecteam can only be used in teamgames\n");
+ sprint( self, "selectteam can only be used in teamgames\n");
} else if(cvar("g_campaign")) {
//JoinBestTeam(self, 0);
+ } else if(self.team_forced > 0) {
+ sprint( self, "selectteam can not be used as your team is forced\n");
} else if(lockteams) {
sprint( self, "^7The game has already begun, you must wait until the next map to be able to join a team.\n");
} else if( argv(1) == "red" ) {
float allowed_to_spawn; // boolean variable used by the clan arena code to determine if a player can spawn (after the round has ended)
float serverflags;
+
+.float team_forced; // can be a team number to force a team, or 0 for default action, or -1 for forced spectator
BADCVAR("bgmvolume");
// private
+ BADCVAR("developer");
+ BADCVAR("g_banned_list");
+ BADCVAR("log_dest_udp");
+ BADCVAR("log_file");
+ BADCVAR("net_address");
+ BADCVAR("net_address_ipv6");
+ BADCVAR("port");
+ BADCVAR("savedgamecfg");
BADCVAR("serverconfig");
+ BADCVAR("sv_heartbeatperiod");
+ BADCVAR("sv_vote_master_password");
+ BADCVAR("sys_colortranslation");
+ BADCVAR("sys_specialcharactertranslation");
+ BADCVAR("timestamps");
+ BADPREFIX("developer_");
BADPREFIX("g_ban_");
BADPREFIX("g_chat_flood_");
BADPREFIX("g_voice_flood_");
BADPREFIX("sv_eventlog");
BADPREFIX("sv_logscores_");
BADPREFIX("sv_master");
- BADCVAR("g_banned_list");
- BADCVAR("log_dest_udp");
- BADCVAR("log_file");
- BADCVAR("net_address");
- BADCVAR("port");
- BADCVAR("savedgamecfg");
- BADCVAR("sv_heartbeatperiod");
- BADCVAR("sv_vote_master_password");
- BADCVAR("sys_colortranslation");
- BADCVAR("sys_specialcharactertranslation");
- BADCVAR("timestamps");
- BADCVAR("net_address");
- BADCVAR("net_address_ipv6");
BADPREFIX("sv_weaponstats_");
- BADCVAR("developer");
- BADPREFIX("developer_");
+
+ // these can contain player IDs, so better hide
+ BADCVAR("g_forced_team_red");
+ BADCVAR("g_forced_team_blue");
+ BADCVAR("g_forced_team_yellow");
+ BADCVAR("g_forced_team_pink");
// mapinfo
BADCVAR("timelimit");
BADCVAR("sv_checkforpacketsduringsleep");
BADPREFIX("crypto_");
BADPREFIX("g_chat_");
+ BADPREFIX("net_");
BADPREFIX("prvm_");
BADPREFIX("sv_fragmessage_");
BADPREFIX("sv_vote_");
BADCVAR("sv_vote_master_password");
BADCVAR("sv_vote_simple_majority_factor");
BADCVAR("timelimit_override");
+
+ if(cvar("g_minstagib"))
+ {
+ BADCVAR("g_grappling_hook");
+ BADCVAR("g_jetpack");
+ }
#undef BADPREFIX
#undef BADCVAR
bprint("That command can only be used in a team-based gamemode.\n");
return;
}
- if(argv(0) == "movetoteam")
- if(argc == 3 || argc == 4) {
-// sv_cmd movetoteam player_id team_colour
-// sv_cmd movetoteam player_id team_colour type_of_move
+ if(argv(0) == "movetoteam") if(argc == 3 || argc == 4) {
+ // sv_cmd movetoteam player_id team_colour
+ // sv_cmd movetoteam player_id team_colour type_of_move
-// type of move
-// 0 (00) automove centerprint, admin message
-// 1 (01) automove centerprint, no admin message
-// 2 (10) no centerprint, admin message
-// 3 (11) no centerprint, no admin message
+ // type of move
+ // 0 (00) automove centerprint, admin message
+ // 1 (01) automove centerprint, no admin message
+ // 2 (10) no centerprint, admin message
+ // 3 (11) no centerprint, no admin message
if(!teams_matter) { // death match
print("Currently not playing a team game\n");
return;
}
- client = edict_num(entno);
+ client = edict_num(entno);
// player entity is not a client
if not(client.flags & FL_CLIENT) {
// find the team to move the player to
float team_colour;
+ float save;
+
+ save = client.team_forced;
+ client.team_forced = 0;
team_colour = ColourToNumber(argv(2));
if(team_colour == client.team) { // player already on the team
print("Player ", argv(1), " (", client.netname, ") is already on the ", ColoredTeamName(client.team), "\n");
+ // keep the forcing undone
return;
} else if(team_colour == 0) // auto team
team_colour = NumberToTeamNumber(FindSmallestTeam(client, FALSE));
+ else
+ CheckAllowedTeams(client);
+
+ client.team_forced = save;
switch(team_colour) {
case COLOR_TEAM1:
if(c1 == -1) {
print("Sorry, there isn't a red team\n");
return;
- }
- break;
+ }
+ break;
case COLOR_TEAM2:
if(c2 == -1) {
print("Sorry, there isn't a blue team\n");
- return;
- }
- break;
+ return;
+ }
+ break;
case COLOR_TEAM3:
if(c3 == -1) {
print("Sorry, there isn't a yellow team\n");
return;
}
- break;
+ break;
case COLOR_TEAM4:
if(c4 == -1) {
print("Sorry, there isn't a pink team\n");
return;
}
- break;
+ break;
default:
print("Sorry, team ", argv(2), " doesn't exist\n");
}
print("Player ", argv(1), " (", client.netname, ") has been moved to the ", ColoredTeamName(team_colour), "\n");
+ client.team_forced = 0;
MoveToTeam(client, team_colour, 6, stof(argv(3)));
return;
c1 = -1;
}
}
+
+ // if player has a forced team, ONLY allow that one
+ if(self.team_forced == COLOR_TEAM1 && c1 >= 0)
+ c2 = c3 = c4 = -1;
+ else if(self.team_forced == COLOR_TEAM2 && c2 >= 0)
+ c1 = c3 = c4 = -1;
+ else if(self.team_forced == COLOR_TEAM3 && c3 >= 0)
+ c1 = c2 = c4 = -1;
+ else if(self.team_forced == COLOR_TEAM4 && c4 >= 0)
+ c1 = c2 = c3 = -1;
}
float PlayerValue(entity p)
if(c4 >= 0)
totalteams = totalteams + 1;
- if(cvar("bot_vs_human") && totalteams == 1)
+ if((cvar("bot_vs_human") || pl.team_forced > 0) && totalteams == 1)
totalteams += 1;
if(totalteams <= 1)
}
if(n >= 2)
{
-
-
if(e.projectiledeathtype & HITTYPE_SECONDARY)
{
if(cvar("g_balance_crylink_secondary_joinexplode"))
cvar("g_balance_crylink_secondary_joinexplode_edgedamage") * n,
cvar("g_balance_crylink_secondary_joinexplode_radius") * n, world,
cvar("g_balance_crylink_secondary_joinexplode_force") * n, e.projectiledeathtype, other);
+
+ pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n);
}
}
else
cvar("g_balance_crylink_primary_joinexplode_edgedamage") * n,
cvar("g_balance_crylink_primary_joinexplode_radius") * n, world,
cvar("g_balance_crylink_primary_joinexplode_force") * n, e.projectiledeathtype, other);
+
+ pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n);
}
}
-
- // they seem to touch...
- // TODO make a specific particle effect for this
- pointparticles(particleeffectnum("crylink_linkjoin"), self.origin, '0 0 0', 1);
}
}
remove(self);
kojn
Maik "SavageX" Merten
MrBougo
+Samual Lenks
Stephan "esteel" Stahl
Wolfgang "Blub\0" Bumiller
Robert "ai" Kuroto
Ronan
Sajt
-Samual Lenks
Severin "sev" Meyer
Shaggy
Shank