1//************************************************************************** 2//** 3//** ## ## ## ## ## #### #### ### ### 4//** ## ## ## ## ## ## ## ## ## ## #### #### 5//** ## ## ## ## ## ## ## ## ## ## ## ## ## ## 6//** ## ## ######## ## ## ## ## ## ## ## ### ## 7//** ### ## ## ### ## ## ## ## ## ## 8//** # ## ## # #### #### ## ## 9//** 10//** $Id: IntermissionScreen.vc 4082 2009-10-22 11:48:22Z dj_jl $ 11//** 12//** Copyright (C) 1999-2006 Jānis Legzdiņš 13//** 14//** This program is free software; you can redistribute it and/or 15//** modify it under the terms of the GNU General Public License 16//** as published by the Free Software Foundation; either version 2 17//** of the License, or (at your option) any later version. 18//** 19//** This program is distributed in the hope that it will be useful, 20//** but WITHOUT ANY WARRANTY; without even the implied warranty of 21//** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22//** GNU General Public License for more details. 23//** 24//************************************************************************** 25 26class IntermissionScreen : Widget; 27 28// Intermission states 29enum 30{ 31 IMS_Stats, 32 IMS_NextLoc, 33 IMS_NoState, 34 IMS_Text, 35 IMS_Done 36}; 37 38ClientGameBase ClGame; 39 40// GLOBAL LOCATIONS 41const int WI_SPACINGY = 33; 42 43const int WI_TITLEY = 12; 44 45// SINGPLE-PLAYER STUFF 46const int SP_STATSX = 210; 47const int SP_STATSY = 190; 48 49const int SP_TIMEX = 176; 50const int SP_TIMEY = 308; 51 52const int SP_PARX = 376; 53const int SP_PARY = 308; 54 55// NET GAME STUFF 56const int NG_STATSY = 210; 57const int NG_STATSX = (172 + 32 / 2); 58 59const int NG_SPACINGX = 64; 60 61// DEATHMATCH STUFF 62const int DM_MATRIXX = 202; 63const int DM_MATRIXY = 208; 64 65const int DM_TOTALSX = 329; 66const int DM_DEATHSX = 429; 67 68const int DM_SPACINGX = 40; 69 70// in seconds 71const float SHOWNEXTLOCDELAY = 4.0; 72 73// Different between registered DOOM (1994) and Ultimate DOOM - Final 74// edition (retail, 1995?). 75const int NUMEPISODES = 3; 76const int NUMMAPS = 9; 77 78const float TEXTSPEED = 0.1; 79const float TEXTWAIT = 7.0; 80 81int LeaveTitlePic; 82int EnterTitlePic; 83 84int interstate; 85 86// used for timing of background animation 87float btime; 88 89int sp_state; 90int ng_state; 91int dm_state; 92 93int TotalKills; 94int TotalItems; 95int TotalSecret; 96 97int cnt_kills[MAXPLAYERS]; 98int cnt_items[MAXPLAYERS]; 99int cnt_secret[MAXPLAYERS]; 100int cnt_time; 101float cnt_pause; 102int cnt_frags[MAXPLAYERS]; 103 104int dm_Frags[MAXPLAYERS]; 105int dm_Deaths[MAXPLAYERS]; 106 107// Face background, your face, your dead face 108int p[MAXPLAYERS]; 109 110int star; 111int star_width; 112 113int bstar; 114 115// used for general timing 116float cnt; 117 118#ifndef DOOM2 119 120int im_episode; 121int im_map; 122int im_nextepisode; 123int im_nextmap; 124 125#endif 126 127IntermissionBackground Background; 128 129//========================================================================== 130// 131// Start 132// 133//========================================================================== 134 135void Start() 136{ 137 ClGame.skipintermission = false; 138 cnt = 0.0; 139 btime = 0.0; 140 141 if (!Background) 142 { 143 Background = NewChild(IntermissionBackground); 144 Background.ScaleX = itof(Width) / itof(Background.Width); 145 Background.ScaleY = itof(Height) / itof(Background.Height); 146 } 147 148#ifndef DOOM2 149 FindEpisodeAndMap(ClGame.im.LeaveMap, &im_episode, &im_map); 150 FindEpisodeAndMap(ClGame.im.EnterMap, &im_nextepisode, &im_nextmap); 151#endif 152 153 IM_InitAnimatedBack(); 154 155 TotalKills = ClGame.cl.Level.TotalKills; 156 TotalItems = ClGame.cl.Level.TotalItems; 157 TotalSecret = ClGame.cl.Level.TotalSecret; 158 159 if (!TotalKills) 160 TotalKills = 1; 161 162 if (!TotalItems) 163 TotalItems = 1; 164 165 if (!TotalSecret) 166 TotalSecret = 1; 167 168 if (ClGame.deathmatch) 169 IM_InitDeathmatchStats(); 170 else if (ClGame.maxclients > 1) 171 IM_InitCooperativeStats(); 172 else 173 IM_InitSingleStats(); 174 175 if (interstate == IMS_Stats) 176 { 177 IM_LoadData(); 178 179 // intermission music 180 if (ClGame.im.InterMusic) 181 { 182 CmdBuf_AddText(va("music loop %n\n", ClGame.im.InterMusic)); 183 } 184 else 185 { 186#ifdef FIXME 187#ifdef DOOM2 188 S_StartSong("D_DM2INT", P_GetCDIntermissionTrack(), true); 189#else 190 S_StartSong("D_INTER", P_GetCDIntermissionTrack(), true); 191#endif 192#else 193#ifdef DOOM2 194 CmdBuf_AddText("music loop D_DM2INT\n"); 195#else 196 CmdBuf_AddText("music loop D_INTER\n"); 197#endif 198#endif 199 } 200 } 201 else 202 { 203 IM_InitText(); 204 } 205} 206 207#ifndef DOOM2 208//========================================================================== 209// 210// FindEpisodeAndMap 211// 212//========================================================================== 213 214void FindEpisodeAndMap(name Name, int *epi, int *map) 215{ 216 int e; 217 int m; 218 219 for (e = 1; e <= 3; e++) 220 { 221 for (m = 1; m <= 9; m++) 222 { 223 if (Name == StrToName(va("e%dm%d", e, m))) 224 { 225 *epi = e; 226 *map = m; 227 return; 228 } 229 } 230 } 231 *epi = 4; 232 *map = 1; 233} 234#endif 235 236//========================================================================== 237// 238// Tick 239// 240// Updates stuff each frame 241// 242//========================================================================== 243 244void Tick(float DeltaTime) 245{ 246 // counter for general background animation 247 btime += DeltaTime; 248 249 switch (interstate) 250 { 251 case IMS_Stats: 252 if (ClGame.deathmatch) 253 IM_UpdateDeathmatchStats(DeltaTime); 254 else if (ClGame.maxclients > 1) 255 IM_UpdateCooperativeStats(DeltaTime); 256 else 257 IM_UpdateSingleStats(DeltaTime); 258 break; 259 260#ifndef DOOM2 261 case IMS_NextLoc: 262 IM_UpdateNextLoc(DeltaTime); 263 break; 264#endif 265 266 case IMS_NoState: 267 IM_UpdateNoState(DeltaTime); 268 break; 269 270 case IMS_Text: 271 IM_UpdateText(DeltaTime); 272 break; 273 274 case IMS_Done: 275 break; 276 } 277} 278 279//========================================================================== 280// 281// OnPostDraw 282// 283//========================================================================== 284 285void OnPostDraw() 286{ 287 SetFont('bigfont'); 288 289 switch (interstate) 290 { 291 case IMS_Stats: 292 if (ClGame.deathmatch) 293 { 294 IM_DrawDeathmatchStats(); 295 } 296 else if (ClGame.maxclients > 1) 297 { 298 IM_DrawCooperativeStats(); 299 } 300 else 301 { 302 IM_DrawSingleStats(); 303 } 304 break; 305 306#ifndef DOOM2 307 case IMS_NextLoc: 308 IM_DrawNextLoc(); 309 break; 310#endif 311 312 case IMS_NoState: 313 IM_DrawNoState(); 314 break; 315 316 case IMS_Text: 317 IM_DrawText(); 318 break; 319 320 case IMS_Done: 321 break; 322 } 323} 324 325//************************************************************************** 326//** 327//** Animated background 328//** 329//************************************************************************** 330 331//========================================================================== 332// 333// IM_InitAnimatedBack 334// 335//========================================================================== 336 337void IM_InitAnimatedBack() 338{ 339 name BgPic = interstate ? ClGame.im.ExitPic : ClGame.im.EnterPic; 340 if (!BgPic) 341 { 342#ifdef DOOM2 343 BgPic = 'interpic'; 344#else 345 if (im_episode > 3) 346 { 347 BgPic = 'interpic'; 348 } 349 else 350 { 351 BgPic = StrToName(va("$in_epi%d", im_episode)); 352 } 353#endif 354 } 355 Background.Init(BgPic, interstate ? 356 IntermissionBackground::STATE_NextLoc : 357 IntermissionBackground::STATE_Default, ClientGameShared(ClGame)); 358} 359 360//========================================================================== 361// 362// IM_LoadData 363// 364//========================================================================== 365 366void IM_LoadData() 367{ 368 picinfo_t info; 369 int i; 370 371 if (ClGame.im.LeaveTitlePatch) 372 { 373 LeaveTitlePic = R_RegisterPic(ClGame.im.LeaveTitlePatch); 374 } 375 if (ClGame.im.EnterTitlePatch) 376 { 377 EnterTitlePic = R_RegisterPic(ClGame.im.EnterTitlePatch); 378 } 379 380 if (ClGame.maxclients > 1 || ClGame.deathmatch) 381 { 382 // face backgrounds 383// for (i = 0; i < MAXPLAYERS; i++) 384 for (i = 0; i < 4; i++) 385 { 386 p[i] = R_RegisterPic(StrToName(va("stpb%i", i))); 387 } 388 389 // your face 390 star = R_RegisterPic('stfst01'); 391 R_GetPicInfo(star, &info); 392 star_width = info.width; 393 394 // dead face 395 bstar = R_RegisterPic('stfdead0'); 396 } 397} 398 399//========================================================================== 400// 401// IM_UnloadData 402// 403//========================================================================== 404 405void IM_UnloadData() 406{ 407} 408 409//========================================================================== 410// 411// IM_DrawLF 412// 413// Draws "<Levelname> Finished!" 414// 415//========================================================================== 416 417void IM_DrawLF() 418{ 419 picinfo_t info; 420 int y = WI_TITLEY; 421 422 // draw <LevelName> 423 if (ClGame.im.LeaveTitlePatch) 424 { 425 R_GetPicInfo(LeaveTitlePic, &info); 426 DrawPic(320 - info.width / 2, y, LeaveTitlePic); 427 y += info.height + TextHeight("DUMMY") / 4; 428 } 429 else 430 { 431 SetTextAlign(hcentre, vtop); 432 DrawText(320, y, ClGame.im.LeaveName); 433 y += (5 * TextHeight("DUMMY")) / 4; 434 } 435 436 // draw "Finished!" 437 SetTextAlign(hcentre, vtop); 438 DrawText(320, y, "finished"); 439} 440 441//========================================================================== 442// 443// IM_DrawEL 444// 445// Draws "Entering <LevelName>" 446// 447//========================================================================== 448 449void IM_DrawEL() 450{ 451 picinfo_t info; 452 int y = WI_TITLEY; 453 454 // draw "Entering" 455 SetTextAlign(hcentre, vtop); 456 DrawText(320, y, "entering"); 457 458 // draw level 459 y += (5 * TextHeight("DUMMY")) / 4; 460 if (ClGame.im.EnterTitlePatch) 461 { 462 R_GetPicInfo(EnterTitlePic, &info); 463 DrawPic(320 - info.width / 2, y, EnterTitlePic); 464 } 465 else 466 { 467 DrawText(320, y, ClGame.im.EnterName); 468 } 469} 470 471//========================================================================== 472// 473// IM_DrawPercent 474// 475//========================================================================== 476 477void IM_DrawPercent(int x, int y, int p) 478{ 479 if (p < 0) 480 return; 481 482 SetTextAlign(hright, vtop); 483 DrawText(x, y, va("%d%%", p)); 484} 485 486//========================================================================== 487// 488// IM_DrawTime 489// 490// Display level completion time and par, or "sucks" message if overflow. 491// 492//========================================================================== 493 494void IM_DrawTime(int x, int y, int t, string BaseText, bool sucks) 495{ 496 if (t < 0) 497 return; 498 499 SetTextAlign(hleft, vtop); 500 501 string Text; 502 if (!sucks || !ClGame.cl.Level.SuckTime || t < ClGame.cl.Level.SuckTime * 60 * 60) 503 { 504 Text = BaseText; 505 if (t >= 60 * 60) 506 { 507 Text = strcat(Text, va("%d:", t / (60 * 60))); 508 if ((t / 60) % 60 < 10) 509 Text = strcat(Text, va("0%d", (t / 60) % 60)); 510 else 511 Text = strcat(Text, va("%d", (t / 60) % 60)); 512 } 513 else 514 Text = strcat(Text, va("%d", t / 60)); 515 if (t % 60 < 10) 516 Text = strcat(Text, va(":0%d", t % 60)); 517 else 518 Text = strcat(Text, va(":%d", t % 60)); 519 } 520 else 521 { 522 // "sucks" 523 Text = strcat(BaseText, "sucks"); 524 } 525 DrawText(x, y, Text); 526} 527 528//========================================================================== 529// 530// IM_InitSingleStats 531// 532//========================================================================== 533 534void IM_InitSingleStats() 535{ 536 interstate = IMS_Stats; 537 ClGame.skipintermission = 0; 538 sp_state = 1; 539 cnt_kills[0] = -1; 540 cnt_items[0] = -1; 541 cnt_secret[0] = -1; 542 cnt_time = -1; 543 cnt_pause = 1.0; 544 if (ClGame.cl.Level.bNoIntermission) 545 { 546 interstate = IMS_NoState; 547 } 548} 549 550//========================================================================== 551// 552// IM_DrawSingleStats 553// 554//========================================================================== 555 556void IM_DrawSingleStats() 557{ 558 // line height 559 int lh; 560 561 lh = (3 * TextHeight("DUMMY")) / 2; 562 563 IM_DrawLF(); 564 565 SetTextAlign(hleft, vtop); 566 567 DrawText(SP_STATSX, SP_STATSY, "kills"); 568 DrawText(SP_STATSX, SP_STATSY + lh, "items"); 569 DrawText(SP_STATSX, SP_STATSY + 2 * lh, "scrt"); 570 571 IM_DrawPercent(640 - SP_STATSX, SP_STATSY, cnt_kills[0]); 572 IM_DrawPercent(640 - SP_STATSX, SP_STATSY + lh, cnt_items[0]); 573 IM_DrawPercent(640 - SP_STATSX, SP_STATSY + 2 * lh, cnt_secret[0]); 574 IM_DrawTime(SP_TIMEX, SP_TIMEY, cnt_time, "time: ", true); 575 if (cnt_time >= 0 && ClGame.cl.Level.ParTime) 576 IM_DrawTime(SP_PARX, SP_PARY, ClGame.cl.Level.ParTime, "par: ", false); 577} 578 579//========================================================================== 580// 581// IM_UpdateSingleStats 582// 583//========================================================================== 584 585void IM_UpdateSingleStats(float DeltaTime) 586{ 587 if (ClGame.skipintermission && sp_state != 10) 588 { 589 ClGame.skipintermission = 0; 590 cnt_kills[0] = (ClGame.cl.KillCount * 100) / TotalKills; 591 cnt_items[0] = (ClGame.cl.ItemCount * 100) / TotalItems; 592 cnt_secret[0] = (ClGame.cl.SecretCount * 100) / TotalSecret; 593 cnt_time = ftoi(ClGame.GLevel.LevelInfo.CompletitionTime); 594 LocalSound('weapons/rocklx'); 595 sp_state = 10; 596 } 597 598 if (sp_state == 2) 599 { 600 cnt_kills[0] += 2; 601 602 if (!(ftoi(btime * 35.0) & 3)) 603 LocalSound('weapons/pistol'); 604 605 if (cnt_kills[0] >= (ClGame.cl.KillCount * 100) / TotalKills) 606 { 607 cnt_kills[0] = (ClGame.cl.KillCount * 100) / TotalKills; 608 LocalSound('weapons/rocklx'); 609 sp_state++; 610 } 611 } 612 else if (sp_state == 4) 613 { 614 cnt_items[0] += 2; 615 616 if (!(ftoi(btime * 35.0) & 3)) 617 LocalSound('weapons/pistol'); 618 619 if (cnt_items[0] >= (ClGame.cl.ItemCount * 100) / TotalItems) 620 { 621 cnt_items[0] = (ClGame.cl.ItemCount * 100) / TotalItems; 622 LocalSound('weapons/rocklx'); 623 sp_state++; 624 } 625 } 626 else if (sp_state == 6) 627 { 628 cnt_secret[0] += 2; 629 630 if (!(ftoi(btime * 35.0) & 3)) 631 LocalSound('weapons/pistol'); 632 633 if (cnt_secret[0] >= (ClGame.cl.SecretCount * 100) / TotalSecret) 634 { 635 cnt_secret[0] = (ClGame.cl.SecretCount * 100) / TotalSecret; 636 LocalSound('weapons/rocklx'); 637 sp_state++; 638 } 639 } 640 641 else if (sp_state == 8) 642 { 643 if (!(ftoi(btime * 35.0) & 3)) 644 LocalSound('weapons/pistol'); 645 646 cnt_time += 3; 647 648 if (cnt_time >= ftoi(ClGame.GLevel.LevelInfo.CompletitionTime)) 649 { 650 cnt_time = ftoi(ClGame.GLevel.LevelInfo.CompletitionTime); 651 LocalSound('weapons/rocklx'); 652 sp_state++; 653 } 654 } 655 else if (sp_state == 10) 656 { 657 if (ClGame.skipintermission) 658 { 659 LocalSound('weapons/shotgr'); 660 661#ifdef DOOM2 662 IM_InitNoState(); 663#else 664 IM_InitNextLoc(); 665#endif 666 } 667 } 668 else if (sp_state & 1) 669 { 670 cnt_pause -= DeltaTime; 671 if (cnt_pause <= 0.0) 672 { 673 sp_state++; 674 cnt_pause = 1.0; 675 } 676 } 677 678} 679 680//========================================================================== 681// 682// IM_InitCooperativeStats 683// 684//========================================================================== 685 686void IM_InitCooperativeStats() 687{ 688 int i; 689 690 interstate = IMS_Stats; 691 ClGame.skipintermission = 0; 692 ng_state = 1; 693 694 cnt_pause = 1.0; 695 696 for (i = 0; i < MAXPLAYERS; i++) 697 { 698 cnt_kills[i] = 0; 699 cnt_items[i] = 0; 700 cnt_secret[i] = 0; 701 cnt_frags[i] = 0; 702 } 703 704 if (ClGame.cl.Level.bNoIntermission) 705 { 706 interstate = IMS_NoState; 707 } 708} 709 710//========================================================================== 711// 712// IM_DrawCooperativeStats 713// 714//========================================================================== 715 716void IM_DrawCooperativeStats() 717{ 718 int i; 719 int x; 720 int y; 721 int pwidth; 722 picinfo_t info; 723 PlayerReplicationInfo RepInfo; 724 725 pwidth = TextWidth("%"); 726 727 IM_DrawLF(); 728 729 SetTextAlign(hright, vtop); 730 // draw stat titles (top line) 731 DrawText(NG_STATSX + NG_SPACINGX, NG_STATSY, "kills"); 732 733 DrawText(NG_STATSX + 2 * NG_SPACINGX, NG_STATSY, "items"); 734 735 DrawText(NG_STATSX + 3 * NG_SPACINGX, NG_STATSY, "scrt"); 736 737 DrawText(NG_STATSX + 4 * NG_SPACINGX, NG_STATSY, "frgs"); 738 739 // draw stats 740 y = NG_STATSY + TextHeight("kills"); 741 742 foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo) 743 { 744 i = RepInfo.PlayerNum; 745 x = NG_STATSX; 746 R_GetPicInfo(p[i], &info); 747 DrawPic(x - info.width, y, p[i]); 748 749 if (i == ClGame.cl.ClientNum) 750 DrawPic(x - info.width, y, star); 751 752 x += NG_SPACINGX; 753 IM_DrawPercent(x - pwidth, y + 10, cnt_kills[i]); 754 x += NG_SPACINGX; 755 IM_DrawPercent(x - pwidth, y + 10, cnt_items[i]); 756 x += NG_SPACINGX; 757 IM_DrawPercent(x - pwidth, y + 10, cnt_secret[i]); 758 x += NG_SPACINGX; 759 760 SetTextAlign(hright, vtop); 761 DrawText(x, y + 10, va("%d", cnt_frags[i])); 762 763 y += WI_SPACINGY; 764 } 765} 766 767//========================================================================== 768// 769// IM_UpdateCooperativeStats 770// 771//========================================================================== 772 773void IM_UpdateCooperativeStats(float DeltaTime) 774{ 775 int fsum; 776 PlayerReplicationInfo RepInfo; 777 778 bool stillticking; 779 780 if (ClGame.skipintermission && ng_state != 10) 781 { 782 ClGame.skipintermission = 0; 783 784 foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo) 785 { 786 cnt_kills[RepInfo.PlayerNum] = (RepInfo.KillCount * 100) / TotalKills; 787 cnt_items[RepInfo.PlayerNum] = (RepInfo.ItemCount * 100) / TotalItems; 788 cnt_secret[RepInfo.PlayerNum] = (RepInfo.SecretCount * 100) / TotalSecret; 789 cnt_frags[RepInfo.PlayerNum] = RepInfo.Frags; 790 } 791 LocalSound('weapons/rocklx'); 792 ng_state = 10; 793 } 794 795 if (ng_state == 2) 796 { 797 if (!(ftoi(btime * 35.0) & 3)) 798 LocalSound('weapons/pistol'); 799 800 stillticking = false; 801 802 foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo) 803 { 804 cnt_kills[RepInfo.PlayerNum] += 2; 805 806 if (cnt_kills[RepInfo.PlayerNum] >= (RepInfo.KillCount * 100) / TotalKills) 807 cnt_kills[RepInfo.PlayerNum] = (RepInfo.KillCount * 100) / TotalKills; 808 else 809 stillticking = true; 810 } 811 812 if (!stillticking) 813 { 814 LocalSound('weapons/rocklx'); 815 ng_state++; 816 } 817 } 818 else if (ng_state == 4) 819 { 820 if (!(ftoi(btime * 35.0) & 3)) 821 LocalSound('weapons/pistol'); 822 823 stillticking = false; 824 825 foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo) 826 { 827 cnt_items[RepInfo.PlayerNum] += 2; 828 if (cnt_items[RepInfo.PlayerNum] >= (RepInfo.ItemCount * 100) / TotalItems) 829 cnt_items[RepInfo.PlayerNum] = (RepInfo.ItemCount * 100) / TotalItems; 830 else 831 stillticking = true; 832 } 833 if (!stillticking) 834 { 835 LocalSound('weapons/rocklx'); 836 ng_state++; 837 } 838 } 839 else if (ng_state == 6) 840 { 841 if (!(ftoi(btime * 35.0) & 3)) 842 LocalSound('weapons/pistol'); 843 844 stillticking = false; 845 846 foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo) 847 { 848 cnt_secret[RepInfo.PlayerNum] += 2; 849 850 if (cnt_secret[RepInfo.PlayerNum] >= RepInfo.SecretCount * 100 / TotalSecret) 851 cnt_secret[RepInfo.PlayerNum] = RepInfo.SecretCount * 100 / TotalSecret; 852 else 853 stillticking = true; 854 } 855 856 if (!stillticking) 857 { 858 LocalSound('weapons/rocklx'); 859 ng_state += 1; 860 } 861 } 862 else if (ng_state == 8) 863 { 864 if (!(ftoi(btime * 35.0) & 3)) 865 LocalSound('weapons/pistol'); 866 867 stillticking = false; 868 869 foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo) 870 { 871 cnt_frags[RepInfo.PlayerNum] += 1; 872 873 if (cnt_frags[RepInfo.PlayerNum] >= RepInfo.Frags) 874 cnt_frags[RepInfo.PlayerNum] = RepInfo.Frags; 875 else 876 stillticking = true; 877 } 878 879 if (!stillticking) 880 { 881 LocalSound('*death'); 882 ng_state++; 883 } 884 } 885 else if (ng_state == 10) 886 { 887 if (ClGame.skipintermission) 888 { 889 LocalSound('weapons/shotgr'); 890#ifdef DOOM2 891 IM_InitNoState(); 892#else 893 IM_InitNextLoc(); 894#endif 895 } 896 } 897 else if (ng_state & 1) 898 { 899 cnt_pause -= DeltaTime; 900 if (cnt_pause <= 0.0) 901 { 902 ng_state++; 903 cnt_pause = 1.0; 904 } 905 } 906} 907 908//========================================================================== 909// 910// IM_InitDeathmatchStats 911// 912//========================================================================== 913 914void IM_InitDeathmatchStats() 915{ 916 int i; 917 int j; 918 PlayerReplicationInfo RepInfo; 919 920 interstate = IMS_Stats; 921 ClGame.skipintermission = 0; 922 dm_state = 1; 923 924 cnt_pause = 1.0; 925 926 foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo) 927 { 928 i = RepInfo.PlayerNum; 929 dm_Frags[i] = 0; 930 dm_Deaths[i] = 0; 931 } 932} 933 934//========================================================================== 935// 936// IM_DrawDeathmatchStats 937// 938//========================================================================== 939 940void IM_DrawDeathmatchStats() 941{ 942 int y; 943 picinfo_t info; 944 PlayerReplicationInfo RepInfo; 945 946 IM_DrawLF(); 947 948 SetTextAlign(hcentre, vtop); 949 // draw stat titles (top line) 950 DrawText(DM_TOTALSX, DM_MATRIXY - WI_SPACINGY, "FRAGS"); 951 DrawText(DM_DEATHSX, DM_MATRIXY - WI_SPACINGY, "DEATHS"); 952 953 // draw stats 954 y = DM_MATRIXY; 955 956 foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo) 957 { 958 if (RepInfo.PlayerNum == ClGame.cl.ClientNum) 959 { 960 R_GetPicInfo(star, &info); 961 DrawPic(DM_MATRIXX - info.width - 5, y - 8, star); 962 } 963 SetTextAlign(hleft, vtop); 964 SetFont('smallfont'); 965 DrawText(DM_MATRIXX, y + 5, RepInfo.PlayerName); 966 SetTextAlign(hright, vtop); 967 SetFont('bigfont'); 968 DrawText(DM_TOTALSX, y, va("%d", dm_Frags[RepInfo.PlayerNum])); 969 DrawText(DM_DEATHSX, y, va("%d", dm_Deaths[RepInfo.PlayerNum])); 970 y += 24; 971 } 972} 973 974//========================================================================== 975// 976// IM_UpdateDeathmatchStats 977// 978//========================================================================== 979 980void IM_UpdateDeathmatchStats(float DeltaTime) 981{ 982 int i; 983 984 bool stillticking; 985 PlayerReplicationInfo RepInfo; 986 987 if (ClGame.skipintermission && dm_state != 4) 988 { 989 ClGame.skipintermission = 0; 990 991 foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo) 992 { 993 dm_Frags[RepInfo.PlayerNum] = RepInfo.Frags; 994 dm_Deaths[RepInfo.PlayerNum] = RepInfo.Deaths; 995 } 996 997 LocalSound('weapons/rocklx'); 998 dm_state = 4; 999 } 1000 1001 if (dm_state == 2) 1002 { 1003 if (!(ftoi(btime * 35.0) & 3)) 1004 LocalSound('weapons/pistol'); 1005 1006 stillticking = false; 1007 1008 foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo) 1009 { 1010 i = RepInfo.PlayerNum; 1011 if (dm_Frags[i] != RepInfo.Frags) 1012 { 1013 if (RepInfo.Frags < 0) 1014 dm_Frags[i]--; 1015 else 1016 dm_Frags[i]++; 1017 1018 stillticking = true; 1019 } 1020 if (dm_Deaths[i] != RepInfo.Deaths) 1021 { 1022 if (RepInfo.Deaths < 0) 1023 dm_Deaths[i]--; 1024 else 1025 dm_Deaths[i]++; 1026 1027 stillticking = true; 1028 } 1029 } 1030 if (!stillticking) 1031 { 1032 LocalSound('weapons/rocklx'); 1033 dm_state++; 1034 } 1035 1036 } 1037 else if (dm_state == 4) 1038 { 1039 if (ClGame.skipintermission) 1040 { 1041 LocalSound('misc/gibbed'); 1042 1043#ifdef DOOM2 1044 IM_InitNoState(); 1045#else 1046 IM_InitNextLoc(); 1047#endif 1048 } 1049 } 1050 else if (dm_state & 1) 1051 { 1052 cnt_pause -= DeltaTime; 1053 if (cnt_pause <= 0.0) 1054 { 1055 dm_state++; 1056 cnt_pause = 1.0; 1057 } 1058 } 1059} 1060 1061#ifndef DOOM2 1062 1063//========================================================================== 1064// 1065// IM_InitNextLoc 1066// 1067//========================================================================== 1068 1069void IM_InitNextLoc() 1070{ 1071 interstate = IMS_NextLoc; 1072 ClGame.skipintermission = 0; 1073 cnt = SHOWNEXTLOCDELAY; 1074 1075 IM_InitAnimatedBack(); 1076} 1077 1078//========================================================================== 1079// 1080// IM_DrawNextLoc 1081// 1082//========================================================================== 1083 1084void IM_DrawNextLoc() 1085{ 1086 // draws which level you are entering.. 1087 IM_DrawEL(); 1088} 1089 1090//========================================================================== 1091// 1092// IM_UpdateNextLoc 1093// 1094//========================================================================== 1095 1096void IM_UpdateNextLoc(float DeltaTime) 1097{ 1098 cnt -= DeltaTime; 1099 if (cnt <= 0.0 || ClGame.skipintermission) 1100 IM_InitNoState(); 1101} 1102 1103#endif 1104 1105//========================================================================== 1106// 1107// IM_InitNoState 1108// 1109//========================================================================== 1110 1111void IM_InitNoState() 1112{ 1113 interstate = IMS_NoState; 1114 ClGame.skipintermission = 0; 1115 cnt = 0.3; 1116} 1117 1118//========================================================================== 1119// 1120// IM_DrawNoState 1121// 1122//========================================================================== 1123 1124void IM_DrawNoState() 1125{ 1126#ifdef DOOM2 1127 // draws which level you are entering.. 1128 if (ClGame.im.LeaveMap != 'map30') 1129 { 1130 IM_DrawEL(); 1131 } 1132#else 1133 IM_DrawNextLoc(); 1134#endif 1135} 1136 1137//========================================================================== 1138// 1139// IM_UpdateNoState 1140// 1141//========================================================================== 1142 1143void IM_UpdateNoState(float DeltaTime) 1144{ 1145 cnt -= DeltaTime; 1146 if (cnt <= 0.0) 1147 { 1148 IM_UnloadData(); 1149 IM_InitText(); 1150 } 1151} 1152 1153//========================================================================== 1154// 1155// 1156// 1157//========================================================================== 1158 1159// specifies current state 1160float intertime; 1161 1162float HubCount; 1163string HubText; 1164 1165name TextFlat; 1166int TextPic; 1167 1168//========================================================================== 1169// 1170// IM_InitText 1171// 1172//========================================================================== 1173 1174void IM_InitText() 1175{ 1176 if (ClGame.deathmatch || !ClGame.im.Text) 1177 { 1178 CmdBuf_AddText("TeleportNewMap\n"); 1179 interstate = IMS_Done; 1180 Background.State = IntermissionBackground::STATE_Done; 1181 return; 1182 } 1183 1184 if (ClGame.im.bTextIsLump) 1185 { 1186 HubText = LoadTextLump(StrToName(ClGame.im.Text)); 1187 } 1188 else 1189 { 1190 HubText = ClGame.im.Text; 1191 } 1192 HubCount = itof(strlen(HubText)) * TEXTSPEED + TEXTWAIT; 1193 1194 TextFlat = ''; 1195 TextPic = 0; 1196 if (ClGame.im.TextPic) 1197 { 1198 TextPic = R_RegisterPic(ClGame.im.TextPic); 1199 } 1200 else if (ClGame.im.TextFlat) 1201 { 1202 TextFlat = ClGame.im.TextFlat; 1203 } 1204 1205 interstate = IMS_Text; 1206 intertime = 0.0; 1207 1208 if (ClGame.im.TextMusic) 1209 { 1210 CmdBuf_AddText(va("music loop %n\n", ClGame.im.TextMusic)); 1211 } 1212 else 1213 { 1214#ifdef DOOM2 1215#ifdef FIXME 1216 S_StartSong("d_read_m", P_GetCDEnd1Track(), true); 1217#else 1218 CmdBuf_AddText("music loop d_read_m\n"); 1219#endif 1220#else 1221#ifdef FIXME 1222 S_StartSong("D_VICTOR", P_GetCDEnd1Track(), true); 1223#else 1224 CmdBuf_AddText("music loop D_VICTOR\n"); 1225#endif 1226#endif 1227 } 1228} 1229 1230//========================================================================== 1231// 1232// IM_DrawText 1233// 1234//========================================================================== 1235 1236void IM_DrawText() 1237{ 1238 int count; 1239 1240 // erase the entire screen to a tiled background 1241 if (TextPic) 1242 { 1243 DrawFullScreenPic(TextPic); 1244 } 1245 else if (TextFlat) 1246 { 1247 FillRectWithFlat(0, 0, 640, 480, TextFlat); 1248 } 1249 else 1250 { 1251 R_FillRect(0, 0, 640, 480, 0); 1252 } 1253 1254 // draw some of the text onto the screen 1255 count = ftoi((intertime - 0.3) / TEXTSPEED); 1256 if (count < 0) 1257 count = 0; 1258 if (count > strlen(HubText)) 1259 count = strlen(HubText); 1260 1261 SetFont('smallfont'); 1262 SetTextAlign(hleft, vtop); 1263 DrawText(170, 150, substr(HubText, 0, count)); 1264} 1265 1266//========================================================================== 1267// 1268// IM_UpdateText 1269// 1270//========================================================================== 1271 1272void IM_UpdateText(float DeltaTime) 1273{ 1274 intertime += DeltaTime; 1275 if (ClGame.skipintermission || intertime > HubCount) 1276 { 1277 ClGame.skipintermission = false; 1278 CmdBuf_AddText("TeleportNewMap\n"); 1279 interstate = IMS_Done; 1280 Background.State = IntermissionBackground::STATE_Done; 1281 } 1282} 1283 1284//========================================================================== 1285// 1286// OnVisibilityChanged 1287// 1288//========================================================================== 1289 1290void OnVisibilityChanged(bool bNewVisibility) 1291{ 1292 bTickEnabled = bNewVisibility; 1293 if (Background) 1294 { 1295 Background.bTickEnabled = bNewVisibility; 1296 } 1297} 1298 1299defaultproperties 1300{ 1301 bTickEnabled = true; 1302 Focusable = true; 1303 Width = 640; 1304 Height = 480; 1305} 1306