]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/gamec/clientcommands.c
add missing variable declaration
[divverent/nexuiz.git] / data / qcsrc / server / gamec / clientcommands.c
1 void ReadyCount();
2
3 .float vote_finished;
4
5 void SV_ParseClientCommand(string s) {
6         local float index;
7
8         tokenize(s);
9
10         if(argv(0) == "clogin") {
11                 if(cvar("sv_clientcommands")) {
12                         if(self.adminstatus < -5) {
13                                 sprint(self, "Too many unsuccessful tries.\n");
14                         } else if(argv(1) == cvar_string("sv_clientcommands_password")) {
15                                 self.adminstatus = 1;
16                                 sprint(self, "You now have remote admin status.\n");
17                         } else {
18                                 sprint(self, "Wrong password.\n");
19                                 // use of -- produces compiler warning in the if() line???
20                                 self.adminstatus = self.adminstatus - 1;
21                                 if(self.adminstatus == 0)
22                                         sprint(self, "You lost remote admin status.\n");
23                         }
24                 } else {
25                         sprint(self, "Clientside commands NOT allowed.\n");
26                 }
27         } else if(argv(0) == "ccmd") {
28                 if(cvar("sv_clientcommands")) {
29                         if(self.adminstatus > 0) {
30                                 local string command;
31                                 command = argv(1);
32                                 index = 2;
33                                 while(argv(index) != "") {
34                                         command = strcat(command, " ", argv(index));
35                                         index++;
36                                 }
37                                 localcmd(command);
38                         } else
39                                 sprint(self, "You don't have remote admin status.\n");
40                 } else {
41                         sprint(self, "Clientside commands NOT allowed.\n");
42                 }
43         } else if(argv(0) == "vote") {
44                 if(argv(1) == "help") {
45                         sprint(self, "^7You can use voting with \"^2cmd vote help^7\" \"^2cmd vote status^7\" \"^2cmd vote call ^3COMMAND ARGUMENTS^7\" \"^2cmd vote stop^7\" \"^2cmd vote master^7\" \"^2cmd vote do ^3COMMAND ARGUMENTS^7\" \"^2cmd vote yes^7\" \"^2cmd vote no^7\".\n");
46                         sprint(self, "^7Or if your version is up to date you can use these aliases \"^2vhelp^7\" \"^2vstatus^7\" \"^2vcall ^3COMMAND ARGUMENTS^7\" \"^2vstop^7\" \"^2vmaster^7\" \"^2vdo ^3COMMAND ARGUMENTS^7\" \"^2vyes^7\" \"^2vno^7\".\n");
47                         sprint(self, "^7\"^2help^7\" shows this info.\n");
48                         sprint(self, "^7\"^2status^7\" shows if there is a vote called and who called it.\n");
49                         sprint(self, "^7\"^2call^7\" is used to call a vote. See the list of allowed commands.\n");
50                         sprint(self, "^7\"^2stop^7\" can be used by the vote caller or an admin to stop a vote and maybe correct it.\n");
51                         sprint(self, "^7\"^2master^7\" is used to call a vote to become a master.\n");
52                         sprint(self, "^7\"^2do^7\" If you are a master you can execute a command without a vote. See the list of allowed commands.\n");
53                         sprint(self, "^7\"^2yes^7\" and \"^2no^7\" to make your vote.\n");
54                         sprint(self, "^7If more then 50% of the players vote yes the vote is accepted.\n");
55                         sprint(self, "^7If more then 50% of the players vote no the vote is rejected.\n");
56                         sprint(self, strcat("^7The vote will end after ", cvar_string("sv_vote_timeout"), "^7 seconds.\n"));
57                         sprint(self, "^7You can call a vote for or execute these commands:\n");
58                         sprint(self, strcat("^3", cvar_string("sv_vote_commands"), "^7 and maybe further ^3arguments^7\n"));
59                 } else if(argv(1) == "status") {
60                         if(votecalled) {
61                                 sprint(self, strcat("^7Vote for \"^1", votecalledvote, "^7\" called by \"^7", votecaller.netname, "^7\".\n"));
62                         } else {
63                                 sprint(self, "^1No vote called.\n");
64                         }
65                 } else if(argv(1) == "call") {
66                         if(cvar("sv_vote_call")) {
67                                 if(votecalled) {
68                                         sprint(self, "^1There is already a vote called.\n");
69                                 } else {
70                                         local string vote;
71                                         vote = VoteParse();
72                                         if(vote == "") {
73                                                 sprint(self, "^1Your vote is empty. See help for more info.\n");
74                                         } else if(time < self.vote_next) {
75                                                 sprint(self, strcat("^1You have to wait ^2", ftos(self.vote_next - time), "^1 seconds before you can again call a vote.\n"));
76                                         } else if(VoteAllowed(strcat(argv(2)))) { // strcat seems to be necessary
77                                                 votecalled = TRUE;
78                                                 votecalledmaster = FALSE;
79                                                 votecalledvote = strzone(vote);
80                                                 votecaller = self; // remember who called the vote
81                                                 votecaller.vote_vote = 1; // of course you vote yes
82                                                 votecaller.vote_finished = time + cvar("sv_vote_timeout");
83                                                 votecaller.vote_next = time + cvar("sv_vote_wait");
84                                                 bprint(strcat("^3Vote for \"^1", votecalledvote, "^3\" called by \"^7", votecaller.netname, "^3\".\n"));
85                                                 VoteCount(); // needed if you are the only one
86                                         } else {
87                                                 sprint(self, "^1This vote is not ok. See help for more info.\n");
88                                         }
89                                 }
90                         } else {
91                                 sprint(self, "^1Vote calling is NOT allowed.\n");
92                         }
93                 } else if(argv(1) == "stop") {
94                         if(!votecalled) {
95                                 sprint(self, "^1No vote called.\n");
96                         } else if(self == votecaller
97                                   || self.adminstatus > 0) { // the votecaller and admins can stop a vote
98                                 VoteStop(self);
99                         } else {
100                                 sprint(self, "^1You are not allowed to stop that Vote.\n");
101                         }
102                 } else if(argv(1) == "master") {
103                         if(cvar("sv_vote_master")) {
104                                 if(votecalled) {
105                                         sprint(self, "^1There is already a vote called.\n");
106                                 } else {
107                                         votecalled = TRUE;
108                                         votecalledmaster = TRUE;
109                                         votecalledvote = strzone("^3master");
110                                         votecaller = self; // remember who called the vote
111                                         votecaller.vote_vote = 1; // of course you vote yes
112                                         votecaller.vote_finished = time + cvar("sv_vote_timeout");
113                                         votecaller.vote_next = time + cvar("sv_vote_wait");
114                                         bprint(strcat("\"^7", votecaller.netname, "^3\" called a vote to become ^3master^3.\n"));
115                                         VoteCount(); // needed if you are the only one
116                                 }
117                         } else {
118                                 sprint(self, "^1Vote to become master is NOT allowed.\n");
119                         }
120                 } else if(argv(1) == "do") {
121                         if(self.vote_master) {
122                                 local string dovote;
123                                 dovote = VoteParse();
124                                 if(dovote == "") {
125                                         sprint(self, "^1Your command was empty. See help for more info.\n");
126                                 } else if(VoteAllowed(strcat(argv(2)))) { // strcat seems to be necessary
127                                         bprint("\"^7", strcat(self.netname, "^2 used his ^3master^2 status to do \"^2", dovote, "^2\".\n"));
128                                         localcmd(dovote);
129                                 } else {
130                                         sprint(self, "^1This command is not ok. See help for more info.\n");
131                                 }
132                         } else {
133                                 sprint(self, "^1You are NOT a master.\n");
134                         }
135                 } else if(argv(1) == "yes") {
136                         if(!votecalled) {
137                                 sprint(self, "^1No vote called.\n");
138                         } else if(self.vote_vote == 0
139                                   || cvar("sv_vote_change")) {
140                                 sprint(self, "^1You accepted the vote.\n");
141                                 self.vote_vote = 1;
142                                 if(!cvar("sv_vote_singlecount")) {
143                                         VoteCount();
144                                 }
145                         } else {
146                                 sprint(self, "^1You have already voted.\n");
147                         }
148                 } else if(argv(1) == "no") {
149                         if(!votecalled) {
150                                 sprint(self, "^1No vote called.\n");
151                         } else if(self.vote_vote == 0
152                                   || cvar("sv_vote_change")) {
153                                 sprint(self, "^1You rejected the vote.\n");
154                                 self.vote_vote = -1;
155                                 if(!cvar("sv_vote_singlecount")) {
156                                         VoteCount();
157                                 }
158                         } else {
159                                 sprint(self, "^1You have already voted.\n");
160                         }
161                 } else {
162                         // ignore this?
163                         sprint(self, "^1Unknown vote command.\n");
164                 }
165         } else if(argv(0) == "autoswitch") {
166                 // be backwards compatible with older clients (enabled)
167                 self.autoswitch = ("0" != argv(1));
168                 local string autoswitchmsg;
169                 if (self.autoswitch) {
170                         autoswitchmsg = "on";
171                 } else {
172                         autoswitchmsg = "off";
173                 }
174                 sprint(self, strcat("^1autoswitch turned ", autoswitchmsg, "\n"));
175         } else if(argv(0) == "clientversion") {
176                 if (argv(1) == "$g_nexuizversion_major") {
177                         //versionmsg = "^1client is too old to get versioninfo.\nUPDATE!!! (http://www.nexuiz.com)^8";
178                         // either that or someone wants to be funny
179                         self.version = 1;
180                 } else {
181                         self.version = stof(argv(1));
182                 }
183         } else if(argv(0) == "spectate") {
184                 if(cvar("g_lms"))
185                         return; // don't allow spectating in lms, unless player runs out of lives
186                 if(self.classname == "player" && cvar("sv_spectate") == 1) {
187                         self.classname = "observer";
188                         PutClientInServer();
189                 }
190         } else if(argv(0) == "join") {
191                 self.classname = "player";
192                 self.frags = 0;
193                 // TODO: I have no idea whether this is needed or not
194                 if(!cvar("g_lms")) {
195                         bprint (strcat("^4", self.netname, "^4 is playing now\n"));
196                 }
197                 PutClientInServer();
198         } else if( argv(0) == "selectteam" ) {
199                 if( argv(1) == "none" ) {
200                         SV_ChangeTeam( 0 );
201                 } else if( argv(1) == "red" ) {
202                         SV_ChangeTeam( COLOR_TEAM1 - 1 );
203                 } else if( argv(1) == "blue" ) {
204                         SV_ChangeTeam( COLOR_TEAM2 - 1 );
205                 } else if( argv(1) == "pink" ) {
206                         SV_ChangeTeam( COLOR_TEAM3 - 1 );
207                 } else if( argv(1) == "yellow" ) {
208                         SV_ChangeTeam( COLOR_TEAM4 - 1 );
209                 } else if( argv(1) == "auto" ) {
210                         JoinBestTeam( self, 0 );
211                 } else {
212                         sprint( self, strcat( "selectteam none/red/blue/pink/yellow/auto - \"", argv(1), "\" not recognised\n" ) );
213                 }
214         } else if(argv(0) == "ready") {
215                 if(cvar("sv_ready_restart"))
216                 {
217                         self.ready = TRUE;
218                         ReadyCount();
219                 }
220         } else {
221                 clientcommand(self,s);
222         }
223 }
224
225 void VoteThink() {
226         if(self.vote_finished > 0 // this player has called a vote
227             && time > self.vote_finished) // time is up
228         {
229                 VoteCount();
230         }
231 }
232
233 string VoteParse() {
234         local float index;
235         index = 3;
236         local string vote;
237         vote = argv(2);
238         while(argv(index) != "") {
239                 vote = strcat(vote, " ", argv(index));
240                 index++;
241         }
242
243         // necessary for some of the string operations
244         vote = strzone(vote);
245
246         // now we remove some things that could be misused
247         index = 0;
248         local float found;
249         found = FALSE;
250         local float votelength;
251         votelength = strlen(vote);
252         while(!found && index < votelength)
253         {
254                 local string badchar;
255                 badchar = substring(vote, index, 1);
256                 if(badchar == ";"
257                    || badchar == "\n")
258                 {
259                         found = TRUE;
260                 } else {
261                         index++;
262                 }
263         }
264         return substring(vote, 0, index);
265 }
266
267 float VoteAllowed(string votecommand) {
268         tokenize(cvar_string("sv_vote_commands"));
269         local float index;
270         index = 0;
271         while(argv(index) != "") {
272                 local string allowed;
273                 allowed = argv(index);
274                 if(votecommand == allowed) {
275                         return TRUE;
276                 }
277                 index++;
278         }
279         return FALSE;
280 }
281
282 void VoteReset() {
283         local string searchclass;
284         searchclass = "player";
285
286         while (TRUE)
287         {
288                 local entity player;
289                 player = find(player, classname, searchclass);
290                 while(player)
291                 {
292                         player.vote_vote = 0;
293                         player.vote_finished = 0;
294                         player = find(player, classname, searchclass);
295                 }
296
297                 if("player" == searchclass) {
298                         searchclass = "observer";
299                 } else if("observer" == searchclass) {
300                         searchclass = "spectator";
301                 } else {
302                         break;
303                 }
304         }
305
306         votecalled = FALSE;
307         votecalledmaster = FALSE;
308 }
309
310 void VoteAccept() {
311         bprint(strcat("^2The vote for \"^1", votecalledvote, "^2\" from \"^7", votecaller.netname, "^2\" was accepted.\n"));
312         if(votecalledmaster)
313         {
314                 votecaller.vote_master = 1;
315         } else {
316                 localcmd(votecalledvote);
317         }
318         votecaller.vote_next = 0; // people like your votes, no wait for next vote
319         VoteReset();
320 }
321
322 void VoteReject() {
323         bprint(strcat("^2The vote for \"^1", votecalledvote, "^2\" from \"^7", votecaller.netname, "^2\" was rejected.\n"));
324         VoteReset();
325 }
326
327 void VoteTimeout() {
328         bprint(strcat("^5The vote for \"^1", votecalledvote, "^5\" from \"^7", votecaller.netname, "^5\" did timeout.\n"));
329         VoteReset();
330 }
331
332 void VoteStop(entity stopper) {
333         bprint(strcat("^5The vote for \"^1", votecalledvote, "^5\" from \"^7", votecaller.netname, "^5\" was stopped by \"^5", stopper.netname, "^5\".\n"));
334         if(stopper == votecaller) {
335                 // no wait for next vote so you can correct your vote
336                 votecaller.vote_next = 0;
337         }
338         VoteReset();
339 }
340
341 void VoteCount() {
342         local float playercount;
343         playercount = 0;
344         local float yescount;
345         yescount = 0;
346         local float nocount;
347         nocount = 0;
348         local string searchclass;
349         searchclass = "player";
350
351         while (TRUE)
352         {
353                 local entity player;
354                 player = find(player, classname, searchclass);
355
356                 while(player)
357                 {
358                         if(clienttype(player) != CLIENTTYPE_BOT) {
359                                 if(player.vote_vote < 0) {
360                                         nocount++;
361                                 } else if(player.vote_vote > 0) {
362                                         yescount++;
363                                 }
364                                 playercount++;
365                         }
366                         player = find(player, classname, searchclass);
367                 }
368
369                 if("player" == searchclass) {
370                         searchclass = "observer";
371                 } else if("observer" == searchclass) {
372                         searchclass = "specator";
373                 } else {
374                         break;
375                 }
376         }
377
378         if((playercount / 2) < yescount) { // vote accepted
379                 VoteAccept();
380         } else if((playercount / 2) < nocount) { // vote rejected
381                 VoteReject();
382         } else if(time > votecaller.vote_finished) { // vote timedout
383                 VoteTimeout();
384         } // else still running
385 }
386
387
388 void ReadyCount()
389 {
390         local entity e;
391         local float r, p;
392
393         e = find(world, classname, "player");
394
395         while(e)
396         {
397                 if(clienttype(e) == CLIENTTYPE_REAL)
398                 {
399                         p += 1;
400                         if(e.ready) r += 1;
401                 }
402                 e = find(e, classname, "player");
403         }
404
405         if(p && r == p)
406         {
407                 bprint("^1Server is restarting...\n");
408                 localcmd("restart\n");
409         }
410 }