hud.cpp 97 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Commando *
  23. * *
  24. * $Archive:: /Commando/Code/Combat/hud.cpp $*
  25. * *
  26. * $Author:: Byon_g $*
  27. * *
  28. * $Modtime:: 2/11/02 2:27p $*
  29. * *
  30. * $Revision:: 228 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "hud.h"
  36. #include <stdio.h>
  37. #include "wwprofile.h"
  38. #include "assets.h"
  39. #include "font3d.h"
  40. #include "combat.h"
  41. #include "soldier.h"
  42. #include "debug.h"
  43. #include "ccamera.h"
  44. #include "vehicle.h"
  45. #include "weapons.h"
  46. #include "radar.h"
  47. #include "texture.h"
  48. #include "phys.h"
  49. #include "render2d.h"
  50. #include "hudinfo.h"
  51. #include "globalsettings.h"
  52. #include "translatedb.h"
  53. #include "playerdata.h"
  54. #include "playertype.h"
  55. #include "sniper.h"
  56. #include "render2dsentence.h"
  57. #include "input.h"
  58. #include "building.h"
  59. #include "objectives.h"
  60. #include "weaponbag.h"
  61. #include "string_ids.h"
  62. #include "gametype.h"
  63. #include "stylemgr.h"
  64. static void Generate_WChar_Text_From_Number(WCHAR* text,int digits,int min_digits,int value)
  65. {
  66. text[digits]=0;
  67. while (digits) {
  68. digits--;
  69. text[digits]=value%10+'0';
  70. value/=10;
  71. min_digits--;
  72. if (value==0 && (min_digits == 0)) break;
  73. }
  74. if ((min_digits==0) && digits) {
  75. int i=0;
  76. while (WCHAR c=text[digits++]) {
  77. text[i++]=c;
  78. }
  79. text[i]=0;
  80. }
  81. }
  82. /*
  83. **
  84. */
  85. Vector2 INFO_UV_SCALE( 1.0f/256.0f, 1.0f/256.0f );
  86. Vector2 INFO_OFFSET( 7, -179 );
  87. Vector2 FRAME_1_UV_UL( 96, 105 );
  88. Vector2 FRAME_1_UV_LR( 214, 255 );
  89. Vector2 FRAME_1_OFFSET( -3, -1 );
  90. Vector2 FRAME_2_UV_UL( 215, 125 );
  91. Vector2 FRAME_2_UV_LR( 255, 192 );
  92. Vector2 FRAME_2_OFFSET( 114, 57 );
  93. Vector2 FRAME_3_UV_UL( 218, 192 );
  94. Vector2 FRAME_3_UV_LR( 255, 201 );
  95. Vector2 FRAME_3_OFFSET( 154, 115 );
  96. Vector2 FRAME_4_UV_UL( 216, 200 );
  97. Vector2 FRAME_4_UV_LR( 255, 255 );
  98. Vector2 FRAME_4_OFFSET( 191, 115 );
  99. Vector2 FRAME_5_UV_UL( 80, 203 );
  100. Vector2 FRAME_5_UV_LR( 100, 258 );
  101. Vector2 FRAME_5_OFFSET( 230, 116 );
  102. Vector2 FRAME_6_UV_UL( 216, 101 );
  103. Vector2 FRAME_6_UV_LR( 240, 125 );
  104. Vector2 FRAME_6_OFFSET( 74, 149 );
  105. Vector2 HEALTH_BACK_UV_UL( 183, 241 );
  106. Vector2 HEALTH_BACK_UV_LR( 186, 248 );
  107. Vector2 HEALTH_BACK_UL( 98, 122 );
  108. Vector2 HEALTH_BACK_LR( 224, 168 );
  109. Vector2 GRADIENT_BLACK_UV_UL( 3, 135 );
  110. Vector2 GRADIENT_BLACK_UV_LR( 44, 144 );
  111. Vector2 HEALTH_TEXT_BACK_UL( 77, 124 );
  112. Vector2 HEALTH_TEXT_BACK_LR( 163, 150 );
  113. Vector2 HEALTH_UV_UL( 94, 52 );
  114. Vector2 HEALTH_UV_LR( 249, 100 );
  115. Vector2 HEALTH_OFFSET( 73, 121 );
  116. Vector2 SHIELD_UV_UL( 66, 97 );
  117. Vector2 SHIELD_UV_LR( 96, 132 );
  118. Vector2 SHIELD_OFFSET( 211, 140 );
  119. Vector2 KEY_1_UV_UL( 30, 180 );
  120. Vector2 KEY_1_UV_LR( 57, 197 );
  121. Vector2 KEY_1_OFFSET( 32, 134 );
  122. Vector2 KEY_2_UV_UL( 0, 181 );
  123. Vector2 KEY_2_UV_LR( 30, 197 );
  124. Vector2 KEY_2_OFFSET( 41, 140 );
  125. Vector2 KEY_3_UV_UL( 69, 133 );
  126. Vector2 KEY_3_UV_LR( 97, 149 );
  127. Vector2 KEY_3_OFFSET( 50, 148 );
  128. Vector2 HEALTH_CROSS_1_UV_UL( 33, 199 );
  129. Vector2 HEALTH_CROSS_1_UV_LR( 63, 226 );
  130. Vector2 HEALTH_CROSS_1_OFFSET( 77, 124 );
  131. Vector2 HEALTH_CROSS_2_UV_UL( 33, 228 );
  132. Vector2 HEALTH_CROSS_2_UV_LR( 63, 258 );
  133. Vector2 HEALTH_CROSS_2_OFFSET( 77, 124 );
  134. Vector2 TIME_BACK_UL( 150, 97 );
  135. Vector2 TIME_BACK_LR( 213, 116 );
  136. Vector2 TIME_CLOCK_UV_UL( 46, 125 );
  137. Vector2 TIME_CLOCK_UV_LR( 66, 148 );
  138. Vector2 TIME_CLOCK_OFFSET( 186, 94 );
  139. Vector2 WEAPON_BOX_UV_UL( 0, 0 );
  140. Vector2 WEAPON_BOX_UV_LR( 95, 95 );
  141. Vector2 WEAPON_BOX_OFFSET( 195, -53 );
  142. Vector2 POWER_OUT_ICON_UV_UL( 0, 95 );
  143. Vector2 POWER_OUT_ICON_UV_LR( 30, 129 );
  144. Vector2 POWER_OUT_ICON_OFFSET( 143, 41 );
  145. Vector2 REPAIR_ICON_UV_UL( 31, 97 );
  146. Vector2 REPAIR_ICON_UV_LR( 61, 126 );
  147. Vector2 REPAIR_ICON_OFFSET( 181, 43 );
  148. Vector2 GDI_ICON_UV_UL( 14, 222 );
  149. Vector2 GDI_ICON_UV_LR( 34, 238 );
  150. Vector2 GDI_ICON_OFFSET( 217, 77 );
  151. Vector2 NOD_ICON_UV_UL( 14, 205 );
  152. Vector2 NOD_ICON_UV_LR( 34, 221 );
  153. Vector2 NOD_ICON_OFFSET( 238, 76 );
  154. Vector2 NEUTRAL_ICON_UV_UL( 14, 238 );
  155. Vector2 NEUTRAL_ICON_UV_LR( 33, 257 );
  156. Vector2 NEUTRAL_ICON_OFFSET( 260, 77 );
  157. Vector2 BULLET_ICON_UV_UL( 2, 211 );
  158. Vector2 BULLET_ICON_UV_LR( 13, 255 );
  159. Vector2 BULLET_ICON_OFFSET( -20, -30 );
  160. Vector2 RADAR_CENTER_OFFSET( 55, 78 );
  161. Vector2 DAMAGE_1_UV_UL( 65, 184 );
  162. Vector2 DAMAGE_1_UV_LR( 78, 255 );
  163. Vector2 DAMAGE_2_UV_UL( 200, 3 );
  164. Vector2 DAMAGE_2_UV_LR( 248, 51 );
  165. Vector2 HORIZ_DAMAGE_SIZE( 81, 14 );
  166. Vector2 VERT_DAMAGE_SIZE( 15, 78 );
  167. Vector2 DIAG_DAMAGE_SIZE( 53, 59 );
  168. Vector2 HV_DAMAGE_OFFSET( 170, 168 );
  169. Vector2 DIAG_DAMAGE_OFFSET( 119, 117 );
  170. //Vector2 POWERUP_BOX_UV_UL( 48, 0 );
  171. //Vector2 POWERUP_BOX_UV_LR( 129, 54 );
  172. Vector2 POWERUP_BOX_UV_UL( 50, 1 );
  173. Vector2 POWERUP_BOX_UV_LR( 127, 52 );
  174. Vector2 RADAR_RINGS_UV_UL( 95, 0 );
  175. Vector2 RADAR_RINGS_UV_LR( 197, 53 );
  176. Vector2 RADAR_RINGS_L_OFFSET( -51, -50 );
  177. Vector2 RADAR_RINGS_R_OFFSET( 0, -50 );
  178. Vector2 RADAR_STAR_UV_UL( 241, 103 );
  179. Vector2 RADAR_STAR_UV_LR( 249, 111 );
  180. Vector2 RADAR_STAR_OFFSET( 280, 50 );
  181. Vector2 RADAR_SQUARE_UV_UL( 247, 85 );
  182. Vector2 RADAR_SQUARE_UV_LR( 255, 93 );
  183. Vector2 RADAR_SQUARE_OFFSET( 290, 50 );
  184. Vector2 RADAR_TRIANGLE_UV_UL( 247, 93 );
  185. Vector2 RADAR_TRIANGLE_UV_LR( 255, 101 );
  186. Vector2 RADAR_TRIANGLE_OFFSET( 300, 50 );
  187. Vector2 RADAR_CIRCLE_UV_UL( 247, 77 );
  188. Vector2 RADAR_CIRCLE_UV_LR( 255, 85 );
  189. Vector2 RADAR_CIRCLE_OFFSET( 310, 50 );
  190. Vector2 RADAR_BRACKET_UV_UL( 241, 114 );
  191. Vector2 RADAR_BRACKET_UV_LR( 249, 122 );
  192. Vector2 RADAR_BRACKET_OFFSET( 320, 50 );
  193. Vector2 RADAR_SWEEP_UV_UL( 80, 182 );
  194. Vector2 RADAR_SWEEP_UV_LR( 95, 191 );
  195. Vector2 RADAR_SWEEP_OFFSET( 330, 50 );
  196. Vector2 TARGET_HEALTH_L_UV_UL( 0, 165 );
  197. Vector2 TARGET_HEALTH_L_UV_LR( 20, 181 );
  198. Vector2 TARGET_HEALTH_R_UV_UL( 20, 165 );
  199. //Vector2 TARGET_HEALTH_R_UV_LR( 96, 181 );
  200. Vector2 TARGET_HEALTH_R_UV_LR( 96, 173 );
  201. Vector2 TARGET_HEALTH_OFFSET( 123, 5 );
  202. Vector2 TARGET_NAME_UV_UL( 1, 149 );
  203. Vector2 TARGET_NAME_UV_LR( 91, 164 );
  204. Vector2 TARGET_NAME_OFFSET( 125, 24 );
  205. // Reticle
  206. #define RETICLE_WIDTH (64.0f/640.0f)
  207. #define RETICLE_HEIGHT (64.0f/480.0f)
  208. //
  209. Vector2 TARGET_ENTERABLE_UV_UL( 45, 209 );
  210. Vector2 TARGET_ENTERABLE_UV_LR( 51, 215 );
  211. Vector2 TARGET_ENTERABLE_SIZE( 32, 32 );
  212. float TARGET_ENTERABLE_BOUNCE = 4;
  213. /*
  214. **
  215. */
  216. //#define LARGE_FONT "FONT24x36.TGA"
  217. #define LARGE_FONT "FONT12x16.TGA"
  218. #define MEDIUM_FONT "FONT12x16.TGA"
  219. #define SMALL_FONT "FONT6x8.TGA"
  220. enum
  221. {
  222. HUD_HELP_TEXT_DISPLAYING = 0,
  223. HUD_HELP_TEXT_FADING,
  224. HUD_HELP_TEXT_DONE
  225. };
  226. /*
  227. **
  228. */
  229. #define HUD_MAIN_TEXTURE "HUD_MAIN.TGA"
  230. #define HUD_CHATPBOX_TEXTURE "HUD_CHATPBOX.TGA"
  231. #define HUD_WEAPONS_TEXTURE "hud_TibRVoltR.tga" /* This should be removed */
  232. Render2DClass * InfoRenderer;
  233. Render2DSentenceClass * HUDHelpTextRenderer;
  234. Vector2 HUDHelpTextExtents (0, 0);
  235. float HUDHelpTextTimer = 0;
  236. int HUDHelpTextState = HUD_HELP_TEXT_DISPLAYING;
  237. /*
  238. **
  239. */
  240. unsigned long COLOR( float alpha, unsigned long color = 0x00FFFFFF )
  241. {
  242. alpha = WWMath::Clamp( alpha, 0, 1 ) * 255.0f;
  243. color &= 0x00FFFFFF;
  244. color |= ((int)alpha) << 24;
  245. return color;
  246. }
  247. unsigned long Get_Health_Color( float percent )
  248. {
  249. Vector3 color = HUDGlobalSettingsDef::Get_Instance()->Get_Health_High_Color();
  250. if ( percent <= 0.5f ) {
  251. color = HUDGlobalSettingsDef::Get_Instance()->Get_Health_Med_Color();
  252. }
  253. if ( percent <= 0.25f ) {
  254. color = HUDGlobalSettingsDef::Get_Instance()->Get_Health_Low_Color();
  255. }
  256. return color.Convert_To_ARGB();
  257. }
  258. /*
  259. ** Powerup Display
  260. */
  261. struct PowerupIconStruct {
  262. PowerupIconStruct( void ) : Renderer( NULL ), Number( 0 ) {}
  263. ~PowerupIconStruct( void ) {
  264. if ( Renderer != NULL ) {
  265. delete Renderer;
  266. Renderer = NULL;
  267. }
  268. }
  269. WideStringClass Name;
  270. int Number;
  271. Render2DClass * Renderer;
  272. RectClass UV;
  273. RectClass IconBox;
  274. float Timer;
  275. };
  276. // Two lists. A right one for weapons, health, and armor
  277. static DynamicVectorClass<PowerupIconStruct*> RightPowerupIconList;
  278. // and a left one for keys
  279. static DynamicVectorClass<PowerupIconStruct*> LeftPowerupIconList;
  280. Render2DClass * PowerupBoxRenderer;
  281. Render2DSentenceClass * PowerupTextRenderer;
  282. #define MAX_ICONS 5
  283. #define POWERUP_TIME 6
  284. static void Powerup_Init( void )
  285. {
  286. PowerupBoxRenderer = new Render2DClass();
  287. PowerupBoxRenderer->Set_Texture( HUD_CHATPBOX_TEXTURE );
  288. PowerupBoxRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  289. PowerupBoxRenderer->Enable_Additive( true );
  290. FontCharsClass * font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT );
  291. PowerupTextRenderer = new Render2DSentenceClass();
  292. PowerupTextRenderer->Set_Font( font );
  293. WWASSERT( LeftPowerupIconList.Count() == 0 );
  294. WWASSERT( RightPowerupIconList.Count() == 0 );
  295. }
  296. static void Powerup_Shutdown( void )
  297. {
  298. delete PowerupBoxRenderer;
  299. PowerupBoxRenderer = NULL;
  300. delete PowerupTextRenderer;
  301. PowerupTextRenderer = NULL;
  302. int i;
  303. for ( i = 0; i < LeftPowerupIconList.Count(); i++ ) {
  304. delete LeftPowerupIconList[i];
  305. }
  306. LeftPowerupIconList.Delete_All();
  307. for ( i = 0; i < RightPowerupIconList.Count(); i++ ) {
  308. delete RightPowerupIconList[i];
  309. }
  310. RightPowerupIconList.Delete_All();
  311. }
  312. static void Powerup_Add( const WCHAR * name, int number, const char * texture_name, const RectClass & uv, const Vector2 & offset, bool right_list = true )
  313. {
  314. PowerupIconStruct * data = new PowerupIconStruct();
  315. data->Renderer = new Render2DClass();
  316. StringClass new_name(true);
  317. Strip_Path_From_Filename( new_name, texture_name );
  318. data->Renderer->Set_Texture( new_name );
  319. data->Renderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  320. // data->Renderer->Enable_Additive( true );
  321. // SurfaceClass::SurfaceDescription surface_desc;
  322. // data->Renderer->Peek_Texture()->Get_Level_Description( surface_desc );
  323. // float size = surface_desc.Width; // Assume square
  324. float size = data->Renderer->Peek_Texture()->Get_Width(); // Assume square
  325. data->UV = uv;
  326. if ( size > 0 ) {
  327. data->UV.Scale( Vector2( 1/size, 1/size ) );
  328. }
  329. data->IconBox = uv;
  330. data->IconBox += offset + Vector2( 0, -40.0f ) - data->IconBox.Upper_Left();
  331. data->Name = name;
  332. data->Number = number;
  333. data->Timer = POWERUP_TIME;
  334. if ( right_list ) {
  335. RightPowerupIconList.Add( data );
  336. } else {
  337. LeftPowerupIconList.Add( data );
  338. }
  339. }
  340. void Powerup_Reset( void )
  341. {
  342. while ( LeftPowerupIconList.Count() ) {
  343. delete LeftPowerupIconList[0];
  344. LeftPowerupIconList.Delete(0);
  345. }
  346. while ( RightPowerupIconList.Count() ) {
  347. delete RightPowerupIconList[0];
  348. RightPowerupIconList.Delete(0);
  349. }
  350. }
  351. #define POWERUP_BOX_BASE POWERUP_BOX_WIDTH + 6, 112
  352. #define POWERUP_BOX_WIDTH 80
  353. #define POWERUP_BOX_HEIGHT 55
  354. #define POWERUP_BOX_SPACING (POWERUP_BOX_HEIGHT + 10)
  355. #define POWERUP_BOX_UV 127,0,207,55
  356. static void Powerup_Update( void )
  357. {
  358. PowerupBoxRenderer->Reset();
  359. PowerupTextRenderer->Reset();
  360. RectClass box_uv( POWERUP_BOX_UV_UL, POWERUP_BOX_UV_LR );
  361. box_uv.Scale( Vector2( 1.0f/128.0f, 1.0f/128.0f ) );
  362. #define ANIMATE_TIME 1.0f
  363. // Two timers
  364. static float LeftAnimateTimer = 0;
  365. static float RightAnimateTimer = 0;
  366. if ( LeftPowerupIconList.Count() > 0 && LeftPowerupIconList[0]->Timer < 0 ) {
  367. LeftAnimateTimer += TimeManager::Get_Frame_Seconds();
  368. if ( LeftAnimateTimer > ANIMATE_TIME ) {
  369. LeftAnimateTimer = 0;
  370. if ( LeftPowerupIconList.Count() ) {
  371. delete LeftPowerupIconList[0];
  372. LeftPowerupIconList.Delete(0);
  373. }
  374. }
  375. } else {
  376. LeftAnimateTimer = 0;
  377. }
  378. if ( RightPowerupIconList.Count() > 0 && RightPowerupIconList[0]->Timer < 0 ) {
  379. RightAnimateTimer += TimeManager::Get_Frame_Seconds();
  380. if ( RightAnimateTimer > ANIMATE_TIME ) {
  381. RightAnimateTimer = 0;
  382. if ( RightPowerupIconList.Count() ) {
  383. delete RightPowerupIconList[0];
  384. RightPowerupIconList.Delete(0);
  385. }
  386. }
  387. } else {
  388. RightAnimateTimer = 0;
  389. }
  390. RectClass box( POWERUP_BOX_UV_UL, POWERUP_BOX_UV_LR );
  391. Vector2 start = Render2DClass::Get_Screen_Resolution().Lower_Right() - Vector2( POWERUP_BOX_BASE );
  392. box += start - box.Lower_Left();
  393. box -= Vector2( box.Left - 6, +75 );
  394. int i;
  395. for ( i = 0; i < MAX_ICONS && i < LeftPowerupIconList.Count(); i++ ) {
  396. LeftPowerupIconList[i]->Timer -= TimeManager::Get_Frame_Seconds();
  397. RectClass draw_box = box;
  398. int green = 0xFF00FF00;
  399. int white = 0xFFFFFFFF;
  400. // Slide the bottom (first) icon away
  401. if ( i == 0 && LeftAnimateTimer > 0.0f ) {
  402. green = COLOR( WWMath::Clamp( 1.0f - (LeftAnimateTimer/ANIMATE_TIME), 0, 1 ), green ) ;
  403. white = COLOR( WWMath::Clamp( 1.0f - (LeftAnimateTimer/ANIMATE_TIME), 0, 1 ), white ) ;
  404. }
  405. #if 0 // No boxes
  406. // The box is drawn additive, so his color is green alpha
  407. int box_color = (white & 0xFF000000) | ((white >> 16) & 0x0000FF00);
  408. PowerupBoxRenderer->Add_Quad( draw_box, box_uv, box_color );
  409. #endif
  410. // Draw powerup name
  411. PowerupTextRenderer->Build_Sentence( LeftPowerupIconList[i]->Name );
  412. PowerupTextRenderer->Set_Location( Vector2( draw_box.Left + 1, draw_box.Top + POWERUP_BOX_HEIGHT - 15 ) );
  413. PowerupTextRenderer->Draw_Sentence( white );
  414. #if 0
  415. // Draw powerup count
  416. if ( LeftPowerupIconList[i]->Number != 0 ) {
  417. WideStringClass num(0,true);
  418. num.Format( L"%d", LeftPowerupIconList[i]->Number );
  419. PowerupTextRenderer->Build_Sentence( num );
  420. PowerupTextRenderer->Set_Location( Vector2( draw_box.Right - 12, draw_box.Top + 1 ) );
  421. PowerupTextRenderer->Draw_Sentence( white );
  422. }
  423. #endif
  424. RectClass icon_box = LeftPowerupIconList[i]->IconBox;
  425. icon_box += draw_box.Upper_Left();
  426. LeftPowerupIconList[i]->Renderer->Reset();
  427. LeftPowerupIconList[i]->Renderer->Add_Quad( icon_box, LeftPowerupIconList[i]->UV, white );
  428. // Drop the remaining icons down
  429. if ( i == 0 && LeftAnimateTimer > ANIMATE_TIME * 0.5f ) {
  430. box += Vector2( 0, ((2*LeftAnimateTimer/ANIMATE_TIME)-1) * POWERUP_BOX_SPACING );
  431. }
  432. box -= Vector2( 0, POWERUP_BOX_SPACING );
  433. }
  434. // Setup box for right
  435. box = RectClass( POWERUP_BOX_UV_UL, POWERUP_BOX_UV_LR );
  436. start = Render2DClass::Get_Screen_Resolution().Lower_Right() - Vector2( POWERUP_BOX_BASE );
  437. box += start - box.Lower_Left();
  438. for ( i = 0; i < MAX_ICONS && i < RightPowerupIconList.Count(); i++ ) {
  439. RightPowerupIconList[i]->Timer -= TimeManager::Get_Frame_Seconds();
  440. RectClass draw_box = box;
  441. int green = 0xFF00FF00;
  442. int white = 0xFFFFFFFF;
  443. // Slide the bottom (first) icon away
  444. if ( i == 0 && RightAnimateTimer > 0.0f ) {
  445. green = COLOR( WWMath::Clamp( 1.0f - (RightAnimateTimer/ANIMATE_TIME), 0, 1 ), green ) ;
  446. white = COLOR( WWMath::Clamp( 1.0f - (RightAnimateTimer/ANIMATE_TIME), 0, 1 ), white ) ;
  447. }
  448. #if 0 // No boxes
  449. // The box is drawn additive, so his color is green alpha
  450. int box_color = (white & 0xFF000000) | ((white >> 16) & 0x0000FF00);
  451. PowerupBoxRenderer->Add_Quad( draw_box, box_uv, box_color );
  452. #endif
  453. // Draw powerup name
  454. PowerupTextRenderer->Build_Sentence( RightPowerupIconList[i]->Name );
  455. float left_edge = draw_box.Left + 1;
  456. Vector2 extents = PowerupTextRenderer->Get_Text_Extents( RightPowerupIconList[i]->Name );
  457. if ( left_edge + extents.X + 1> Render2DClass::Get_Screen_Resolution().Right ) {
  458. left_edge = Render2DClass::Get_Screen_Resolution().Right - extents.X - 1;
  459. }
  460. PowerupTextRenderer->Set_Location( Vector2( left_edge, draw_box.Top + POWERUP_BOX_HEIGHT - 15 ) );
  461. PowerupTextRenderer->Draw_Sentence( white );
  462. // Draw powerup count
  463. if ( RightPowerupIconList[i]->Number != 0 ) {
  464. WideStringClass num(0,true);
  465. num.Format( L"%d", RightPowerupIconList[i]->Number );
  466. PowerupTextRenderer->Build_Sentence( num );
  467. PowerupTextRenderer->Set_Location( Vector2( draw_box.Right - 12, draw_box.Top + 1 ) );
  468. PowerupTextRenderer->Draw_Sentence( white );
  469. }
  470. RectClass icon_box = RightPowerupIconList[i]->IconBox;
  471. icon_box += draw_box.Upper_Left();
  472. RightPowerupIconList[i]->Renderer->Reset();
  473. RightPowerupIconList[i]->Renderer->Add_Quad( icon_box, RightPowerupIconList[i]->UV, green );
  474. // Drop the remaining icons down
  475. if ( i == 0 && RightAnimateTimer > ANIMATE_TIME * 0.5f ) {
  476. box += Vector2( 0, ((2*RightAnimateTimer/ANIMATE_TIME)-1) * POWERUP_BOX_SPACING );
  477. }
  478. box -= Vector2( 0, POWERUP_BOX_SPACING );
  479. }
  480. }
  481. static void Powerup_Render( void )
  482. {
  483. #if 0 // No boxes
  484. PowerupBoxRenderer->Render();
  485. #endif
  486. int i;
  487. for ( i = 0; i < MAX_ICONS && i < LeftPowerupIconList.Count(); i++ ) {
  488. LeftPowerupIconList[i]->Renderer->Render();
  489. }
  490. for ( i = 0; i < MAX_ICONS && i < RightPowerupIconList.Count(); i++ ) {
  491. RightPowerupIconList[i]->Renderer->Render();
  492. }
  493. PowerupTextRenderer->Render();
  494. }
  495. /*
  496. ** Weapon Display
  497. */
  498. Render2DClass * WeaponBoxRenderer;
  499. Render2DClass * WeaponImageRenderer;
  500. Render2DTextClass * WeaponClipCountRenderer;
  501. Render2DTextClass * WeaponTotalCountRenderer;
  502. Render2DSentenceClass * WeaponNameRenderer;
  503. Vector2 WeaponBase;
  504. WeaponClass * _LastHUDWeapon = NULL;
  505. int _LastVehicleSeat = -1;
  506. #define WEAPON_OFFSET 100, 110
  507. //#define WEAPON_BOX_UV 0,0,95,95
  508. #define SNIPER_UV 90,0,255,53
  509. #define SNIPER_OFFSET -80,-4
  510. static void HUD_Help_Text_Init( void )
  511. {
  512. //
  513. // Load the font...
  514. //
  515. FontCharsClass *font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_BIG_TXT );
  516. WWASSERT (font != NULL);
  517. //
  518. // Configure the renderer
  519. //
  520. HUDHelpTextRenderer = new Render2DSentenceClass;
  521. HUDHelpTextRenderer->Set_Font( font );
  522. HUDHelpTextExtents.Set (0, 0);
  523. HUDHelpTextTimer = 0;
  524. HUDHelpTextState = HUD_HELP_TEXT_DISPLAYING;
  525. return ;
  526. }
  527. static void HUD_Help_Text_Render( void )
  528. {
  529. const float HUD_HELP_TEXT_FADE_TIME = 2.0F;
  530. const float HUD_HELP_TEXT_DISPLAY_TIME = 2.0F;
  531. const WideStringClass &string = HUDInfo::Get_HUD_Help_Text();
  532. bool is_empty = string.Is_Empty();
  533. //
  534. // Rebuild the renderer (if necessary)
  535. //
  536. if (HUDInfo::Is_HUD_Help_Text_Dirty()) {
  537. HUDHelpTextState = HUD_HELP_TEXT_DISPLAYING;
  538. HUDInfo::Set_Is_HUD_Help_Text_Dirty( false );
  539. HUDHelpTextRenderer->Reset();
  540. if (is_empty == false) {
  541. HUDHelpTextRenderer->Build_Sentence( string );
  542. HUDHelpTextTimer = HUD_HELP_TEXT_DISPLAY_TIME;
  543. }
  544. HUDHelpTextExtents = HUDHelpTextRenderer->Get_Text_Extents (string);
  545. }
  546. //
  547. // Draw the text if there's something to draw
  548. //
  549. if ( is_empty == false ) {
  550. HUDHelpTextRenderer->Reset_Polys();
  551. //
  552. // Render the text above the reticle
  553. //
  554. Vector2 reticle_offset = COMBAT_CAMERA->Get_Camera_Target_2D_Offset();
  555. const RectClass &screen_rect = Render2DClass::Get_Screen_Resolution();
  556. float x_pos = screen_rect.Center ().X - (HUDHelpTextExtents.X * 0.5F);
  557. float y_pos = screen_rect.Center ().Y - (HUDHelpTextExtents.Y);
  558. y_pos -= (RETICLE_HEIGHT * screen_rect.Height () * 0.25F);
  559. HUDHelpTextRenderer->Set_Location( Vector2( x_pos, y_pos ) );
  560. HUDHelpTextRenderer->Draw_Sentence( RGB_TO_INT32 (0, 0, 0) );
  561. HUDHelpTextRenderer->Set_Location( Vector2( x_pos-1, y_pos-1 ) );
  562. HUDHelpTextRenderer->Draw_Sentence( VRGB_TO_INT32 (HUDInfo::Get_HUD_Help_Text_Color ()) );
  563. //
  564. // Fade the text out (if necessary)
  565. //
  566. if (HUDHelpTextState == HUD_HELP_TEXT_FADING) {
  567. float percent = WWMath::Clamp ((HUDHelpTextTimer / HUD_HELP_TEXT_FADE_TIME), 0.0F, 1.0F);
  568. HUDHelpTextRenderer->Force_Alpha (percent * 0.5F);
  569. } else {
  570. HUDHelpTextRenderer->Force_Alpha (0.5F);
  571. }
  572. //
  573. // Render the quads
  574. //
  575. HUDHelpTextRenderer->Render();
  576. //
  577. // Advance to the next state
  578. //
  579. HUDHelpTextTimer -= TimeManager::Get_Frame_Seconds ();
  580. if (HUDHelpTextTimer <= 0) {
  581. HUDHelpTextState ++;
  582. //
  583. // Clear the text if necessary
  584. //
  585. if (HUDHelpTextState >= HUD_HELP_TEXT_DONE) {
  586. HUDInfo::Set_HUD_Help_Text( L"" );
  587. HUDHelpTextRenderer->Reset();
  588. } else if (HUDHelpTextState == HUD_HELP_TEXT_FADING) {
  589. HUDHelpTextTimer = HUD_HELP_TEXT_FADE_TIME;
  590. }
  591. }
  592. }
  593. return ;
  594. }
  595. static void HUD_Help_Text_Shutdown( void )
  596. {
  597. delete HUDHelpTextRenderer;
  598. HUDHelpTextRenderer = NULL;
  599. return ;
  600. }
  601. static void Weapon_Init( void )
  602. {
  603. WeaponBoxRenderer = new Render2DClass();
  604. WeaponBoxRenderer->Set_Texture( HUD_MAIN_TEXTURE );
  605. WeaponBoxRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  606. RectClass box_uv( WEAPON_BOX_UV_UL, WEAPON_BOX_UV_LR );
  607. RectClass draw_box = box_uv;
  608. box_uv.Scale( Vector2( 1.0f/256.0f, 1.0f/256.0f ) );
  609. draw_box += Render2DClass::Get_Screen_Resolution().Lower_Right() - Vector2( WEAPON_OFFSET ) - draw_box.Upper_Left();
  610. WeaponBoxRenderer->Add_Quad( draw_box, box_uv );
  611. WeaponBase = draw_box.Upper_Left();
  612. WeaponImageRenderer = new Render2DClass();
  613. WeaponImageRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  614. FontCharsClass *chars_font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT );
  615. WeaponNameRenderer = new Render2DSentenceClass();
  616. WeaponNameRenderer->Set_Font( chars_font );
  617. // WeaponNameRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  618. Font3DInstanceClass * font = WW3DAssetManager::Get_Instance()->Get_Font3DInstance( LARGE_FONT );
  619. SET_REF_OWNER( font );
  620. WeaponClipCountRenderer = new Render2DTextClass( font );
  621. WeaponClipCountRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  622. font->Release_Ref();
  623. font = WW3DAssetManager::Get_Instance()->Get_Font3DInstance( SMALL_FONT );
  624. SET_REF_OWNER( font );
  625. WeaponTotalCountRenderer = new Render2DTextClass( font );
  626. WeaponTotalCountRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  627. font->Release_Ref();
  628. _LastHUDWeapon = NULL;
  629. _LastVehicleSeat = -1;
  630. }
  631. static void Weapon_Shutdown( void )
  632. {
  633. delete WeaponBoxRenderer;
  634. WeaponBoxRenderer = NULL;
  635. delete WeaponImageRenderer;
  636. WeaponImageRenderer = NULL;
  637. delete WeaponNameRenderer;
  638. WeaponNameRenderer = NULL;
  639. delete WeaponClipCountRenderer;
  640. WeaponClipCountRenderer = NULL;
  641. delete WeaponTotalCountRenderer;
  642. WeaponTotalCountRenderer = NULL;
  643. }
  644. #define CLIP_ROUNDS_OFFSET 15,27
  645. #define TOTAL_ROUNDS_OFFSET 65,34
  646. #define WEAPON_NAME_OFFSET -10, 95
  647. float LastClipCount = 0;
  648. float CenterClipCountTimer = 0;
  649. const float CENTER_CLIP_COUNT_TIME = 2.0f;
  650. enum {
  651. SEAT_DRIVER = 0,
  652. SEAT_GUNNER,
  653. SEAT_PASENGER,
  654. };
  655. const char * _Seat_Textures[3] = {
  656. "hud_driverseat.tga", // SEAT_DRIVER = 0,
  657. "hud_gunseat.tga", // SEAT_GUNNER,
  658. "hud_passseat.tga", // SEAT_PASENGER,
  659. };
  660. static void Weapon_Reset( void )
  661. {
  662. _LastHUDWeapon = (WeaponClass *)0xFFFFFFFF; // force weapon to re-draw next
  663. _LastVehicleSeat = -1; // force vehicle seat to re-draw next
  664. }
  665. static void Weapon_Update( void )
  666. {
  667. WeaponClass * weapon = NULL;
  668. if ( COMBAT_STAR ) {
  669. weapon = COMBAT_STAR->Get_Weapon();
  670. if ( COMBAT_STAR->Get_Vehicle() ) {
  671. weapon = COMBAT_STAR->Get_Vehicle()->Get_Weapon();
  672. }
  673. }
  674. WeaponClipCountRenderer->Reset();
  675. WeaponTotalCountRenderer->Reset();
  676. if ( weapon != NULL ) {
  677. // StringClass text;
  678. // text.Format( "%03d", weapon->Get_Clip_Rounds() );
  679. WCHAR tmp_text[5];
  680. if ( weapon->Get_Clip_Rounds() == -1 ) {
  681. //text.Format( "999", weapon->Get_Total_Rounds() );
  682. tmp_text[0]='9';
  683. tmp_text[1]='9';
  684. tmp_text[2]='9';
  685. tmp_text[3]=0;
  686. } else {
  687. Generate_WChar_Text_From_Number(tmp_text,3,3,weapon->Get_Clip_Rounds());
  688. }
  689. WeaponClipCountRenderer->Set_Location( WeaponBase + Vector2( CLIP_ROUNDS_OFFSET ) );
  690. WeaponClipCountRenderer->Draw_Text( tmp_text );
  691. if ( LastClipCount != weapon->Get_Clip_Rounds() ) {
  692. LastClipCount = weapon->Get_Clip_Rounds();
  693. CenterClipCountTimer = CENTER_CLIP_COUNT_TIME;
  694. }
  695. if ( CenterClipCountTimer > 0 ) {
  696. // Also draw the above at the center
  697. Vector2 center_clip_count_offset = Render2DClass::Get_Screen_Resolution().Center();
  698. center_clip_count_offset.X *= 1.5;
  699. float fade = WWMath::Clamp( CenterClipCountTimer, 0, 1 );
  700. RectClass uv;
  701. uv.Set( BULLET_ICON_UV_UL, BULLET_ICON_UV_LR );
  702. RectClass draw = uv;
  703. uv.Scale( INFO_UV_SCALE );
  704. draw += center_clip_count_offset + BULLET_ICON_OFFSET - draw.Upper_Left();
  705. InfoRenderer->Add_Quad( draw, uv, COLOR( fade ) );
  706. WeaponClipCountRenderer->Set_Location( draw.Upper_Right() + Vector2( 4, 15 ) );
  707. WeaponClipCountRenderer->Draw_Text( tmp_text, COLOR( fade ) );
  708. CenterClipCountTimer -= TimeManager::Get_Frame_Seconds();
  709. }
  710. if ( weapon->Get_Total_Rounds() == -1 ) {
  711. //text.Format( "999", weapon->Get_Total_Rounds() );
  712. tmp_text[0]='9';
  713. tmp_text[1]='9';
  714. tmp_text[2]='9';
  715. tmp_text[3]=0;
  716. } else {
  717. // text.Format( "%03d", weapon->Get_Total_Rounds() - weapon->Get_Clip_Rounds() );
  718. Generate_WChar_Text_From_Number(tmp_text,3,3,weapon->Get_Total_Rounds() - weapon->Get_Clip_Rounds());
  719. }
  720. WeaponTotalCountRenderer->Set_Location( WeaponBase + Vector2( TOTAL_ROUNDS_OFFSET ) );
  721. WeaponTotalCountRenderer->Draw_Text( tmp_text );
  722. }
  723. // If in vehicle, don't draw the weapon icon and name,
  724. // draw a seat icon and the vehicle name
  725. if ( COMBAT_STAR->Get_Vehicle() ) {
  726. int seat = SEAT_PASENGER;
  727. if ( COMBAT_STAR->Get_Vehicle()->Get_Driver() == COMBAT_STAR ) {
  728. seat = SEAT_DRIVER;
  729. } else if ( COMBAT_STAR->Get_Vehicle()->Get_Gunner() == COMBAT_STAR ) {
  730. seat = SEAT_GUNNER;
  731. }
  732. if ( _LastVehicleSeat != seat ) {
  733. _LastVehicleSeat = seat;
  734. _LastHUDWeapon = (WeaponClass *)0xFFFFFFFF; // force weapon to re-draw next
  735. WeaponImageRenderer->Reset();
  736. StringClass filename = _Seat_Textures[seat];
  737. WeaponImageRenderer->Set_Texture( filename );
  738. Vector2 offset( 16, 34 );
  739. RectClass icon_box( 0,0,64,64 );
  740. icon_box += WeaponBase + offset - icon_box.Upper_Left();
  741. WeaponImageRenderer->Add_Quad( icon_box );
  742. // Draw Name Backdrop
  743. WeaponNameRenderer->Reset();
  744. WideStringClass name(COMBAT_STAR->Get_Vehicle()->Get_Vehicle_Name(),true);
  745. WeaponNameRenderer->Build_Sentence( name );
  746. Vector2 text_size = WeaponNameRenderer->Get_Text_Extents( name );
  747. WeaponNameRenderer->Set_Location( Render2DClass::Get_Screen_Resolution().Lower_Right() - text_size );
  748. WeaponNameRenderer->Draw_Sentence();
  749. }
  750. } else if ( _LastHUDWeapon != weapon ) { // Update the weapon icon
  751. WWPROFILE( "Weapon Change" );
  752. _LastHUDWeapon = weapon;
  753. _LastVehicleSeat = -1; // force vehicle seat to re-draw next
  754. WeaponImageRenderer->Reset();
  755. WeaponNameRenderer->Reset();
  756. if ( weapon != NULL ) {
  757. StringClass filename( HUD_WEAPONS_TEXTURE, true );
  758. RectClass uv( 0,64,128,128 );
  759. Vector2 offset( -24, 38 );
  760. const WeaponDefinitionClass * def = weapon->Get_Definition();
  761. if ( !def->IconTextureName.Is_Empty() ) {
  762. Strip_Path_From_Filename( filename, def->IconTextureName );
  763. uv = def->IconTextureUV;
  764. offset = def->IconOffset;
  765. #if 0 // Used to find offsets
  766. static Vector2 tweak_add(0,0);
  767. Vector2 add(0,0);
  768. add.X += Input::Get_Amount( INPUT_FUNCTION_MOVE_LEFT ) - Input::Get_Amount( INPUT_FUNCTION_MOVE_RIGHT );
  769. add.Y += Input::Get_Amount( INPUT_FUNCTION_MOVE_FORWARD ) - Input::Get_Amount( INPUT_FUNCTION_MOVE_BACKWARD );
  770. tweak_add -= add;
  771. offset += tweak_add;
  772. _LastHUDWeapon = NULL;
  773. if ( add.Length() != 0 ) {
  774. Debug_Say(( "%s offset %f %f\n", def->Get_Name(), offset.X, offset.Y ));
  775. }
  776. #endif
  777. }
  778. RectClass icon_box = uv;
  779. icon_box += WeaponBase + offset - icon_box.Upper_Left();
  780. {
  781. StringClass new_name(true);
  782. Strip_Path_From_Filename( new_name, filename );
  783. WeaponImageRenderer->Set_Texture( new_name );
  784. }
  785. // SurfaceClass::SurfaceDescription surface_desc;
  786. // WeaponImageRenderer->Peek_Texture()->Get_Level_Description( surface_desc );
  787. // float size = surface_desc.Width; // Assume square
  788. float size = WeaponImageRenderer->Peek_Texture()->Get_Width(); // Assume square
  789. if ( size > 0 ) {
  790. uv.Scale( Vector2( 1/size, 1/size ) );
  791. }
  792. int color = 0xFF00FF00; // green
  793. WeaponImageRenderer->Add_Quad( icon_box, uv, color );
  794. // Draw Name Backdrop
  795. // Right justify Name
  796. WideStringClass name(0,true); // = L"Rocket Launcher";
  797. name = TranslateDBClass::Get_String( def->IconNameID );
  798. WeaponNameRenderer->Build_Sentence( name );
  799. Vector2 text_size = WeaponNameRenderer->Get_Text_Extents( name ) + Vector2( 1, 0 );
  800. WeaponNameRenderer->Set_Location( Render2DClass::Get_Screen_Resolution().Lower_Right() - text_size );
  801. WeaponNameRenderer->Draw_Sentence();
  802. }
  803. }
  804. }
  805. static void Weapon_Render( void )
  806. {
  807. WeaponBoxRenderer->Render();
  808. WeaponImageRenderer->Render();
  809. WeaponNameRenderer->Render();
  810. WeaponClipCountRenderer->Render();
  811. WeaponTotalCountRenderer->Render();
  812. }
  813. /*
  814. ** Weapon Chart Display
  815. */
  816. Render2DClass * WeaponChartBoxRenderer;
  817. static DynamicVectorClass<Render2DClass *> WeaponChartIcons;
  818. Render2DSentenceClass * WeaponChartKeynameRenderer;
  819. float WeaponChartTimer;
  820. #define WEAPON_CHART_TIME 3.0f
  821. static void Weapon_Chart_Init( void )
  822. {
  823. WeaponChartBoxRenderer = new Render2DClass();
  824. WeaponChartBoxRenderer->Enable_Texturing( false );
  825. WeaponChartBoxRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  826. FontCharsClass *chars_font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT );
  827. WeaponChartKeynameRenderer = new Render2DSentenceClass();
  828. WeaponChartKeynameRenderer->Set_Font( chars_font );
  829. }
  830. static void Weapon_Chart_Shutdown( void )
  831. {
  832. delete WeaponChartBoxRenderer;
  833. WeaponChartBoxRenderer = NULL;
  834. for ( int i = 0; i < WeaponChartIcons.Count(); i++) {
  835. delete WeaponChartIcons[i];
  836. WeaponChartIcons[i] = NULL;
  837. }
  838. WeaponChartIcons.Delete_All();
  839. delete WeaponChartKeynameRenderer;
  840. WeaponChartKeynameRenderer = NULL;
  841. }
  842. Vector2 WeaponChartBase( 0.11f, 0.05f );
  843. Vector2 WeaponChartSpacing( 0.075f, 0.05f );
  844. float WeaponChartIconScale = 0.45f / 640.0f;
  845. static void Clear_Weapon_Chart_Icons( void )
  846. {
  847. if ( WeaponChartIcons.Count != 0 ) {
  848. int i;
  849. for ( i = 0; i < WeaponChartIcons.Count(); i++) {
  850. delete WeaponChartIcons[i];
  851. WeaponChartIcons[i] = NULL;
  852. }
  853. WeaponChartIcons.Delete_All();
  854. WeaponChartKeynameRenderer->Reset();
  855. }
  856. }
  857. static void Build_Weapon_Chart_Icons( void )
  858. {
  859. WeaponBagClass * weapon_bag = COMBAT_STAR->Get_Weapon_Bag();
  860. Clear_Weapon_Chart_Icons();
  861. float screen_scale = Render2DClass::Get_Screen_Resolution().Width();
  862. Vector2 pos = WeaponChartBase * screen_scale;
  863. // For each column...
  864. for ( int column = 1; column <= 10; column++ ) {
  865. // Add column header
  866. int key = Input::Get_Primary_Key_For_Function(INPUT_FUNCTION_SELECT_WEAPON_0 + (column%10) );
  867. WideStringClass name(0,true);
  868. Input::Get_Translated_Key_Name( key, name );
  869. WeaponChartKeynameRenderer->Build_Sentence( name );
  870. Vector2 text_size = WeaponChartKeynameRenderer->Get_Text_Extents( name );
  871. Vector2 text_offset = pos - text_size/2 - Vector2( 0, WeaponChartSpacing.Y * screen_scale * 0.75f );
  872. text_offset.X = (int)text_offset.X;
  873. text_offset.Y = (int)text_offset.Y;
  874. WeaponChartKeynameRenderer->Set_Location( text_offset );
  875. WeaponChartKeynameRenderer->Draw_Sentence();
  876. // Draw weapons in that column
  877. for ( int i = 0; i < weapon_bag->Get_Count(); i++ ) {
  878. WeaponClass * weapon = weapon_bag->Peek_Weapon( i );
  879. if ( weapon != NULL ) {
  880. if ( (int)weapon->Get_Key_Number() != (column%10) ) {
  881. continue;
  882. }
  883. StringClass filename( HUD_WEAPONS_TEXTURE, true );
  884. RectClass uv( 0,64,128,128 );
  885. Vector2 offset( -40, 40 );
  886. const WeaponDefinitionClass * def = weapon->Get_Definition();
  887. if ( !def->IconTextureName.Is_Empty() ) {
  888. Strip_Path_From_Filename( filename, def->IconTextureName );
  889. uv = def->IconTextureUV;
  890. offset = def->IconOffset;
  891. }
  892. RectClass icon_box = uv;
  893. // icon_box += pos - icon_box.Upper_Left();
  894. // icon_box += offset - icon_box.Upper_Left() + pos;
  895. icon_box += pos - icon_box.Center();
  896. icon_box.Scale_Relative_Center( WeaponChartIconScale * screen_scale );
  897. pos.Y += WeaponChartSpacing.Y * screen_scale;
  898. // Draw Icon
  899. Render2DClass * renderer = new Render2DClass();
  900. WeaponChartIcons.Add( renderer );
  901. renderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  902. StringClass new_name(true);
  903. Strip_Path_From_Filename( new_name, filename );
  904. renderer->Set_Texture( new_name );
  905. if ( renderer->Peek_Texture() != NULL ) {
  906. // SurfaceClass::SurfaceDescription surface_desc;
  907. // renderer->Peek_Texture()->Get_Level_Description( surface_desc );
  908. // float size = surface_desc.Width; // Assume square
  909. float size = renderer->Peek_Texture()->Get_Width(); // Assume square
  910. if ( size > 0 ) {
  911. uv.Scale( Vector2( 1/size, 1/size ) );
  912. }
  913. }
  914. renderer->Add_Quad( icon_box, uv );
  915. }
  916. }
  917. // Goto next column
  918. pos.Y = WeaponChartBase.Y * screen_scale;
  919. pos.X += WeaponChartSpacing.X * screen_scale;
  920. }
  921. }
  922. bool ForceChartRebuild = false;
  923. void HUDClass::Force_Weapon_Chart_Update( void )
  924. {
  925. ForceChartRebuild = true;
  926. }
  927. void HUDClass::Force_Weapon_Chart_Display( void )
  928. {
  929. WeaponChartTimer = WEAPON_CHART_TIME;
  930. }
  931. static void Weapon_Chart_Update( void )
  932. {
  933. if ( COMBAT_STAR == NULL || COMBAT_STAR->Get_Weapon_Bag() == NULL || COMBAT_STAR->Get_Vehicle() != NULL ) {
  934. Clear_Weapon_Chart_Icons();
  935. return;
  936. }
  937. int i;
  938. WeaponBagClass * weapon_bag = COMBAT_STAR->Get_Weapon_Bag();
  939. if ( weapon_bag->HUD_Is_Changed() ) {
  940. weapon_bag->HUD_Reset_Changed();
  941. WeaponChartTimer = WEAPON_CHART_TIME;
  942. }
  943. WeaponChartTimer -= TimeManager::Get_Frame_Seconds();
  944. if ( WeaponChartTimer <= 0 ) {
  945. return;
  946. }
  947. // Rebuild the icons if necessary
  948. // subtract 1 because the first is always null
  949. if ( ForceChartRebuild || (weapon_bag->Get_Count()-1 != WeaponChartIcons.Count()) ) {
  950. ForceChartRebuild = false;
  951. Debug_Say(( "Build icons\n" ));
  952. Build_Weapon_Chart_Icons();
  953. }
  954. float alpha = WWMath::Clamp( WeaponChartTimer, 0, 1 );
  955. WeaponChartBoxRenderer->Reset();
  956. // For each column...
  957. int index = 0;
  958. for ( int column = 1; column <= 10; column++ ) {
  959. // Update intensities in that column
  960. for ( i = 0; i < weapon_bag->Get_Count(); i++ ) {
  961. WeaponClass * weapon = weapon_bag->Peek_Weapon( i );
  962. if ( weapon != NULL ) {
  963. if ( (int)weapon->Get_Key_Number() != (column%10) ) {
  964. continue;
  965. }
  966. long color = 0x000FF00; // Dim
  967. if ( weapon_bag->Get_Index() == i ) {
  968. color = 0x0000FF00; // Bright
  969. }
  970. // Draw yellow if empty or reloading
  971. // if ( weapon->Is_Reloading() || weapon->Is_Switching() || weapon->Get_Total_Rounds() == 0 ) {
  972. // if ( weapon->Is_Switching() || weapon->Get_Total_Rounds() == 0 ) {
  973. if ( weapon->Get_Total_Rounds() == 0 ) {
  974. color = 0x00FFFF00; // Dim yellow
  975. if ( weapon_bag->Get_Index() == i ) {
  976. color = 0x00FFFF00; // Bright yellow
  977. }
  978. }
  979. #if 01
  980. if ( weapon_bag->Get_Index() == i ) {
  981. color = COLOR( alpha, color );
  982. } else {
  983. color = COLOR( alpha * 0.5f, color );
  984. }
  985. #endif
  986. WeaponChartIcons[index]->Force_Color( color );
  987. index++;
  988. }
  989. }
  990. }
  991. WeaponChartKeynameRenderer->Force_Alpha( alpha );
  992. }
  993. static void Weapon_Chart_Render( void )
  994. {
  995. if ( WeaponChartTimer <= 0 ) {
  996. return;
  997. }
  998. WeaponChartBoxRenderer->Render();
  999. for ( int i = 0; i < WeaponChartIcons.Count(); i++) {
  1000. WeaponChartIcons[i]->Render();
  1001. }
  1002. WeaponChartKeynameRenderer->Render();
  1003. }
  1004. /*
  1005. ** Damage Display
  1006. */
  1007. Render2DClass * DamageRenderer;
  1008. const int NUM_DAMAGE_INDICATORS = 8;
  1009. float DamageIndicatorIntensity[ NUM_DAMAGE_INDICATORS ];
  1010. bool DamageIndicatorIntensityChanging;
  1011. bool DamageIndicatorOrientation;
  1012. static void Damage_Reset( void )
  1013. {
  1014. for ( int i = 0; i < NUM_DAMAGE_INDICATORS; i++ ) {
  1015. DamageIndicatorIntensity[ i ] = 0;
  1016. }
  1017. DamageIndicatorIntensityChanging = true;
  1018. CombatManager::Clear_Star_Damage_Direction();
  1019. }
  1020. static void Damage_Init( void )
  1021. {
  1022. DamageRenderer = new Render2DClass();
  1023. DamageRenderer->Set_Texture( HUD_MAIN_TEXTURE );
  1024. DamageRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1025. DamageRenderer->Enable_Additive( true );
  1026. Damage_Reset();
  1027. }
  1028. static void Damage_Shutdown( void )
  1029. {
  1030. delete DamageRenderer;
  1031. DamageRenderer = NULL;
  1032. }
  1033. static void Damage_Add_Indicator( int index, float start_x, float start_y, float end_x, float end_y )
  1034. {
  1035. Vector2 vert[4];
  1036. vert[0] = Vector2( start_x, start_y );
  1037. vert[1] = Vector2( start_x, end_y );
  1038. vert[2] = Vector2( end_x, start_y );
  1039. vert[3] = Vector2( end_x, end_y );
  1040. if ( !CombatManager::Is_First_Person() ) {
  1041. for ( int i = 0; i < 4; i++ ) {
  1042. vert[i].X *= WWMath::Fabs(1 + vert[i].Y); // Skew
  1043. vert[i].Y /= 2; // Squash vertical
  1044. vert[i].Y += 0.25f; // Lower
  1045. }
  1046. }
  1047. for ( int i = 0; i < 4; i++ ) {
  1048. // Numbers are -0.5 to 0.5, switch them to pixels, to match the info_renderer mode
  1049. vert[i].X = (vert[i].X + 0.5f) * Render2DClass::Get_Screen_Resolution().Width();
  1050. vert[i].Y = (vert[i].Y + 0.5f) * Render2DClass::Get_Screen_Resolution().Height();
  1051. }
  1052. RectClass uv( DAMAGE_1_UV_UL, DAMAGE_1_UV_LR );
  1053. if ( index & 1 ) {
  1054. uv = RectClass( DAMAGE_2_UV_UL, DAMAGE_2_UV_LR );
  1055. }
  1056. uv.Scale( INFO_UV_SCALE );
  1057. unsigned long color_bits = (int)(DamageIndicatorIntensity[index] * 255) & 0x000000FF;
  1058. unsigned long color = color_bits | color_bits<<8 | color_bits<<16;
  1059. switch (index) {
  1060. case 3:
  1061. case 4: DamageRenderer->Add_Quad( vert[1], vert[3], vert[0], vert[2], uv, color );
  1062. break;
  1063. case 5:
  1064. case 6: DamageRenderer->Add_Quad( vert[0], vert[1], vert[2], vert[3], uv, color );
  1065. break;
  1066. case 7:
  1067. case 0: DamageRenderer->Add_Quad( vert[2], vert[0], vert[3], vert[1], uv, color );
  1068. break;
  1069. case 1:
  1070. case 2: DamageRenderer->Add_Quad( vert[3], vert[2], vert[1], vert[0], uv, color );
  1071. break;
  1072. }
  1073. }
  1074. static void Damage_Update( void )
  1075. {
  1076. DamageRenderer->Reset();
  1077. if (Input::Are_Damage_Indicators_Enabled () == false) {
  1078. return ;
  1079. }
  1080. int new_damage = CombatManager::Get_Star_Damage_Direction();
  1081. //new_damage = 0xFF;
  1082. if ( new_damage != 0 ) {
  1083. DamageIndicatorIntensityChanging = true;
  1084. }
  1085. if ( !DamageIndicatorIntensityChanging &&
  1086. DamageIndicatorOrientation == CombatManager::Is_First_Person() ) {
  1087. return;
  1088. }
  1089. // DamageRenderer->Reset();
  1090. DamageIndicatorOrientation = CombatManager::Is_First_Person();
  1091. DamageIndicatorIntensityChanging = false;
  1092. // Update the intensities
  1093. CombatManager::Clear_Star_Damage_Direction();
  1094. for ( int i = 0; i < NUM_DAMAGE_INDICATORS; i++ ) {
  1095. if ( new_damage & (1<<i) ) { // Apply new damage
  1096. DamageIndicatorIntensity[ i ] = 1;
  1097. DamageIndicatorIntensityChanging = true;
  1098. } else {
  1099. if ( DamageIndicatorIntensity[ i ] > 0 ) {
  1100. DamageIndicatorIntensity[ i ] -= TimeManager::Get_Frame_Seconds(); // and fade it away
  1101. DamageIndicatorIntensity[ i ] = WWMath::Clamp( DamageIndicatorIntensity[ i ], 0, 1 );
  1102. DamageIndicatorIntensityChanging = true;
  1103. }
  1104. }
  1105. }
  1106. // Redraw the indicators
  1107. #if 0
  1108. const float HORIZ_WIDTH = 58.0f/640.0f;
  1109. const float HORIZ_HEIGHT = 20.0f/480.0f;
  1110. const float VERT_WIDTH = 20.0f/640.0f;
  1111. const float VERT_HEIGHT = 58.0f/480.0f;
  1112. const float OFFSET_X = 220.0f/640.0f;
  1113. const float OFFSET_Y = 190.0f/480.0f;
  1114. const float DIAG_WIDTH = 46.0f/640.0f;
  1115. const float DIAG_HEIGHT = 46.0f/480.0f;
  1116. const float DIAG_OFFSET_X = 160.0f/640.0f;
  1117. const float DIAG_OFFSET_Y = 130.0f/480.0f;
  1118. #else
  1119. float HORIZ_WIDTH = HORIZ_DAMAGE_SIZE.U/640.0f;
  1120. float HORIZ_HEIGHT = HORIZ_DAMAGE_SIZE.V/480.0f;
  1121. float VERT_WIDTH = VERT_DAMAGE_SIZE.U/640.0f;
  1122. float VERT_HEIGHT = VERT_DAMAGE_SIZE.V/480.0f;
  1123. float OFFSET_X = HV_DAMAGE_OFFSET.U/640.0f;
  1124. float OFFSET_Y = HV_DAMAGE_OFFSET.V/480.0f;
  1125. float DIAG_WIDTH = DIAG_DAMAGE_SIZE.U/640.0f;
  1126. float DIAG_HEIGHT = DIAG_DAMAGE_SIZE.V/480.0f;
  1127. float DIAG_OFFSET_X = DIAG_DAMAGE_OFFSET.U/640.0f;
  1128. float DIAG_OFFSET_Y = DIAG_DAMAGE_OFFSET.V/480.0f;
  1129. #endif
  1130. Damage_Add_Indicator( 0, -HORIZ_WIDTH/2, -OFFSET_Y-HORIZ_HEIGHT/2, HORIZ_WIDTH/2, -OFFSET_Y+HORIZ_HEIGHT/2 );
  1131. Damage_Add_Indicator( 2, OFFSET_X-VERT_WIDTH/2, -VERT_HEIGHT/2, OFFSET_X+VERT_WIDTH/2, VERT_HEIGHT/2 );
  1132. Damage_Add_Indicator( 4, -HORIZ_WIDTH/2, OFFSET_Y-HORIZ_HEIGHT/2, HORIZ_WIDTH/2, OFFSET_Y+HORIZ_HEIGHT/2 );
  1133. Damage_Add_Indicator( 6, -OFFSET_X-VERT_WIDTH/2, -VERT_HEIGHT/2, -OFFSET_X+VERT_WIDTH/2, VERT_HEIGHT/2 );
  1134. Damage_Add_Indicator( 1, DIAG_OFFSET_X-DIAG_WIDTH/2, -DIAG_OFFSET_Y-DIAG_HEIGHT/2, DIAG_OFFSET_X+DIAG_WIDTH/2, -DIAG_OFFSET_Y+DIAG_HEIGHT/2 );
  1135. Damage_Add_Indicator( 3, DIAG_OFFSET_X-DIAG_WIDTH/2, DIAG_OFFSET_Y-DIAG_HEIGHT/2, DIAG_OFFSET_X+DIAG_WIDTH/2, DIAG_OFFSET_Y+DIAG_HEIGHT/2 );
  1136. Damage_Add_Indicator( 5, -DIAG_OFFSET_X-DIAG_WIDTH/2, DIAG_OFFSET_Y-DIAG_HEIGHT/2, -DIAG_OFFSET_X+DIAG_WIDTH/2, DIAG_OFFSET_Y+DIAG_HEIGHT/2 );
  1137. Damage_Add_Indicator( 7, -DIAG_OFFSET_X-DIAG_WIDTH/2, -DIAG_OFFSET_Y-DIAG_HEIGHT/2, -DIAG_OFFSET_X+DIAG_WIDTH/2, -DIAG_OFFSET_Y+DIAG_HEIGHT/2 );
  1138. }
  1139. void HUDClass::Damage_Render( void )
  1140. {
  1141. DamageRenderer->Render();
  1142. }
  1143. /*
  1144. ** Target Display
  1145. */
  1146. Render2DClass * TargetRenderer;
  1147. Render2DClass * TargetBoxRenderer;
  1148. Render2DSentenceClass * TargetNameRenderer;
  1149. Render2DSentenceClass * InfoDebugRenderer;
  1150. WideStringClass TargetNameString; // Cache the current target name string so that we know when the string changes
  1151. Vector2 TargetNameLocation; // Cache the name location as well
  1152. static void Target_Init( void )
  1153. {
  1154. TargetRenderer = new Render2DClass();
  1155. TargetRenderer->Set_Texture( HUD_MAIN_TEXTURE );
  1156. TargetRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1157. TargetBoxRenderer = new Render2DClass();
  1158. TargetBoxRenderer->Enable_Texturing( false );
  1159. TargetBoxRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1160. FontCharsClass *chars_font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT );
  1161. TargetNameRenderer = new Render2DSentenceClass();
  1162. TargetNameRenderer->Set_Font( chars_font );
  1163. InfoDebugRenderer = new Render2DSentenceClass();
  1164. InfoDebugRenderer->Set_Font( chars_font );
  1165. // TargetNameRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1166. }
  1167. static void Target_Shutdown( void )
  1168. {
  1169. delete TargetRenderer;
  1170. TargetRenderer = NULL;
  1171. delete TargetBoxRenderer;
  1172. TargetBoxRenderer = NULL;
  1173. delete TargetNameRenderer;
  1174. TargetNameRenderer = NULL;
  1175. TargetNameString="";
  1176. delete InfoDebugRenderer;
  1177. InfoDebugRenderer = NULL;
  1178. }
  1179. bool InfoDebug = false;
  1180. static RectClass Get_Target_Box( PhysicalGameObj * obj );
  1181. static void Target_Box_Edge( const Vector2 & a, const Vector2 & b, unsigned int color );
  1182. static void Target_Update( void )
  1183. {
  1184. TargetRenderer->Reset();
  1185. TargetBoxRenderer->Reset();
  1186. // TargetNameRenderer->Reset();
  1187. InfoDebugRenderer->Reset();
  1188. HUDInfo::Update_Info_Object();
  1189. static float box_zoom_size = 0;
  1190. DamageableGameObj * d_obj = HUDInfo::Get_Info_Object();
  1191. if ( d_obj != NULL ) {
  1192. PhysicalGameObj * p_obj = d_obj->As_PhysicalGameObj();
  1193. BuildingGameObj * building = d_obj->As_BuildingGameObj();
  1194. DamageableGameObj * obj = d_obj;
  1195. if ( obj && COMBAT_STAR ) {
  1196. box_zoom_size += TimeManager::Get_Frame_Seconds() * 4;
  1197. box_zoom_size = WWMath::Clamp( box_zoom_size, 0, 1 );
  1198. int color = HUDGlobalSettingsDef::Get_Instance()->Get_No_Relation_Color().Convert_To_ARGB();
  1199. if ( p_obj != NULL ) {
  1200. if ( COMBAT_STAR->Is_Teammate(p_obj) ) {
  1201. color = HUDGlobalSettingsDef::Get_Instance()->Get_Friendly_Color().Convert_To_ARGB();
  1202. } else if ( COMBAT_STAR->Is_Enemy(p_obj) ) {
  1203. color = HUDGlobalSettingsDef::Get_Instance()->Get_Enemy_Color().Convert_To_ARGB();
  1204. }
  1205. }
  1206. if ( building != NULL ) {
  1207. // if ( building->Is_GDI() ) {
  1208. if ( COMBAT_STAR->Is_Teammate(building) ) {
  1209. color = HUDGlobalSettingsDef::Get_Instance()->Get_Friendly_Color().Convert_To_ARGB();
  1210. // } else if ( building->Is_Nod() ) {
  1211. } else if ( COMBAT_STAR->Is_Enemy(building) ) {
  1212. color = HUDGlobalSettingsDef::Get_Instance()->Get_Enemy_Color().Convert_To_ARGB();
  1213. }
  1214. }
  1215. RectClass box = Render2DClass::Get_Screen_Resolution();
  1216. if ( obj->As_PhysicalGameObj() ) {
  1217. box = Get_Target_Box( obj->As_PhysicalGameObj() );
  1218. } else {
  1219. // Build a box for the buildings
  1220. box.Scale_Relative_Center( 0.3f );
  1221. // center on cursor reticle
  1222. Vector2 new_center = (COMBAT_CAMERA->Get_Camera_Target_2D_Offset() * 0.5f );
  1223. new_center.Y *= -1.0f;
  1224. new_center += Vector2( 0.5f, 0.5f );
  1225. new_center.X *= Render2DClass::Get_Screen_Resolution().Right;
  1226. new_center.Y *= Render2DClass::Get_Screen_Resolution().Bottom;
  1227. box += new_center - box.Center();
  1228. }
  1229. // Scale the box to let it zoom in
  1230. if ( box_zoom_size < 1 ) {
  1231. box.Scale_Relative_Center( 1 + ((1-box_zoom_size) * 0.3f) );
  1232. }
  1233. box.Snap_To_Units( Vector2( 1, 1 ) );
  1234. // Clamp box to fit on screen;
  1235. RectClass res = Render2DClass::Get_Screen_Resolution();
  1236. if ( box.Top < 0 ) {
  1237. box.Top = 0;
  1238. }
  1239. if ( box.Left < 0 ) {
  1240. box.Left = 0;
  1241. }
  1242. if ( box.Right > res.Right-1 ) {
  1243. box.Right = res.Right-1;
  1244. }
  1245. // Leave room for info at the bottom
  1246. if ( box.Bottom > res.Bottom - 26 ) {
  1247. box.Bottom = res.Bottom - 26;
  1248. }
  1249. Target_Box_Edge( box.Upper_Left(), box.Upper_Right(), color );
  1250. Target_Box_Edge( box.Upper_Left(), box.Lower_Left(), color );
  1251. Target_Box_Edge( box.Lower_Right(), box.Upper_Right(), color );
  1252. Target_Box_Edge( box.Lower_Right(), box.Lower_Left(), color );
  1253. RectClass uv( TARGET_HEALTH_R_UV_UL, TARGET_HEALTH_R_UV_LR );
  1254. RectClass draw = uv;
  1255. RectClass draw2;
  1256. bool draw_health = obj->Is_Health_Bar_Displayed();
  1257. if ( draw_health ) {
  1258. float health_percent = 0;
  1259. // float health = 0;
  1260. const DefenseObjectClass * def = obj->Get_Defense_Object();
  1261. if ( def ) {
  1262. // health = def->Get_Health();
  1263. // health_percent = WWMath::Clamp( def->Get_Health() / def->Get_Health_Max(), 0, 1 );
  1264. float health_max = def->Get_Health_Max();
  1265. float shield_max = def->Get_Shield_Strength_Max();
  1266. float max = health_max + shield_max;
  1267. float health = def->Get_Health();
  1268. float shield = def->Get_Shield_Strength();
  1269. // if ( health_max && ((health/health_max) < 0.25) ) {
  1270. // shield *= ((health/health_max) / 0.25f);
  1271. // }
  1272. // Display less shield as health drops
  1273. if ( health_max ) {
  1274. shield *= (health/health_max);
  1275. }
  1276. float total = health + shield;
  1277. if ( max != 0 ) {
  1278. health_percent = total / max;
  1279. health_percent = WWMath::Clamp( health_percent, 0, 1 );
  1280. }
  1281. }
  1282. int health_color = Get_Health_Color( health_percent );
  1283. // Draw Health
  1284. static float power_flash = 0;
  1285. power_flash += TimeManager::Get_Frame_Seconds();
  1286. power_flash = WWMath::Wrap( power_flash, 0, 2 );
  1287. RectClass uv3( POWER_OUT_ICON_UV_UL, POWER_OUT_ICON_UV_LR );
  1288. RectClass draw3 = uv3;
  1289. uv3.Scale( INFO_UV_SCALE );
  1290. RectClass black( HEALTH_BACK_UV_UL, HEALTH_BACK_UV_LR );
  1291. black.Scale( INFO_UV_SCALE );
  1292. uv.Scale( INFO_UV_SCALE );
  1293. // draw += box.Upper_Left() - draw.Lower_Left() - Vector2( 0, 1 );
  1294. draw += box.Lower_Left() - draw.Upper_Left() + Vector2( 0, 18 );
  1295. // draw += Vector2( (box.Width() - draw.Width())/2 + 10, 0 ); // Center
  1296. draw += Vector2( (box.Width() - draw.Width())/2 + 2, 0 ); // Center
  1297. draw3 += draw.Center() - draw3.Center();
  1298. // Draw background
  1299. draw.Inflate( Vector2( 1, 1 ) );
  1300. TargetRenderer->Add_Quad( draw, black );
  1301. draw.Inflate( Vector2( -1, -1 ) );
  1302. draw.Right = draw.Left + draw.Width() * health_percent;
  1303. uv.Right = uv.Left + uv.Width() * health_percent;
  1304. TargetRenderer->Add_Quad( draw, uv, health_color );
  1305. // power out
  1306. if ( power_flash < 1 ) {
  1307. // TargetRenderer->Add_Quad( draw3, uv3 );
  1308. }
  1309. uv.Set( TARGET_HEALTH_L_UV_UL, TARGET_HEALTH_L_UV_LR );
  1310. draw2 = uv;
  1311. #if 0
  1312. uv.Scale( INFO_UV_SCALE );
  1313. draw2 += draw.Upper_Left() - draw2.Upper_Right();
  1314. TargetRenderer->Add_Quad( draw2, uv, health_color );
  1315. WideStringClass num(0,true);
  1316. if ( health < 1 && health > 0 ) {
  1317. health = 1;
  1318. }
  1319. num.Format( L"%d", (int)health );
  1320. TargetNameRenderer->Build_Sentence( num );
  1321. Vector2 text_size = TargetNameRenderer->Get_Text_Extents( num );
  1322. text_size.U -= 1;
  1323. text_size.V = -1;
  1324. draw -= text_size;
  1325. draw.Snap_To_Units( Vector2( 1, 1 ) );
  1326. TargetNameRenderer->Set_Location( draw.Upper_Left() );
  1327. TargetNameRenderer->Draw_Sentence( health_color );
  1328. #endif
  1329. }
  1330. // Draw Name
  1331. uv.Set( TARGET_NAME_UV_UL, TARGET_NAME_UV_LR );
  1332. draw = uv;
  1333. uv.Scale( INFO_UV_SCALE );
  1334. draw += box.Lower_Left() - draw.Upper_Left() + Vector2( 0, 1 );
  1335. draw += Vector2( (box.Width() - draw.Width())/2 + 10, 0 );
  1336. draw.Snap_To_Units( Vector2( 1, 1 ) );
  1337. TargetRenderer->Add_Quad( draw, uv, color );
  1338. if ( obj->Get_Translated_Name_ID() != 0 ) {
  1339. TDBObjClass *translate_obj = TranslateDBClass::Find_Object( obj->Get_Translated_Name_ID() );
  1340. if ( translate_obj ) {
  1341. WideStringClass translate_string=translate_obj->Get_String();
  1342. if ( building != NULL && HUDInfo::Get_Info_Object_Is_MCT() ) {
  1343. translate_string=TRANSLATE( IDS_Enc_Struct_Nod_MCT_Name );
  1344. }
  1345. Vector2 string_loc=draw.Upper_Left() + Vector2( 3.0f,1.0f );
  1346. if (translate_string!=TargetNameString) {
  1347. TargetNameRenderer->Reset();
  1348. TargetNameString=translate_string;
  1349. TargetNameLocation = string_loc;
  1350. TargetNameRenderer->Build_Sentence( TargetNameString );
  1351. TargetNameRenderer->Set_Location( TargetNameLocation );
  1352. TargetNameRenderer->Set_Base_Location( TargetNameLocation );
  1353. TargetNameRenderer->Draw_Sentence( color );
  1354. }
  1355. if (string_loc!=TargetNameLocation) {
  1356. TargetNameLocation=string_loc;
  1357. TargetNameRenderer->Set_Base_Location( TargetNameLocation );
  1358. }
  1359. }
  1360. else {
  1361. TargetNameRenderer->Reset();
  1362. TargetNameString="";
  1363. TargetNameLocation = Vector2(0.0f,0.0f);
  1364. }
  1365. }
  1366. else {
  1367. TargetNameRenderer->Reset();
  1368. TargetNameString="";
  1369. TargetNameLocation = Vector2(0.0f,0.0f);
  1370. }
  1371. // Draw Team Icon
  1372. int team = PLAYERTYPE_GDI;
  1373. if ( p_obj != NULL ) {
  1374. team = p_obj->Get_Player_Type();
  1375. }
  1376. if ( building != NULL ) {
  1377. if ( building->Is_GDI() ) {
  1378. team = PLAYERTYPE_GDI;
  1379. } else if ( building->Is_Nod() ) {
  1380. team = PLAYERTYPE_NOD;
  1381. } else {
  1382. team = PLAYERTYPE_NEUTRAL;
  1383. }
  1384. }
  1385. if ( team == PLAYERTYPE_NOD ) {
  1386. uv.Set( NOD_ICON_UV_UL, NOD_ICON_UV_LR );
  1387. } else if ( team == PLAYERTYPE_GDI ) {
  1388. uv.Set( GDI_ICON_UV_UL, GDI_ICON_UV_LR );
  1389. } else {
  1390. uv.Set( NEUTRAL_ICON_UV_UL, NEUTRAL_ICON_UV_LR );
  1391. }
  1392. draw2 = uv;
  1393. uv.Scale( INFO_UV_SCALE );
  1394. draw2 += draw.Upper_Left() - draw2.Upper_Right();
  1395. TargetRenderer->Add_Quad( draw2, uv );
  1396. // Draw chevrons
  1397. bool draw_chevrons = false;
  1398. if ( p_obj != NULL && p_obj->Is_HUD_Pokable_Indicator_Enabled() ) {
  1399. draw_chevrons = true;
  1400. }
  1401. if ( obj->As_SmartGameObj() != NULL &&
  1402. obj->As_SmartGameObj()->As_VehicleGameObj() != NULL &&
  1403. COMBAT_STAR->Is_Permitted_To_Enter_Vehicle() &&
  1404. obj->As_SmartGameObj()->As_VehicleGameObj()->Is_Entry_Permitted( COMBAT_STAR ) ) {
  1405. draw_chevrons = true;
  1406. }
  1407. if ( draw_chevrons ) {
  1408. RectClass enterable_box( Vector2(0,0), TARGET_ENTERABLE_SIZE );
  1409. enterable_box += Vector2( box.Center().X - enterable_box.Center().X ,
  1410. box.Top - enterable_box.Bottom );
  1411. static float enterable_bounce = 0;
  1412. enterable_bounce += TimeManager::Get_Frame_Seconds() * 5;
  1413. enterable_bounce = WWMath::Wrap( enterable_bounce, 0, DEG_TO_RADF( 360 ) );
  1414. enterable_box += Vector2( 0, TARGET_ENTERABLE_BOUNCE * (WWMath::Sin( enterable_bounce ) - 1) );
  1415. uv.Set( TARGET_ENTERABLE_UV_UL, TARGET_ENTERABLE_UV_LR );
  1416. uv.Scale( INFO_UV_SCALE );
  1417. color = Get_Health_Color( 1 );
  1418. // TargetRenderer->Add_Quad( enterable_box, uv );
  1419. enterable_box -= Vector2( 0, enterable_box.Height() * 0.6f );
  1420. TargetRenderer->Add_Tri( enterable_box.Upper_Right(), enterable_box.Upper_Left(), enterable_box.Center(),
  1421. uv.Upper_Right(), uv.Upper_Left(), uv.Center(), color );
  1422. enterable_box += Vector2( 0, enterable_box.Height() * 0.6f );
  1423. TargetRenderer->Add_Tri( enterable_box.Upper_Right(), enterable_box.Upper_Left(), enterable_box.Center(),
  1424. uv.Upper_Right(), uv.Upper_Left(), uv.Center(), color );
  1425. enterable_box += Vector2( 0, enterable_box.Height() * 0.6f );
  1426. TargetRenderer->Add_Tri( enterable_box.Upper_Right(), enterable_box.Upper_Left(), enterable_box.Center(),
  1427. uv.Upper_Right(), uv.Upper_Left(), uv.Center(), color );
  1428. }
  1429. }
  1430. if ( InfoDebug ) {
  1431. StringClass info(0,true);
  1432. obj->Get_Information( info );
  1433. WideStringClass str(0,true);
  1434. str.Convert_From( info );
  1435. InfoDebugRenderer->Build_Sentence( str );
  1436. InfoDebugRenderer->Set_Location( Vector2( 520, 240 ) );
  1437. // InfoDebugRenderer->Set_Base_Location( Vector2( 520, 240 ) );
  1438. InfoDebugRenderer->Draw_Sentence();
  1439. }
  1440. } else {
  1441. TargetNameRenderer->Reset();
  1442. TargetNameString="";
  1443. TargetNameLocation = Vector2(0.0f,0.0f);
  1444. box_zoom_size = 0;
  1445. HUDInfo::Clear_Info_Object();
  1446. }
  1447. }
  1448. static void Target_Render( void )
  1449. {
  1450. TargetRenderer->Render();
  1451. TargetBoxRenderer->Render();
  1452. TargetNameRenderer->Render();
  1453. InfoDebugRenderer->Render();
  1454. }
  1455. static RectClass Get_Target_Box( PhysicalGameObj * obj )
  1456. {
  1457. // Lets draw a box around the target
  1458. WWASSERT( obj );
  1459. PhysClass * po = obj->Peek_Physical_Object();
  1460. Vector2 top(0,0);
  1461. Vector2 bottom(0,0);
  1462. if ( po != NULL ) {
  1463. // Get the Obj AABox in Camera Space
  1464. AABoxClass obj_box;
  1465. po->Get_Shadow_Blob_Box( &obj_box );
  1466. Matrix3D obj_tm = po->Get_Transform();
  1467. Matrix3D boxview_tm;
  1468. Matrix3D boxview_inv_tm;
  1469. boxview_tm.Look_At(COMBAT_CAMERA->Get_Transform().Get_Translation(),obj_tm * obj_box.Center,0.0f);
  1470. boxview_tm.Get_Orthogonal_Inverse(boxview_inv_tm);
  1471. Matrix3D obj_to_boxview_tm = boxview_inv_tm * obj_tm;
  1472. AABoxClass boxview_box;
  1473. obj_to_boxview_tm.Transform_Center_Extent_AABox( obj_box.Center, obj_box.Extent, &boxview_box.Center, &boxview_box.Extent );
  1474. Matrix3D camera_tm = COMBAT_CAMERA->Get_Transform();
  1475. Matrix3D camera_inv_tm;
  1476. camera_tm.Get_Orthogonal_Inverse(camera_inv_tm);
  1477. Matrix3D boxview_to_camera_tm = camera_inv_tm * boxview_tm;
  1478. AABoxClass camera_box;
  1479. boxview_to_camera_tm.Transform_Center_Extent_AABox( boxview_box.Center, boxview_box.Extent, &camera_box.Center, &camera_box.Extent);
  1480. camera_box.Extent.Z = 0.0f;
  1481. Vector3 ctop = camera_box.Center - camera_box.Extent;
  1482. Vector3 cbottom = camera_box.Center + camera_box.Extent;
  1483. Vector3 temp;
  1484. COMBAT_CAMERA->Project_Camera_Space_Point( temp, ctop );
  1485. top.X = temp.X;
  1486. top.Y = temp.Y;
  1487. COMBAT_CAMERA->Project_Camera_Space_Point( temp, cbottom );
  1488. bottom.X = temp.X;
  1489. bottom.Y = temp.Y;
  1490. }
  1491. // Get Box in proper convention
  1492. RectClass screen = Render2DClass::Get_Screen_Resolution();
  1493. top.X = top.X * 0.5f + 0.5f;
  1494. top.Y = top.Y * -0.5f + 0.5f;
  1495. bottom.X = bottom.X * 0.5f + 0.5f;
  1496. bottom.Y = bottom.Y * -0.5f + 0.5f;
  1497. float temp = top.Y;
  1498. top.Y = bottom.Y;
  1499. bottom.Y = temp;
  1500. static RectClass info_box;
  1501. info_box.Set( top.X * screen.Right, top.Y * screen.Bottom, bottom.X * screen.Right, bottom.Y * screen.Bottom ); // convention 0,0 - 1,1
  1502. return info_box;
  1503. }
  1504. static void Target_Box_Edge( const Vector2 & a, const Vector2 & b, unsigned int color )
  1505. {
  1506. float percent = 0.2f;
  1507. Vector2 a_ = b - a;
  1508. a_ *= percent;
  1509. a_ += a;
  1510. TargetBoxRenderer->Add_Line( a, a_, 2, color );
  1511. Vector2 b_ = a - b;
  1512. b_ *= percent;
  1513. b_ += b;
  1514. TargetBoxRenderer->Add_Line( b, b_, 2, color );
  1515. }
  1516. /*
  1517. ** Score Display
  1518. */
  1519. /*
  1520. Render2DTextClass * ScoreRenderer;
  1521. static void Score_Init( void )
  1522. {
  1523. Font3DInstanceClass * font = WW3DAssetManager::Get_Instance()->Get_Font3DInstance( LARGE_FONT );
  1524. SET_REF_OWNER( font );
  1525. ScoreRenderer = new Render2DTextClass( font );
  1526. ScoreRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1527. font->Release_Ref();
  1528. }
  1529. static void Score_Shutdown( void )
  1530. {
  1531. delete ScoreRenderer;
  1532. ScoreRenderer = NULL;
  1533. }
  1534. static void Score_Update( void )
  1535. {
  1536. ScoreRenderer->Reset();
  1537. //TSS2001e if ( COMBAT_STAR ) {
  1538. if ( COMBAT_STAR && COMBAT_STAR->Get_Player_Data() ) {
  1539. int score = COMBAT_STAR->Get_Player_Data()->Get_Score();
  1540. // WideStringClass scorestring;
  1541. // scorestring.Format( L"%d", score );
  1542. WCHAR score_string[12]; // 12 digits ought to be enough...
  1543. Generate_WChar_Text_From_Number(score_string,sizeof(score_string),false,score);
  1544. Vector2 position = Render2DClass::Get_Screen_Resolution().Center();
  1545. position.Y = Render2DClass::Get_Screen_Resolution().Bottom;
  1546. Vector2 size = ScoreRenderer->Get_Text_Extents( score_string );
  1547. size.X *= 0.5f;
  1548. position -= size;
  1549. ScoreRenderer->Set_Location( position );
  1550. ScoreRenderer->Draw_Text( score_string );
  1551. }
  1552. }
  1553. static void Score_Render( void )
  1554. {
  1555. ScoreRenderer->Render();
  1556. }
  1557. */
  1558. /*
  1559. ** Objective Display
  1560. */
  1561. DynamicVectorClass<Render2DClass *> ObjectivePogRenderers;
  1562. Render2DClass * ObjectiveArrowRenderer;
  1563. Render2DSentenceClass * ObjectiveTextRenderer;
  1564. int CurrentObjectiveIndex = 0;
  1565. void * CurrentObjective = NULL;
  1566. static int CachedObjectiveIndex=-1;
  1567. int CachedRange=0;
  1568. #define OBJECTIVE_ARROW_TEXTURE "HUD_obje_arrow.TGA"
  1569. static void Objective_Init( void )
  1570. {
  1571. ObjectiveArrowRenderer = new Render2DClass();
  1572. ObjectiveArrowRenderer->Set_Texture( OBJECTIVE_ARROW_TEXTURE );
  1573. ObjectiveArrowRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1574. FontCharsClass *font = StyleMgrClass::Peek_Font( StyleMgrClass::FONT_INGAME_TXT );
  1575. ObjectiveTextRenderer = new Render2DSentenceClass();
  1576. ObjectiveTextRenderer->Set_Font( font );
  1577. CurrentObjectiveIndex=0;
  1578. CurrentObjective=NULL;
  1579. CachedObjectiveIndex=-1;
  1580. CachedRange=0;
  1581. }
  1582. static void Objective_Release_Pogs( void )
  1583. {
  1584. for ( int i = 0; i < ObjectivePogRenderers.Count(); i++ ) {
  1585. delete ObjectivePogRenderers[i];
  1586. ObjectivePogRenderers[i] = NULL;
  1587. }
  1588. ObjectivePogRenderers.Delete_All();
  1589. }
  1590. static void Objective_Shutdown( void )
  1591. {
  1592. Objective_Release_Pogs();
  1593. delete ObjectiveArrowRenderer;
  1594. ObjectiveArrowRenderer = NULL;
  1595. delete ObjectiveTextRenderer;
  1596. ObjectiveTextRenderer = NULL;
  1597. }
  1598. #define POG_FLY_TIME 2.0f
  1599. static void Objective_Update( void )
  1600. {
  1601. RectClass pog_box( 0, 0, 64, 64 );
  1602. pog_box += Render2DClass::Get_Screen_Resolution().Upper_Right() - pog_box.Upper_Right();
  1603. pog_box += Vector2( -16, 8 );
  1604. #define POG_SPACING Vector2( 10, 0 )
  1605. bool rebuild = false;
  1606. int objective_count = ObjectiveManager::Get_Num_HUD_Objectives();
  1607. if ( objective_count > 0 ) {
  1608. // maintain the index
  1609. if ( CurrentObjective != ObjectiveManager::Get_Objective( CurrentObjectiveIndex ) ) {
  1610. CurrentObjectiveIndex = 0;
  1611. rebuild = true;
  1612. #if 0 // no, just go for the first
  1613. // Try to find the last objective
  1614. for ( int i = 0; i < objective_count; i++ ) {
  1615. if ( CurrentObjective == ObjectiveManager::Get_Objective( i ) ) {
  1616. CurrentObjectiveIndex = i;
  1617. }
  1618. }
  1619. #endif
  1620. }
  1621. if ( IS_MISSION && Input::Get_State( INPUT_FUNCTION_CYCLE_POG ) ) {
  1622. rebuild = true;
  1623. CurrentObjectiveIndex++;
  1624. if ( CurrentObjectiveIndex >= objective_count ) {
  1625. CurrentObjectiveIndex = 0;
  1626. }
  1627. }
  1628. CurrentObjective = ObjectiveManager::Get_Objective( CurrentObjectiveIndex );
  1629. } else {
  1630. if (CurrentObjectiveIndex!=0 || CurrentObjective!=NULL) {
  1631. rebuild=true;
  1632. }
  1633. CurrentObjectiveIndex = 0;
  1634. CurrentObjective = NULL;
  1635. }
  1636. // re-Create the Pogs, if needed
  1637. if ( rebuild || ObjectiveManager::Are_HUD_Objectives_Changed() )
  1638. {
  1639. // Debug_Say(( "Rebuild Hud Pogs\n" ));
  1640. Objective_Release_Pogs();
  1641. // Reset text
  1642. ObjectiveTextRenderer->Reset();
  1643. CachedRange=0;
  1644. CachedObjectiveIndex=-1;
  1645. int count = objective_count;
  1646. pog_box += POG_SPACING * (float)count;
  1647. bool dont_clear = false;
  1648. for ( int i = count - 1; i >= 0; i-- ) {
  1649. int index = (i + CurrentObjectiveIndex) % objective_count;
  1650. pog_box -= POG_SPACING;
  1651. // Add Pog
  1652. Render2DClass * renderer = new Render2DClass();
  1653. if ( renderer ) {
  1654. renderer->Set_Texture( ObjectiveManager::Get_HUD_Objectives_Pog_Texture_Name( index ) );
  1655. renderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1656. float age = ObjectiveManager::Get_HUD_Objectives_Age( index );
  1657. if ( age < POG_FLY_TIME ) {
  1658. Vector2 offset = Render2DClass::Get_Screen_Resolution().Center() - Render2DClass::Get_Screen_Resolution().Upper_Right();
  1659. offset.X *= 0.75f;
  1660. float fly = WWMath::Clamp( (2.0f-(2.0f*age/POG_FLY_TIME)), 0, 1 );
  1661. offset *= fly;
  1662. pog_box += offset;
  1663. renderer->Add_Quad( pog_box );
  1664. pog_box -= offset;
  1665. dont_clear = true;
  1666. // AND, make an extra renderer for the radar star
  1667. Render2DClass * renderer = new Render2DClass();
  1668. if ( renderer ) {
  1669. renderer->Set_Texture( "HUD_STAR.TGA" );
  1670. renderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1671. RectClass star_box( -32, -32, 32, 32 );
  1672. star_box.Scale( fly );
  1673. Vector2 star_fly_start = Render2DClass::Get_Screen_Resolution().Center();
  1674. Vector2 star_fly_end = Render2DClass::Get_Screen_Resolution().Lower_Left();
  1675. star_fly_start.X *= 0.85f;
  1676. star_fly_start.Y *= 1.175f;
  1677. star_fly_end.X += 40.0f;
  1678. star_fly_end.Y *= 0.8f;
  1679. star_box += star_fly_end;
  1680. Vector2 offset = star_fly_start - star_fly_end;
  1681. offset *= fly;
  1682. star_box += offset;
  1683. Vector3 color3( 0,1,0 );
  1684. if ( ObjectiveManager::Get_Objective(index) != NULL ) {
  1685. color3 = ObjectiveManager::Get_Objective(index)->Type_To_Color();
  1686. }
  1687. unsigned int color = color3.Convert_To_ARGB();
  1688. renderer->Add_Quad( star_box, color );
  1689. ObjectivePogRenderers.Add( renderer );
  1690. }
  1691. } else {
  1692. renderer->Add_Quad( pog_box );
  1693. }
  1694. ObjectivePogRenderers.Add( renderer );
  1695. }
  1696. }
  1697. if ( !dont_clear ) {
  1698. ObjectiveManager::Clear_HUD_Objectives_Changed();
  1699. }
  1700. }
  1701. ObjectiveArrowRenderer->Reset();
  1702. float range = 0;
  1703. int count = objective_count;
  1704. if ( count > 0 ) {
  1705. // Create Arrow
  1706. float angle = 0;
  1707. Vector3 objective_pos = ObjectiveManager::Get_HUD_Objectives_Location( CurrentObjectiveIndex );
  1708. if ( COMBAT_STAR ) {
  1709. Vector3 rel_pos;
  1710. Matrix3D::Inverse_Transform_Vector( COMBAT_STAR->Get_Transform(), objective_pos, &rel_pos );
  1711. angle = ::atan2( rel_pos.Y, rel_pos.X );
  1712. range = rel_pos.Length();
  1713. }
  1714. Vector2 arrow_vertex;
  1715. arrow_vertex.X = WWMath::Fast_Sin( angle + DEG_TO_RAD( 180 + 45 ) );
  1716. arrow_vertex.Y = WWMath::Fast_Cos( angle + DEG_TO_RAD( 180 + 45 ) );
  1717. Vector2 verts[4];
  1718. verts[0] = Vector2( arrow_vertex.X, arrow_vertex.Y );
  1719. verts[1] = Vector2( arrow_vertex.Y, -arrow_vertex.X );
  1720. verts[2] = Vector2( -arrow_vertex.Y, arrow_vertex.X );
  1721. verts[3] = Vector2( -arrow_vertex.X, -arrow_vertex.Y );
  1722. Vector2 offset;
  1723. offset.Y = WWMath::Fast_Sin( -angle + DEG_TO_RAD( -90 ) );
  1724. offset.X = WWMath::Fast_Cos( -angle + DEG_TO_RAD( -90 ) );
  1725. offset *= 35;
  1726. offset += pog_box.Center();
  1727. const float SIN_45=0.70710678118654752440084436210485f;
  1728. for ( int i = 0; i < 4; i++ ) {
  1729. verts[i] *= 0.5f * 16 / SIN_45;//::sin( DEG_TO_RAD( 45 ) );
  1730. verts[i] += offset;
  1731. }
  1732. ObjectiveArrowRenderer->Add_Quad( verts[0], verts[1], verts[2], verts[3] );
  1733. }
  1734. int irange=(int)(range);
  1735. irange=(irange/10)*10;
  1736. if (CachedObjectiveIndex!=CurrentObjectiveIndex || irange!=CachedRange) {
  1737. ObjectiveTextRenderer->Reset();
  1738. if (objective_count>0) {
  1739. CachedRange=irange;
  1740. CachedObjectiveIndex=CurrentObjectiveIndex;
  1741. // Draw message
  1742. Vector2 position = pog_box.Lower_Left();
  1743. position += Vector2( 0, -15 );
  1744. WideStringClass str(ObjectiveManager::Get_HUD_Objectives_Message( CurrentObjectiveIndex ),true);
  1745. ObjectiveTextRenderer->Build_Sentence( str );
  1746. Vector2 text_size = ObjectiveTextRenderer->Get_Text_Extents( str );
  1747. position.X = (int)(pog_box.Center().X - (text_size.X/2));
  1748. ObjectiveTextRenderer->Set_Location( position );
  1749. ObjectiveTextRenderer->Draw_Sentence();
  1750. // Draw range
  1751. position = pog_box.Lower_Left();
  1752. str.Format( TRANSLATE(IDS_HUD_RANGE), irange );
  1753. ObjectiveTextRenderer->Build_Sentence( str );
  1754. text_size = ObjectiveTextRenderer->Get_Text_Extents( str );
  1755. position.X = (int)(pog_box.Center().X - (text_size.X/2));
  1756. ObjectiveTextRenderer->Set_Location( position );
  1757. ObjectiveTextRenderer->Draw_Sentence();
  1758. }
  1759. else {
  1760. CachedRange=0;
  1761. CachedObjectiveIndex=-1;
  1762. }
  1763. }
  1764. }
  1765. static void Objective_Render( void )
  1766. {
  1767. for ( int i = 0; i < ObjectivePogRenderers.Count(); i++ ) {
  1768. ObjectivePogRenderers[i]->Render();
  1769. }
  1770. ObjectiveArrowRenderer->Render();
  1771. ObjectiveTextRenderer->Render();
  1772. }
  1773. /*
  1774. ** Info Display
  1775. */
  1776. struct InfoEditorField {
  1777. const char * Name;
  1778. Vector2 * Value;
  1779. bool operator == (InfoEditorField const & rec) const { return false; }
  1780. bool operator != (InfoEditorField const & rec) const { return true; }
  1781. };
  1782. static DynamicVectorClass<InfoEditorField> InfoEditorFieldList;
  1783. #define INFO_EDITOR_ADD(x) field.Name = #x; field.Value = &x; InfoEditorFieldList.Add( field );
  1784. static void Info_Editor_Init( void )
  1785. {
  1786. #if 0
  1787. InfoEditorField field;
  1788. INFO_EDITOR_ADD( INFO_OFFSET );
  1789. INFO_EDITOR_ADD( FRAME_1_UV_UL );
  1790. INFO_EDITOR_ADD( FRAME_1_UV_LR );
  1791. INFO_EDITOR_ADD( FRAME_1_OFFSET );
  1792. INFO_EDITOR_ADD( FRAME_2_UV_UL );
  1793. INFO_EDITOR_ADD( FRAME_2_UV_LR );
  1794. INFO_EDITOR_ADD( FRAME_2_OFFSET );
  1795. INFO_EDITOR_ADD( FRAME_3_UV_UL );
  1796. INFO_EDITOR_ADD( FRAME_3_UV_LR );
  1797. INFO_EDITOR_ADD( FRAME_3_OFFSET );
  1798. INFO_EDITOR_ADD( FRAME_4_UV_UL );
  1799. INFO_EDITOR_ADD( FRAME_4_UV_LR );
  1800. INFO_EDITOR_ADD( FRAME_4_OFFSET );
  1801. INFO_EDITOR_ADD( FRAME_5_UV_UL );
  1802. INFO_EDITOR_ADD( FRAME_5_UV_LR );
  1803. INFO_EDITOR_ADD( FRAME_5_OFFSET );
  1804. INFO_EDITOR_ADD( FRAME_6_UV_UL );
  1805. INFO_EDITOR_ADD( FRAME_6_UV_LR );
  1806. INFO_EDITOR_ADD( FRAME_6_OFFSET );
  1807. INFO_EDITOR_ADD( HEALTH_BACK_UV_UL );
  1808. INFO_EDITOR_ADD( HEALTH_BACK_UV_LR );
  1809. INFO_EDITOR_ADD( HEALTH_BACK_UL );
  1810. INFO_EDITOR_ADD( HEALTH_BACK_LR );
  1811. INFO_EDITOR_ADD( GRADIENT_BLACK_UV_UL );
  1812. INFO_EDITOR_ADD( GRADIENT_BLACK_UV_LR );
  1813. INFO_EDITOR_ADD( HEALTH_TEXT_BACK_UL );
  1814. INFO_EDITOR_ADD( HEALTH_TEXT_BACK_LR );
  1815. INFO_EDITOR_ADD( HEALTH_UV_UL );
  1816. INFO_EDITOR_ADD( HEALTH_UV_LR );
  1817. INFO_EDITOR_ADD( HEALTH_OFFSET );
  1818. INFO_EDITOR_ADD( SHIELD_UV_UL );
  1819. INFO_EDITOR_ADD( SHIELD_UV_LR );
  1820. INFO_EDITOR_ADD( SHIELD_OFFSET );
  1821. INFO_EDITOR_ADD( KEY_1_UV_UL );
  1822. INFO_EDITOR_ADD( KEY_1_UV_LR );
  1823. INFO_EDITOR_ADD( KEY_1_OFFSET );
  1824. INFO_EDITOR_ADD( KEY_2_UV_UL );
  1825. INFO_EDITOR_ADD( KEY_2_UV_LR );
  1826. INFO_EDITOR_ADD( KEY_2_OFFSET );
  1827. INFO_EDITOR_ADD( KEY_3_UV_UL );
  1828. INFO_EDITOR_ADD( KEY_3_UV_LR );
  1829. INFO_EDITOR_ADD( KEY_3_OFFSET );
  1830. INFO_EDITOR_ADD( HEALTH_CROSS_1_UV_UL );
  1831. INFO_EDITOR_ADD( HEALTH_CROSS_1_UV_LR );
  1832. INFO_EDITOR_ADD( HEALTH_CROSS_1_OFFSET );
  1833. INFO_EDITOR_ADD( HEALTH_CROSS_2_UV_UL );
  1834. INFO_EDITOR_ADD( HEALTH_CROSS_2_UV_LR );
  1835. INFO_EDITOR_ADD( HEALTH_CROSS_2_OFFSET );
  1836. INFO_EDITOR_ADD( TIME_BACK_UL );
  1837. INFO_EDITOR_ADD( TIME_BACK_LR );
  1838. INFO_EDITOR_ADD( TIME_CLOCK_UV_UL );
  1839. INFO_EDITOR_ADD( TIME_CLOCK_UV_LR );
  1840. INFO_EDITOR_ADD( TIME_CLOCK_OFFSET );
  1841. INFO_EDITOR_ADD( WEAPON_BOX_UV_UL );
  1842. INFO_EDITOR_ADD( WEAPON_BOX_UV_LR );
  1843. INFO_EDITOR_ADD( WEAPON_BOX_OFFSET );
  1844. INFO_EDITOR_ADD( POWER_OUT_ICON_UV_UL );
  1845. INFO_EDITOR_ADD( POWER_OUT_ICON_UV_LR );
  1846. INFO_EDITOR_ADD( POWER_OUT_ICON_OFFSET );
  1847. INFO_EDITOR_ADD( REPAIR_ICON_UV_UL );
  1848. INFO_EDITOR_ADD( REPAIR_ICON_UV_LR );
  1849. INFO_EDITOR_ADD( REPAIR_ICON_OFFSET );
  1850. INFO_EDITOR_ADD( GDI_ICON_UV_UL );
  1851. INFO_EDITOR_ADD( GDI_ICON_UV_LR );
  1852. INFO_EDITOR_ADD( GDI_ICON_OFFSET );
  1853. INFO_EDITOR_ADD( NOD_ICON_UV_UL );
  1854. INFO_EDITOR_ADD( NOD_ICON_UV_LR );
  1855. INFO_EDITOR_ADD( NOD_ICON_OFFSET );
  1856. INFO_EDITOR_ADD( NEUTRAL_ICON_UV_UL );
  1857. INFO_EDITOR_ADD( NEUTRAL_ICON_UV_LR );
  1858. INFO_EDITOR_ADD( NEUTRAL_ICON_OFFSET );
  1859. INFO_EDITOR_ADD( BULLET_ICON_UV_UL );
  1860. INFO_EDITOR_ADD( BULLET_ICON_UV_LR );
  1861. INFO_EDITOR_ADD( BULLET_ICON_OFFSET );
  1862. INFO_EDITOR_ADD( RADAR_CENTER_OFFSET );
  1863. INFO_EDITOR_ADD( DAMAGE_1_UV_UL );
  1864. INFO_EDITOR_ADD( DAMAGE_1_UV_LR );
  1865. INFO_EDITOR_ADD( DAMAGE_2_UV_UL );
  1866. INFO_EDITOR_ADD( DAMAGE_2_UV_LR );
  1867. INFO_EDITOR_ADD( HORIZ_DAMAGE_SIZE );
  1868. INFO_EDITOR_ADD( VERT_DAMAGE_SIZE );
  1869. INFO_EDITOR_ADD( DIAG_DAMAGE_SIZE );
  1870. INFO_EDITOR_ADD( HV_DAMAGE_OFFSET );
  1871. INFO_EDITOR_ADD( DIAG_DAMAGE_OFFSET );
  1872. INFO_EDITOR_ADD( POWERUP_BOX_UV_UL );
  1873. INFO_EDITOR_ADD( POWERUP_BOX_UV_LR );
  1874. INFO_EDITOR_ADD( RADAR_RINGS_UV_UL );
  1875. INFO_EDITOR_ADD( RADAR_RINGS_UV_LR );
  1876. INFO_EDITOR_ADD( RADAR_RINGS_L_OFFSET );
  1877. INFO_EDITOR_ADD( RADAR_RINGS_R_OFFSET );
  1878. INFO_EDITOR_ADD( RADAR_STAR_UV_UL );
  1879. INFO_EDITOR_ADD( RADAR_STAR_UV_LR );
  1880. INFO_EDITOR_ADD( RADAR_STAR_OFFSET );
  1881. INFO_EDITOR_ADD( RADAR_SQUARE_UV_UL );
  1882. INFO_EDITOR_ADD( RADAR_SQUARE_UV_LR );
  1883. INFO_EDITOR_ADD( RADAR_SQUARE_OFFSET);
  1884. INFO_EDITOR_ADD( RADAR_TRIANGLE_UV_UL);
  1885. INFO_EDITOR_ADD( RADAR_TRIANGLE_UV_LR);
  1886. INFO_EDITOR_ADD( RADAR_TRIANGLE_OFFSET );
  1887. INFO_EDITOR_ADD( RADAR_CIRCLE_UV_UL );
  1888. INFO_EDITOR_ADD( RADAR_CIRCLE_UV_LR );
  1889. INFO_EDITOR_ADD( RADAR_CIRCLE_OFFSET );
  1890. INFO_EDITOR_ADD( RADAR_BRACKET_UV_UL );
  1891. INFO_EDITOR_ADD( RADAR_BRACKET_UV_LR );
  1892. INFO_EDITOR_ADD( RADAR_BRACKET_OFFSET );
  1893. INFO_EDITOR_ADD( RADAR_SWEEP_UV_UL );
  1894. INFO_EDITOR_ADD( RADAR_SWEEP_UV_LR );
  1895. INFO_EDITOR_ADD( RADAR_SWEEP_OFFSET );
  1896. INFO_EDITOR_ADD( TARGET_HEALTH_L_UV_UL );
  1897. INFO_EDITOR_ADD( TARGET_HEALTH_L_UV_LR );
  1898. INFO_EDITOR_ADD( TARGET_HEALTH_R_UV_UL );
  1899. INFO_EDITOR_ADD( TARGET_HEALTH_R_UV_LR );
  1900. INFO_EDITOR_ADD( TARGET_HEALTH_OFFSET );
  1901. INFO_EDITOR_ADD( TARGET_NAME_UV_UL );
  1902. INFO_EDITOR_ADD( TARGET_NAME_UV_LR );
  1903. INFO_EDITOR_ADD( TARGET_NAME_OFFSET );
  1904. #endif
  1905. }
  1906. static void Info_Editor_Update( void )
  1907. {
  1908. return;
  1909. bool changed = false;
  1910. static int index = 0;
  1911. static float _move = 0;
  1912. float move = Input::Get_Amount( INPUT_FUNCTION_MOVE_LEFT ) - Input::Get_Amount( INPUT_FUNCTION_MOVE_RIGHT );
  1913. if ( _move != move ) {
  1914. _move = move;
  1915. index += (int)-move;
  1916. index = (int)WWMath::Wrap( index, (float)0, (float)(InfoEditorFieldList.Count()) );
  1917. if ( move != 0 ) {
  1918. changed = true;
  1919. }
  1920. }
  1921. float _forward = 0;
  1922. float forward = Input::Get_Amount( INPUT_FUNCTION_MOVE_FORWARD ) - Input::Get_Amount( INPUT_FUNCTION_MOVE_BACKWARD );
  1923. forward *= 10;
  1924. forward = WWMath::Clamp( forward, -1, 1 );
  1925. if ( _forward != forward ) {
  1926. _forward = forward;
  1927. InfoEditorFieldList[index].Value->V += forward;
  1928. if ( forward != 0 ) {
  1929. changed = true;
  1930. }
  1931. }
  1932. float _left = 0;
  1933. float left = Input::Get_Amount( INPUT_FUNCTION_TURN_LEFT ) - Input::Get_Amount( INPUT_FUNCTION_TURN_RIGHT );
  1934. left *= 10;
  1935. left = WWMath::Clamp( left, -1, 1 );
  1936. if ( _left != left ) {
  1937. _left = left;
  1938. InfoEditorFieldList[index].Value->U += left;
  1939. if ( left != 0 ) {
  1940. changed = true;
  1941. }
  1942. }
  1943. if ( changed ) {
  1944. Debug_Say(( "Vector2 %s( %d, %d );\n", InfoEditorFieldList[index].Name, (int)InfoEditorFieldList[index].Value->U, (int)InfoEditorFieldList[index].Value->V ));
  1945. }
  1946. }
  1947. static void Info_Editor_Shutdown( void )
  1948. {
  1949. while ( InfoEditorFieldList.Count() > 0 ) {
  1950. Debug_Say(( "Vector2 %s( %d, %d );\n", InfoEditorFieldList[0].Name, (int)InfoEditorFieldList[0].Value->U, (int)InfoEditorFieldList[0].Value->V ));
  1951. InfoEditorFieldList.Delete(0);
  1952. }
  1953. }
  1954. /*
  1955. **
  1956. */
  1957. Render2DTextClass * InfoHealthCountRenderer;
  1958. Render2DTextClass * InfoShieldCountRenderer;
  1959. Vector2 InfoBase(0,0);
  1960. float LastHealth = 0;
  1961. float CenterHealthTimer = 0;
  1962. const float CENTER_HEALTH_TIME = 2.0f;
  1963. static void Info_Init( void )
  1964. {
  1965. Info_Editor_Init();
  1966. InfoRenderer = new Render2DClass();
  1967. InfoRenderer->Set_Texture( HUD_MAIN_TEXTURE );
  1968. InfoRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1969. Font3DInstanceClass * font = WW3DAssetManager::Get_Instance()->Get_Font3DInstance( LARGE_FONT );
  1970. SET_REF_OWNER( font );
  1971. InfoHealthCountRenderer = new Render2DTextClass( font );
  1972. InfoHealthCountRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1973. font->Release_Ref();
  1974. font = WW3DAssetManager::Get_Instance()->Get_Font3DInstance( SMALL_FONT );
  1975. SET_REF_OWNER( font );
  1976. InfoShieldCountRenderer = new Render2DTextClass( font );
  1977. InfoShieldCountRenderer->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  1978. font->Release_Ref();
  1979. InfoBase = Render2DClass::Get_Screen_Resolution().Lower_Left() + Vector2( INFO_OFFSET );
  1980. }
  1981. static void Info_Shutdown( void )
  1982. {
  1983. Info_Editor_Shutdown() ;
  1984. delete InfoRenderer;
  1985. InfoRenderer = NULL;
  1986. delete InfoHealthCountRenderer;
  1987. InfoHealthCountRenderer = NULL;
  1988. delete InfoShieldCountRenderer;
  1989. InfoShieldCountRenderer = NULL;
  1990. }
  1991. static void Info_Update_Health_Shield( void )
  1992. {
  1993. // Draw Health
  1994. float health = 0;
  1995. float health_percent = 0;
  1996. float shield = 0;
  1997. float shield_percent = 0;
  1998. if ( COMBAT_STAR ) {
  1999. const DefenseObjectClass * def = COMBAT_STAR->Get_Defense_Object();
  2000. if ( COMBAT_STAR->Get_Vehicle() ) {
  2001. def = COMBAT_STAR->Get_Vehicle()->Get_Defense_Object();
  2002. }
  2003. if ( def && def->Get_Health_Max() ) {
  2004. health = def->Get_Health();
  2005. health_percent = WWMath::Clamp( def->Get_Health() / def->Get_Health_Max(), 0, 1 );
  2006. }
  2007. if ( def && def->Get_Shield_Strength_Max() ) {
  2008. shield = def->Get_Shield_Strength();
  2009. shield_percent = WWMath::Clamp( def->Get_Shield_Strength() / def->Get_Shield_Strength_Max(), 0, 1 );
  2010. }
  2011. }
  2012. RectClass uv;
  2013. RectClass draw;
  2014. // Draw Health Bar
  2015. uv.Set( HEALTH_UV_UL, HEALTH_UV_LR );
  2016. draw = uv;
  2017. uv.Scale( INFO_UV_SCALE );
  2018. draw += InfoBase + HEALTH_OFFSET - draw.Upper_Left();
  2019. // Scale bars
  2020. static float _last_health_percent = 0;
  2021. float diff = health_percent - _last_health_percent;
  2022. float max_change = TimeManager::Get_Frame_Seconds();
  2023. _last_health_percent += WWMath::Clamp( diff, -max_change, max_change );
  2024. uv.Right = uv.Left + uv.Width() * _last_health_percent;
  2025. draw.Right = draw.Left + draw.Width() * _last_health_percent;
  2026. // Get bar color
  2027. float color_percent = MAX( _last_health_percent, health_percent );
  2028. InfoRenderer->Add_Quad( draw, uv, Get_Health_Color( color_percent ) );
  2029. uv.Set( GRADIENT_BLACK_UV_UL, GRADIENT_BLACK_UV_LR );
  2030. uv.Scale( INFO_UV_SCALE );
  2031. draw.Set( HEALTH_TEXT_BACK_UL, HEALTH_TEXT_BACK_LR );
  2032. draw += InfoBase;
  2033. InfoRenderer->Add_Quad( draw, uv );
  2034. // Draw Cross
  2035. static float flash = 0;
  2036. flash += TimeManager::Get_Frame_Seconds() * 4;
  2037. if ( flash > 2 ) {
  2038. flash -= 2;
  2039. }
  2040. if ( health_percent > 0.25f ) {
  2041. flash = 0;
  2042. }
  2043. float intensity = flash;
  2044. if ( flash > 1 ) {
  2045. intensity = 2 - flash;
  2046. }
  2047. int health_color = Get_Health_Color( color_percent );
  2048. uv.Set( HEALTH_CROSS_1_UV_UL, HEALTH_CROSS_1_UV_LR );
  2049. draw = uv;
  2050. uv.Scale( INFO_UV_SCALE );
  2051. draw += InfoBase + HEALTH_CROSS_1_OFFSET - draw.Upper_Left();
  2052. InfoRenderer->Add_Quad( draw, uv, COLOR( intensity, health_color ) );
  2053. RectClass uv2;
  2054. uv2.Set( HEALTH_CROSS_2_UV_UL, HEALTH_CROSS_2_UV_LR );
  2055. uv2.Scale( INFO_UV_SCALE );
  2056. InfoRenderer->Add_Quad( draw, uv2, COLOR( 1-intensity, health_color ) );
  2057. // Draw Health Number
  2058. InfoHealthCountRenderer->Reset();
  2059. // StringClass text;
  2060. if ( health < 1 && health > 0 ) {
  2061. health = 1;
  2062. }
  2063. //text.Format( "%03d", (int)health );
  2064. long lhealth=WWMath::Float_To_Long(health);
  2065. WCHAR tmp_text[5];
  2066. Generate_WChar_Text_From_Number(tmp_text,4,3,lhealth);
  2067. InfoHealthCountRenderer->Set_Location( draw.Upper_Right() + Vector2( 4,4) );
  2068. InfoHealthCountRenderer->Draw_Text( tmp_text, health_color );
  2069. if ( health != LastHealth || health_percent <= 0.25f ) {
  2070. LastHealth = health;
  2071. CenterHealthTimer = CENTER_HEALTH_TIME;
  2072. }
  2073. if ( CenterHealthTimer > 0 ) {
  2074. // Also draw the above at the center
  2075. Vector2 health_center_offset = Render2DClass::Get_Screen_Resolution().Center();
  2076. health_center_offset.X *= 0.5;
  2077. health_center_offset.Y -= draw.Height() / 2;
  2078. health_center_offset -= HEALTH_CROSS_1_OFFSET;
  2079. float fade = WWMath::Clamp( CenterHealthTimer, 0, 1 );
  2080. uv.Set( GRADIENT_BLACK_UV_UL, GRADIENT_BLACK_UV_LR );
  2081. uv.Scale( INFO_UV_SCALE );
  2082. draw.Set( HEALTH_TEXT_BACK_UL, HEALTH_TEXT_BACK_LR );
  2083. draw += health_center_offset;
  2084. InfoRenderer->Add_Quad( draw, uv, COLOR( fade ) );
  2085. uv.Set( HEALTH_CROSS_1_UV_UL, HEALTH_CROSS_1_UV_LR );
  2086. draw = uv;
  2087. uv.Scale( INFO_UV_SCALE );
  2088. draw += health_center_offset + HEALTH_CROSS_1_OFFSET - draw.Upper_Left();
  2089. InfoRenderer->Add_Quad( draw, uv, COLOR( fade * intensity, health_color ) );
  2090. InfoRenderer->Add_Quad( draw, uv2, COLOR( fade * (1-intensity), health_color ) );
  2091. InfoHealthCountRenderer->Set_Location( draw.Upper_Right() + Vector2( 4,4) );
  2092. InfoHealthCountRenderer->Draw_Text( tmp_text, COLOR( fade, health_color ) );
  2093. CenterHealthTimer -= TimeManager::Get_Frame_Seconds();
  2094. }
  2095. // Draw Shield
  2096. static float _last_shield_percent = 0;
  2097. diff = shield_percent - _last_shield_percent;
  2098. max_change = TimeManager::Get_Frame_Seconds();
  2099. _last_shield_percent += WWMath::Clamp( diff, -max_change, max_change );
  2100. shield_percent = _last_shield_percent;
  2101. uv.Right = uv.Left + uv.Width() * shield_percent;
  2102. draw.Right = draw.Left + draw.Width() * shield_percent;
  2103. if ( shield_percent > 0 ) {
  2104. #define TOTAL_SHIELD_MOVEMENT 80
  2105. for ( float percent = 0; percent < shield_percent; percent += 0.1f ) {
  2106. uv.Set( SHIELD_UV_UL, SHIELD_UV_LR );
  2107. draw = uv;
  2108. uv.Scale( INFO_UV_SCALE );
  2109. draw += InfoBase + SHIELD_OFFSET - draw.Upper_Left();
  2110. draw += Vector2( (int)(-percent * TOTAL_SHIELD_MOVEMENT), 0 );
  2111. InfoRenderer->Add_Quad( draw, uv );
  2112. }
  2113. uv.Set( SHIELD_UV_UL, SHIELD_UV_LR );
  2114. draw = uv;
  2115. uv.Scale( INFO_UV_SCALE );
  2116. draw += InfoBase + SHIELD_OFFSET - draw.Upper_Left();
  2117. draw += Vector2( (int)(-shield_percent * TOTAL_SHIELD_MOVEMENT), 0 );
  2118. InfoRenderer->Add_Quad( draw, uv );
  2119. // Draw Shield Number
  2120. InfoShieldCountRenderer->Reset();
  2121. // StringClass text;
  2122. // text.Format( "%03d", (int)shield );
  2123. long lshield=WWMath::Float_To_Long(shield);
  2124. WCHAR tmp_text[5];
  2125. Generate_WChar_Text_From_Number(tmp_text,4,3,lshield);
  2126. InfoShieldCountRenderer->Set_Location( draw.Upper_Left() + Vector2( 4,4) );
  2127. InfoShieldCountRenderer->Draw_Text( tmp_text );
  2128. } else {
  2129. InfoShieldCountRenderer->Reset();
  2130. }
  2131. }
  2132. static void Info_Update( void )
  2133. {
  2134. // Info_Editor_Update();
  2135. // Clear the renderer
  2136. InfoRenderer->Reset();
  2137. // Draw the Frame
  2138. RectClass uv;
  2139. uv.Set( FRAME_1_UV_UL, FRAME_1_UV_LR );
  2140. RectClass draw = uv;
  2141. uv.Scale( INFO_UV_SCALE );
  2142. draw += InfoBase + FRAME_1_OFFSET - draw.Upper_Left();
  2143. InfoRenderer->Add_Quad( draw, uv );
  2144. uv.Set( FRAME_2_UV_UL, FRAME_2_UV_LR );
  2145. draw = uv;
  2146. uv.Scale( INFO_UV_SCALE );
  2147. draw += InfoBase + FRAME_2_OFFSET - draw.Upper_Left();
  2148. InfoRenderer->Add_Quad( draw, uv );
  2149. uv.Set( FRAME_3_UV_UL, FRAME_3_UV_LR );
  2150. draw = uv;
  2151. uv.Scale( INFO_UV_SCALE );
  2152. draw += InfoBase + FRAME_3_OFFSET - draw.Upper_Left();
  2153. InfoRenderer->Add_Quad( draw, uv );
  2154. uv.Set( FRAME_4_UV_UL, FRAME_4_UV_LR );
  2155. draw = uv;
  2156. uv.Scale( INFO_UV_SCALE );
  2157. draw += InfoBase + FRAME_4_OFFSET - draw.Upper_Left();
  2158. InfoRenderer->Add_Quad( draw, uv );
  2159. uv.Set( FRAME_5_UV_UL, FRAME_5_UV_LR );
  2160. draw = uv;
  2161. uv.Scale( INFO_UV_SCALE );
  2162. draw += InfoBase + FRAME_5_OFFSET - draw.Upper_Left();
  2163. InfoRenderer->Add_Quad( draw, uv );
  2164. uv.Set( FRAME_6_UV_UL, FRAME_6_UV_LR );
  2165. draw = uv;
  2166. uv.Scale( INFO_UV_SCALE );
  2167. draw += InfoBase + FRAME_6_OFFSET - draw.Upper_Left();
  2168. InfoRenderer->Add_Quad( draw, uv );
  2169. uv.Set( HEALTH_BACK_UV_UL, HEALTH_BACK_UV_LR );
  2170. uv.Scale( INFO_UV_SCALE );
  2171. draw.Set( HEALTH_BACK_UL, HEALTH_BACK_LR );
  2172. draw += InfoBase;
  2173. InfoRenderer->Add_Quad( draw, uv );
  2174. // Draw Health and Shield
  2175. Info_Update_Health_Shield();
  2176. if ( COMBAT_STAR ) {
  2177. if ( COMBAT_STAR->Has_Key( 1 ) ) {
  2178. uv.Set( KEY_1_UV_UL, KEY_1_UV_LR );
  2179. draw = uv;
  2180. uv.Scale( INFO_UV_SCALE );
  2181. draw += InfoBase + KEY_1_OFFSET - draw.Upper_Left();
  2182. InfoRenderer->Add_Quad( draw, uv );
  2183. }
  2184. if ( COMBAT_STAR->Has_Key( 2 ) ) {
  2185. uv.Set( KEY_2_UV_UL, KEY_2_UV_LR );
  2186. draw = uv;
  2187. uv.Scale( INFO_UV_SCALE );
  2188. draw += InfoBase + KEY_2_OFFSET - draw.Upper_Left();
  2189. InfoRenderer->Add_Quad( draw, uv );
  2190. }
  2191. if ( COMBAT_STAR->Has_Key( 3 ) ) {
  2192. uv.Set( KEY_3_UV_UL, KEY_3_UV_LR );
  2193. draw = uv;
  2194. uv.Scale( INFO_UV_SCALE );
  2195. draw += InfoBase + KEY_3_OFFSET - draw.Upper_Left();
  2196. InfoRenderer->Add_Quad( draw, uv );
  2197. }
  2198. }
  2199. #if 0
  2200. return;
  2201. uv.Set( TARGET_HEALTH_L_UV_UL, TARGET_HEALTH_L_UV_LR );
  2202. draw = uv;
  2203. uv.Scale( INFO_UV_SCALE );
  2204. draw += InfoBase + TARGET_HEALTH_OFFSET - draw.Upper_Left();
  2205. InfoRenderer->Add_Quad( draw, uv );
  2206. uv.Set( TARGET_HEALTH_R_UV_UL, TARGET_HEALTH_R_UV_LR );
  2207. draw = uv;
  2208. uv.Scale( INFO_UV_SCALE );
  2209. draw += InfoBase + TARGET_HEALTH_OFFSET - draw.Upper_Left() + Vector2( 0, 20 );
  2210. InfoRenderer->Add_Quad( draw, uv );
  2211. uv.Set( TARGET_NAME_UV_UL, TARGET_NAME_UV_LR );
  2212. draw = uv;
  2213. uv.Scale( INFO_UV_SCALE );
  2214. draw += InfoBase + TARGET_NAME_OFFSET - draw.Upper_Left();
  2215. InfoRenderer->Add_Quad( draw, uv );
  2216. uv.Set( GRADIENT_BLACK_UV_UL, GRADIENT_BLACK_UV_LR );
  2217. uv.Scale( INFO_UV_SCALE );
  2218. draw.Set( TIME_BACK_UL, TIME_BACK_LR );
  2219. draw += InfoBase;
  2220. InfoRenderer->Add_Quad( draw, uv );
  2221. uv.Set( TIME_CLOCK_UV_UL, TIME_CLOCK_UV_LR );
  2222. draw = uv;
  2223. uv.Scale( INFO_UV_SCALE );
  2224. draw += InfoBase + TIME_CLOCK_OFFSET - draw.Upper_Left();
  2225. InfoRenderer->Add_Quad( draw, uv );
  2226. uv.Set( WEAPON_BOX_UV_UL, WEAPON_BOX_UV_LR );
  2227. draw = uv;
  2228. uv.Scale( INFO_UV_SCALE );
  2229. draw += InfoBase + WEAPON_BOX_OFFSET - draw.Upper_Left();
  2230. InfoRenderer->Add_Quad( draw, uv );
  2231. uv.Set( POWER_OUT_ICON_UV_UL, POWER_OUT_ICON_UV_LR );
  2232. draw = uv;
  2233. uv.Scale( INFO_UV_SCALE );
  2234. draw += InfoBase + POWER_OUT_ICON_OFFSET - draw.Upper_Left();
  2235. InfoRenderer->Add_Quad( draw, uv );
  2236. uv.Set( REPAIR_ICON_UV_UL, REPAIR_ICON_UV_LR );
  2237. draw = uv;
  2238. uv.Scale( INFO_UV_SCALE );
  2239. draw += InfoBase + REPAIR_ICON_OFFSET - draw.Upper_Left();
  2240. InfoRenderer->Add_Quad( draw, uv );
  2241. uv.Set( GDI_ICON_UV_UL, GDI_ICON_UV_LR );
  2242. draw = uv;
  2243. uv.Scale( INFO_UV_SCALE );
  2244. draw += InfoBase + GDI_ICON_OFFSET - draw.Upper_Left();
  2245. InfoRenderer->Add_Quad( draw, uv );
  2246. uv.Set( NOD_ICON_UV_UL, NOD_ICON_UV_LR );
  2247. draw = uv;
  2248. uv.Scale( INFO_UV_SCALE );
  2249. draw += InfoBase + NOD_ICON_OFFSET - draw.Upper_Left();
  2250. InfoRenderer->Add_Quad( draw, uv );
  2251. uv.Set( NEUTRAL_ICON_UV_UL, NEUTRAL_ICON_UV_LR );
  2252. draw = uv;
  2253. uv.Scale( INFO_UV_SCALE );
  2254. draw += InfoBase + NEUTRAL_ICON_OFFSET - draw.Upper_Left();
  2255. InfoRenderer->Add_Quad( draw, uv );
  2256. // Radar
  2257. uv.Set( RADAR_STAR_UV_UL, RADAR_STAR_UV_LR );
  2258. draw = uv;
  2259. uv.Scale( INFO_UV_SCALE );
  2260. draw += InfoBase + RADAR_STAR_OFFSET - draw.Upper_Left();
  2261. InfoRenderer->Add_Quad( draw, uv );
  2262. uv.Set( RADAR_STAR_UV_UL, RADAR_STAR_UV_LR );
  2263. draw = uv;
  2264. uv.Scale( INFO_UV_SCALE );
  2265. draw += InfoBase + RADAR_STAR_OFFSET - draw.Upper_Left();
  2266. InfoRenderer->Add_Quad( draw, uv );
  2267. uv.Set( RADAR_SQUARE_UV_UL, RADAR_SQUARE_UV_LR );
  2268. draw = uv;
  2269. uv.Scale( INFO_UV_SCALE );
  2270. draw += InfoBase + RADAR_SQUARE_OFFSET - draw.Upper_Left();
  2271. InfoRenderer->Add_Quad( draw, uv );
  2272. uv.Set( RADAR_TRIANGLE_UV_UL, RADAR_TRIANGLE_UV_LR );
  2273. draw = uv;
  2274. uv.Scale( INFO_UV_SCALE );
  2275. draw += InfoBase + RADAR_TRIANGLE_OFFSET - draw.Upper_Left();
  2276. InfoRenderer->Add_Quad( draw, uv );
  2277. uv.Set( RADAR_CIRCLE_UV_UL, RADAR_CIRCLE_UV_LR );
  2278. draw = uv;
  2279. uv.Scale( INFO_UV_SCALE );
  2280. draw += InfoBase + RADAR_CIRCLE_OFFSET - draw.Upper_Left();
  2281. InfoRenderer->Add_Quad( draw, uv );
  2282. uv.Set( RADAR_BRACKET_UV_UL, RADAR_BRACKET_UV_LR );
  2283. draw = uv;
  2284. uv.Scale( INFO_UV_SCALE );
  2285. draw += InfoBase + RADAR_BRACKET_OFFSET - draw.Upper_Left();
  2286. InfoRenderer->Add_Quad( draw, uv );
  2287. uv.Set( RADAR_SWEEP_UV_UL, RADAR_SWEEP_UV_LR );
  2288. draw = uv;
  2289. uv.Scale( INFO_UV_SCALE );
  2290. draw += InfoBase + RADAR_SWEEP_OFFSET - draw.Upper_Left();
  2291. InfoRenderer->Add_Quad( draw, uv );
  2292. #endif
  2293. }
  2294. static void Info_Render( void )
  2295. {
  2296. InfoRenderer->Render();
  2297. InfoHealthCountRenderer->Render();
  2298. InfoShieldCountRenderer->Render();
  2299. }
  2300. /*
  2301. ** OLD HUD STUFF
  2302. */
  2303. static bool _HUDEnabled = true;
  2304. static bool _HUDInited = false;
  2305. #ifdef ATI_DEMO_HACK
  2306. typedef enum {
  2307. DEMO_HUD_IMAGE=0,
  2308. DEMO_HUD_IMAGE2,
  2309. NUM_RENDER_IMAGES,
  2310. };
  2311. #else
  2312. typedef enum {
  2313. RETICLE = 0,
  2314. RETICLE_HIT,
  2315. ACTION_STATUSBAR_RENDERER,
  2316. DEMO_HUD_IMAGE,
  2317. DEMO_HUD_IMAGE2,
  2318. NUM_RENDER_IMAGES,
  2319. };
  2320. #endif
  2321. Render2DClass * RenderImages[ NUM_RENDER_IMAGES ];
  2322. /*
  2323. **
  2324. */
  2325. static bool Is_HUD_Displayed( void );
  2326. /*
  2327. **
  2328. */
  2329. void HUDClass::Init(bool render_available)
  2330. {
  2331. for( int i = 0; i < NUM_RENDER_IMAGES; i++ ) {
  2332. RenderImages[i] = NULL;
  2333. }
  2334. // Reticles
  2335. #ifndef ATI_DEMO_HACK
  2336. RenderImages[RETICLE] = new Render2DClass();
  2337. RenderImages[RETICLE]->Set_Texture( "HD_reticle.tga" );
  2338. RenderImages[RETICLE]->Set_Hidden( true );
  2339. RenderImages[RETICLE_HIT] = new Render2DClass();
  2340. RenderImages[RETICLE_HIT]->Set_Texture( "HD_reticle_hit.tga" );
  2341. RenderImages[RETICLE_HIT]->Set_Hidden( true );
  2342. // Action Status Bar (arming/disarming explosives, etc)
  2343. RenderImages[ACTION_STATUSBAR_RENDERER] = new Render2DClass();
  2344. RenderImages[ACTION_STATUSBAR_RENDERER]->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  2345. #else
  2346. RectClass rect=Render2DClass::Get_Screen_Resolution();
  2347. RenderImages[DEMO_HUD_IMAGE] = new Render2DClass();
  2348. RenderImages[DEMO_HUD_IMAGE]->Reset();
  2349. RenderImages[DEMO_HUD_IMAGE]->Set_Texture( "renegade_demo.tga" );
  2350. RenderImages[DEMO_HUD_IMAGE]->Set_Hidden( false );
  2351. RenderImages[DEMO_HUD_IMAGE]->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  2352. RenderImages[DEMO_HUD_IMAGE]->Add_Quad( RectClass( float(8),float(-8),float(256+8),float(128-8)), RectClass(0.0f,0.0f,1.0f,0.5f),0xffffffff);
  2353. RenderImages[DEMO_HUD_IMAGE2] = new Render2DClass();
  2354. RenderImages[DEMO_HUD_IMAGE2]->Reset();
  2355. RenderImages[DEMO_HUD_IMAGE2]->Set_Texture( "renegade_demo.tga" );
  2356. RenderImages[DEMO_HUD_IMAGE2]->Set_Hidden( false );
  2357. RenderImages[DEMO_HUD_IMAGE2]->Set_Coordinate_Range( Render2DClass::Get_Screen_Resolution() );
  2358. RenderImages[DEMO_HUD_IMAGE2]->Add_Quad( RectClass( rect.Right+float(-256-8),rect.Bottom+float(-128+8),rect.Right+float(-8),rect.Bottom+float(8)), RectClass(0.0f,0.5f,1.0f,1.0f),0xffffffff);
  2359. #endif
  2360. if (render_available) {
  2361. _HUDEnabled = true;
  2362. SniperHUDClass::Init();
  2363. Powerup_Init();
  2364. Weapon_Init();
  2365. Weapon_Chart_Init();
  2366. Info_Init();
  2367. Damage_Init();
  2368. Target_Init();
  2369. //Score_Init();
  2370. Objective_Init();
  2371. HUD_Help_Text_Init();
  2372. _HUDInited = true;
  2373. }
  2374. }
  2375. /*
  2376. **
  2377. */
  2378. void HUDClass::Shutdown()
  2379. {
  2380. if (_HUDInited) {
  2381. Objective_Shutdown();
  2382. //Score_Shutdown();
  2383. Target_Shutdown();
  2384. Damage_Shutdown();
  2385. Info_Shutdown();
  2386. Weapon_Chart_Shutdown();
  2387. Weapon_Shutdown();
  2388. Powerup_Shutdown();
  2389. HUD_Help_Text_Shutdown();
  2390. SniperHUDClass::Shutdown();
  2391. for( int i = 0; i < NUM_RENDER_IMAGES; i++ ) {
  2392. if ( RenderImages[i] ) {
  2393. delete RenderImages[i];
  2394. RenderImages[i] = NULL;
  2395. }
  2396. }
  2397. _HUDInited = false;
  2398. }
  2399. }
  2400. void HUDClass::Reset( void )
  2401. {
  2402. Powerup_Reset();
  2403. Damage_Reset();
  2404. Weapon_Reset();
  2405. }
  2406. void HUDClass::Render()
  2407. {
  2408. WWPROFILE( "HUD Render" );
  2409. #ifdef ATI_DEMO_HACK
  2410. RenderImages[DEMO_HUD_IMAGE]->Render();
  2411. RenderImages[DEMO_HUD_IMAGE2]->Render();
  2412. #else
  2413. if ( COMBAT_CAMERA && COMBAT_CAMERA->Draw_Sniper() ) {
  2414. SniperHUDClass::Render();
  2415. }
  2416. // Only render if Combat is active, and Menu is not, and we have a star who is not sniping
  2417. if ( Is_HUD_Displayed() ) {
  2418. Powerup_Render();
  2419. Weapon_Render();
  2420. Weapon_Chart_Render();
  2421. Info_Render();
  2422. Damage_Render();
  2423. Target_Render();
  2424. //Score_Render();
  2425. HUD_Help_Text_Render();
  2426. Objective_Render();
  2427. RadarManager::Render();
  2428. for( int i = 0; i < NUM_RENDER_IMAGES; i++ ) {
  2429. if ( RenderImages[i] ) {
  2430. RenderImages[i]->Render();
  2431. }
  2432. }
  2433. }
  2434. #endif
  2435. }
  2436. static bool Is_HUD_Displayed( void )
  2437. {
  2438. return ( _HUDEnabled &&
  2439. COMBAT_STAR &&
  2440. !COMBAT_STAR->Is_Dead() &&
  2441. !COMBAT_STAR->Is_Destroyed() );
  2442. }
  2443. /*
  2444. ** called each time through the main loop
  2445. */
  2446. void HUDClass::Think()
  2447. {
  2448. WWPROFILE( "HUD Think" );
  2449. #ifndef ATI_DEMO_HACK
  2450. if ( COMBAT_CAMERA && COMBAT_CAMERA->Draw_Sniper() ) {
  2451. SniperHUDClass::Update();
  2452. }
  2453. if ( !Is_HUD_Displayed() ) {
  2454. return;
  2455. }
  2456. if ( HUDInfo::Display_Action_Status_Bar() ) {
  2457. RenderImages[ACTION_STATUSBAR_RENDERER]->Set_Hidden( false );
  2458. RenderImages[ACTION_STATUSBAR_RENDERER]->Reset();
  2459. RenderImages[ACTION_STATUSBAR_RENDERER]->Enable_Texturing( false );
  2460. //
  2461. // Plot the rectangle
  2462. //
  2463. const RectClass &screen_rect = Render2DClass::Get_Screen_Resolution();
  2464. RectClass status_bar_rect (0.4F, 0.95F, 0.6F, 0.98F);
  2465. status_bar_rect.Left = int(status_bar_rect.Left * screen_rect.Width());
  2466. status_bar_rect.Right = int(status_bar_rect.Right * screen_rect.Width());
  2467. status_bar_rect.Top = int(status_bar_rect.Top * screen_rect.Height());
  2468. status_bar_rect.Bottom = int(status_bar_rect.Bottom * screen_rect.Height());
  2469. RenderImages[ACTION_STATUSBAR_RENDERER]->Add_Line( status_bar_rect.Upper_Left (), status_bar_rect.Upper_Right (), 1, 0xFFFFFFFF );
  2470. RenderImages[ACTION_STATUSBAR_RENDERER]->Add_Line( status_bar_rect.Upper_Right (), status_bar_rect.Lower_Right (), 1, 0xFFFFFFFF );
  2471. RenderImages[ACTION_STATUSBAR_RENDERER]->Add_Line( status_bar_rect.Lower_Right (), status_bar_rect.Lower_Left (), 1, 0xFFFFFFFF );
  2472. RenderImages[ACTION_STATUSBAR_RENDERER]->Add_Line( status_bar_rect.Lower_Left (), status_bar_rect.Upper_Left (), 1, 0xFFFFFFFF );
  2473. //
  2474. // Deflate the rectangle
  2475. //
  2476. status_bar_rect.Right -= 1.0F;
  2477. status_bar_rect.Bottom -= 1.0F;
  2478. //
  2479. // Plot the status rectangle
  2480. //
  2481. float width = status_bar_rect.Width() * HUDInfo::Get_Action_Status_Value();
  2482. status_bar_rect.Right = status_bar_rect.Left + int(width);
  2483. DWORD color = VRGB_TO_INT32( Vector3( 1.0F, 0.25F, 0 ) );
  2484. RenderImages[ACTION_STATUSBAR_RENDERER]->Add_Quad( status_bar_rect, color );
  2485. } else {
  2486. RenderImages[ACTION_STATUSBAR_RENDERER]->Set_Hidden( true );
  2487. }
  2488. SmartGameObj * star = COMBAT_STAR;
  2489. if ( COMBAT_STAR->Get_Vehicle() ) {
  2490. star = COMBAT_STAR->Get_Vehicle();
  2491. }
  2492. Info_Update();
  2493. Powerup_Update();
  2494. Weapon_Update();
  2495. Weapon_Chart_Update();
  2496. Damage_Update();
  2497. Target_Update();
  2498. //Score_Update();
  2499. Objective_Update();
  2500. // Radar
  2501. Matrix3D tm;
  2502. star->Get_Transform().Get_Inverse( tm );
  2503. if ( star->As_VehicleGameObj() && COMBAT_CAMERA && !COMBAT_CAMERA->Is_2D_Targeting() ) {
  2504. // Make a tm facing target
  2505. Matrix3D gun;
  2506. gun.Obj_Look_At( star->Get_Transform().Get_Translation(), star->Get_Targeting_Pos(), 0 );
  2507. gun.Get_Inverse( tm );
  2508. }
  2509. PhysicalGameObj * obj = NULL;
  2510. if ( HUDInfo::Get_Info_Object() ) {
  2511. obj = HUDInfo::Get_Info_Object()->As_PhysicalGameObj();
  2512. }
  2513. RadarManager::Set_Bracket_Object( obj );
  2514. Vector2 radar_center = InfoBase + RADAR_CENTER_OFFSET;
  2515. RadarManager::Update( tm, radar_center );
  2516. unsigned long reticle_color = HUDGlobalSettingsDef::Get_Instance()->Get_No_Relation_Color().Convert_To_ARGB();
  2517. if ( HUDInfo::Get_Weapon_Target_Object() != NULL ) {
  2518. reticle_color = HUDGlobalSettingsDef::Get_Instance()->Get_Friendly_Color().Convert_To_ARGB();
  2519. PhysicalGameObj * pgo = HUDInfo::Get_Weapon_Target_Object()->As_PhysicalGameObj();
  2520. if ( pgo && pgo->Is_Enemy( star ) ) {
  2521. reticle_color = HUDGlobalSettingsDef::Get_Instance()->Get_Enemy_Color().Convert_To_ARGB();
  2522. }
  2523. }
  2524. WeaponClass * weapon = star->Get_Weapon();
  2525. if ( weapon ) {
  2526. if ( weapon->Is_Reloading() || weapon->Is_Switching() || !weapon->Is_Loaded() ) {
  2527. reticle_color = 0xFFFFFF00; // yellow
  2528. }
  2529. }
  2530. Vector2 reticle_offset = COMBAT_CAMERA->Get_Camera_Target_2D_Offset();
  2531. RenderImages[RETICLE]->Reset();
  2532. RenderImages[RETICLE]->Add_Quad( RectClass( reticle_offset.X - RETICLE_WIDTH/2, reticle_offset.Y - RETICLE_HEIGHT/2, reticle_offset.X + RETICLE_WIDTH/2, reticle_offset.Y + RETICLE_HEIGHT/2 ), reticle_color);
  2533. //RenderImages[RETICLE]->Set_Hidden( false );
  2534. //TSS092401
  2535. if ( CombatManager::Is_Gameplay_Permitted() ) {
  2536. RenderImages[RETICLE]->Set_Hidden( false );
  2537. } else {
  2538. RenderImages[RETICLE]->Set_Hidden( true );
  2539. }
  2540. //TSS092401 if ( weapon ) {
  2541. if ( CombatManager::Is_Gameplay_Permitted() && (weapon != NULL) && CombatManager::Is_Hit_Reticle_Enabled() ) {
  2542. WWPROFILE( "Reticle" );
  2543. Vector3 pos3d = HUDInfo::Get_Weapon_Target_Position();
  2544. Vector3 reticle_hit_offset;
  2545. COMBAT_CAMERA->Project( reticle_hit_offset, pos3d );
  2546. // weapon_hitting = HUDInfo::Get_Weapon_Target_Object() != NULL;
  2547. RenderImages[RETICLE_HIT]->Reset();
  2548. RenderImages[RETICLE_HIT]->Add_Quad( RectClass( reticle_hit_offset.X - RETICLE_WIDTH/2, reticle_hit_offset.Y - RETICLE_HEIGHT/2, reticle_hit_offset.X + RETICLE_WIDTH/2, reticle_hit_offset.Y + RETICLE_HEIGHT/2 ), reticle_color);
  2549. RenderImages[RETICLE_HIT]->Set_Hidden( false );
  2550. } else {
  2551. RenderImages[RETICLE_HIT]->Set_Hidden( true );
  2552. }
  2553. #if 0
  2554. // Display points
  2555. if ( _HUDTimer > 0 ) {
  2556. WWPROFILE( "Points" );
  2557. _HUDTimer -= TimeManager::Get_Frame_Seconds();
  2558. StringClass pointstring;
  2559. int points = _HUDPoints;
  2560. if ( points ) {
  2561. Vector2 position = Render2DClass::Get_Screen_Resolution().Lower_Right();
  2562. position /= 2;
  2563. float scale = WWMath::Clamp( 2 * _HUDTimer / HUD_POINTS_TIME, 0, 1 );
  2564. position.Y *= 0.3f + (scale/2);
  2565. pointstring.Format( "%d", points );
  2566. ((Render2DTextClass *)RenderImages[TEXT_RENDERER])->Set_Location( position );
  2567. Font3DInstanceClass * font = ((Render2DTextClass *)RenderImages[TEXT_RENDERER])->Peek_Font();
  2568. if ( font ) {
  2569. font->Set_Scale( 2 + (scale * 3) );
  2570. position.X -= font->String_Width( pointstring ) / 2;
  2571. position.Y -= font->Char_Height() / 2;
  2572. ((Render2DTextClass *)RenderImages[TEXT_RENDERER])->Set_Location( position );
  2573. ((Render2DTextClass *)RenderImages[TEXT_RENDERER])->Draw_Text( pointstring, COLOR( scale ) );
  2574. font->Set_Scale( 1 );
  2575. }
  2576. }
  2577. }
  2578. #endif
  2579. #endif // ATI_DEMO_HACK
  2580. }
  2581. void HUDClass::Toggle_Hide_Points( void )
  2582. {
  2583. // _HUDHidePoints = !_HUDHidePoints;
  2584. }
  2585. void HUDClass::Display_Points( float points )
  2586. {
  2587. /* if ( !_HUDHidePoints ) {
  2588. _HUDPoints = points;
  2589. _HUDTimer = HUD_POINTS_TIME;
  2590. }*/
  2591. }
  2592. bool HUDClass::Is_Enabled( void )
  2593. {
  2594. return _HUDEnabled;
  2595. }
  2596. void HUDClass::Enable( bool enable )
  2597. {
  2598. _HUDEnabled = enable;
  2599. }
  2600. #define SNIPER_AMMO_UV 3, 139,79,191
  2601. #define SNIPER_AMMO_OFFSET -10,-4
  2602. #define NUKE_UV 193,187,244,246
  2603. #define NUKE_OFFSET 10,-4
  2604. #define ION_UV 101,196,164,246
  2605. #define ION_OFFSET 10,-4
  2606. void HUDClass::Add_Powerup_Weapon( int id, int rounds )
  2607. {
  2608. const WeaponDefinitionClass * def = WeaponManager::Find_Weapon_Definition( id );
  2609. if ( def ) {
  2610. if ( !def->IconTextureName.Is_Empty() ) {
  2611. Powerup_Add( TranslateDBClass::Get_String( def->IconNameID ), rounds,
  2612. def->IconTextureName, def->IconTextureUV, def->IconOffset );
  2613. }
  2614. }
  2615. }
  2616. void HUDClass::Add_Powerup_Ammo( int id, int rounds )
  2617. {
  2618. Add_Powerup_Weapon( id, rounds );
  2619. #if 0
  2620. const WeaponDefinitionClass * wdef = WeaponManager::Find_Weapon_Definition( id );
  2621. if ( wdef ) {
  2622. const AmmoDefinitionClass * def = WeaponManager::Find_Ammo_Definition( wdef->PrimaryAmmoDefID );
  2623. if ( def ) {
  2624. if ( !def->IconTextureName.Is_Empty() ) {
  2625. Powerup_Add( TranslateDBClass::Get_String( def->IconNameID ), rounds,
  2626. def->IconTextureName, def->IconTextureUV, def->IconOffset );
  2627. }
  2628. }
  2629. }
  2630. #endif
  2631. }
  2632. void HUDClass::Add_Shield_Grant( float strength )
  2633. {
  2634. const char * texture_name = "hud_armor3.tga";
  2635. if ( strength > 75 ) {
  2636. texture_name = "hud_armor1.tga";
  2637. } else if ( strength > 30 ) {
  2638. texture_name = "hud_armor2.tga";
  2639. }
  2640. Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_Armor_00), (int)strength, texture_name, RectClass( 0,0,64,64 ), Vector2( 10,40 ) );
  2641. }
  2642. void HUDClass::Add_Health_Grant( float amount )
  2643. {
  2644. const char * texture_name = "hud_health1.tga";
  2645. if ( amount > 75 ) {
  2646. texture_name = "hud_health3.tga";
  2647. } else if ( amount > 30 ) {
  2648. texture_name = "hud_health2.tga";
  2649. }
  2650. Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_Health_00), (int)amount, texture_name, RectClass( 0,0,64,64 ), Vector2( 10,40 ) );
  2651. }
  2652. void HUDClass::Add_Shield_Upgrade_Grant( float strength )
  2653. {
  2654. Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_Armor_Upgrade), (int)strength, "hud_armedal.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false );
  2655. }
  2656. void HUDClass::Add_Health_Upgrade_Grant( float amount )
  2657. {
  2658. Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_Health_Upgrade), (int)amount, "hud_hemedal.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false );
  2659. }
  2660. void HUDClass::Add_Key_Grant( int key )
  2661. {
  2662. const char * texture_name = "hud_keycard_green.tga";
  2663. if ( key == 3 ) {
  2664. texture_name = "hud_keycard_red.tga";
  2665. } else if ( key == 2 ) {
  2666. texture_name = "hud_keycard_yellow.tga";
  2667. }
  2668. Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_SecurityCard), 0, texture_name, RectClass( 0,0,64,64 ), Vector2( 10,40 ), false );
  2669. }
  2670. void HUDClass::Add_Objective( int type )
  2671. {
  2672. if ( type == ObjectiveManager::TYPE_PRIMARY ) {
  2673. Powerup_Add( TranslateDBClass::Get_String(IDS_Enc_Obj_Priority_0_Primary), 0, "p_eva1.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false );
  2674. } else if ( type == ObjectiveManager::TYPE_SECONDARY ) {
  2675. Powerup_Add( TranslateDBClass::Get_String(IDS_Enc_Obj_Priority_0_Secondary), 0, "p_eva2.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false );
  2676. }
  2677. }
  2678. void HUDClass::Add_Data_Link( void )
  2679. {
  2680. int cur = TimeManager::Get_Total_Seconds() * 2.0f;
  2681. static int last = 0;
  2682. // Don't accept too fast;
  2683. if ( cur == last ) {
  2684. return;
  2685. }
  2686. last = cur;
  2687. Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_DataDisc_01), 0, "hud_cd_rom.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false );
  2688. }
  2689. void HUDClass::Add_Map_Reveal( void )
  2690. {
  2691. Add_Data_Link();
  2692. // Powerup_Add( TranslateDBClass::Get_String(IDS_Power_up_DataDisc_01), 0, "hud_cd_rom.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false );
  2693. // Powerup_Add( TranslateDBClass::Get_String(IDS_Enc_Pow_Bonus_Map_Name), 0, "hud_cd_rom.tga", RectClass( 0,0,64,64 ), Vector2( 10,40 ), false );
  2694. }
  2695. /*
  2696. **
  2697. */
  2698. enum {
  2699. CHUNKID_VARIABLES = 1117011622,
  2700. CHUNKID_MARKER_ENTRY,
  2701. MICROCHUNKID_ENABLED = 1,
  2702. };
  2703. /*
  2704. **
  2705. */
  2706. bool HUDClass::Save( ChunkSaveClass &csave )
  2707. {
  2708. csave.Begin_Chunk( CHUNKID_VARIABLES );
  2709. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_ENABLED, _HUDEnabled );
  2710. csave.End_Chunk();
  2711. return true;
  2712. }
  2713. bool HUDClass::Load( ChunkLoadClass &cload )
  2714. {
  2715. while (cload.Open_Chunk()) {
  2716. switch(cload.Cur_Chunk_ID()) {
  2717. case CHUNKID_VARIABLES:
  2718. while (cload.Open_Micro_Chunk()) {
  2719. switch(cload.Cur_Micro_Chunk_ID()) {
  2720. READ_MICRO_CHUNK( cload, MICROCHUNKID_ENABLED, _HUDEnabled );
  2721. default:
  2722. Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
  2723. break;
  2724. }
  2725. cload.Close_Micro_Chunk();
  2726. }
  2727. break;
  2728. default:
  2729. Debug_Say(("Unhandled Chunk:%d File:%s Line:%d\r\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
  2730. break;
  2731. }
  2732. cload.Close_Chunk();
  2733. }
  2734. return true;
  2735. }