]> icculus.org git repositories - divverent/nexuiz.git/blob - qcsrc/gamec/cl_client.c
Wazat's teamplay gamemodes
[divverent/nexuiz.git] / qcsrc / gamec / cl_client.c
1 void info_player_start (void)
2 {
3         self.classname = "info_player_deathmatch";
4 }
5
6 void info_player_deathmatch (void)
7 {
8 }
9
10 float spawn_goodspots, spawn_badspots;
11 entity Spawn_ClassifyPoints(entity firstspot, entity playerlist, float mindist, float goodspotnum, float badspotnum)
12 {
13         local entity spot, player;
14         local float pcount;
15         spawn_goodspots = 0;
16         spawn_badspots = 0;
17         spot = firstspot;
18         while (spot)
19         {
20                 pcount = 0;
21                 player = playerlist;
22                 while (player)
23                 {
24                         if (player != self)
25                         if (vlen(player.origin - spot.origin) < 100)
26                                 pcount = pcount + 1;
27                         player = player.chain;
28                 }
29                 if (pcount)
30                 {
31                         if (spawn_goodspots >= badspotnum)
32                                 return spot;
33                         spawn_badspots = spawn_badspots + 1;
34                 }
35                 else
36                 {
37                         if (spawn_goodspots >= goodspotnum)
38                                 return spot;
39                         spawn_goodspots = spawn_goodspots + 1;
40                 }
41                 spot = find(spot, classname, "info_player_deathmatch");
42         }
43         return firstspot;
44 }
45
46 entity Spawn_FurthestPoint(entity firstspot, entity playerlist)
47 {
48         local entity best, spot, player;
49         local float bestrating, rating;
50         best = world;
51         bestrating = -1000000;
52         spot = firstspot;
53         while (spot)
54         {
55                 rating = 1000000000;
56                 player = playerlist;
57                 while (player)
58                 {
59                         if (player != self)
60                                 rating = min(rating, vlen(player.origin - spot.origin));
61                         player = player.chain;
62                 }
63                 rating = rating + random() * 16;
64                 if (bestrating < rating)
65                 {
66                         best = spot;
67                         bestrating = rating;
68                 }
69                 spot = find(spot, classname, "info_player_deathmatch");
70         }
71         return best;
72 }
73
74 /*
75 =============
76 SelectSpawnPoint
77
78 Finds a point to respawn
79 =============
80 */
81 entity SelectSpawnPoint (float anypoint)
82 {
83         local entity spot, firstspot, playerlist;
84         string spotname;
85
86         spot = find (world, classname, "testplayerstart");
87         if (spot)
88                 return spot;
89
90         spotname = "info_player_deathmatch";
91
92         if(!anypoint && cvar("g_ctf") )
93         {
94                 if(self.team == 5)//4)
95                         spotname = "info_player_team1";
96                 if(self.team == 14)//13)
97                         spotname = "info_player_team2";
98                 if(self.team == 4)//3)
99                         spotname = "info_player_team3";
100                 if(self.team == 13)//12)
101                         spotname = "info_player_team4";
102         }
103
104         playerlist = findchain(classname, "player");
105         firstspot = find(world, classname, spotname);
106         Spawn_ClassifyPoints(firstspot, playerlist, 100, 1000000, 1000000);
107         // first check if there are ANY good spots
108         if (spawn_goodspots > 0)
109         {
110                 // good spots exist, there is 50/50 chance of choosing a random good
111                 // spot or the furthest spot
112                 // (this means that roughly every other spawn will be furthest, so you
113                 // usually won't get fragged at spawn twice in a row)
114                 if (random() > 0.5)
115                         spot = Spawn_ClassifyPoints(firstspot, playerlist, 100, min(floor(random() * spawn_goodspots), spawn_goodspots - 1), 1000000);
116                 else
117                         spot = Spawn_FurthestPoint(firstspot, playerlist);
118         }
119         else
120         {
121                 // no good spots exist, pick a random bad spot
122                 spot = Spawn_ClassifyPoints(firstspot, playerlist, 100, 1000000, min(floor(random() * spawn_badspots), spawn_badspots - 1));
123         }
124
125         if (!spot)
126         {
127                 if(anypoint)
128                         error ("PutClientInServer: no start points on level");
129                 else // try again with deathmatch spots
130                         spot = SelectSpawnPoint(TRUE);
131         }
132
133         return spot;
134 }
135
136 /*
137 =============
138 CheckPlayerModel
139
140 Checks if the argument string can be a valid playermodel.
141 Returns a valid one in doubt.
142 =============
143 */
144 string CheckPlayerModel(string plyermodel) {
145         if( substring(plyermodel,0,14) != "models/player/") plyermodel = "models/player/marine.zym";
146
147         /* Possible Fixme: Check if server can open the model?
148            This would kill custom models, however. */
149
150         return plyermodel;
151 }
152
153
154 /*
155 =============
156 PutClientInServer
157
158 Called when a client spawns in the server
159 =============
160 */
161 void PutClientInServer (void)
162 {
163         entity  spot;
164
165         spot = SelectSpawnPoint (FALSE);
166
167         self.classname = "player";
168         self.iscreature = TRUE;
169         self.movetype = MOVETYPE_WALK;
170         self.solid = SOLID_SLIDEBOX;
171         self.flags = FL_CLIENT;
172         self.takedamage = DAMAGE_AIM;
173         self.effects = 0;
174         self.health = cvar("g_balance_health_start");
175         self.armorvalue = cvar("g_balance_armor_start");
176         self.pauserotarmor_finished = time + 10;
177         self.pauserothealth_finished = time + 10;
178         self.pauseregen_finished = 0;
179         self.damageforcescale = 2;
180         self.death_time = 0;
181         self.dead_time = 0;
182         self.dead_frame = 0;
183         self.die_frame = 0;
184         self.alpha = 0;
185         self.scale = 0;
186         self.fade_time = 0;
187         self.pain_frame = 0;
188         self.pain_finished = 0;
189         self.strength_finished = 0;
190         self.invincible_finished = 0;
191         self.pushltime = 0;
192         //self.speed_finished = 0;
193         //self.slowmo_finished = 0;
194         // players have no think function
195         self.think = SUB_Null;
196         self.nextthink = 0;
197
198         self.runes = 0;
199
200         self.deadflag = DEAD_NO;
201
202         self.angles = spot.angles;
203
204         self.angles_z = 0; // never spawn tilted even if the spot says to
205         self.fixangle = TRUE; // turn this way immediately
206         self.velocity = '0 0 0';
207         self.avelocity = '0 0 0';
208         self.punchangle = '0 0 0';
209         self.punchvector = '0 0 0';
210         self.oldvelocity = self.velocity;
211
212         self.viewzoom = 0.6;
213
214
215         self.playermodel = CheckPlayerModel(self.playermodel);
216
217         precache_model (self.playermodel);
218         setmodel (self, self.playermodel);
219         self.skin = stof(self.playerskin);
220         self.crouch = FALSE;
221         self.view_ofs = PL_VIEW_OFS;
222         setsize (self, PL_MIN, PL_MAX);
223         setorigin (self, spot.origin + '0 0 1' * (1 - self.mins_z - 24));
224         // don't reset back to last position, even if new position is stuck in solid
225         self.oldorigin = self.origin;
226
227 //      self.items = IT_LASER | IT_UZI| IT_SHOTGUN | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER;
228 //      self.weapon = IT_UZI;
229
230         if (cvar("g_instagib") == 1)
231         {
232                 self.items = IT_NEX;
233                 self.switchweapon = WEP_NEX;
234                 self.ammo_shells = 0;
235                 self.ammo_nails = 0;
236                 self.ammo_rockets = 0;
237                 self.ammo_cells = 999;
238         }
239         else if (cvar("g_rocketarena") == 1)
240         {
241                 self.items = IT_ROCKET_LAUNCHER;
242                 self.switchweapon = WEP_ROCKET_LAUNCHER;
243                 self.ammo_shells = 0;
244                 self.ammo_nails = 0;
245                 self.ammo_rockets = 999;
246                 self.ammo_cells = 0;
247         }
248         else
249         {
250                 self.items = IT_LASER | IT_SHOTGUN;
251                 self.switchweapon = WEP_SHOTGUN;
252                 self.ammo_shells = 50;
253                 self.ammo_nails = 0;
254                 self.ammo_rockets = 0;
255                 self.ammo_cells = 0;
256         }
257
258         self.event_damage = PlayerDamage;
259
260         self.statdraintime = time + 5;
261         self.button0 = self.button1 = self.button2 = self.button3 = 0;
262
263         /*
264         W_UpdateWeapon();
265         W_UpdateAmmo();
266         */
267         CL_SpawnWeaponentity();
268
269         //stuffcmd(self, "chase_active 0");
270 }
271
272 /*
273 =============
274 SetNewParms
275 =============
276 */
277 void SetNewParms (void)
278 {
279
280 }
281
282 /*
283 =============
284 SetChangeParms
285 =============
286 */
287 void SetChangeParms (void)
288 {
289
290 }
291
292 /*
293 =============
294 ClientKill
295
296 Called when a client types 'kill' in the console
297 =============
298 */
299 void ClientKill (void)
300 {
301         Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
302 }
303
304 /*
305 =============
306 ClientConnect
307
308 Called when a client connects to the server
309 =============
310 */
311 string ColoredTeamName(float t);
312 //void dom_player_join_team(entity pl);
313 void ClientConnect (void)
314 {
315         self.classname = "player_joining";
316
317         //if(cvar("g_domination"))
318         //      dom_player_join_team(self);
319
320         JoinBestTeam(self, FALSE);
321
322         self.classname = "player";
323
324
325
326         bprint ("^4",self.netname);
327         bprint (" connected");
328
329         if(cvar("g_domination") || cvar("g_ctf"))
330         {
331                 bprint(" and joined the ");
332                 bprint(ColoredTeamName(self.team));
333         }
334
335         bprint("\n");
336
337         self.welcomemessage_time = time + cvar("welcome_message_time");
338         self.welcomemessage_time2 = 0;
339
340
341         stuffcmd(self, strcat("exec maps/", mapname, ".cfg\n"));
342         // send prediction settings to the client
343         stuffcmd(self, strcat("cl_movement_maxspeed ", ftos(cvar("sv_maxspeed")), "\n"));
344         stuffcmd(self, strcat("cl_movement_maxairspeed ", ftos(cvar("sv_maxairspeed")), "\n"));
345         stuffcmd(self, strcat("cl_movement_accelerate ", ftos(cvar("sv_accelerate")), "\n"));
346         stuffcmd(self, strcat("cl_movement_friction ", ftos(cvar("sv_friction")), "\n"));
347         stuffcmd(self, strcat("cl_movement_stopspeed ", ftos(cvar("sv_stopspeed")), "\n"));
348         stuffcmd(self, strcat("cl_movement_jumpvelocity ", ftos(cvar("g_balance_jumpheight")), "\n"));
349         stuffcmd(self, strcat("cl_movement_stepheight ", ftos(cvar("sv_stepheight")), "\n"));
350         stuffcmd(self, strcat("cl_movement_edgefriction 0\n"));
351 }
352
353 /*
354 =============
355 ClientDisconnect
356
357 Called when a client disconnects from the server
358 =============
359 */
360 .entity chatbubbleentity;
361 void ClientDisconnect (void)
362 {
363         bprint ("^4",self.netname);
364         bprint (" disconnected\n");
365
366         if (self.chatbubbleentity)
367         {
368                 remove (self.chatbubbleentity);
369                 self.chatbubbleentity = world;
370         }
371         DropAllRunes(self);
372 }
373
374 .float buttonchat;
375 void() ChatBubbleThink =
376 {
377         self.nextthink = time;
378         if (!self.owner.modelindex || self.owner.chatbubbleentity != self)
379         {
380                 remove(self);
381                 return;
382         }
383         setorigin(self, self.owner.origin + '0 0 15' + self.owner.maxs_z * '0 0 1');
384         if (self.owner.buttonchat && !self.owner.deadflag)
385                 self.model = self.mdl;
386         else
387                 self.model = "";
388 };
389
390 void() UpdateChatBubble =
391 {
392         if (!self.modelindex)
393                 return;
394         // spawn a chatbubble entity if needed
395         if (!self.chatbubbleentity)
396         {
397                 self.chatbubbleentity = spawn();
398                 self.chatbubbleentity.owner = self;
399                 self.chatbubbleentity.exteriormodeltoclient = self;
400                 self.chatbubbleentity.think = ChatBubbleThink;
401                 self.chatbubbleentity.nextthink = time;
402                 setmodel(self.chatbubbleentity, "models/misc/chatbubble.spr");
403                 setorigin(self.chatbubbleentity, self.origin + '0 0 15' + self.maxs_z * '0 0 1');
404                 self.chatbubbleentity.mdl = self.chatbubbleentity.model;
405                 self.chatbubbleentity.model = "";
406         }
407 }
408
409 // LordHavoc: this hack will be removed when proper _pants/_shirt layers are
410 // added to the model skins
411 void() UpdateColorModHack =
412 {
413         local float c;
414         c = self.clientcolors & 15;
415         // LordHavoc: only bothering to support white, green, red, yellow, blue
416              if (teamplay == 0) self.colormod = '0 0 0';
417         else if (c ==  0) self.colormod = '1.00 1.00 1.00';
418         else if (c ==  3) self.colormod = '0.10 1.73 0.10';
419         else if (c ==  4) self.colormod = '1.73 0.10 0.10';
420         else if (c == 12) self.colormod = '1.22 1.22 0.10';
421         else if (c == 13) self.colormod = '0.10 0.10 1.73';
422         else self.colormod = '1 1 1';
423 };
424
425 /*
426 =============
427 PlayerJump
428
429 When you press the jump key
430 =============
431 */
432 void PlayerJump (void)
433 {
434         float mjumpheight;
435
436         mjumpheight = cvar("g_balance_jumpheight");
437         if (self.waterlevel >= 2)
438         {
439                 if (self.watertype == CONTENT_WATER)
440                         self.velocity_z = 200;
441                 else if (self.watertype == CONTENT_SLIME)
442                         self.velocity_z = 80;
443                 else
444                         self.velocity_z = 50;
445
446                 return;
447         }
448
449
450         if (!(self.flags & FL_ONGROUND))
451                 return;
452
453         if (!(self.flags & FL_JUMPRELEASED))
454                 return;
455
456         if(cvar("g_runematch"))
457         {
458                 if(self.runes & RUNE_SPEED)
459                 {
460                         if(self.runes & CURSE_SLOW)
461                                 mjumpheight = mjumpheight * cvar("g_balance_rune_speed_combo_jumpheight");
462                         else
463                                 mjumpheight = mjumpheight * cvar("g_balance_rune_speed_jumpheight");
464                 }
465                 else if(self.runes & CURSE_SLOW)
466                 {
467                         mjumpheight = mjumpheight * cvar("g_balance_curse_slow_jumpheight");
468                 }
469         }
470
471         self.velocity_z = self.velocity_z + mjumpheight;
472         self.oldvelocity_z = self.velocity_z;
473
474         self.flags = self.flags - FL_ONGROUND;
475         self.flags = self.flags - FL_JUMPRELEASED;
476 }
477
478 void() CheckWaterJump =
479 {
480         local vector start, end;
481
482 // check for a jump-out-of-water
483         makevectors (self.angles);
484         start = self.origin;
485         start_z = start_z + 8;
486         v_forward_z = 0;
487         normalize(v_forward);
488         end = start + v_forward*24;
489         traceline (start, end, TRUE, self);
490         if (trace_fraction < 1)
491         {       // solid at waist
492                 start_z = start_z + self.maxs_z - 8;
493                 end = start + v_forward*24;
494                 self.movedir = trace_plane_normal * -50;
495                 traceline (start, end, TRUE, self);
496                 if (trace_fraction == 1)
497                 {       // open at eye level
498                         self.flags = self.flags | FL_WATERJUMP;
499                         self.velocity_z = 225;
500                         self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
501                         self.teleport_time = time + 2;  // safety net
502                         return;
503                 }
504         }
505 };
506
507
508 void respawn(void)
509 {
510         CopyBody(1);
511         PutClientInServer();
512 }
513
514 void player_powerups (void)
515 {
516         self.effects = self.effects - (self.effects & (EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT));
517         if (self.items & IT_STRENGTH)
518         {
519                 self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
520                 if (time > self.strength_finished)
521                 {
522                         self.items = self.items - (self.items & IT_STRENGTH);
523                         sprint(self, "^3Strength has worn off\n");
524                 }
525         }
526         else
527         {
528                 if (time < self.strength_finished)
529                 {
530                         self.items = self.items | IT_STRENGTH;
531                         sprint(self, "^3Strength infuses your weapons with devestating power\n");
532                 }
533         }
534         if (self.items & IT_INVINCIBLE)
535         {
536                 self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
537                 if (time > self.invincible_finished)
538                 {
539                         self.items = self.items - (self.items & IT_INVINCIBLE);
540                         sprint(self, "^3Shield has worn off\n");
541                 }
542         }
543         else
544         {
545                 if (time < self.invincible_finished)
546                 {
547                         self.items = self.items | IT_INVINCIBLE;
548                         sprint(self, "^3Shield surrounds you\n");
549                 }
550         }
551         
552         if (cvar("g_fullbrightplayers"))
553                 self.effects = EF_FULLBRIGHT;
554         
555 }
556
557 void player_regen (void)
558 {
559         float maxh, maxa, max_mod, regen_mod, rot_mod;
560         maxh = cvar("g_balance_health_stable");
561         maxa = cvar("g_balance_armor_stable");
562
563         if(cvar("g_runematch"))
564         {
565                 max_mod = regen_mod = rot_mod = 1;
566                 if (self.runes & RUNE_REGEN)
567                 {
568                         if (self.runes & CURSE_VENOM) // do we have both rune/curse?
569                         {
570                                 regen_mod = cvar("g_balance_rune_regen_combo_regenrate");
571                                 max_mod = cvar("g_balance_rune_regen_combo_hpmod");
572                         }
573                         else
574                         {
575                                 regen_mod = cvar("g_balance_rune_regen_regenrate");
576                                 max_mod = cvar("g_balance_rune_regen_hpmod");
577                         }
578                 }
579                 else if (self.runes & CURSE_VENOM)
580                 {
581                         max_mod = cvar("g_balance_curse_venom_hpmod");
582                         if (self.runes & RUNE_REGEN) // do we have both rune/curse?
583                                 rot_mod = cvar("g_balance_rune_regen_combo_rotrate");
584                         else
585                                 rot_mod = cvar("g_balance_curse_venom_rotrate");
586                         //if (!self.runes & RUNE_REGEN)
587                         //      rot_mod = cvar("g_balance_curse_venom_rotrate");
588                 }
589                 maxh = maxh * max_mod;
590                 //maxa = maxa * max_mod;
591
592                 if (time > self.pauserotarmor_finished)
593                 {
594                         if (self.armorvalue > maxa)
595                                 self.armorvalue = bound(0, self.armorvalue + (maxa - self.armorvalue) * cvar("g_balance_armor_rot") * frametime, 1000);
596                 }
597                 if (time > self.pauserothealth_finished)
598                 {
599                         if (self.health > maxh)
600                                 self.health = bound(0, self.health + (maxh - self.health) * rot_mod*cvar("g_balance_health_rot") * frametime, 1000);
601                 }
602                 if (time > self.pauseregen_finished)
603                 {
604                         if (self.health < maxh)
605                                 self.health = bound(0, self.health + (maxh- self.health) * regen_mod*cvar("g_balance_health_regen") * frametime, 1000);
606                         if (self.armorvalue < maxa)
607                                 self.armorvalue = bound(0, self.armorvalue + (maxa - self.armorvalue) * cvar("g_balance_armor_regen") * frametime, 1000);
608                 }
609         }
610         else
611         {
612                 if (time > self.pauserothealth_finished)
613                 if (self.health > maxh)
614                         self.health = bound(0, self.health + (maxh - self.health) * cvar("g_balance_health_rot") * frametime, 1000);
615                 if (time > self.pauserotarmor_finished)
616                 if (self.armorvalue > maxa)
617                         self.armorvalue = bound(0, self.armorvalue + (maxa - self.armorvalue) * cvar("g_balance_armor_rot") * frametime, 1000);
618                 if (time > self.pauseregen_finished)
619                 {
620                         if (self.health < maxh)
621                                 self.health = bound(0, self.health + (maxh- self.health) * cvar("g_balance_health_regen") * frametime, 1000);
622                         if (self.armorvalue < maxa)
623                                 self.armorvalue = bound(0, self.armorvalue + (maxa - self.armorvalue) * cvar("g_balance_armor_regen") * frametime, 1000);
624                 }
625         }
626 }
627
628 /*
629 =============
630 PlayerPreThink
631
632 Called every frame for each client before the physics are run
633 =============
634 */
635 void PlayerPreThink (void)
636 {
637         local vector m1, m2;
638
639 //      MauveBot_AI();
640
641 //      if(self.netname == "Wazat")
642 //              bprint(strcat(self.classname, "\n"));
643
644         CheckRules_Player();
645
646         if (intermission_running)
647         {
648                 IntermissionThink ();   // otherwise a button could be missed between
649                 return;                                 // the think tics
650         }
651
652         if (self.deadflag != DEAD_NO)
653         {
654                 player_anim();
655                 weapon_freeze();
656                 if (self.deadflag == DEAD_DYING)
657                 {
658                         if (time > self.dead_time)
659                                 self.deadflag = DEAD_DEAD;
660                 }
661                 else if (self.deadflag == DEAD_DEAD)
662                 {
663                         if (!self.button0 && !self.button2 && !self.button3)
664                                 self.deadflag = DEAD_RESPAWNABLE;
665                 }
666                 else if (self.deadflag == DEAD_RESPAWNABLE)
667                 {
668                         if (self.button0 || self.button2 || self.button3  || self.button4)
669                                 respawn();
670                 }
671                 return;
672         }
673
674         if (self.button5)
675         {
676                 if (!self.crouch)
677                 {
678                         self.crouch = TRUE;
679                         self.view_ofs = PL_CROUCH_VIEW_OFS;
680                         setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX);
681                 }
682         }
683         else
684         {
685                 if (self.crouch)
686                 {
687                         tracebox(self.origin, PL_MIN, PL_MAX, self.origin, FALSE, self);
688                         if (!trace_startsolid)
689                         {
690                                 self.crouch = FALSE;
691                                 self.view_ofs = PL_VIEW_OFS;
692                                 setsize (self, PL_MIN, PL_MAX);
693                         }
694                 }
695         }
696
697         if (self.playermodel != self.model)
698         {
699                 self.playermodel = CheckPlayerModel(self.playermodel);
700                 m1 = self.mins;
701                 m2 = self.maxs;
702                 precache_model (self.playermodel);
703                 setmodel (self, self.playermodel);
704                 setsize (self, m1, m2);
705         }
706
707         // Savage: Check for nameless players
708         if (strlen(self.netname) < 1) {
709                 self.netname = "Player";
710                 stuffcmd(self, "name Player\n");
711         }
712
713         if (self.skin != stof(self.playerskin))
714                 self.skin = stof(self.playerskin);
715
716         W_WeaponFrame();
717
718         if (self.button4 || (self.weapon == WEP_NEX && self.button3))
719         {
720                 if (self.viewzoom > 0.4)
721                         self.viewzoom = max (0.4, self.viewzoom - frametime * 2);
722         }
723         else if (self.viewzoom < 1.0)
724                 self.viewzoom = min (1.0, self.viewzoom + frametime);
725
726
727         if (self.button2)
728                 PlayerJump ();
729         else
730                 self.flags = self.flags | FL_JUMPRELEASED;
731
732
733         player_powerups();
734         player_regen();
735         player_anim();
736
737         //self.angles_y=self.v_angle_y + 90;   // temp
738
739         if (self.waterlevel == 2)
740                 CheckWaterJump ();
741
742         //if (TetrisPreFrame()) return;
743 }
744
745 /*
746 =============
747 PlayerPostThink
748
749 Called every frame for each client after the physics are run
750 =============
751 */
752 void PlayerPostThink (void)
753 {
754         CheckRules_Player();
755         UpdateChatBubble();
756         UpdateColorModHack();
757         if (self.deadflag == DEAD_NO)
758         if (self.impulse)
759                 ImpulseCommands ();
760         if (intermission_running)
761                 return;         // intermission or finale
762
763         PrintWelcomeMessage(self);
764         //if (TetrisPostFrame()) return;
765 }