PageRenderTime 512ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/v1.13.124/cockpit/hud.cpp

https://github.com/simX/d2x-xl
C++ | 395 lines | 312 code | 40 blank | 43 comment | 98 complexity | 9edee7f48b744390d760d2f2208aa19f MD5 | raw file
Possible License(s): GPL-2.0
  1. /* $Id: hud.c,v 1.8 2003/10/10 09:36:35 btb Exp $ */
  2. /*
  3. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  4. SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  5. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  6. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  7. IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  8. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  9. FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  10. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  11. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  12. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  13. */
  14. #ifdef HAVE_CONFIG_H
  15. #include <conf.h>
  16. #endif
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include <stdlib.h>
  20. #include "inferno.h"
  21. #include "u_mem.h"
  22. #include "strutil.h"
  23. #include "gauges.h"
  24. #include "error.h"
  25. #include "newdemo.h"
  26. #include "gamefont.h"
  27. #include "screens.h"
  28. #include "text.h"
  29. #include "args.h"
  30. void CopyBackgroundRect (int left,int top,int right,int bot);
  31. char szDisplayedBackgroundMsg [2][HUD_MESSAGE_LENGTH] = {"",""};
  32. int nLastMsgYCrd = -1;
  33. int nLastMsgHeight = 6;
  34. int bMSGPlayerMsgs = 0;
  35. int bNoMsgRedundancy = 0;
  36. int nModexHUDMsgs;
  37. gsrCanvas *PrintToCanvas (char *s,grsFont *font, unsigned int fc, unsigned int bc, int doubleFlag);
  38. // ----------------------------------------------------------------------------
  39. void ClearBackgroundMessages (void)
  40. {
  41. if (((gameStates.render.cockpit.nMode == CM_STATUS_BAR) || (gameStates.render.cockpit.nMode == CM_FULL_SCREEN)) &&
  42. (nLastMsgYCrd != -1) && (gameStates.render.vr.buffers.subRender [0].cvBitmap.bmProps.y >= 6)) {
  43. gsrCanvas *canv_save = grdCurCanv;
  44. GrSetCurrentCanvas (GetCurrentGameScreen ());
  45. CopyBackgroundRect (0, nLastMsgYCrd, grdCurCanv->cvBitmap.bmProps.w, nLastMsgYCrd+nLastMsgHeight-1);
  46. GrSetCurrentCanvas (canv_save);
  47. nLastMsgYCrd = -1;
  48. }
  49. szDisplayedBackgroundMsg [gameStates.render.vr.nCurrentPage][0] = 0;
  50. }
  51. // -----------------------------------------------------------------------------
  52. void HUDClearMessages ()
  53. {
  54. int i, j;
  55. tHUDMessage *pMsgs;
  56. for (j = 2, pMsgs = gameData.hud.msgs; j; j--, pMsgs++) {
  57. pMsgs->nMessages = 0;
  58. pMsgs->nFirst =
  59. pMsgs->nLast = 0;
  60. pMsgs->xTimer = 0;
  61. ClearBackgroundMessages ();
  62. for (i = 0; i < HUD_MAX_MSGS; i++)
  63. #if 1
  64. *pMsgs->szMsgs [i] = '\0';
  65. #else
  66. sprintf (pMsgs->szMsgs [i], TXT_SLAGEL);
  67. #endif
  68. }
  69. }
  70. // -----------------------------------------------------------------------------
  71. // print to buffer, double heights, and blit bitmap to screen
  72. void HUDModexMessage (int x, int y, char *s, grsFont *font, unsigned int color)
  73. {
  74. gsrCanvas *tempCanv = PrintToCanvas (s, font, color, 0, 1);
  75. GrBitmapM (x, y, &tempCanv->cvBitmap, 2);
  76. GrFreeCanvas (tempCanv);
  77. }
  78. // ----------------------------------------------------------------------------
  79. void HUDRenderMessages (ubyte nType)
  80. {
  81. int h, i, n, w, y, aw, yStart, nMsg;
  82. char *pszMsg;
  83. tHUDMessage *pMsgs = gameData.hud.msgs + nType;
  84. if ((pMsgs->nMessages < 0) || (pMsgs->nMessages > HUD_MAX_MSGS))
  85. return; // Get Rob!
  86. if ((pMsgs->nMessages < 1) && (nModexHUDMsgs == 0))
  87. return;
  88. pMsgs->xTimer -= gameData.time.xFrame;
  89. if (pMsgs->xTimer < 0) {
  90. // Timer expired... get rid of oldest pszMsg...
  91. if (pMsgs->nLast != pMsgs->nFirst) {
  92. int temp;
  93. //&pMsgs->szMsgs.szMsg [pMsgs->nFirst][0] is deing deleted...;
  94. pMsgs->nFirst = (pMsgs->nFirst + 1) % HUD_MAX_MSGS;
  95. pMsgs->xTimer = F1_0*2;
  96. if (!--pMsgs->nMessages)
  97. nModexHUDMsgs = 2;
  98. temp = nLastMsgYCrd;
  99. ClearBackgroundMessages (); // If in status bar mode and no messages, then erase.
  100. if (nModexHUDMsgs)
  101. nLastMsgYCrd = temp;
  102. }
  103. }
  104. if (pMsgs->nMessages > 0) {
  105. if (pMsgs->nColor == (unsigned int) -1)
  106. pMsgs->nColor = GREEN_RGBA;
  107. if ((gameStates.render.vr.nRenderMode == VR_NONE) && ((gameStates.render.cockpit.nMode == CM_STATUS_BAR) ||
  108. (gameStates.render.cockpit.nMode == CM_FULL_SCREEN)) && (gameStates.render.vr.buffers.subRender [0].cvBitmap.bmProps.y >= (gameData.render.window.hMax/8))) {
  109. // Only display the most recent pszMsg in this mode
  110. nMsg = (pMsgs->nFirst + pMsgs->nMessages-1) % HUD_MAX_MSGS;
  111. pszMsg = pMsgs->szMsgs [nMsg];
  112. if (strcmp (szDisplayedBackgroundMsg [gameStates.render.vr.nCurrentPage], pszMsg)) {
  113. gsrCanvas *canv_save = grdCurCanv;
  114. int ycrd = grdCurCanv->cvBitmap.bmProps.y - (SMALL_FONT->ftHeight+2);
  115. if (ycrd < 0)
  116. ycrd = 0;
  117. GrSetCurrentCanvas (GetCurrentGameScreen ());
  118. GrSetCurFont (SMALL_FONT);
  119. GrGetStringSize (pszMsg, &w, &h, &aw);
  120. ClearBackgroundMessages ();
  121. if (grdCurCanv->cvBitmap.bmProps.nType == BM_MODEX) {
  122. ycrd -= h;
  123. h *= 2;
  124. HUDModexMessage ((grdCurCanv->cvBitmap.bmProps.w-w)/2, ycrd, pszMsg, SMALL_FONT, pMsgs->nColor);
  125. if (nModexHUDMsgs > 0) {
  126. nModexHUDMsgs--;
  127. szDisplayedBackgroundMsg [gameStates.render.vr.nCurrentPage][0] = '!';
  128. }
  129. else
  130. strcpy (szDisplayedBackgroundMsg [gameStates.render.vr.nCurrentPage], pszMsg);
  131. }
  132. else {
  133. if (pMsgs->nColor == (unsigned int) -1)
  134. pMsgs->nColor = GREEN_RGBA;
  135. GrSetFontColorRGBi (pMsgs->nColor, 1, 0, 0);
  136. pMsgs->nMsgIds [nMsg] = GrPrintF (pMsgs->nMsgIds + nMsg, (grdCurCanv->cvBitmap.bmProps.w-w) / 2, ycrd, pszMsg);
  137. strcpy (szDisplayedBackgroundMsg [gameStates.render.vr.nCurrentPage], pszMsg);
  138. }
  139. GrSetCurrentCanvas (canv_save);
  140. nLastMsgYCrd = ycrd;
  141. nLastMsgHeight = h;
  142. }
  143. }
  144. else {
  145. GrSetCurFont (SMALL_FONT);
  146. if ((gameStates.render.cockpit.nMode == CM_FULL_SCREEN) ||
  147. (gameStates.render.cockpit.nMode == CM_LETTERBOX)) {
  148. if (gameData.render.window.w == gameData.render.window.wMax)
  149. yStart = SMALL_FONT->ftHeight / 2;
  150. else
  151. yStart= SMALL_FONT->ftHeight * 2;
  152. }
  153. else
  154. yStart = SMALL_FONT->ftHeight / 2;
  155. if (gameOpts->render.cockpit.bGuidedInMainView) {
  156. tGuidedMissileInfo *gmiP = gameData.objs.guidedMissile + gameData.multiplayer.nLocalPlayer;
  157. tObject *gmObjP = gmiP->objP;
  158. if (gmObjP &&
  159. (gmObjP->info.nType == OBJ_WEAPON) &&
  160. (gmObjP->info.nId == GUIDEDMSL_ID) &&
  161. (gmObjP->info.nSignature == gmiP->nSignature))
  162. yStart += SMALL_FONT->ftHeight + 3;
  163. }
  164. for (i = 0, y = yStart; i < pMsgs->nMessages; i++) {
  165. n = (pMsgs->nFirst + i) % HUD_MAX_MSGS;
  166. if ((n < 0) || (n >= HUD_MAX_MSGS))
  167. return; // Get Rob!!
  168. if (!strcmp (pMsgs->szMsgs [n], "This is a bug."))
  169. return; // Get Rob!!
  170. GrGetStringSize (pMsgs->szMsgs [n], &w, &h, &aw);
  171. GrSetFontColorRGBi (pMsgs->nColor, 1, 0, 0);
  172. y = yStart + i * (h + 1);
  173. if (nType)
  174. y += ((2 * HUD_MAX_MSGS - 1) * (h + 1)) / 2;
  175. #if 1
  176. GrString ((grdCurCanv->cvBitmap.bmProps.w-w)/2, y, pMsgs->szMsgs [n], NULL);
  177. #else
  178. pMsgs->nMsgIds [n] = GrString ((grdCurCanv->cvBitmap.bmProps.w-w)/2, y, pMsgs->szMsgs [n], pMsgs->nMsgIds + n);
  179. #endif
  180. if (!gameOpts->render.cockpit.bSplitHUDMsgs)
  181. y += h + 1;
  182. }
  183. }
  184. }
  185. else if (GetCurrentGameScreen ()->cvBitmap.bmProps.nType == BM_MODEX) {
  186. if (nModexHUDMsgs) {
  187. int temp = nLastMsgYCrd;
  188. nModexHUDMsgs--;
  189. ClearBackgroundMessages (); // If in status bar mode and no messages, then erase.
  190. nLastMsgYCrd = temp;
  191. }
  192. }
  193. GrSetCurFont (GAME_FONT);
  194. }
  195. // ----------------------------------------------------------------------------
  196. // Writes a pszMsg on the HUD and checks its timer.
  197. void HUDRenderMessageFrame (void)
  198. {
  199. HUDRenderMessages (0);
  200. if (gameOpts->render.cockpit.bSplitHUDMsgs)
  201. HUDRenderMessages (1);
  202. }
  203. //------------------------------------------------------------------------------
  204. // Call to flash a message on the HUD. Returns true if message drawn.
  205. // (pszMsg might not be drawn if previous pszMsg was same)
  206. int HUDInitMessageVA (ubyte nType, const char * format, va_list args)
  207. {
  208. tHUDMessage *pMsgs = gameData.hud.msgs + (gameOpts->render.cockpit.bSplitHUDMsgs ? nType : 0);
  209. int temp;
  210. char *pszMsg = NULL,
  211. *pszLastMsg = NULL;
  212. char con_message [HUD_MESSAGE_LENGTH + 3];
  213. if (!gameOpts->render.cockpit.bHUDMsgs)
  214. return 0;
  215. nModexHUDMsgs = 2;
  216. if ((pMsgs->nLast < 0) || (pMsgs->nLast >= HUD_MAX_MSGS))
  217. return 0; // Get Rob!!
  218. pszMsg = pMsgs->szMsgs [pMsgs->nLast];
  219. vsprintf (pszMsg, format, args);
  220. /* Produce a colorised version and send it to the console */
  221. con_message [0] = CC_COLOR;
  222. if (pMsgs->nColor != (unsigned int) -1) {
  223. con_message [1] = (char) RGBA_RED (pMsgs->nColor) / 2 + 128;
  224. con_message [2] = (char) RGBA_GREEN (pMsgs->nColor) / 2 + 128;
  225. con_message [3] = (char) RGBA_BLUE (pMsgs->nColor) / 2 + 128;
  226. }
  227. else if (nType) {
  228. con_message [1] = (char) (127 + 128);
  229. con_message [2] = (char) (95 + 128);
  230. con_message [3] = (char) (0 + 128);
  231. }
  232. else {
  233. con_message [1] = (char) (0 + 128);
  234. con_message [3] = (char) (0 + 128);
  235. con_message [2] = (char) (63 + 128);
  236. }
  237. con_message [4] = '\0';
  238. strcat (con_message, pszMsg);
  239. #if TRACE
  240. con_printf (CON_NORMAL, "%s\n", con_message);
  241. #endif
  242. // Added by Leighton
  243. if (IsMultiGame) {
  244. if (gameOpts->multi.bNoRedundancy && !strnicmp ("You already", pszMsg, 11))
  245. return 0;
  246. if (!gameData.hud.bPlayerMessage && FindArg ("-PlayerMessages"))
  247. return 0;
  248. }
  249. if (pMsgs->nMessages > 1) {
  250. pszLastMsg = pMsgs->szMsgs [((pMsgs->nLast - 1) ? pMsgs->nLast : HUD_MAX_MSGS) - 2];
  251. if (pszLastMsg && (!strcmp (pszLastMsg, pszMsg))) {
  252. pMsgs->xTimer = F1_0 * 3; // 1 second per 5 characters
  253. return 0; // ignore since it is the same as the last one
  254. }
  255. }
  256. if (pMsgs->nMessages > 0)
  257. pszLastMsg = pMsgs->szMsgs [(pMsgs->nLast ? pMsgs->nLast : HUD_MAX_MSGS) - 1];
  258. temp = (pMsgs->nLast + 1) % HUD_MAX_MSGS;
  259. if (temp == pMsgs->nFirst) { // If too many messages, remove oldest pszMsg to make room
  260. pMsgs->nFirst = (pMsgs->nFirst + 1) % HUD_MAX_MSGS;
  261. pMsgs->nMessages--;
  262. }
  263. if (pszLastMsg && (!strcmp (pszLastMsg, pszMsg))) {
  264. pMsgs->xTimer = F1_0 * 3; // 1 second per 5 characters
  265. return 0; // ignore since it is the same as the last one
  266. }
  267. pMsgs->nLast = temp;
  268. // Check if memory has been overwritten at this point.
  269. if (strlen (pszMsg) >= HUD_MESSAGE_LENGTH)
  270. Error ("Your message to HUD is too long. Limit is %i characters.\n", HUD_MESSAGE_LENGTH);
  271. #ifdef NEWDEMO
  272. if (gameData.demo.nState == ND_STATE_RECORDING)
  273. NDRecordHUDMessage (pszMsg);
  274. #endif
  275. pMsgs->xTimer = F1_0*3; // 1 second per 5 characters
  276. pMsgs->nMessages++;
  277. return 1;
  278. }
  279. //------------------------------------------------------------------------------
  280. int _CDECL_ HUDInitMessage (const char *format, ...)
  281. {
  282. int ret = 0;
  283. if (gameOpts->render.cockpit.bHUDMsgs) {
  284. va_list args;
  285. va_start (args, format);
  286. ret = HUDInitMessageVA (0, format, args);
  287. va_end (args);
  288. }
  289. return ret;
  290. }
  291. //------------------------------------------------------------------------------
  292. void PlayerDeadMessage (void)
  293. {
  294. if (gameOpts->render.cockpit.bHUDMsgs && gameStates.app.bPlayerExploded) {
  295. tHUDMessage *pMsgs = gameData.hud.msgs;
  296. if (LOCALPLAYER.lives < 2) {
  297. int x, y, w, h, aw;
  298. GrSetCurFont (HUGE_FONT);
  299. GrGetStringSize (TXT_GAME_OVER, &w, &h, &aw);
  300. w += 20;
  301. h += 8;
  302. x = (grdCurCanv->cv_w - w) / 2;
  303. y = (grdCurCanv->cv_h - h) / 2;
  304. gameStates.render.grAlpha = 2 * 7;
  305. GrSetColorRGB (0, 0, 0, 255);
  306. GrRect (x, y, x+w, y+h);
  307. gameStates.render.grAlpha = GR_ACTUAL_FADE_LEVELS;
  308. GrString (0x8000, (grdCurCanv->cv_h - grdCurCanv->cvFont->ftHeight)/2 + h/8, TXT_GAME_OVER, NULL);
  309. #if 0
  310. // Automatically exit death after 10 secs
  311. if (gameData.time.xGame > gameStates.app.nPlayerTimeOfDeath + F1_0*10) {
  312. SetFunctionMode (FMODE_MENU);
  313. gameData.app.nGameMode = GM_GAME_OVER;
  314. __asm int 3; longjmp (gameExitPoint, 1); // Exit out of game loop
  315. }
  316. #endif
  317. }
  318. GrSetCurFont (GAME_FONT);
  319. if (pMsgs->nColor == (unsigned int) -1)
  320. pMsgs->nColor = RGBA_PAL2 (0, 28, 0);
  321. GrSetFontColorRGBi (pMsgs->nColor, 1, 0, 0);
  322. GrString (0x8000, grdCurCanv->cv_h- (grdCurCanv->cvFont->ftHeight+3), TXT_PRESS_ANY_KEY, NULL);
  323. }
  324. }
  325. //------------------------------------------------------------------------------
  326. // void say_afterburner_status (void)
  327. // {
  328. // if (LOCALPLAYER.flags & PLAYER_FLAGS_AFTERBURNER)
  329. // InitHUDMessage ("Afterburner engaged.");
  330. // else
  331. // InitHUDMessage ("Afterburner disengaged.");
  332. // }
  333. void _CDECL_ HUDMessage (int nClass, const char *format, ...)
  334. {
  335. if (gameOpts->render.cockpit.bHUDMsgs &&
  336. (!bNoMsgRedundancy || (nClass & MSGC_NOREDUNDANCY)) &&
  337. (!bMSGPlayerMsgs || !(gameData.app.nGameMode & GM_MULTI) || (nClass & MSGC_PLAYERMESSAGES))) {
  338. va_list vp;
  339. va_start (vp, format);
  340. HUDInitMessageVA (0, format, vp);
  341. va_end (vp);
  342. }
  343. }
  344. //------------------------------------------------------------------------------
  345. void _CDECL_ HUDPlayerMessage (const char *format, ...)
  346. {
  347. va_list vp;
  348. if (gameOpts->render.cockpit.bHUDMsgs) {
  349. va_start (vp, format);
  350. HUDInitMessageVA (1, format, vp);
  351. va_end (vp);
  352. }
  353. }
  354. //------------------------------------------------------------------------------
  355. //eof