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
28enum
29{
30	IMS_Stats,
31	IMS_Text,
32	IMS_Done
33};
34
35ClientGameBase ClGame;
36
37const float TALLY_EFFECT_TIME	= 0.625;
38const float TALLY_FINAL_X_DELTA	= 23.0;
39const float TALLY_FINAL_Y_DELTA	= 13.0;
40const float TALLY_START_XPOS	= 338.0;
41const float TALLY_STOP_XPOS		= 250.0;
42const float TALLY_START_YPOS	= 272.0;
43const float TALLY_STOP_YPOS		= 223.0;
44const int TALLY_TOP_X			= 245;
45const int TALLY_TOP_Y			= 149;
46const int TALLY_LEFT_X			= 167;
47const int TALLY_LEFT_Y			= 211;
48const int TALLY_TOTALS_X		= 451;
49
50float TextSpeed;
51float TextWait;
52name TextFlat;
53int TextPic;
54
55// specifies current state
56int interstate;
57float intertime;
58
59// background (map of levels).
60int patchINTERPIC;
61
62float HubCount;
63string HubText;
64
65// used for general timing
66float cnt;
67
68int slaughterboy;
69
70int tallytop;
71int tallylft;
72
73bool showTotals;
74
75//==========================================================================
76//
77//  Start
78//
79//==========================================================================
80
81void Start()
82{
83	IM_InitStats();
84	IM_LoadPics();
85
86	if (!ClGame.deathmatch && !HubCount)
87	{
88		interstate = IMS_Done;
89		cnt = 0.3;
90	}
91}
92
93//==========================================================================
94//
95//	Tick
96//
97//==========================================================================
98
99void Tick(float DeltaTime)
100{
101	if (interstate == IMS_Done)
102	{
103		if (cnt > 0.0)
104		{
105			cnt -= DeltaTime;
106			if (cnt <= 0.0)
107			{
108				IM_UnloadPics();
109				CmdBuf_AddText("TeleportNewMap\n");
110			}
111		}
112		return;
113	}
114	intertime += DeltaTime;
115	if (ClGame.skipintermission || (!ClGame.deathmatch && !HubCount))
116	{
117		interstate = IMS_Done;
118		cnt = 0.3;
119		ClGame.skipintermission = false;
120	}
121}
122
123//==========================================================================
124//
125//  OnDraw
126//
127//==========================================================================
128
129void OnDraw()
130{
131	if (interstate == IMS_Done)
132	{
133		return;
134	}
135
136	switch (interstate)
137	{
138	case IMS_Stats:
139		IM_DrawDeathTally();
140		break;
141
142	case IMS_Text:
143		IM_DrawHubText();
144	}
145}
146
147//========================================================================
148//
149//  IM_LoadPics
150//
151//========================================================================
152
153void IM_LoadPics()
154{
155}
156
157//========================================================================
158//
159//  IM_UnloadPics
160//
161//========================================================================
162
163void IM_UnloadPics()
164{
165}
166
167//========================================================================
168//
169//  IM_InitStats
170//
171//  Initialises the stats for single player mode
172//
173//========================================================================
174
175void IM_InitStats()
176{
177	int i;
178	int j;
179	int slaughterfrags;
180	int posnum;
181	int slaughtercount;
182	int playercount;
183	PlayerReplicationInfo RepInfo;
184	PlayerReplicationInfo Other;
185
186	ClGame.skipintermission = false;
187	intertime = 0.0;
188	if (!ClGame.deathmatch)
189	{
190		if (!ClGame.cl.Level.bNoIntermission)
191		{
192			print("Single player stats are not implemented");
193		}
194		IM_InitHubText();
195	}
196	else
197	{
198		patchINTERPIC = R_RegisterPic('interpic');
199		tallytop = R_RegisterPic('tallytop');
200		tallylft = R_RegisterPic('tallylft');
201
202		interstate = IMS_Stats;
203		slaughterboy = 0;
204		slaughterfrags = -9999;
205		posnum = 0;
206		playercount = 0;
207		slaughtercount = 0;
208		foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo)
209		{
210			i = RepInfo.PlayerNum;
211			playercount++;
212			posnum++;
213			if (RepInfo.Frags > slaughterfrags)
214			{
215				slaughterboy = 1 << i;
216				slaughterfrags = RepInfo.Frags;
217				slaughtercount = 1;
218			}
219			else if (RepInfo.Frags == slaughterfrags)
220			{
221				slaughterboy |= 1 << i;
222				slaughtercount++;
223			}
224		}
225		if (playercount == slaughtercount)
226		{	// don't do the slaughter stuff if everyone is equal
227			slaughterboy = 0;
228		}
229#ifdef FIXME
230		S_StartSong("hub", P_GetCDIntermissionTrack(), true);
231#else
232		CmdBuf_AddText("music loop hub\n");
233#endif
234	}
235}
236
237//========================================================================
238//
239//  IM_InitHubText
240//
241//  Initialises the stats for single player mode
242//
243//========================================================================
244
245void IM_InitHubText()
246{
247	interstate = IMS_Text;
248	HubCount = 0.0;
249	if (ClGame.im.Text)
250	{
251		if (ClGame.im.bTextIsLump)
252		{
253			HubText = LoadTextLump(StrToName(ClGame.im.Text));
254		}
255		else
256		{
257			HubText = ClGame.im.Text;
258		}
259		HubCount = itof(strlen(HubText)) * TextSpeed + TextWait;
260
261		TextFlat = '';
262		TextPic = 0;
263		if (ClGame.im.TextPic)
264		{
265			TextPic = R_RegisterPic(ClGame.im.TextPic);
266		}
267		else if (ClGame.im.TextFlat)
268		{
269			TextFlat = ClGame.im.TextFlat;
270		}
271
272		if (ClGame.im.TextMusic)
273		{
274			CmdBuf_AddText(va("music loop %n\n", ClGame.im.TextMusic));
275		}
276		else
277		{
278#ifdef FIXME
279			S_StartSong("hub", P_GetCDIntermissionTrack(), true);
280#else
281			CmdBuf_AddText("music loop hub\n");
282#endif
283		}
284	}
285}
286
287//===========================================================================
288//
289//  IM_DrawHubText
290//
291//===========================================================================
292
293void IM_DrawHubText()
294{
295	if (TextPic)
296	{
297		DrawFullScreenPic(TextPic);
298	}
299	else if (TextFlat)
300	{
301		FillRectWithFlat(0, 0, 640, 480, TextFlat);
302	}
303	else
304	{
305		R_FillRect(0, 0, 640, 480, 0);
306	}
307	int count = ftoi((intertime - 0.3) / TextSpeed);
308	if (count < 0)
309	{
310		count = 0;
311	}
312	if (count > strlen(HubText))
313	{
314		count = strlen(HubText);
315	}
316	SetFont('smallfont');
317	SetTextAlign(hleft, vtop);
318	DrawText(170, 145, substr(HubText, 0, count));
319}
320
321//==========================================================================
322//
323//  IM_DrawNumber
324//
325//==========================================================================
326
327void IM_DrawNumber(int val, int x, int y, int wrapThresh)
328{
329	SetFont('smallfont');
330	SetTextAlign(hcentre, vtop);
331	if (!(val < -9 && wrapThresh < 1000))
332	{
333		DrawText(x, y, va("%d",
334				val >= wrapThresh ? val % wrapThresh : val));
335	}
336	else
337	{
338		DrawText(x, y, "XX");
339	}
340}
341
342//==========================================================================
343//
344//  IM_DrawNumberBold
345//
346//==========================================================================
347
348void IM_DrawNumberBold(int val, int x, int y, int wrapThresh)
349{
350	SetFont('smallfont');
351	SetTextAlign(hcentre, vtop);
352	if (!(val < -9 && wrapThresh < 1000))
353	{
354		DrawText(x, y, va("%d", val >= wrapThresh ? val % wrapThresh : val), CR_YELLOW);
355	}
356	else
357	{
358		DrawText(x, y, "XX", CR_YELLOW);
359	}
360}
361
362//========================================================================
363//
364//  IM_DrawDeathTally
365//
366//========================================================================
367
368void IM_DrawDeathTally()
369{
370	int i, j;
371	float xPos, yPos;
372	float xDelta, yDelta;
373	float xStart, scale;
374	int x, y;
375	bool bold;
376	PlayerReplicationInfo RepInfo;
377	PlayerReplicationInfo Other;
378
379	DrawFullScreenPic(patchINTERPIC);
380	if (intertime < TALLY_EFFECT_TIME)
381	{
382		showTotals = false;
383		scale = intertime / TALLY_EFFECT_TIME;
384		xDelta = scale * TALLY_FINAL_X_DELTA;
385		yDelta = scale * TALLY_FINAL_Y_DELTA;
386		xStart = TALLY_START_XPOS -
387			scale * (TALLY_START_XPOS - TALLY_STOP_XPOS);
388		yPos = TALLY_START_YPOS -
389			scale * (TALLY_START_YPOS - TALLY_STOP_YPOS);
390	}
391	else
392	{
393		xDelta = TALLY_FINAL_X_DELTA;
394		yDelta = TALLY_FINAL_Y_DELTA;
395		xStart = TALLY_STOP_XPOS;
396		yPos = TALLY_STOP_YPOS;
397	}
398	if (intertime >= TALLY_EFFECT_TIME && showTotals == false)
399	{
400		showTotals = true;
401		LocalSound('PlatformStop');
402	}
403	y = ftoi(yPos);
404	foreach ClGame.GLevel.LevelInfo.AllThinkers(PlayerReplicationInfo, RepInfo)
405	{
406		i = RepInfo.PlayerNum;
407		xPos = xStart;
408		SetFont('smallfont');
409		SetTextAlign(hleft, vtop);
410		DrawText(ftoi(xPos), y, RepInfo.PlayerName,
411			i == ClGame.cl.ClientNum ? CR_YELLOW : CR_WHITE);
412		if (showTotals && !((slaughterboy & (1 << i)) &&
413			!(ftoi(32.0 * intertime) & 16)))
414		{
415			if (i == ClGame.cl.ClientNum)
416			{
417				IM_DrawNumberBold(RepInfo.Frags, TALLY_TOTALS_X, y, 1000);
418			}
419			else
420			{
421				IM_DrawNumber(RepInfo.Frags, TALLY_TOTALS_X, y, 1000);
422			}
423		}
424		yPos += yDelta;
425		y = ftoi(yPos);
426	}
427}
428
429//==========================================================================
430//
431//	OnVisibilityChanged
432//
433//==========================================================================
434
435void OnVisibilityChanged(bool bNewVisibility)
436{
437	bTickEnabled = bNewVisibility;
438}
439
440defaultproperties
441{
442	bTickEnabled = true;
443	Focusable = true;
444	Width = 640;
445	Height = 480;
446	TextSpeed = 0.1;
447	TextWait = 4.0;
448}
449