cg_newdraw.c 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #ifndef MISSIONPACK // bk001204
  19. #error This file not be used for classic Q3A.
  20. #endif
  21. #include "cg_local.h"
  22. #include "../ui/ui_shared.h"
  23. extern displayContextDef_t cgDC;
  24. // set in CG_ParseTeamInfo
  25. //static int sortedTeamPlayers[TEAM_MAXOVERLAY];
  26. //static int numSortedTeamPlayers;
  27. int drawTeamOverlayModificationCount = -1;
  28. //static char systemChat[256];
  29. //static char teamChat1[256];
  30. //static char teamChat2[256];
  31. void CG_InitTeamChat() {
  32. memset(teamChat1, 0, sizeof(teamChat1));
  33. memset(teamChat2, 0, sizeof(teamChat2));
  34. memset(systemChat, 0, sizeof(systemChat));
  35. }
  36. void CG_SetPrintString(int type, const char *p) {
  37. if (type == SYSTEM_PRINT) {
  38. strcpy(systemChat, p);
  39. } else {
  40. strcpy(teamChat2, teamChat1);
  41. strcpy(teamChat1, p);
  42. }
  43. }
  44. void CG_CheckOrderPending() {
  45. if (cgs.gametype < GT_CTF) {
  46. return;
  47. }
  48. if (cgs.orderPending) {
  49. //clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[cg_currentSelectedPlayer.integer];
  50. const char *p1, *p2, *b;
  51. p1 = p2 = b = NULL;
  52. switch (cgs.currentOrder) {
  53. case TEAMTASK_OFFENSE:
  54. p1 = VOICECHAT_ONOFFENSE;
  55. p2 = VOICECHAT_OFFENSE;
  56. b = "+button7; wait; -button7";
  57. break;
  58. case TEAMTASK_DEFENSE:
  59. p1 = VOICECHAT_ONDEFENSE;
  60. p2 = VOICECHAT_DEFEND;
  61. b = "+button8; wait; -button8";
  62. break;
  63. case TEAMTASK_PATROL:
  64. p1 = VOICECHAT_ONPATROL;
  65. p2 = VOICECHAT_PATROL;
  66. b = "+button9; wait; -button9";
  67. break;
  68. case TEAMTASK_FOLLOW:
  69. p1 = VOICECHAT_ONFOLLOW;
  70. p2 = VOICECHAT_FOLLOWME;
  71. b = "+button10; wait; -button10";
  72. break;
  73. case TEAMTASK_CAMP:
  74. p1 = VOICECHAT_ONCAMPING;
  75. p2 = VOICECHAT_CAMP;
  76. break;
  77. case TEAMTASK_RETRIEVE:
  78. p1 = VOICECHAT_ONGETFLAG;
  79. p2 = VOICECHAT_RETURNFLAG;
  80. break;
  81. case TEAMTASK_ESCORT:
  82. p1 = VOICECHAT_ONFOLLOWCARRIER;
  83. p2 = VOICECHAT_FOLLOWFLAGCARRIER;
  84. break;
  85. }
  86. if (cg_currentSelectedPlayer.integer == numSortedTeamPlayers) {
  87. // to everyone
  88. trap_SendConsoleCommand(va("cmd vsay_team %s\n", p2));
  89. } else {
  90. // for the player self
  91. if (sortedTeamPlayers[cg_currentSelectedPlayer.integer] == cg.snap->ps.clientNum && p1) {
  92. trap_SendConsoleCommand(va("teamtask %i\n", cgs.currentOrder));
  93. //trap_SendConsoleCommand(va("cmd say_team %s\n", p2));
  94. trap_SendConsoleCommand(va("cmd vsay_team %s\n", p1));
  95. } else if (p2) {
  96. //trap_SendConsoleCommand(va("cmd say_team %s, %s\n", ci->name,p));
  97. trap_SendConsoleCommand(va("cmd vtell %d %s\n", sortedTeamPlayers[cg_currentSelectedPlayer.integer], p2));
  98. }
  99. }
  100. if (b) {
  101. trap_SendConsoleCommand(b);
  102. }
  103. cgs.orderPending = qfalse;
  104. }
  105. }
  106. static void CG_SetSelectedPlayerName() {
  107. if (cg_currentSelectedPlayer.integer >= 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
  108. clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[cg_currentSelectedPlayer.integer];
  109. if (ci) {
  110. trap_Cvar_Set("cg_selectedPlayerName", ci->name);
  111. trap_Cvar_Set("cg_selectedPlayer", va("%d", sortedTeamPlayers[cg_currentSelectedPlayer.integer]));
  112. cgs.currentOrder = ci->teamTask;
  113. }
  114. } else {
  115. trap_Cvar_Set("cg_selectedPlayerName", "Everyone");
  116. }
  117. }
  118. int CG_GetSelectedPlayer() {
  119. if (cg_currentSelectedPlayer.integer < 0 || cg_currentSelectedPlayer.integer >= numSortedTeamPlayers) {
  120. cg_currentSelectedPlayer.integer = 0;
  121. }
  122. return cg_currentSelectedPlayer.integer;
  123. }
  124. void CG_SelectNextPlayer() {
  125. CG_CheckOrderPending();
  126. if (cg_currentSelectedPlayer.integer >= 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
  127. cg_currentSelectedPlayer.integer++;
  128. } else {
  129. cg_currentSelectedPlayer.integer = 0;
  130. }
  131. CG_SetSelectedPlayerName();
  132. }
  133. void CG_SelectPrevPlayer() {
  134. CG_CheckOrderPending();
  135. if (cg_currentSelectedPlayer.integer > 0 && cg_currentSelectedPlayer.integer < numSortedTeamPlayers) {
  136. cg_currentSelectedPlayer.integer--;
  137. } else {
  138. cg_currentSelectedPlayer.integer = numSortedTeamPlayers;
  139. }
  140. CG_SetSelectedPlayerName();
  141. }
  142. static void CG_DrawPlayerArmorIcon( rectDef_t *rect, qboolean draw2D ) {
  143. centity_t *cent;
  144. playerState_t *ps;
  145. vec3_t angles;
  146. vec3_t origin;
  147. if ( cg_drawStatus.integer == 0 ) {
  148. return;
  149. }
  150. cent = &cg_entities[cg.snap->ps.clientNum];
  151. ps = &cg.snap->ps;
  152. if ( draw2D || ( !cg_draw3dIcons.integer && cg_drawIcons.integer) ) { // bk001206 - parentheses
  153. CG_DrawPic( rect->x, rect->y + rect->h/2 + 1, rect->w, rect->h, cgs.media.armorIcon );
  154. } else if (cg_draw3dIcons.integer) {
  155. VectorClear( angles );
  156. origin[0] = 90;
  157. origin[1] = 0;
  158. origin[2] = -10;
  159. angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
  160. CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, cgs.media.armorModel, 0, origin, angles );
  161. }
  162. }
  163. static void CG_DrawPlayerArmorValue(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
  164. char num[16];
  165. int value;
  166. centity_t *cent;
  167. playerState_t *ps;
  168. cent = &cg_entities[cg.snap->ps.clientNum];
  169. ps = &cg.snap->ps;
  170. value = ps->stats[STAT_ARMOR];
  171. if (shader) {
  172. trap_R_SetColor( color );
  173. CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
  174. trap_R_SetColor( NULL );
  175. } else {
  176. Com_sprintf (num, sizeof(num), "%i", value);
  177. value = CG_Text_Width(num, scale, 0);
  178. CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
  179. }
  180. }
  181. #ifndef MISSIONPACK // bk001206
  182. static float healthColors[4][4] = {
  183. // { 0.2, 1.0, 0.2, 1.0 } , { 1.0, 0.2, 0.2, 1.0 }, {0.5, 0.5, 0.5, 1} };
  184. // bk0101016 - float const
  185. { 1.0f, 0.69f, 0.0f, 1.0f } , // normal
  186. { 1.0f, 0.2f, 0.2f, 1.0f }, // low health
  187. { 0.5f, 0.5f, 0.5f, 1.0f}, // weapon firing
  188. { 1.0f, 1.0f, 1.0f, 1.0f } }; // health > 100
  189. #endif
  190. static void CG_DrawPlayerAmmoIcon( rectDef_t *rect, qboolean draw2D ) {
  191. centity_t *cent;
  192. playerState_t *ps;
  193. vec3_t angles;
  194. vec3_t origin;
  195. cent = &cg_entities[cg.snap->ps.clientNum];
  196. ps = &cg.snap->ps;
  197. if ( draw2D || (!cg_draw3dIcons.integer && cg_drawIcons.integer) ) { // bk001206 - parentheses
  198. qhandle_t icon;
  199. icon = cg_weapons[ cg.predictedPlayerState.weapon ].ammoIcon;
  200. if ( icon ) {
  201. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, icon );
  202. }
  203. } else if (cg_draw3dIcons.integer) {
  204. if ( cent->currentState.weapon && cg_weapons[ cent->currentState.weapon ].ammoModel ) {
  205. VectorClear( angles );
  206. origin[0] = 70;
  207. origin[1] = 0;
  208. origin[2] = 0;
  209. angles[YAW] = 90 + 20 * sin( cg.time / 1000.0 );
  210. CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, cg_weapons[ cent->currentState.weapon ].ammoModel, 0, origin, angles );
  211. }
  212. }
  213. }
  214. static void CG_DrawPlayerAmmoValue(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
  215. char num[16];
  216. int value;
  217. centity_t *cent;
  218. playerState_t *ps;
  219. cent = &cg_entities[cg.snap->ps.clientNum];
  220. ps = &cg.snap->ps;
  221. if ( cent->currentState.weapon ) {
  222. value = ps->ammo[cent->currentState.weapon];
  223. if ( value > -1 ) {
  224. if (shader) {
  225. trap_R_SetColor( color );
  226. CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
  227. trap_R_SetColor( NULL );
  228. } else {
  229. Com_sprintf (num, sizeof(num), "%i", value);
  230. value = CG_Text_Width(num, scale, 0);
  231. CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
  232. }
  233. }
  234. }
  235. }
  236. static void CG_DrawPlayerHead(rectDef_t *rect, qboolean draw2D) {
  237. vec3_t angles;
  238. float size, stretch;
  239. float frac;
  240. float x = rect->x;
  241. VectorClear( angles );
  242. if ( cg.damageTime && cg.time - cg.damageTime < DAMAGE_TIME ) {
  243. frac = (float)(cg.time - cg.damageTime ) / DAMAGE_TIME;
  244. size = rect->w * 1.25 * ( 1.5 - frac * 0.5 );
  245. stretch = size - rect->w * 1.25;
  246. // kick in the direction of damage
  247. x -= stretch * 0.5 + cg.damageX * stretch * 0.5;
  248. cg.headStartYaw = 180 + cg.damageX * 45;
  249. cg.headEndYaw = 180 + 20 * cos( crandom()*M_PI );
  250. cg.headEndPitch = 5 * cos( crandom()*M_PI );
  251. cg.headStartTime = cg.time;
  252. cg.headEndTime = cg.time + 100 + random() * 2000;
  253. } else {
  254. if ( cg.time >= cg.headEndTime ) {
  255. // select a new head angle
  256. cg.headStartYaw = cg.headEndYaw;
  257. cg.headStartPitch = cg.headEndPitch;
  258. cg.headStartTime = cg.headEndTime;
  259. cg.headEndTime = cg.time + 100 + random() * 2000;
  260. cg.headEndYaw = 180 + 20 * cos( crandom()*M_PI );
  261. cg.headEndPitch = 5 * cos( crandom()*M_PI );
  262. }
  263. size = rect->w * 1.25;
  264. }
  265. // if the server was frozen for a while we may have a bad head start time
  266. if ( cg.headStartTime > cg.time ) {
  267. cg.headStartTime = cg.time;
  268. }
  269. frac = ( cg.time - cg.headStartTime ) / (float)( cg.headEndTime - cg.headStartTime );
  270. frac = frac * frac * ( 3 - 2 * frac );
  271. angles[YAW] = cg.headStartYaw + ( cg.headEndYaw - cg.headStartYaw ) * frac;
  272. angles[PITCH] = cg.headStartPitch + ( cg.headEndPitch - cg.headStartPitch ) * frac;
  273. CG_DrawHead( x, rect->y, rect->w, rect->h, cg.snap->ps.clientNum, angles );
  274. }
  275. static void CG_DrawSelectedPlayerHealth( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
  276. clientInfo_t *ci;
  277. int value;
  278. char num[16];
  279. ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
  280. if (ci) {
  281. if (shader) {
  282. trap_R_SetColor( color );
  283. CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
  284. trap_R_SetColor( NULL );
  285. } else {
  286. Com_sprintf (num, sizeof(num), "%i", ci->health);
  287. value = CG_Text_Width(num, scale, 0);
  288. CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
  289. }
  290. }
  291. }
  292. static void CG_DrawSelectedPlayerArmor( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
  293. clientInfo_t *ci;
  294. int value;
  295. char num[16];
  296. ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
  297. if (ci) {
  298. if (ci->armor > 0) {
  299. if (shader) {
  300. trap_R_SetColor( color );
  301. CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
  302. trap_R_SetColor( NULL );
  303. } else {
  304. Com_sprintf (num, sizeof(num), "%i", ci->armor);
  305. value = CG_Text_Width(num, scale, 0);
  306. CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
  307. }
  308. }
  309. }
  310. }
  311. qhandle_t CG_StatusHandle(int task) {
  312. qhandle_t h = cgs.media.assaultShader;
  313. switch (task) {
  314. case TEAMTASK_OFFENSE :
  315. h = cgs.media.assaultShader;
  316. break;
  317. case TEAMTASK_DEFENSE :
  318. h = cgs.media.defendShader;
  319. break;
  320. case TEAMTASK_PATROL :
  321. h = cgs.media.patrolShader;
  322. break;
  323. case TEAMTASK_FOLLOW :
  324. h = cgs.media.followShader;
  325. break;
  326. case TEAMTASK_CAMP :
  327. h = cgs.media.campShader;
  328. break;
  329. case TEAMTASK_RETRIEVE :
  330. h = cgs.media.retrieveShader;
  331. break;
  332. case TEAMTASK_ESCORT :
  333. h = cgs.media.escortShader;
  334. break;
  335. default :
  336. h = cgs.media.assaultShader;
  337. break;
  338. }
  339. return h;
  340. }
  341. static void CG_DrawSelectedPlayerStatus( rectDef_t *rect ) {
  342. clientInfo_t *ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
  343. if (ci) {
  344. qhandle_t h;
  345. if (cgs.orderPending) {
  346. // blink the icon
  347. if ( cg.time > cgs.orderTime - 2500 && (cg.time >> 9 ) & 1 ) {
  348. return;
  349. }
  350. h = CG_StatusHandle(cgs.currentOrder);
  351. } else {
  352. h = CG_StatusHandle(ci->teamTask);
  353. }
  354. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, h );
  355. }
  356. }
  357. static void CG_DrawPlayerStatus( rectDef_t *rect ) {
  358. clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum];
  359. if (ci) {
  360. qhandle_t h = CG_StatusHandle(ci->teamTask);
  361. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, h);
  362. }
  363. }
  364. static void CG_DrawSelectedPlayerName( rectDef_t *rect, float scale, vec4_t color, qboolean voice, int textStyle) {
  365. clientInfo_t *ci;
  366. ci = cgs.clientinfo + ((voice) ? cgs.currentVoiceClient : sortedTeamPlayers[CG_GetSelectedPlayer()]);
  367. if (ci) {
  368. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, ci->name, 0, 0, textStyle);
  369. }
  370. }
  371. static void CG_DrawSelectedPlayerLocation( rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
  372. clientInfo_t *ci;
  373. ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
  374. if (ci) {
  375. const char *p = CG_ConfigString(CS_LOCATIONS + ci->location);
  376. if (!p || !*p) {
  377. p = "unknown";
  378. }
  379. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, p, 0, 0, textStyle);
  380. }
  381. }
  382. static void CG_DrawPlayerLocation( rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
  383. clientInfo_t *ci = &cgs.clientinfo[cg.snap->ps.clientNum];
  384. if (ci) {
  385. const char *p = CG_ConfigString(CS_LOCATIONS + ci->location);
  386. if (!p || !*p) {
  387. p = "unknown";
  388. }
  389. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, p, 0, 0, textStyle);
  390. }
  391. }
  392. static void CG_DrawSelectedPlayerWeapon( rectDef_t *rect ) {
  393. clientInfo_t *ci;
  394. ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
  395. if (ci) {
  396. if ( cg_weapons[ci->curWeapon].weaponIcon ) {
  397. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_weapons[ci->curWeapon].weaponIcon );
  398. } else {
  399. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.deferShader);
  400. }
  401. }
  402. }
  403. static void CG_DrawPlayerScore( rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
  404. char num[16];
  405. int value = cg.snap->ps.persistant[PERS_SCORE];
  406. if (shader) {
  407. trap_R_SetColor( color );
  408. CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
  409. trap_R_SetColor( NULL );
  410. } else {
  411. Com_sprintf (num, sizeof(num), "%i", value);
  412. value = CG_Text_Width(num, scale, 0);
  413. CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
  414. }
  415. }
  416. static void CG_DrawPlayerItem( rectDef_t *rect, float scale, qboolean draw2D) {
  417. int value;
  418. vec3_t origin, angles;
  419. value = cg.snap->ps.stats[STAT_HOLDABLE_ITEM];
  420. if ( value ) {
  421. CG_RegisterItemVisuals( value );
  422. if (qtrue) {
  423. CG_RegisterItemVisuals( value );
  424. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_items[ value ].icon );
  425. } else {
  426. VectorClear( angles );
  427. origin[0] = 90;
  428. origin[1] = 0;
  429. origin[2] = -10;
  430. angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
  431. CG_Draw3DModel(rect->x, rect->y, rect->w, rect->h, cg_items[ value ].models[0], 0, origin, angles );
  432. }
  433. }
  434. }
  435. static void CG_DrawSelectedPlayerPowerup( rectDef_t *rect, qboolean draw2D ) {
  436. clientInfo_t *ci;
  437. int j;
  438. float x, y;
  439. ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
  440. if (ci) {
  441. x = rect->x;
  442. y = rect->y;
  443. for (j = 0; j < PW_NUM_POWERUPS; j++) {
  444. if (ci->powerups & (1 << j)) {
  445. gitem_t *item;
  446. item = BG_FindItemForPowerup( j );
  447. if (item) {
  448. CG_DrawPic( x, y, rect->w, rect->h, trap_R_RegisterShader( item->icon ) );
  449. x += 3;
  450. y += 3;
  451. return;
  452. }
  453. }
  454. }
  455. }
  456. }
  457. static void CG_DrawSelectedPlayerHead( rectDef_t *rect, qboolean draw2D, qboolean voice ) {
  458. clipHandle_t cm;
  459. clientInfo_t *ci;
  460. float len;
  461. vec3_t origin;
  462. vec3_t mins, maxs, angles;
  463. ci = cgs.clientinfo + ((voice) ? cgs.currentVoiceClient : sortedTeamPlayers[CG_GetSelectedPlayer()]);
  464. if (ci) {
  465. if ( cg_draw3dIcons.integer ) {
  466. cm = ci->headModel;
  467. if ( !cm ) {
  468. return;
  469. }
  470. // offset the origin y and z to center the head
  471. trap_R_ModelBounds( cm, mins, maxs );
  472. origin[2] = -0.5 * ( mins[2] + maxs[2] );
  473. origin[1] = 0.5 * ( mins[1] + maxs[1] );
  474. // calculate distance so the head nearly fills the box
  475. // assume heads are taller than wide
  476. len = 0.7 * ( maxs[2] - mins[2] );
  477. origin[0] = len / 0.268; // len / tan( fov/2 )
  478. // allow per-model tweaking
  479. VectorAdd( origin, ci->headOffset, origin );
  480. angles[PITCH] = 0;
  481. angles[YAW] = 180;
  482. angles[ROLL] = 0;
  483. CG_Draw3DModel( rect->x, rect->y, rect->w, rect->h, ci->headModel, ci->headSkin, origin, angles );
  484. } else if ( cg_drawIcons.integer ) {
  485. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, ci->modelIcon );
  486. }
  487. // if they are deferred, draw a cross out
  488. if ( ci->deferred ) {
  489. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.deferShader );
  490. }
  491. }
  492. }
  493. static void CG_DrawPlayerHealth(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
  494. playerState_t *ps;
  495. int value;
  496. char num[16];
  497. ps = &cg.snap->ps;
  498. value = ps->stats[STAT_HEALTH];
  499. if (shader) {
  500. trap_R_SetColor( color );
  501. CG_DrawPic(rect->x, rect->y, rect->w, rect->h, shader);
  502. trap_R_SetColor( NULL );
  503. } else {
  504. Com_sprintf (num, sizeof(num), "%i", value);
  505. value = CG_Text_Width(num, scale, 0);
  506. CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
  507. }
  508. }
  509. static void CG_DrawRedScore(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
  510. int value;
  511. char num[16];
  512. if ( cgs.scores1 == SCORE_NOT_PRESENT ) {
  513. Com_sprintf (num, sizeof(num), "-");
  514. }
  515. else {
  516. Com_sprintf (num, sizeof(num), "%i", cgs.scores1);
  517. }
  518. value = CG_Text_Width(num, scale, 0);
  519. CG_Text_Paint(rect->x + rect->w - value, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
  520. }
  521. static void CG_DrawBlueScore(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
  522. int value;
  523. char num[16];
  524. if ( cgs.scores2 == SCORE_NOT_PRESENT ) {
  525. Com_sprintf (num, sizeof(num), "-");
  526. }
  527. else {
  528. Com_sprintf (num, sizeof(num), "%i", cgs.scores2);
  529. }
  530. value = CG_Text_Width(num, scale, 0);
  531. CG_Text_Paint(rect->x + rect->w - value, rect->y + rect->h, scale, color, num, 0, 0, textStyle);
  532. }
  533. // FIXME: team name support
  534. static void CG_DrawRedName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
  535. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cg_redTeamName.string , 0, 0, textStyle);
  536. }
  537. static void CG_DrawBlueName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
  538. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cg_blueTeamName.string, 0, 0, textStyle);
  539. }
  540. static void CG_DrawBlueFlagName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
  541. int i;
  542. for ( i = 0 ; i < cgs.maxclients ; i++ ) {
  543. if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_RED && cgs.clientinfo[i].powerups & ( 1<< PW_BLUEFLAG )) {
  544. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cgs.clientinfo[i].name, 0, 0, textStyle);
  545. return;
  546. }
  547. }
  548. }
  549. static void CG_DrawBlueFlagStatus(rectDef_t *rect, qhandle_t shader) {
  550. if (cgs.gametype != GT_CTF && cgs.gametype != GT_1FCTF) {
  551. if (cgs.gametype == GT_HARVESTER) {
  552. vec4_t color = {0, 0, 1, 1};
  553. trap_R_SetColor(color);
  554. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.blueCubeIcon );
  555. trap_R_SetColor(NULL);
  556. }
  557. return;
  558. }
  559. if (shader) {
  560. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
  561. } else {
  562. gitem_t *item = BG_FindItemForPowerup( PW_BLUEFLAG );
  563. if (item) {
  564. vec4_t color = {0, 0, 1, 1};
  565. trap_R_SetColor(color);
  566. if( cgs.blueflag >= 0 && cgs.blueflag <= 2 ) {
  567. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[cgs.blueflag] );
  568. } else {
  569. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[0] );
  570. }
  571. trap_R_SetColor(NULL);
  572. }
  573. }
  574. }
  575. static void CG_DrawBlueFlagHead(rectDef_t *rect) {
  576. int i;
  577. for ( i = 0 ; i < cgs.maxclients ; i++ ) {
  578. if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_RED && cgs.clientinfo[i].powerups & ( 1<< PW_BLUEFLAG )) {
  579. vec3_t angles;
  580. VectorClear( angles );
  581. angles[YAW] = 180 + 20 * sin( cg.time / 650.0 );;
  582. CG_DrawHead( rect->x, rect->y, rect->w, rect->h, 0,angles );
  583. return;
  584. }
  585. }
  586. }
  587. static void CG_DrawRedFlagName(rectDef_t *rect, float scale, vec4_t color, int textStyle ) {
  588. int i;
  589. for ( i = 0 ; i < cgs.maxclients ; i++ ) {
  590. if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_BLUE && cgs.clientinfo[i].powerups & ( 1<< PW_REDFLAG )) {
  591. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, cgs.clientinfo[i].name, 0, 0, textStyle);
  592. return;
  593. }
  594. }
  595. }
  596. static void CG_DrawRedFlagStatus(rectDef_t *rect, qhandle_t shader) {
  597. if (cgs.gametype != GT_CTF && cgs.gametype != GT_1FCTF) {
  598. if (cgs.gametype == GT_HARVESTER) {
  599. vec4_t color = {1, 0, 0, 1};
  600. trap_R_SetColor(color);
  601. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.redCubeIcon );
  602. trap_R_SetColor(NULL);
  603. }
  604. return;
  605. }
  606. if (shader) {
  607. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
  608. } else {
  609. gitem_t *item = BG_FindItemForPowerup( PW_REDFLAG );
  610. if (item) {
  611. vec4_t color = {1, 0, 0, 1};
  612. trap_R_SetColor(color);
  613. if( cgs.redflag >= 0 && cgs.redflag <= 2) {
  614. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[cgs.redflag] );
  615. } else {
  616. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[0] );
  617. }
  618. trap_R_SetColor(NULL);
  619. }
  620. }
  621. }
  622. static void CG_DrawRedFlagHead(rectDef_t *rect) {
  623. int i;
  624. for ( i = 0 ; i < cgs.maxclients ; i++ ) {
  625. if ( cgs.clientinfo[i].infoValid && cgs.clientinfo[i].team == TEAM_BLUE && cgs.clientinfo[i].powerups & ( 1<< PW_REDFLAG )) {
  626. vec3_t angles;
  627. VectorClear( angles );
  628. angles[YAW] = 180 + 20 * sin( cg.time / 650.0 );;
  629. CG_DrawHead( rect->x, rect->y, rect->w, rect->h, 0,angles );
  630. return;
  631. }
  632. }
  633. }
  634. static void CG_HarvesterSkulls(rectDef_t *rect, float scale, vec4_t color, qboolean force2D, int textStyle ) {
  635. char num[16];
  636. vec3_t origin, angles;
  637. qhandle_t handle;
  638. int value = cg.snap->ps.generic1;
  639. if (cgs.gametype != GT_HARVESTER) {
  640. return;
  641. }
  642. if( value > 99 ) {
  643. value = 99;
  644. }
  645. Com_sprintf (num, sizeof(num), "%i", value);
  646. value = CG_Text_Width(num, scale, 0);
  647. CG_Text_Paint(rect->x + (rect->w - value), rect->y + rect->h, scale, color, num, 0, 0, textStyle);
  648. if (cg_drawIcons.integer) {
  649. if (!force2D && cg_draw3dIcons.integer) {
  650. VectorClear(angles);
  651. origin[0] = 90;
  652. origin[1] = 0;
  653. origin[2] = -10;
  654. angles[YAW] = ( cg.time & 2047 ) * 360 / 2048.0;
  655. if( cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE ) {
  656. handle = cgs.media.redCubeModel;
  657. } else {
  658. handle = cgs.media.blueCubeModel;
  659. }
  660. CG_Draw3DModel( rect->x, rect->y, 35, 35, handle, 0, origin, angles );
  661. } else {
  662. if( cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE ) {
  663. handle = cgs.media.redCubeIcon;
  664. } else {
  665. handle = cgs.media.blueCubeIcon;
  666. }
  667. CG_DrawPic( rect->x + 3, rect->y + 16, 20, 20, handle );
  668. }
  669. }
  670. }
  671. static void CG_OneFlagStatus(rectDef_t *rect) {
  672. if (cgs.gametype != GT_1FCTF) {
  673. return;
  674. } else {
  675. gitem_t *item = BG_FindItemForPowerup( PW_NEUTRALFLAG );
  676. if (item) {
  677. if( cgs.flagStatus >= 0 && cgs.flagStatus <= 4 ) {
  678. vec4_t color = {1, 1, 1, 1};
  679. int index = 0;
  680. if (cgs.flagStatus == FLAG_TAKEN_RED) {
  681. color[1] = color[2] = 0;
  682. index = 1;
  683. } else if (cgs.flagStatus == FLAG_TAKEN_BLUE) {
  684. color[0] = color[1] = 0;
  685. index = 1;
  686. } else if (cgs.flagStatus == FLAG_DROPPED) {
  687. index = 2;
  688. }
  689. trap_R_SetColor(color);
  690. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cgs.media.flagShaders[index] );
  691. }
  692. }
  693. }
  694. }
  695. static void CG_DrawCTFPowerUp(rectDef_t *rect) {
  696. int value;
  697. if (cgs.gametype < GT_CTF) {
  698. return;
  699. }
  700. value = cg.snap->ps.stats[STAT_PERSISTANT_POWERUP];
  701. if ( value ) {
  702. CG_RegisterItemVisuals( value );
  703. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, cg_items[ value ].icon );
  704. }
  705. }
  706. static void CG_DrawTeamColor(rectDef_t *rect, vec4_t color) {
  707. CG_DrawTeamBackground(rect->x, rect->y, rect->w, rect->h, color[3], cg.snap->ps.persistant[PERS_TEAM]);
  708. }
  709. static void CG_DrawAreaPowerUp(rectDef_t *rect, int align, float special, float scale, vec4_t color) {
  710. char num[16];
  711. int sorted[MAX_POWERUPS];
  712. int sortedTime[MAX_POWERUPS];
  713. int i, j, k;
  714. int active;
  715. playerState_t *ps;
  716. int t;
  717. gitem_t *item;
  718. float f;
  719. rectDef_t r2;
  720. float *inc;
  721. r2.x = rect->x;
  722. r2.y = rect->y;
  723. r2.w = rect->w;
  724. r2.h = rect->h;
  725. inc = (align == HUD_VERTICAL) ? &r2.y : &r2.x;
  726. ps = &cg.snap->ps;
  727. if ( ps->stats[STAT_HEALTH] <= 0 ) {
  728. return;
  729. }
  730. // sort the list by time remaining
  731. active = 0;
  732. for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
  733. if ( !ps->powerups[ i ] ) {
  734. continue;
  735. }
  736. t = ps->powerups[ i ] - cg.time;
  737. // ZOID--don't draw if the power up has unlimited time (999 seconds)
  738. // This is true of the CTF flags
  739. if ( t <= 0 || t >= 999000) {
  740. continue;
  741. }
  742. // insert into the list
  743. for ( j = 0 ; j < active ; j++ ) {
  744. if ( sortedTime[j] >= t ) {
  745. for ( k = active - 1 ; k >= j ; k-- ) {
  746. sorted[k+1] = sorted[k];
  747. sortedTime[k+1] = sortedTime[k];
  748. }
  749. break;
  750. }
  751. }
  752. sorted[j] = i;
  753. sortedTime[j] = t;
  754. active++;
  755. }
  756. // draw the icons and timers
  757. for ( i = 0 ; i < active ; i++ ) {
  758. item = BG_FindItemForPowerup( sorted[i] );
  759. if (item) {
  760. t = ps->powerups[ sorted[i] ];
  761. if ( t - cg.time >= POWERUP_BLINKS * POWERUP_BLINK_TIME ) {
  762. trap_R_SetColor( NULL );
  763. } else {
  764. vec4_t modulate;
  765. f = (float)( t - cg.time ) / POWERUP_BLINK_TIME;
  766. f -= (int)f;
  767. modulate[0] = modulate[1] = modulate[2] = modulate[3] = f;
  768. trap_R_SetColor( modulate );
  769. }
  770. CG_DrawPic( r2.x, r2.y, r2.w * .75, r2.h, trap_R_RegisterShader( item->icon ) );
  771. Com_sprintf (num, sizeof(num), "%i", sortedTime[i] / 1000);
  772. CG_Text_Paint(r2.x + (r2.w * .75) + 3 , r2.y + r2.h, scale, color, num, 0, 0, 0);
  773. *inc += r2.w + special;
  774. }
  775. }
  776. trap_R_SetColor( NULL );
  777. }
  778. float CG_GetValue(int ownerDraw) {
  779. centity_t *cent;
  780. clientInfo_t *ci;
  781. playerState_t *ps;
  782. cent = &cg_entities[cg.snap->ps.clientNum];
  783. ps = &cg.snap->ps;
  784. switch (ownerDraw) {
  785. case CG_SELECTEDPLAYER_ARMOR:
  786. ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
  787. return ci->armor;
  788. break;
  789. case CG_SELECTEDPLAYER_HEALTH:
  790. ci = cgs.clientinfo + sortedTeamPlayers[CG_GetSelectedPlayer()];
  791. return ci->health;
  792. break;
  793. case CG_PLAYER_ARMOR_VALUE:
  794. return ps->stats[STAT_ARMOR];
  795. break;
  796. case CG_PLAYER_AMMO_VALUE:
  797. if ( cent->currentState.weapon ) {
  798. return ps->ammo[cent->currentState.weapon];
  799. }
  800. break;
  801. case CG_PLAYER_SCORE:
  802. return cg.snap->ps.persistant[PERS_SCORE];
  803. break;
  804. case CG_PLAYER_HEALTH:
  805. return ps->stats[STAT_HEALTH];
  806. break;
  807. case CG_RED_SCORE:
  808. return cgs.scores1;
  809. break;
  810. case CG_BLUE_SCORE:
  811. return cgs.scores2;
  812. break;
  813. default:
  814. break;
  815. }
  816. return -1;
  817. }
  818. qboolean CG_OtherTeamHasFlag() {
  819. if (cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF) {
  820. int team = cg.snap->ps.persistant[PERS_TEAM];
  821. if (cgs.gametype == GT_1FCTF) {
  822. if (team == TEAM_RED && cgs.flagStatus == FLAG_TAKEN_BLUE) {
  823. return qtrue;
  824. } else if (team == TEAM_BLUE && cgs.flagStatus == FLAG_TAKEN_RED) {
  825. return qtrue;
  826. } else {
  827. return qfalse;
  828. }
  829. } else {
  830. if (team == TEAM_RED && cgs.redflag == FLAG_TAKEN) {
  831. return qtrue;
  832. } else if (team == TEAM_BLUE && cgs.blueflag == FLAG_TAKEN) {
  833. return qtrue;
  834. } else {
  835. return qfalse;
  836. }
  837. }
  838. }
  839. return qfalse;
  840. }
  841. qboolean CG_YourTeamHasFlag() {
  842. if (cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF) {
  843. int team = cg.snap->ps.persistant[PERS_TEAM];
  844. if (cgs.gametype == GT_1FCTF) {
  845. if (team == TEAM_RED && cgs.flagStatus == FLAG_TAKEN_RED) {
  846. return qtrue;
  847. } else if (team == TEAM_BLUE && cgs.flagStatus == FLAG_TAKEN_BLUE) {
  848. return qtrue;
  849. } else {
  850. return qfalse;
  851. }
  852. } else {
  853. if (team == TEAM_RED && cgs.blueflag == FLAG_TAKEN) {
  854. return qtrue;
  855. } else if (team == TEAM_BLUE && cgs.redflag == FLAG_TAKEN) {
  856. return qtrue;
  857. } else {
  858. return qfalse;
  859. }
  860. }
  861. }
  862. return qfalse;
  863. }
  864. // THINKABOUTME: should these be exclusive or inclusive..
  865. //
  866. qboolean CG_OwnerDrawVisible(int flags) {
  867. if (flags & CG_SHOW_TEAMINFO) {
  868. return (cg_currentSelectedPlayer.integer == numSortedTeamPlayers);
  869. }
  870. if (flags & CG_SHOW_NOTEAMINFO) {
  871. return !(cg_currentSelectedPlayer.integer == numSortedTeamPlayers);
  872. }
  873. if (flags & CG_SHOW_OTHERTEAMHASFLAG) {
  874. return CG_OtherTeamHasFlag();
  875. }
  876. if (flags & CG_SHOW_YOURTEAMHASENEMYFLAG) {
  877. return CG_YourTeamHasFlag();
  878. }
  879. if (flags & (CG_SHOW_BLUE_TEAM_HAS_REDFLAG | CG_SHOW_RED_TEAM_HAS_BLUEFLAG)) {
  880. if (flags & CG_SHOW_BLUE_TEAM_HAS_REDFLAG && (cgs.redflag == FLAG_TAKEN || cgs.flagStatus == FLAG_TAKEN_RED)) {
  881. return qtrue;
  882. } else if (flags & CG_SHOW_RED_TEAM_HAS_BLUEFLAG && (cgs.blueflag == FLAG_TAKEN || cgs.flagStatus == FLAG_TAKEN_BLUE)) {
  883. return qtrue;
  884. }
  885. return qfalse;
  886. }
  887. if (flags & CG_SHOW_ANYTEAMGAME) {
  888. if( cgs.gametype >= GT_TEAM) {
  889. return qtrue;
  890. }
  891. }
  892. if (flags & CG_SHOW_ANYNONTEAMGAME) {
  893. if( cgs.gametype < GT_TEAM) {
  894. return qtrue;
  895. }
  896. }
  897. if (flags & CG_SHOW_HARVESTER) {
  898. if( cgs.gametype == GT_HARVESTER ) {
  899. return qtrue;
  900. } else {
  901. return qfalse;
  902. }
  903. }
  904. if (flags & CG_SHOW_ONEFLAG) {
  905. if( cgs.gametype == GT_1FCTF ) {
  906. return qtrue;
  907. } else {
  908. return qfalse;
  909. }
  910. }
  911. if (flags & CG_SHOW_CTF) {
  912. if( cgs.gametype == GT_CTF ) {
  913. return qtrue;
  914. }
  915. }
  916. if (flags & CG_SHOW_OBELISK) {
  917. if( cgs.gametype == GT_OBELISK ) {
  918. return qtrue;
  919. } else {
  920. return qfalse;
  921. }
  922. }
  923. if (flags & CG_SHOW_HEALTHCRITICAL) {
  924. if (cg.snap->ps.stats[STAT_HEALTH] < 25) {
  925. return qtrue;
  926. }
  927. }
  928. if (flags & CG_SHOW_HEALTHOK) {
  929. if (cg.snap->ps.stats[STAT_HEALTH] >= 25) {
  930. return qtrue;
  931. }
  932. }
  933. if (flags & CG_SHOW_SINGLEPLAYER) {
  934. if( cgs.gametype == GT_SINGLE_PLAYER ) {
  935. return qtrue;
  936. }
  937. }
  938. if (flags & CG_SHOW_TOURNAMENT) {
  939. if( cgs.gametype == GT_TOURNAMENT ) {
  940. return qtrue;
  941. }
  942. }
  943. if (flags & CG_SHOW_DURINGINCOMINGVOICE) {
  944. }
  945. if (flags & CG_SHOW_IF_PLAYER_HAS_FLAG) {
  946. if (cg.snap->ps.powerups[PW_REDFLAG] || cg.snap->ps.powerups[PW_BLUEFLAG] || cg.snap->ps.powerups[PW_NEUTRALFLAG]) {
  947. return qtrue;
  948. }
  949. }
  950. return qfalse;
  951. }
  952. static void CG_DrawPlayerHasFlag(rectDef_t *rect, qboolean force2D) {
  953. int adj = (force2D) ? 0 : 2;
  954. if( cg.predictedPlayerState.powerups[PW_REDFLAG] ) {
  955. CG_DrawFlagModel( rect->x + adj, rect->y + adj, rect->w - adj, rect->h - adj, TEAM_RED, force2D);
  956. } else if( cg.predictedPlayerState.powerups[PW_BLUEFLAG] ) {
  957. CG_DrawFlagModel( rect->x + adj, rect->y + adj, rect->w - adj, rect->h - adj, TEAM_BLUE, force2D);
  958. } else if( cg.predictedPlayerState.powerups[PW_NEUTRALFLAG] ) {
  959. CG_DrawFlagModel( rect->x + adj, rect->y + adj, rect->w - adj, rect->h - adj, TEAM_FREE, force2D);
  960. }
  961. }
  962. static void CG_DrawAreaSystemChat(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
  963. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, systemChat, 0, 0, 0);
  964. }
  965. static void CG_DrawAreaTeamChat(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
  966. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color,teamChat1, 0, 0, 0);
  967. }
  968. static void CG_DrawAreaChat(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
  969. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, teamChat2, 0, 0, 0);
  970. }
  971. const char *CG_GetKillerText() {
  972. const char *s = "";
  973. if ( cg.killerName[0] ) {
  974. s = va("Fragged by %s", cg.killerName );
  975. }
  976. return s;
  977. }
  978. static void CG_DrawKiller(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
  979. // fragged by ... line
  980. if ( cg.killerName[0] ) {
  981. int x = rect->x + rect->w / 2;
  982. CG_Text_Paint(x - CG_Text_Width(CG_GetKillerText(), scale, 0) / 2, rect->y + rect->h, scale, color, CG_GetKillerText(), 0, 0, textStyle);
  983. }
  984. }
  985. static void CG_DrawCapFragLimit(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
  986. int limit = (cgs.gametype >= GT_CTF) ? cgs.capturelimit : cgs.fraglimit;
  987. CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", limit),0, 0, textStyle);
  988. }
  989. static void CG_Draw1stPlace(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
  990. if (cgs.scores1 != SCORE_NOT_PRESENT) {
  991. CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", cgs.scores1),0, 0, textStyle);
  992. }
  993. }
  994. static void CG_Draw2ndPlace(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle) {
  995. if (cgs.scores2 != SCORE_NOT_PRESENT) {
  996. CG_Text_Paint(rect->x, rect->y, scale, color, va("%2i", cgs.scores2),0, 0, textStyle);
  997. }
  998. }
  999. const char *CG_GetGameStatusText() {
  1000. const char *s = "";
  1001. if ( cgs.gametype < GT_TEAM) {
  1002. if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) {
  1003. s = va("%s place with %i",CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ),cg.snap->ps.persistant[PERS_SCORE] );
  1004. }
  1005. } else {
  1006. if ( cg.teamScores[0] == cg.teamScores[1] ) {
  1007. s = va("Teams are tied at %i", cg.teamScores[0] );
  1008. } else if ( cg.teamScores[0] >= cg.teamScores[1] ) {
  1009. s = va("Red leads Blue, %i to %i", cg.teamScores[0], cg.teamScores[1] );
  1010. } else {
  1011. s = va("Blue leads Red, %i to %i", cg.teamScores[1], cg.teamScores[0] );
  1012. }
  1013. }
  1014. return s;
  1015. }
  1016. static void CG_DrawGameStatus(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
  1017. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, CG_GetGameStatusText(), 0, 0, textStyle);
  1018. }
  1019. const char *CG_GameTypeString() {
  1020. if ( cgs.gametype == GT_FFA ) {
  1021. return "Free For All";
  1022. } else if ( cgs.gametype == GT_TEAM ) {
  1023. return "Team Deathmatch";
  1024. } else if ( cgs.gametype == GT_CTF ) {
  1025. return "Capture the Flag";
  1026. } else if ( cgs.gametype == GT_1FCTF ) {
  1027. return "One Flag CTF";
  1028. } else if ( cgs.gametype == GT_OBELISK ) {
  1029. return "Overload";
  1030. } else if ( cgs.gametype == GT_HARVESTER ) {
  1031. return "Harvester";
  1032. }
  1033. return "";
  1034. }
  1035. static void CG_DrawGameType(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader, int textStyle ) {
  1036. CG_Text_Paint(rect->x, rect->y + rect->h, scale, color, CG_GameTypeString(), 0, 0, textStyle);
  1037. }
  1038. static void CG_Text_Paint_Limit(float *maxX, float x, float y, float scale, vec4_t color, const char* text, float adjust, int limit) {
  1039. int len, count;
  1040. vec4_t newColor;
  1041. glyphInfo_t *glyph;
  1042. if (text) {
  1043. // TTimo: FIXME
  1044. // const unsigned char *s = text; // bk001206 - unsigned
  1045. const char *s = text;
  1046. float max = *maxX;
  1047. float useScale;
  1048. fontInfo_t *font = &cgDC.Assets.textFont;
  1049. if (scale <= cg_smallFont.value) {
  1050. font = &cgDC.Assets.smallFont;
  1051. } else if (scale > cg_bigFont.value) {
  1052. font = &cgDC.Assets.bigFont;
  1053. }
  1054. useScale = scale * font->glyphScale;
  1055. trap_R_SetColor( color );
  1056. len = strlen(text);
  1057. if (limit > 0 && len > limit) {
  1058. len = limit;
  1059. }
  1060. count = 0;
  1061. while (s && *s && count < len) {
  1062. glyph = &font->glyphs[(int)*s]; // TTimo: FIXME: getting nasty warnings without the cast, hopefully this doesn't break the VM build
  1063. if ( Q_IsColorString( s ) ) {
  1064. memcpy( newColor, g_color_table[ColorIndex(*(s+1))], sizeof( newColor ) );
  1065. newColor[3] = color[3];
  1066. trap_R_SetColor( newColor );
  1067. s += 2;
  1068. continue;
  1069. } else {
  1070. float yadj = useScale * glyph->top;
  1071. if (CG_Text_Width(s, useScale, 1) + x > max) {
  1072. *maxX = 0;
  1073. break;
  1074. }
  1075. CG_Text_PaintChar(x, y - yadj,
  1076. glyph->imageWidth,
  1077. glyph->imageHeight,
  1078. useScale,
  1079. glyph->s,
  1080. glyph->t,
  1081. glyph->s2,
  1082. glyph->t2,
  1083. glyph->glyph);
  1084. x += (glyph->xSkip * useScale) + adjust;
  1085. *maxX = x;
  1086. count++;
  1087. s++;
  1088. }
  1089. }
  1090. trap_R_SetColor( NULL );
  1091. }
  1092. }
  1093. #define PIC_WIDTH 12
  1094. void CG_DrawNewTeamInfo(rectDef_t *rect, float text_x, float text_y, float scale, vec4_t color, qhandle_t shader) {
  1095. int xx;
  1096. float y;
  1097. int i, j, len, count;
  1098. const char *p;
  1099. vec4_t hcolor;
  1100. float pwidth, lwidth, maxx, leftOver;
  1101. clientInfo_t *ci;
  1102. gitem_t *item;
  1103. qhandle_t h;
  1104. // max player name width
  1105. pwidth = 0;
  1106. count = (numSortedTeamPlayers > 8) ? 8 : numSortedTeamPlayers;
  1107. for (i = 0; i < count; i++) {
  1108. ci = cgs.clientinfo + sortedTeamPlayers[i];
  1109. if ( ci->infoValid && ci->team == cg.snap->ps.persistant[PERS_TEAM]) {
  1110. len = CG_Text_Width( ci->name, scale, 0);
  1111. if (len > pwidth)
  1112. pwidth = len;
  1113. }
  1114. }
  1115. // max location name width
  1116. lwidth = 0;
  1117. for (i = 1; i < MAX_LOCATIONS; i++) {
  1118. p = CG_ConfigString(CS_LOCATIONS + i);
  1119. if (p && *p) {
  1120. len = CG_Text_Width(p, scale, 0);
  1121. if (len > lwidth)
  1122. lwidth = len;
  1123. }
  1124. }
  1125. y = rect->y;
  1126. for (i = 0; i < count; i++) {
  1127. ci = cgs.clientinfo + sortedTeamPlayers[i];
  1128. if ( ci->infoValid && ci->team == cg.snap->ps.persistant[PERS_TEAM]) {
  1129. xx = rect->x + 1;
  1130. for (j = 0; j <= PW_NUM_POWERUPS; j++) {
  1131. if (ci->powerups & (1 << j)) {
  1132. item = BG_FindItemForPowerup( j );
  1133. if (item) {
  1134. CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, trap_R_RegisterShader( item->icon ) );
  1135. xx += PIC_WIDTH;
  1136. }
  1137. }
  1138. }
  1139. // FIXME: max of 3 powerups shown properly
  1140. xx = rect->x + (PIC_WIDTH * 3) + 2;
  1141. CG_GetColorForHealth( ci->health, ci->armor, hcolor );
  1142. trap_R_SetColor(hcolor);
  1143. CG_DrawPic( xx, y + 1, PIC_WIDTH - 2, PIC_WIDTH - 2, cgs.media.heartShader );
  1144. //Com_sprintf (st, sizeof(st), "%3i %3i", ci->health, ci->armor);
  1145. //CG_Text_Paint(xx, y + text_y, scale, hcolor, st, 0, 0);
  1146. // draw weapon icon
  1147. xx += PIC_WIDTH + 1;
  1148. // weapon used is not that useful, use the space for task
  1149. #if 0
  1150. if ( cg_weapons[ci->curWeapon].weaponIcon ) {
  1151. CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, cg_weapons[ci->curWeapon].weaponIcon );
  1152. } else {
  1153. CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, cgs.media.deferShader );
  1154. }
  1155. #endif
  1156. trap_R_SetColor(NULL);
  1157. if (cgs.orderPending) {
  1158. // blink the icon
  1159. if ( cg.time > cgs.orderTime - 2500 && (cg.time >> 9 ) & 1 ) {
  1160. h = 0;
  1161. } else {
  1162. h = CG_StatusHandle(cgs.currentOrder);
  1163. }
  1164. } else {
  1165. h = CG_StatusHandle(ci->teamTask);
  1166. }
  1167. if (h) {
  1168. CG_DrawPic( xx, y, PIC_WIDTH, PIC_WIDTH, h);
  1169. }
  1170. xx += PIC_WIDTH + 1;
  1171. leftOver = rect->w - xx;
  1172. maxx = xx + leftOver / 3;
  1173. CG_Text_Paint_Limit(&maxx, xx, y + text_y, scale, color, ci->name, 0, 0);
  1174. p = CG_ConfigString(CS_LOCATIONS + ci->location);
  1175. if (!p || !*p) {
  1176. p = "unknown";
  1177. }
  1178. xx += leftOver / 3 + 2;
  1179. maxx = rect->w - 4;
  1180. CG_Text_Paint_Limit(&maxx, xx, y + text_y, scale, color, p, 0, 0);
  1181. y += text_y + 2;
  1182. if ( y + text_y + 2 > rect->y + rect->h ) {
  1183. break;
  1184. }
  1185. }
  1186. }
  1187. }
  1188. void CG_DrawTeamSpectators(rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
  1189. if (cg.spectatorLen) {
  1190. float maxX;
  1191. if (cg.spectatorWidth == -1) {
  1192. cg.spectatorWidth = 0;
  1193. cg.spectatorPaintX = rect->x + 1;
  1194. cg.spectatorPaintX2 = -1;
  1195. }
  1196. if (cg.spectatorOffset > cg.spectatorLen) {
  1197. cg.spectatorOffset = 0;
  1198. cg.spectatorPaintX = rect->x + 1;
  1199. cg.spectatorPaintX2 = -1;
  1200. }
  1201. if (cg.time > cg.spectatorTime) {
  1202. cg.spectatorTime = cg.time + 10;
  1203. if (cg.spectatorPaintX <= rect->x + 2) {
  1204. if (cg.spectatorOffset < cg.spectatorLen) {
  1205. cg.spectatorPaintX += CG_Text_Width(&cg.spectatorList[cg.spectatorOffset], scale, 1) - 1;
  1206. cg.spectatorOffset++;
  1207. } else {
  1208. cg.spectatorOffset = 0;
  1209. if (cg.spectatorPaintX2 >= 0) {
  1210. cg.spectatorPaintX = cg.spectatorPaintX2;
  1211. } else {
  1212. cg.spectatorPaintX = rect->x + rect->w - 2;
  1213. }
  1214. cg.spectatorPaintX2 = -1;
  1215. }
  1216. } else {
  1217. cg.spectatorPaintX--;
  1218. if (cg.spectatorPaintX2 >= 0) {
  1219. cg.spectatorPaintX2--;
  1220. }
  1221. }
  1222. }
  1223. maxX = rect->x + rect->w - 2;
  1224. CG_Text_Paint_Limit(&maxX, cg.spectatorPaintX, rect->y + rect->h - 3, scale, color, &cg.spectatorList[cg.spectatorOffset], 0, 0);
  1225. if (cg.spectatorPaintX2 >= 0) {
  1226. float maxX2 = rect->x + rect->w - 2;
  1227. CG_Text_Paint_Limit(&maxX2, cg.spectatorPaintX2, rect->y + rect->h - 3, scale, color, cg.spectatorList, 0, cg.spectatorOffset);
  1228. }
  1229. if (cg.spectatorOffset && maxX > 0) {
  1230. // if we have an offset ( we are skipping the first part of the string ) and we fit the string
  1231. if (cg.spectatorPaintX2 == -1) {
  1232. cg.spectatorPaintX2 = rect->x + rect->w - 2;
  1233. }
  1234. } else {
  1235. cg.spectatorPaintX2 = -1;
  1236. }
  1237. }
  1238. }
  1239. void CG_DrawMedal(int ownerDraw, rectDef_t *rect, float scale, vec4_t color, qhandle_t shader) {
  1240. score_t *score = &cg.scores[cg.selectedScore];
  1241. float value = 0;
  1242. char *text = NULL;
  1243. color[3] = 0.25;
  1244. switch (ownerDraw) {
  1245. case CG_ACCURACY:
  1246. value = score->accuracy;
  1247. break;
  1248. case CG_ASSISTS:
  1249. value = score->assistCount;
  1250. break;
  1251. case CG_DEFEND:
  1252. value = score->defendCount;
  1253. break;
  1254. case CG_EXCELLENT:
  1255. value = score->excellentCount;
  1256. break;
  1257. case CG_IMPRESSIVE:
  1258. value = score->impressiveCount;
  1259. break;
  1260. case CG_PERFECT:
  1261. value = score->perfect;
  1262. break;
  1263. case CG_GAUNTLET:
  1264. value = score->guantletCount;
  1265. break;
  1266. case CG_CAPTURES:
  1267. value = score->captures;
  1268. break;
  1269. }
  1270. if (value > 0) {
  1271. if (ownerDraw != CG_PERFECT) {
  1272. if (ownerDraw == CG_ACCURACY) {
  1273. text = va("%i%%", (int)value);
  1274. if (value > 50) {
  1275. color[3] = 1.0;
  1276. }
  1277. } else {
  1278. text = va("%i", (int)value);
  1279. color[3] = 1.0;
  1280. }
  1281. } else {
  1282. if (value) {
  1283. color[3] = 1.0;
  1284. }
  1285. text = "Wow";
  1286. }
  1287. }
  1288. trap_R_SetColor(color);
  1289. CG_DrawPic( rect->x, rect->y, rect->w, rect->h, shader );
  1290. if (text) {
  1291. color[3] = 1.0;
  1292. value = CG_Text_Width(text, scale, 0);
  1293. CG_Text_Paint(rect->x + (rect->w - value) / 2, rect->y + rect->h + 10 , scale, color, text, 0, 0, 0);
  1294. }
  1295. trap_R_SetColor(NULL);
  1296. }
  1297. //
  1298. void CG_OwnerDraw(float x, float y, float w, float h, float text_x, float text_y, int ownerDraw, int ownerDrawFlags, int align, float special, float scale, vec4_t color, qhandle_t shader, int textStyle) {
  1299. rectDef_t rect;
  1300. if ( cg_drawStatus.integer == 0 ) {
  1301. return;
  1302. }
  1303. //if (ownerDrawFlags != 0 && !CG_OwnerDrawVisible(ownerDrawFlags)) {
  1304. // return;
  1305. //}
  1306. rect.x = x;
  1307. rect.y = y;
  1308. rect.w = w;
  1309. rect.h = h;
  1310. switch (ownerDraw) {
  1311. case CG_PLAYER_ARMOR_ICON:
  1312. CG_DrawPlayerArmorIcon(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
  1313. break;
  1314. case CG_PLAYER_ARMOR_ICON2D:
  1315. CG_DrawPlayerArmorIcon(&rect, qtrue);
  1316. break;
  1317. case CG_PLAYER_ARMOR_VALUE:
  1318. CG_DrawPlayerArmorValue(&rect, scale, color, shader, textStyle);
  1319. break;
  1320. case CG_PLAYER_AMMO_ICON:
  1321. CG_DrawPlayerAmmoIcon(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
  1322. break;
  1323. case CG_PLAYER_AMMO_ICON2D:
  1324. CG_DrawPlayerAmmoIcon(&rect, qtrue);
  1325. break;
  1326. case CG_PLAYER_AMMO_VALUE:
  1327. CG_DrawPlayerAmmoValue(&rect, scale, color, shader, textStyle);
  1328. break;
  1329. case CG_SELECTEDPLAYER_HEAD:
  1330. CG_DrawSelectedPlayerHead(&rect, ownerDrawFlags & CG_SHOW_2DONLY, qfalse);
  1331. break;
  1332. case CG_VOICE_HEAD:
  1333. CG_DrawSelectedPlayerHead(&rect, ownerDrawFlags & CG_SHOW_2DONLY, qtrue);
  1334. break;
  1335. case CG_VOICE_NAME:
  1336. CG_DrawSelectedPlayerName(&rect, scale, color, qtrue, textStyle);
  1337. break;
  1338. case CG_SELECTEDPLAYER_STATUS:
  1339. CG_DrawSelectedPlayerStatus(&rect);
  1340. break;
  1341. case CG_SELECTEDPLAYER_ARMOR:
  1342. CG_DrawSelectedPlayerArmor(&rect, scale, color, shader, textStyle);
  1343. break;
  1344. case CG_SELECTEDPLAYER_HEALTH:
  1345. CG_DrawSelectedPlayerHealth(&rect, scale, color, shader, textStyle);
  1346. break;
  1347. case CG_SELECTEDPLAYER_NAME:
  1348. CG_DrawSelectedPlayerName(&rect, scale, color, qfalse, textStyle);
  1349. break;
  1350. case CG_SELECTEDPLAYER_LOCATION:
  1351. CG_DrawSelectedPlayerLocation(&rect, scale, color, textStyle);
  1352. break;
  1353. case CG_SELECTEDPLAYER_WEAPON:
  1354. CG_DrawSelectedPlayerWeapon(&rect);
  1355. break;
  1356. case CG_SELECTEDPLAYER_POWERUP:
  1357. CG_DrawSelectedPlayerPowerup(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
  1358. break;
  1359. case CG_PLAYER_HEAD:
  1360. CG_DrawPlayerHead(&rect, ownerDrawFlags & CG_SHOW_2DONLY);
  1361. break;
  1362. case CG_PLAYER_ITEM:
  1363. CG_DrawPlayerItem(&rect, scale, ownerDrawFlags & CG_SHOW_2DONLY);
  1364. break;
  1365. case CG_PLAYER_SCORE:
  1366. CG_DrawPlayerScore(&rect, scale, color, shader, textStyle);
  1367. break;
  1368. case CG_PLAYER_HEALTH:
  1369. CG_DrawPlayerHealth(&rect, scale, color, shader, textStyle);
  1370. break;
  1371. case CG_RED_SCORE:
  1372. CG_DrawRedScore(&rect, scale, color, shader, textStyle);
  1373. break;
  1374. case CG_BLUE_SCORE:
  1375. CG_DrawBlueScore(&rect, scale, color, shader, textStyle);
  1376. break;
  1377. case CG_RED_NAME:
  1378. CG_DrawRedName(&rect, scale, color, textStyle);
  1379. break;
  1380. case CG_BLUE_NAME:
  1381. CG_DrawBlueName(&rect, scale, color, textStyle);
  1382. break;
  1383. case CG_BLUE_FLAGHEAD:
  1384. CG_DrawBlueFlagHead(&rect);
  1385. break;
  1386. case CG_BLUE_FLAGSTATUS:
  1387. CG_DrawBlueFlagStatus(&rect, shader);
  1388. break;
  1389. case CG_BLUE_FLAGNAME:
  1390. CG_DrawBlueFlagName(&rect, scale, color, textStyle);
  1391. break;
  1392. case CG_RED_FLAGHEAD:
  1393. CG_DrawRedFlagHead(&rect);
  1394. break;
  1395. case CG_RED_FLAGSTATUS:
  1396. CG_DrawRedFlagStatus(&rect, shader);
  1397. break;
  1398. case CG_RED_FLAGNAME:
  1399. CG_DrawRedFlagName(&rect, scale, color, textStyle);
  1400. break;
  1401. case CG_HARVESTER_SKULLS:
  1402. CG_HarvesterSkulls(&rect, scale, color, qfalse, textStyle);
  1403. break;
  1404. case CG_HARVESTER_SKULLS2D:
  1405. CG_HarvesterSkulls(&rect, scale, color, qtrue, textStyle);
  1406. break;
  1407. case CG_ONEFLAG_STATUS:
  1408. CG_OneFlagStatus(&rect);
  1409. break;
  1410. case CG_PLAYER_LOCATION:
  1411. CG_DrawPlayerLocation(&rect, scale, color, textStyle);
  1412. break;
  1413. case CG_TEAM_COLOR:
  1414. CG_DrawTeamColor(&rect, color);
  1415. break;
  1416. case CG_CTF_POWERUP:
  1417. CG_DrawCTFPowerUp(&rect);
  1418. break;
  1419. case CG_AREA_POWERUP:
  1420. CG_DrawAreaPowerUp(&rect, align, special, scale, color);
  1421. break;
  1422. case CG_PLAYER_STATUS:
  1423. CG_DrawPlayerStatus(&rect);
  1424. break;
  1425. case CG_PLAYER_HASFLAG:
  1426. CG_DrawPlayerHasFlag(&rect, qfalse);
  1427. break;
  1428. case CG_PLAYER_HASFLAG2D:
  1429. CG_DrawPlayerHasFlag(&rect, qtrue);
  1430. break;
  1431. case CG_AREA_SYSTEMCHAT:
  1432. CG_DrawAreaSystemChat(&rect, scale, color, shader);
  1433. break;
  1434. case CG_AREA_TEAMCHAT:
  1435. CG_DrawAreaTeamChat(&rect, scale, color, shader);
  1436. break;
  1437. case CG_AREA_CHAT:
  1438. CG_DrawAreaChat(&rect, scale, color, shader);
  1439. break;
  1440. case CG_GAME_TYPE:
  1441. CG_DrawGameType(&rect, scale, color, shader, textStyle);
  1442. break;
  1443. case CG_GAME_STATUS:
  1444. CG_DrawGameStatus(&rect, scale, color, shader, textStyle);
  1445. break;
  1446. case CG_KILLER:
  1447. CG_DrawKiller(&rect, scale, color, shader, textStyle);
  1448. break;
  1449. case CG_ACCURACY:
  1450. case CG_ASSISTS:
  1451. case CG_DEFEND:
  1452. case CG_EXCELLENT:
  1453. case CG_IMPRESSIVE:
  1454. case CG_PERFECT:
  1455. case CG_GAUNTLET:
  1456. case CG_CAPTURES:
  1457. CG_DrawMedal(ownerDraw, &rect, scale, color, shader);
  1458. break;
  1459. case CG_SPECTATORS:
  1460. CG_DrawTeamSpectators(&rect, scale, color, shader);
  1461. break;
  1462. case CG_TEAMINFO:
  1463. if (cg_currentSelectedPlayer.integer == numSortedTeamPlayers) {
  1464. CG_DrawNewTeamInfo(&rect, text_x, text_y, scale, color, shader);
  1465. }
  1466. break;
  1467. case CG_CAPFRAGLIMIT:
  1468. CG_DrawCapFragLimit(&rect, scale, color, shader, textStyle);
  1469. break;
  1470. case CG_1STPLACE:
  1471. CG_Draw1stPlace(&rect, scale, color, shader, textStyle);
  1472. break;
  1473. case CG_2NDPLACE:
  1474. CG_Draw2ndPlace(&rect, scale, color, shader, textStyle);
  1475. break;
  1476. default:
  1477. break;
  1478. }
  1479. }
  1480. void CG_MouseEvent(int x, int y) {
  1481. int n;
  1482. if ( (cg.predictedPlayerState.pm_type == PM_NORMAL || cg.predictedPlayerState.pm_type == PM_SPECTATOR) && cg.showScores == qfalse) {
  1483. trap_Key_SetCatcher(0);
  1484. return;
  1485. }
  1486. cgs.cursorX+= x;
  1487. if (cgs.cursorX < 0)
  1488. cgs.cursorX = 0;
  1489. else if (cgs.cursorX > 640)
  1490. cgs.cursorX = 640;
  1491. cgs.cursorY += y;
  1492. if (cgs.cursorY < 0)
  1493. cgs.cursorY = 0;
  1494. else if (cgs.cursorY > 480)
  1495. cgs.cursorY = 480;
  1496. n = Display_CursorType(cgs.cursorX, cgs.cursorY);
  1497. cgs.activeCursor = 0;
  1498. if (n == CURSOR_ARROW) {
  1499. cgs.activeCursor = cgs.media.selectCursor;
  1500. } else if (n == CURSOR_SIZER) {
  1501. cgs.activeCursor = cgs.media.sizeCursor;
  1502. }
  1503. if (cgs.capturedItem) {
  1504. Display_MouseMove(cgs.capturedItem, x, y);
  1505. } else {
  1506. Display_MouseMove(NULL, cgs.cursorX, cgs.cursorY);
  1507. }
  1508. }
  1509. /*
  1510. ==================
  1511. CG_HideTeamMenus
  1512. ==================
  1513. */
  1514. void CG_HideTeamMenu() {
  1515. Menus_CloseByName("teamMenu");
  1516. Menus_CloseByName("getMenu");
  1517. }
  1518. /*
  1519. ==================
  1520. CG_ShowTeamMenus
  1521. ==================
  1522. */
  1523. void CG_ShowTeamMenu() {
  1524. Menus_OpenByName("teamMenu");
  1525. }
  1526. /*
  1527. ==================
  1528. CG_EventHandling
  1529. ==================
  1530. type 0 - no event handling
  1531. 1 - team menu
  1532. 2 - hud editor
  1533. */
  1534. void CG_EventHandling(int type) {
  1535. cgs.eventHandling = type;
  1536. if (type == CGAME_EVENT_NONE) {
  1537. CG_HideTeamMenu();
  1538. } else if (type == CGAME_EVENT_TEAMMENU) {
  1539. //CG_ShowTeamMenu();
  1540. } else if (type == CGAME_EVENT_SCOREBOARD) {
  1541. }
  1542. }
  1543. void CG_KeyEvent(int key, qboolean down) {
  1544. if (!down) {
  1545. return;
  1546. }
  1547. if ( cg.predictedPlayerState.pm_type == PM_NORMAL || (cg.predictedPlayerState.pm_type == PM_SPECTATOR && cg.showScores == qfalse)) {
  1548. CG_EventHandling(CGAME_EVENT_NONE);
  1549. trap_Key_SetCatcher(0);
  1550. return;
  1551. }
  1552. //if (key == trap_Key_GetKey("teamMenu") || !Display_CaptureItem(cgs.cursorX, cgs.cursorY)) {
  1553. // if we see this then we should always be visible
  1554. // CG_EventHandling(CGAME_EVENT_NONE);
  1555. // trap_Key_SetCatcher(0);
  1556. //}
  1557. Display_HandleKey(key, down, cgs.cursorX, cgs.cursorY);
  1558. if (cgs.capturedItem) {
  1559. cgs.capturedItem = NULL;
  1560. } else {
  1561. if (key == K_MOUSE2 && down) {
  1562. cgs.capturedItem = Display_CaptureItem(cgs.cursorX, cgs.cursorY);
  1563. }
  1564. }
  1565. }
  1566. int CG_ClientNumFromName(const char *p) {
  1567. int i;
  1568. for (i = 0; i < cgs.maxclients; i++) {
  1569. if (cgs.clientinfo[i].infoValid && Q_stricmp(cgs.clientinfo[i].name, p) == 0) {
  1570. return i;
  1571. }
  1572. }
  1573. return -1;
  1574. }
  1575. void CG_ShowResponseHead() {
  1576. Menus_OpenByName("voiceMenu");
  1577. trap_Cvar_Set("cl_conXOffset", "72");
  1578. cg.voiceTime = cg.time;
  1579. }
  1580. void CG_RunMenuScript(char **args) {
  1581. }
  1582. void CG_GetTeamColor(vec4_t *color) {
  1583. if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_RED) {
  1584. (*color)[0] = 1.0f;
  1585. (*color)[3] = 0.25f;
  1586. (*color)[1] = (*color)[2] = 0.0f;
  1587. } else if (cg.snap->ps.persistant[PERS_TEAM] == TEAM_BLUE) {
  1588. (*color)[0] = (*color)[1] = 0.0f;
  1589. (*color)[2] = 1.0f;
  1590. (*color)[3] = 0.25f;
  1591. } else {
  1592. (*color)[0] = (*color)[2] = 0.0f;
  1593. (*color)[1] = 0.17f;
  1594. (*color)[3] = 0.25f;
  1595. }
  1596. }