PlayerView.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code 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. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "Game_local.h"
  23. // _D3XP : rename all gameLocal.time to gameLocal.slow.time for merge!
  24. #ifdef _D3XP
  25. static int MakePowerOfTwo( int num ) {
  26. int pot;
  27. for (pot = 1 ; pot < num ; pot<<=1) {
  28. }
  29. return pot;
  30. }
  31. #endif
  32. const int IMPULSE_DELAY = 150;
  33. /*
  34. ==============
  35. idPlayerView::idPlayerView
  36. ==============
  37. */
  38. idPlayerView::idPlayerView() {
  39. memset( screenBlobs, 0, sizeof( screenBlobs ) );
  40. memset( &view, 0, sizeof( view ) );
  41. player = NULL;
  42. dvMaterial = declManager->FindMaterial( "_scratch" );
  43. tunnelMaterial = declManager->FindMaterial( "textures/decals/tunnel" );
  44. armorMaterial = declManager->FindMaterial( "armorViewEffect" );
  45. berserkMaterial = declManager->FindMaterial( "textures/decals/berserk" );
  46. irGogglesMaterial = declManager->FindMaterial( "textures/decals/irblend" );
  47. bloodSprayMaterial = declManager->FindMaterial( "textures/decals/bloodspray" );
  48. bfgMaterial = declManager->FindMaterial( "textures/decals/bfgvision" );
  49. lagoMaterial = declManager->FindMaterial( LAGO_MATERIAL, false );
  50. bfgVision = false;
  51. dvFinishTime = 0;
  52. kickFinishTime = 0;
  53. kickAngles.Zero();
  54. lastDamageTime = 0.0f;
  55. fadeTime = 0;
  56. fadeRate = 0.0;
  57. fadeFromColor.Zero();
  58. fadeToColor.Zero();
  59. fadeColor.Zero();
  60. shakeAng.Zero();
  61. #ifdef _D3XP
  62. fxManager = NULL;
  63. if ( !fxManager ) {
  64. fxManager = new FullscreenFXManager;
  65. fxManager->Initialize( this );
  66. }
  67. #endif
  68. ClearEffects();
  69. }
  70. /*
  71. ==============
  72. idPlayerView::Save
  73. ==============
  74. */
  75. void idPlayerView::Save( idSaveGame *savefile ) const {
  76. int i;
  77. const screenBlob_t *blob;
  78. blob = &screenBlobs[ 0 ];
  79. for( i = 0; i < MAX_SCREEN_BLOBS; i++, blob++ ) {
  80. savefile->WriteMaterial( blob->material );
  81. savefile->WriteFloat( blob->x );
  82. savefile->WriteFloat( blob->y );
  83. savefile->WriteFloat( blob->w );
  84. savefile->WriteFloat( blob->h );
  85. savefile->WriteFloat( blob->s1 );
  86. savefile->WriteFloat( blob->t1 );
  87. savefile->WriteFloat( blob->s2 );
  88. savefile->WriteFloat( blob->t2 );
  89. savefile->WriteInt( blob->finishTime );
  90. savefile->WriteInt( blob->startFadeTime );
  91. savefile->WriteFloat( blob->driftAmount );
  92. }
  93. savefile->WriteInt( dvFinishTime );
  94. savefile->WriteMaterial( dvMaterial );
  95. savefile->WriteInt( kickFinishTime );
  96. savefile->WriteAngles( kickAngles );
  97. savefile->WriteBool( bfgVision );
  98. savefile->WriteMaterial( tunnelMaterial );
  99. savefile->WriteMaterial( armorMaterial );
  100. savefile->WriteMaterial( berserkMaterial );
  101. savefile->WriteMaterial( irGogglesMaterial );
  102. savefile->WriteMaterial( bloodSprayMaterial );
  103. savefile->WriteMaterial( bfgMaterial );
  104. savefile->WriteFloat( lastDamageTime );
  105. savefile->WriteVec4( fadeColor );
  106. savefile->WriteVec4( fadeToColor );
  107. savefile->WriteVec4( fadeFromColor );
  108. savefile->WriteFloat( fadeRate );
  109. savefile->WriteInt( fadeTime );
  110. savefile->WriteAngles( shakeAng );
  111. savefile->WriteObject( player );
  112. savefile->WriteRenderView( view );
  113. #ifdef _D3XP
  114. if ( fxManager ) {
  115. fxManager->Save( savefile );
  116. }
  117. #endif
  118. }
  119. /*
  120. ==============
  121. idPlayerView::Restore
  122. ==============
  123. */
  124. void idPlayerView::Restore( idRestoreGame *savefile ) {
  125. int i;
  126. screenBlob_t *blob;
  127. blob = &screenBlobs[ 0 ];
  128. for( i = 0; i < MAX_SCREEN_BLOBS; i++, blob++ ) {
  129. savefile->ReadMaterial( blob->material );
  130. savefile->ReadFloat( blob->x );
  131. savefile->ReadFloat( blob->y );
  132. savefile->ReadFloat( blob->w );
  133. savefile->ReadFloat( blob->h );
  134. savefile->ReadFloat( blob->s1 );
  135. savefile->ReadFloat( blob->t1 );
  136. savefile->ReadFloat( blob->s2 );
  137. savefile->ReadFloat( blob->t2 );
  138. savefile->ReadInt( blob->finishTime );
  139. savefile->ReadInt( blob->startFadeTime );
  140. savefile->ReadFloat( blob->driftAmount );
  141. }
  142. savefile->ReadInt( dvFinishTime );
  143. savefile->ReadMaterial( dvMaterial );
  144. savefile->ReadInt( kickFinishTime );
  145. savefile->ReadAngles( kickAngles );
  146. savefile->ReadBool( bfgVision );
  147. savefile->ReadMaterial( tunnelMaterial );
  148. savefile->ReadMaterial( armorMaterial );
  149. savefile->ReadMaterial( berserkMaterial );
  150. savefile->ReadMaterial( irGogglesMaterial );
  151. savefile->ReadMaterial( bloodSprayMaterial );
  152. savefile->ReadMaterial( bfgMaterial );
  153. savefile->ReadFloat( lastDamageTime );
  154. savefile->ReadVec4( fadeColor );
  155. savefile->ReadVec4( fadeToColor );
  156. savefile->ReadVec4( fadeFromColor );
  157. savefile->ReadFloat( fadeRate );
  158. savefile->ReadInt( fadeTime );
  159. savefile->ReadAngles( shakeAng );
  160. savefile->ReadObject( reinterpret_cast<idClass *&>( player ) );
  161. savefile->ReadRenderView( view );
  162. #ifdef _D3XP
  163. if ( fxManager ) {
  164. fxManager->Restore( savefile );
  165. }
  166. #endif
  167. }
  168. /*
  169. ==============
  170. idPlayerView::SetPlayerEntity
  171. ==============
  172. */
  173. void idPlayerView::SetPlayerEntity( idPlayer *playerEnt ) {
  174. player = playerEnt;
  175. }
  176. /*
  177. ==============
  178. idPlayerView::ClearEffects
  179. ==============
  180. */
  181. void idPlayerView::ClearEffects() {
  182. lastDamageTime = MS2SEC( gameLocal.slow.time - 99999 );
  183. dvFinishTime = ( gameLocal.fast.time - 99999 );
  184. kickFinishTime = ( gameLocal.slow.time - 99999 );
  185. for ( int i = 0 ; i < MAX_SCREEN_BLOBS ; i++ ) {
  186. screenBlobs[i].finishTime = gameLocal.slow.time;
  187. }
  188. fadeTime = 0;
  189. bfgVision = false;
  190. }
  191. /*
  192. ==============
  193. idPlayerView::GetScreenBlob
  194. ==============
  195. */
  196. screenBlob_t *idPlayerView::GetScreenBlob() {
  197. screenBlob_t *oldest = &screenBlobs[0];
  198. for ( int i = 1 ; i < MAX_SCREEN_BLOBS ; i++ ) {
  199. if ( screenBlobs[i].finishTime < oldest->finishTime ) {
  200. oldest = &screenBlobs[i];
  201. }
  202. }
  203. return oldest;
  204. }
  205. /*
  206. ==============
  207. idPlayerView::DamageImpulse
  208. LocalKickDir is the direction of force in the player's coordinate system,
  209. which will determine the head kick direction
  210. ==============
  211. */
  212. void idPlayerView::DamageImpulse( idVec3 localKickDir, const idDict *damageDef ) {
  213. //
  214. // double vision effect
  215. //
  216. if ( lastDamageTime > 0.0f && SEC2MS( lastDamageTime ) + IMPULSE_DELAY > gameLocal.slow.time ) {
  217. // keep shotgun from obliterating the view
  218. return;
  219. }
  220. float dvTime = damageDef->GetFloat( "dv_time" );
  221. if ( dvTime ) {
  222. if ( dvFinishTime < gameLocal.fast.time ) {
  223. dvFinishTime = gameLocal.fast.time;
  224. }
  225. dvFinishTime += g_dvTime.GetFloat() * dvTime;
  226. // don't let it add up too much in god mode
  227. if ( dvFinishTime > gameLocal.fast.time + 5000 ) {
  228. dvFinishTime = gameLocal.fast.time + 5000;
  229. }
  230. }
  231. //
  232. // head angle kick
  233. //
  234. float kickTime = damageDef->GetFloat( "kick_time" );
  235. if ( kickTime ) {
  236. kickFinishTime = gameLocal.slow.time + g_kickTime.GetFloat() * kickTime;
  237. // forward / back kick will pitch view
  238. kickAngles[0] = localKickDir[0];
  239. // side kick will yaw view
  240. kickAngles[1] = localKickDir[1]*0.5f;
  241. // up / down kick will pitch view
  242. kickAngles[0] += localKickDir[2];
  243. // roll will come from side
  244. kickAngles[2] = localKickDir[1];
  245. float kickAmplitude = damageDef->GetFloat( "kick_amplitude" );
  246. if ( kickAmplitude ) {
  247. kickAngles *= kickAmplitude;
  248. }
  249. }
  250. //
  251. // screen blob
  252. //
  253. float blobTime = damageDef->GetFloat( "blob_time" );
  254. if ( blobTime ) {
  255. screenBlob_t *blob = GetScreenBlob();
  256. blob->startFadeTime = gameLocal.slow.time;
  257. blob->finishTime = gameLocal.slow.time + blobTime * g_blobTime.GetFloat() * ((float)gameLocal.msec / USERCMD_MSEC);
  258. const char *materialName = damageDef->GetString( "mtr_blob" );
  259. blob->material = declManager->FindMaterial( materialName );
  260. blob->x = damageDef->GetFloat( "blob_x" );
  261. blob->x += ( gameLocal.random.RandomInt()&63 ) - 32;
  262. blob->y = damageDef->GetFloat( "blob_y" );
  263. blob->y += ( gameLocal.random.RandomInt()&63 ) - 32;
  264. float scale = ( 256 + ( ( gameLocal.random.RandomInt()&63 ) - 32 ) ) / 256.0f;
  265. blob->w = damageDef->GetFloat( "blob_width" ) * g_blobSize.GetFloat() * scale;
  266. blob->h = damageDef->GetFloat( "blob_height" ) * g_blobSize.GetFloat() * scale;
  267. blob->s1 = 0;
  268. blob->t1 = 0;
  269. blob->s2 = 1;
  270. blob->t2 = 1;
  271. }
  272. //
  273. // save lastDamageTime for tunnel vision accentuation
  274. //
  275. lastDamageTime = MS2SEC( gameLocal.slow.time );
  276. }
  277. /*
  278. ==================
  279. idPlayerView::AddBloodSpray
  280. If we need a more generic way to add blobs then we can do that
  281. but having it localized here lets the material be pre-looked up etc.
  282. ==================
  283. */
  284. void idPlayerView::AddBloodSpray( float duration ) {
  285. /*
  286. if ( duration <= 0 || bloodSprayMaterial == NULL || g_skipViewEffects.GetBool() ) {
  287. return;
  288. }
  289. // visit this for chainsaw
  290. screenBlob_t *blob = GetScreenBlob();
  291. blob->startFadeTime = gameLocal.slow.time;
  292. blob->finishTime = gameLocal.slow.time + ( duration * 1000 );
  293. blob->material = bloodSprayMaterial;
  294. blob->x = ( gameLocal.random.RandomInt() & 63 ) - 32;
  295. blob->y = ( gameLocal.random.RandomInt() & 63 ) - 32;
  296. blob->driftAmount = 0.5f + gameLocal.random.CRandomFloat() * 0.5;
  297. float scale = ( 256 + ( ( gameLocal.random.RandomInt()&63 ) - 32 ) ) / 256.0f;
  298. blob->w = 600 * g_blobSize.GetFloat() * scale;
  299. blob->h = 480 * g_blobSize.GetFloat() * scale;
  300. float s1 = 0.0f;
  301. float t1 = 0.0f;
  302. float s2 = 1.0f;
  303. float t2 = 1.0f;
  304. if ( blob->driftAmount < 0.6 ) {
  305. s1 = 1.0f;
  306. s2 = 0.0f;
  307. } else if ( blob->driftAmount < 0.75 ) {
  308. t1 = 1.0f;
  309. t2 = 0.0f;
  310. } else if ( blob->driftAmount < 0.85 ) {
  311. s1 = 1.0f;
  312. s2 = 0.0f;
  313. t1 = 1.0f;
  314. t2 = 0.0f;
  315. }
  316. blob->s1 = s1;
  317. blob->t1 = t1;
  318. blob->s2 = s2;
  319. blob->t2 = t2;
  320. */
  321. }
  322. /*
  323. ==================
  324. idPlayerView::WeaponFireFeedback
  325. Called when a weapon fires, generates head twitches, etc
  326. ==================
  327. */
  328. void idPlayerView::WeaponFireFeedback( const idDict *weaponDef ) {
  329. int recoilTime;
  330. recoilTime = weaponDef->GetInt( "recoilTime" );
  331. // don't shorten a damage kick in progress
  332. if ( recoilTime && kickFinishTime < gameLocal.slow.time ) {
  333. idAngles angles;
  334. weaponDef->GetAngles( "recoilAngles", "5 0 0", angles );
  335. kickAngles = angles;
  336. int finish = gameLocal.slow.time + g_kickTime.GetFloat() * recoilTime;
  337. kickFinishTime = finish;
  338. }
  339. }
  340. /*
  341. ===================
  342. idPlayerView::CalculateShake
  343. ===================
  344. */
  345. void idPlayerView::CalculateShake() {
  346. idVec3 origin, matrix;
  347. float shakeVolume = gameSoundWorld->CurrentShakeAmplitudeForPosition( gameLocal.slow.time, player->firstPersonViewOrigin );
  348. //
  349. // shakeVolume should somehow be molded into an angle here
  350. // it should be thought of as being in the range 0.0 -> 1.0, although
  351. // since CurrentShakeAmplitudeForPosition() returns all the shake sounds
  352. // the player can hear, it can go over 1.0 too.
  353. //
  354. shakeAng[0] = gameLocal.random.CRandomFloat() * shakeVolume;
  355. shakeAng[1] = gameLocal.random.CRandomFloat() * shakeVolume;
  356. shakeAng[2] = gameLocal.random.CRandomFloat() * shakeVolume;
  357. }
  358. /*
  359. ===================
  360. idPlayerView::ShakeAxis
  361. ===================
  362. */
  363. idMat3 idPlayerView::ShakeAxis() const {
  364. return shakeAng.ToMat3();
  365. }
  366. /*
  367. ===================
  368. idPlayerView::AngleOffset
  369. kickVector, a world space direction that the attack should
  370. ===================
  371. */
  372. idAngles idPlayerView::AngleOffset() const {
  373. idAngles ang;
  374. ang.Zero();
  375. if ( gameLocal.slow.time < kickFinishTime ) {
  376. float offset = kickFinishTime - gameLocal.slow.time;
  377. ang = kickAngles * offset * offset * g_kickAmplitude.GetFloat();
  378. for ( int i = 0 ; i < 3 ; i++ ) {
  379. if ( ang[i] > 70.0f ) {
  380. ang[i] = 70.0f;
  381. } else if ( ang[i] < -70.0f ) {
  382. ang[i] = -70.0f;
  383. }
  384. }
  385. }
  386. return ang;
  387. }
  388. /*
  389. ==================
  390. idPlayerView::SingleView
  391. ==================
  392. */
  393. void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view ) {
  394. // normal rendering
  395. if ( !view ) {
  396. return;
  397. }
  398. // place the sound origin for the player
  399. gameSoundWorld->PlaceListener( view->vieworg, view->viewaxis, player->entityNumber + 1, gameLocal.slow.time, hud ? hud->State().GetString( "location" ) : "Undefined" );
  400. // if the objective system is up, don't do normal drawing
  401. if ( player->objectiveSystemOpen ) {
  402. player->objectiveSystem->Redraw( gameLocal.fast.time );
  403. return;
  404. }
  405. // hack the shake in at the very last moment, so it can't cause any consistency problems
  406. renderView_t hackedView = *view;
  407. hackedView.viewaxis = hackedView.viewaxis * ShakeAxis();
  408. #ifdef _D3XP
  409. if ( gameLocal.portalSkyEnt.GetEntity() && gameLocal.IsPortalSkyAcive() && g_enablePortalSky.GetBool() ) {
  410. renderView_t portalView = hackedView;
  411. portalView.vieworg = gameLocal.portalSkyEnt.GetEntity()->GetPhysics()->GetOrigin();
  412. // setup global fixup projection vars
  413. if ( 1 ) {
  414. int vidWidth, vidHeight;
  415. idVec2 shiftScale;
  416. renderSystem->GetGLSettings( vidWidth, vidHeight );
  417. float pot;
  418. int w = vidWidth;
  419. pot = MakePowerOfTwo( w );
  420. shiftScale.x = (float)w / pot;
  421. int h = vidHeight;
  422. pot = MakePowerOfTwo( h );
  423. shiftScale.y = (float)h / pot;
  424. hackedView.shaderParms[4] = shiftScale.x;
  425. hackedView.shaderParms[5] = shiftScale.y;
  426. }
  427. gameRenderWorld->RenderScene( &portalView );
  428. renderSystem->CaptureRenderToImage( "_currentRender" );
  429. hackedView.forceUpdate = true; // FIX: for smoke particles not drawing when portalSky present
  430. }
  431. // process the frame
  432. fxManager->Process( &hackedView );
  433. #endif
  434. if ( player->spectating ) {
  435. return;
  436. }
  437. #ifdef _D3XP
  438. if ( !hud ) {
  439. return;
  440. }
  441. #endif
  442. // draw screen blobs
  443. if ( !pm_thirdPerson.GetBool() && !g_skipViewEffects.GetBool() ) {
  444. for ( int i = 0 ; i < MAX_SCREEN_BLOBS ; i++ ) {
  445. screenBlob_t *blob = &screenBlobs[i];
  446. if ( blob->finishTime <= gameLocal.slow.time ) {
  447. continue;
  448. }
  449. blob->y += blob->driftAmount;
  450. float fade = (float)( blob->finishTime - gameLocal.slow.time ) / ( blob->finishTime - blob->startFadeTime );
  451. if ( fade > 1.0f ) {
  452. fade = 1.0f;
  453. }
  454. if ( fade ) {
  455. renderSystem->SetColor4( 1,1,1,fade );
  456. renderSystem->DrawStretchPic( blob->x, blob->y, blob->w, blob->h,blob->s1, blob->t1, blob->s2, blob->t2, blob->material );
  457. }
  458. }
  459. player->DrawHUD( hud );
  460. // armor impulse feedback
  461. float armorPulse = ( gameLocal.fast.time - player->lastArmorPulse ) / 250.0f;
  462. if ( armorPulse > 0.0f && armorPulse < 1.0f ) {
  463. renderSystem->SetColor4( 1, 1, 1, 1.0 - armorPulse );
  464. renderSystem->DrawStretchPic( 0, 0, 640, 480, 0, 0, 1, 1, armorMaterial );
  465. }
  466. // tunnel vision
  467. float health = 0.0f;
  468. if ( g_testHealthVision.GetFloat() != 0.0f ) {
  469. health = g_testHealthVision.GetFloat();
  470. } else {
  471. health = player->health;
  472. }
  473. float alpha = health / 100.0f;
  474. if ( alpha < 0.0f ) {
  475. alpha = 0.0f;
  476. }
  477. if ( alpha > 1.0f ) {
  478. alpha = 1.0f;
  479. }
  480. if ( alpha < 1.0f ) {
  481. renderSystem->SetColor4( ( player->health <= 0.0f ) ? MS2SEC( gameLocal.slow.time ) : lastDamageTime, 1.0f, 1.0f, ( player->health <= 0.0f ) ? 0.0f : alpha );
  482. renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, tunnelMaterial );
  483. }
  484. if ( bfgVision ) {
  485. renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f );
  486. renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, bfgMaterial );
  487. }
  488. }
  489. // test a single material drawn over everything
  490. if ( g_testPostProcess.GetString()[0] ) {
  491. const idMaterial *mtr = declManager->FindMaterial( g_testPostProcess.GetString(), false );
  492. if ( !mtr ) {
  493. common->Printf( "Material not found.\n" );
  494. g_testPostProcess.SetString( "" );
  495. } else {
  496. renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f );
  497. renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, mtr );
  498. }
  499. }
  500. }
  501. /*
  502. =================
  503. idPlayerView::Flash
  504. flashes the player view with the given color
  505. =================
  506. */
  507. void idPlayerView::Flash(idVec4 color, int time ) {
  508. Fade(idVec4(0, 0, 0, 0), time);
  509. fadeFromColor = colorWhite;
  510. }
  511. /*
  512. =================
  513. idPlayerView::Fade
  514. used for level transition fades
  515. assumes: color.w is 0 or 1
  516. =================
  517. */
  518. void idPlayerView::Fade( idVec4 color, int time ) {
  519. #ifdef _D3XP
  520. SetTimeState ts( player->timeGroup );
  521. #endif
  522. if ( !fadeTime ) {
  523. fadeFromColor.Set( 0.0f, 0.0f, 0.0f, 1.0f - color[ 3 ] );
  524. } else {
  525. fadeFromColor = fadeColor;
  526. }
  527. fadeToColor = color;
  528. if ( time <= 0 ) {
  529. fadeRate = 0;
  530. time = 0;
  531. fadeColor = fadeToColor;
  532. } else {
  533. fadeRate = 1.0f / ( float )time;
  534. }
  535. if ( gameLocal.realClientTime == 0 && time == 0 ) {
  536. fadeTime = 1;
  537. } else {
  538. fadeTime = gameLocal.realClientTime + time;
  539. }
  540. }
  541. /*
  542. =================
  543. idPlayerView::ScreenFade
  544. =================
  545. */
  546. void idPlayerView::ScreenFade() {
  547. int msec;
  548. float t;
  549. if ( !fadeTime ) {
  550. return;
  551. }
  552. #ifdef _D3XP
  553. SetTimeState ts( player->timeGroup );
  554. #endif
  555. msec = fadeTime - gameLocal.realClientTime;
  556. if ( msec <= 0 ) {
  557. fadeColor = fadeToColor;
  558. if ( fadeColor[ 3 ] == 0.0f ) {
  559. fadeTime = 0;
  560. }
  561. } else {
  562. t = ( float )msec * fadeRate;
  563. fadeColor = fadeFromColor * t + fadeToColor * ( 1.0f - t );
  564. }
  565. if ( fadeColor[ 3 ] != 0.0f ) {
  566. renderSystem->SetColor4( fadeColor[ 0 ], fadeColor[ 1 ], fadeColor[ 2 ], fadeColor[ 3 ] );
  567. renderSystem->DrawStretchPic( 0, 0, 640, 480, 0, 0, 1, 1, declManager->FindMaterial( "_white" ) );
  568. }
  569. }
  570. /*
  571. ===================
  572. idPlayerView::RenderPlayerView
  573. ===================
  574. */
  575. void idPlayerView::RenderPlayerView( idUserInterface *hud ) {
  576. const renderView_t *view = player->GetRenderView();
  577. SingleView( hud, view );
  578. ScreenFade();
  579. if ( net_clientLagOMeter.GetBool() && lagoMaterial && gameLocal.isClient ) {
  580. renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f );
  581. renderSystem->DrawStretchPic( 10.0f, 380.0f, 64.0f, 64.0f, 0.0f, 0.0f, 1.0f, 1.0f, lagoMaterial );
  582. }
  583. }
  584. #ifdef _D3XP
  585. /*
  586. ===================
  587. idPlayerView::WarpVision
  588. ===================
  589. */
  590. int idPlayerView::AddWarp( idVec3 worldOrigin, float centerx, float centery, float initialRadius, float durationMsec ) {
  591. FullscreenFX_Warp *fx = (FullscreenFX_Warp*)( fxManager->FindFX( "warp" ) );
  592. if ( fx ) {
  593. fx->EnableGrabber( true );
  594. return 1;
  595. }
  596. return 1;
  597. }
  598. void idPlayerView::FreeWarp( int id ) {
  599. FullscreenFX_Warp *fx = (FullscreenFX_Warp*)( fxManager->FindFX( "warp" ) );
  600. if ( fx ) {
  601. fx->EnableGrabber( false );
  602. return;
  603. }
  604. }
  605. /*
  606. ==================
  607. FxFader::FxFader
  608. ==================
  609. */
  610. FxFader::FxFader() {
  611. time = 0;
  612. state = FX_STATE_OFF;
  613. alpha = 0;
  614. msec = 1000;
  615. }
  616. /*
  617. ==================
  618. FxFader::SetTriggerState
  619. ==================
  620. */
  621. bool FxFader::SetTriggerState( bool active ) {
  622. // handle on/off states
  623. if ( active && state == FX_STATE_OFF ) {
  624. state = FX_STATE_RAMPUP;
  625. time = gameLocal.slow.time + msec;
  626. }
  627. else if ( !active && state == FX_STATE_ON ) {
  628. state = FX_STATE_RAMPDOWN;
  629. time = gameLocal.slow.time + msec;
  630. }
  631. // handle rampup/rampdown states
  632. if ( state == FX_STATE_RAMPUP ) {
  633. if ( gameLocal.slow.time >= time ) {
  634. state = FX_STATE_ON;
  635. }
  636. }
  637. else if ( state == FX_STATE_RAMPDOWN ) {
  638. if ( gameLocal.slow.time >= time ) {
  639. state = FX_STATE_OFF;
  640. }
  641. }
  642. // compute alpha
  643. switch ( state ) {
  644. case FX_STATE_ON: alpha = 1; break;
  645. case FX_STATE_OFF: alpha = 0; break;
  646. case FX_STATE_RAMPUP: alpha = 1 - (float)( time - gameLocal.slow.time ) / msec; break;
  647. case FX_STATE_RAMPDOWN: alpha = (float)( time - gameLocal.slow.time ) / msec; break;
  648. }
  649. if ( alpha > 0 ) {
  650. return true;
  651. }
  652. else {
  653. return false;
  654. }
  655. }
  656. /*
  657. ==================
  658. FxFader::Save
  659. ==================
  660. */
  661. void FxFader::Save( idSaveGame *savefile ) {
  662. savefile->WriteInt( time );
  663. savefile->WriteInt( state );
  664. savefile->WriteFloat( alpha );
  665. savefile->WriteInt( msec );
  666. }
  667. /*
  668. ==================
  669. FxFader::Restore
  670. ==================
  671. */
  672. void FxFader::Restore( idRestoreGame *savefile ) {
  673. savefile->ReadInt( time );
  674. savefile->ReadInt( state );
  675. savefile->ReadFloat( alpha );
  676. savefile->ReadInt( msec );
  677. }
  678. /*
  679. ==================
  680. FullscreenFX_Helltime::Save
  681. ==================
  682. */
  683. void FullscreenFX::Save( idSaveGame *savefile ) {
  684. fader.Save( savefile );
  685. }
  686. /*
  687. ==================
  688. FullscreenFX_Helltime::Restore
  689. ==================
  690. */
  691. void FullscreenFX::Restore( idRestoreGame *savefile ) {
  692. fader.Restore( savefile );
  693. }
  694. /*
  695. ==================
  696. FullscreenFX_Helltime::Initialize
  697. ==================
  698. */
  699. void FullscreenFX_Helltime::Initialize() {
  700. acInitMaterials[0] = declManager->FindMaterial( "textures/smf/bloodorb1/ac_init" );
  701. acInitMaterials[1] = declManager->FindMaterial( "textures/smf/bloodorb2/ac_init" );
  702. acInitMaterials[2] = declManager->FindMaterial( "textures/smf/bloodorb3/ac_init" );
  703. acCaptureMaterials[0] = declManager->FindMaterial( "textures/smf/bloodorb1/ac_capture" );
  704. acCaptureMaterials[1] = declManager->FindMaterial( "textures/smf/bloodorb2/ac_capture" );
  705. acCaptureMaterials[2] = declManager->FindMaterial( "textures/smf/bloodorb3/ac_capture" );
  706. acDrawMaterials[0] = declManager->FindMaterial( "textures/smf/bloodorb1/ac_draw" );
  707. acDrawMaterials[1] = declManager->FindMaterial( "textures/smf/bloodorb2/ac_draw" );
  708. acDrawMaterials[2] = declManager->FindMaterial( "textures/smf/bloodorb3/ac_draw" );
  709. crCaptureMaterials[0] = declManager->FindMaterial( "textures/smf/bloodorb1/cr_capture" );
  710. crCaptureMaterials[1] = declManager->FindMaterial( "textures/smf/bloodorb2/cr_capture" );
  711. crCaptureMaterials[2] = declManager->FindMaterial( "textures/smf/bloodorb3/cr_capture" );
  712. crDrawMaterials[0] = declManager->FindMaterial( "textures/smf/bloodorb1/cr_draw" );
  713. crDrawMaterials[1] = declManager->FindMaterial( "textures/smf/bloodorb2/cr_draw" );
  714. crDrawMaterials[2] = declManager->FindMaterial( "textures/smf/bloodorb3/cr_draw" );
  715. clearAccumBuffer = true;
  716. }
  717. /*
  718. ==================
  719. FullscreenFX_Helltime::DetermineLevel
  720. ==================
  721. */
  722. int FullscreenFX_Helltime::DetermineLevel() {
  723. idPlayer *player;
  724. int testfx = g_testHelltimeFX.GetInteger();
  725. // for testing purposes
  726. if ( testfx >= 0 && testfx < 3 ) {
  727. return testfx;
  728. }
  729. player = fxman->GetPlayer();
  730. if ( player->PowerUpActive( INVULNERABILITY ) ) {
  731. return 2;
  732. }
  733. else if ( player->PowerUpActive( BERSERK ) ) {
  734. return 1;
  735. }
  736. else if ( player->PowerUpActive( HELLTIME ) ) {
  737. return 0;
  738. }
  739. return -1;
  740. }
  741. /*
  742. ==================
  743. FullscreenFX_Helltime::Active
  744. ==================
  745. */
  746. bool FullscreenFX_Helltime::Active() {
  747. if ( gameLocal.inCinematic || gameLocal.isMultiplayer ) {
  748. return false;
  749. }
  750. if ( DetermineLevel() >= 0 ) {
  751. return true;
  752. }
  753. else {
  754. // latch the clear flag
  755. if ( fader.GetAlpha() == 0 ) {
  756. clearAccumBuffer = true;
  757. }
  758. }
  759. return false;
  760. }
  761. /*
  762. ==================
  763. FullscreenFX_Helltime::AccumPass
  764. ==================
  765. */
  766. void FullscreenFX_Helltime::AccumPass( const renderView_t *view ) {
  767. idVec2 shiftScale;
  768. int level = DetermineLevel();
  769. // for testing
  770. if ( level < 0 || level > 2 ) {
  771. level = 0;
  772. }
  773. shiftScale = fxman->GetShiftScale();
  774. renderSystem->SetColor4( 1, 1, 1, 1 );
  775. // capture pass
  776. if ( clearAccumBuffer ) {
  777. clearAccumBuffer = false;
  778. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acInitMaterials[level] );
  779. }
  780. else {
  781. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acCaptureMaterials[level] );
  782. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, shiftScale.y, shiftScale.x, 0, crCaptureMaterials[level] );
  783. }
  784. renderSystem->CaptureRenderToImage( "_accum" );
  785. }
  786. /*
  787. ==================
  788. FullscreenFX_Helltime::HighQuality
  789. ==================
  790. */
  791. void FullscreenFX_Helltime::HighQuality() {
  792. idVec2 shiftScale;
  793. int level = DetermineLevel();
  794. // for testing
  795. if ( level < 0 || level > 2 ) {
  796. level = 0;
  797. }
  798. shiftScale = fxman->GetShiftScale();
  799. renderSystem->SetColor4( 1, 1, 1, 1 );
  800. // draw pass
  801. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acDrawMaterials[level] );
  802. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, shiftScale.y, shiftScale.x, 0, crDrawMaterials[level] );
  803. }
  804. /*
  805. ==================
  806. FullscreenFX_Helltime::Restore
  807. ==================
  808. */
  809. void FullscreenFX_Helltime::Restore( idRestoreGame *savefile ) {
  810. FullscreenFX::Restore( savefile );
  811. // latch the clear flag
  812. clearAccumBuffer = true;
  813. }
  814. /*
  815. ==================
  816. FullscreenFX_Multiplayer::Initialize
  817. ==================
  818. */
  819. void FullscreenFX_Multiplayer::Initialize() {
  820. acInitMaterials = declManager->FindMaterial( "textures/smf/multiplayer1/ac_init" );
  821. acCaptureMaterials = declManager->FindMaterial( "textures/smf/multiplayer1/ac_capture" );
  822. acDrawMaterials = declManager->FindMaterial( "textures/smf/multiplayer1/ac_draw" );
  823. crCaptureMaterials = declManager->FindMaterial( "textures/smf/multiplayer1/cr_capture" );
  824. crDrawMaterials = declManager->FindMaterial( "textures/smf/multiplayer1/cr_draw" );
  825. clearAccumBuffer = true;
  826. }
  827. /*
  828. ==================
  829. FullscreenFX_Multiplayer::DetermineLevel
  830. ==================
  831. */
  832. int FullscreenFX_Multiplayer::DetermineLevel() {
  833. idPlayer *player;
  834. int testfx = g_testMultiplayerFX.GetInteger();
  835. // for testing purposes
  836. if ( testfx >= 0 && testfx < 3 ) {
  837. return testfx;
  838. }
  839. player = fxman->GetPlayer();
  840. if ( player->PowerUpActive( INVULNERABILITY ) ) {
  841. return 2;
  842. }
  843. //else if ( player->PowerUpActive( HASTE ) ) {
  844. // return 1;
  845. //}
  846. else if ( player->PowerUpActive( BERSERK ) ) {
  847. return 0;
  848. }
  849. return -1;
  850. }
  851. /*
  852. ==================
  853. FullscreenFX_Multiplayer::Active
  854. ==================
  855. */
  856. bool FullscreenFX_Multiplayer::Active() {
  857. if ( !gameLocal.isMultiplayer && g_testMultiplayerFX.GetInteger() == -1 ) {
  858. return false;
  859. }
  860. if ( DetermineLevel() >= 0 ) {
  861. return true;
  862. }
  863. else {
  864. // latch the clear flag
  865. if ( fader.GetAlpha() == 0 ) {
  866. clearAccumBuffer = true;
  867. }
  868. }
  869. return false;
  870. }
  871. /*
  872. ==================
  873. FullscreenFX_Multiplayer::AccumPass
  874. ==================
  875. */
  876. void FullscreenFX_Multiplayer::AccumPass( const renderView_t *view ) {
  877. idVec2 shiftScale;
  878. int level = DetermineLevel();
  879. // for testing
  880. if ( level < 0 || level > 2 ) {
  881. level = 0;
  882. }
  883. shiftScale = fxman->GetShiftScale();
  884. renderSystem->SetColor4( 1, 1, 1, 1 );
  885. // capture pass
  886. if ( clearAccumBuffer ) {
  887. clearAccumBuffer = false;
  888. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acInitMaterials );
  889. }
  890. else {
  891. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acCaptureMaterials );
  892. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, shiftScale.y, shiftScale.x, 0, crCaptureMaterials );
  893. }
  894. renderSystem->CaptureRenderToImage( "_accum" );
  895. }
  896. /*
  897. ==================
  898. FullscreenFX_Multiplayer::HighQuality
  899. ==================
  900. */
  901. void FullscreenFX_Multiplayer::HighQuality() {
  902. idVec2 shiftScale;
  903. int level = DetermineLevel();
  904. // for testing
  905. if ( level < 0 || level > 2 ) {
  906. level = 0;
  907. }
  908. shiftScale = fxman->GetShiftScale();
  909. renderSystem->SetColor4( 1, 1, 1, 1 );
  910. // draw pass
  911. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, acDrawMaterials );
  912. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, shiftScale.y, shiftScale.x, 0, crDrawMaterials );
  913. }
  914. /*
  915. ==================
  916. FullscreenFX_Multiplayer::Restore
  917. ==================
  918. */
  919. void FullscreenFX_Multiplayer::Restore( idRestoreGame *savefile ) {
  920. FullscreenFX::Restore( savefile );
  921. // latch the clear flag
  922. clearAccumBuffer = true;
  923. }
  924. /*
  925. ==================
  926. FullscreenFX_Warp::Initialize
  927. ==================
  928. */
  929. void FullscreenFX_Warp::Initialize() {
  930. material = declManager->FindMaterial( "textures/smf/warp" );
  931. grabberEnabled = false;
  932. startWarpTime = 0;
  933. }
  934. /*
  935. ==================
  936. FullscreenFX_Warp::Active
  937. ==================
  938. */
  939. bool FullscreenFX_Warp::Active() {
  940. if ( grabberEnabled ) {
  941. return true;
  942. }
  943. return false;
  944. }
  945. /*
  946. ==================
  947. FullscreenFX_Warp::Save
  948. ==================
  949. */
  950. void FullscreenFX_Warp::Save( idSaveGame *savefile ) {
  951. FullscreenFX::Save( savefile );
  952. savefile->WriteBool( grabberEnabled );
  953. savefile->WriteInt( startWarpTime );
  954. }
  955. /*
  956. ==================
  957. FullscreenFX_Warp::Restore
  958. ==================
  959. */
  960. void FullscreenFX_Warp::Restore( idRestoreGame *savefile ) {
  961. FullscreenFX::Restore( savefile );
  962. savefile->ReadBool( grabberEnabled );
  963. savefile->ReadInt( startWarpTime );
  964. }
  965. /*
  966. ==================
  967. FullscreenFX_Warp::DrawWarp
  968. ==================
  969. */
  970. void FullscreenFX_Warp::DrawWarp( WarpPolygon_t wp, float interp ) {
  971. idVec4 mid1_uv, mid2_uv;
  972. idVec4 mid1, mid2;
  973. idVec2 drawPts[6], shiftScale;
  974. WarpPolygon_t trans;
  975. trans = wp;
  976. shiftScale = fxman->GetShiftScale();
  977. // compute mid points
  978. mid1 = trans.outer1 * ( interp ) + trans.center * ( 1 - interp );
  979. mid2 = trans.outer2 * ( interp ) + trans.center * ( 1 - interp );
  980. mid1_uv = trans.outer1 * ( 0.5 ) + trans.center * ( 1 - 0.5 );
  981. mid2_uv = trans.outer2 * ( 0.5 ) + trans.center * ( 1 - 0.5 );
  982. // draw [outer1, mid2, mid1]
  983. drawPts[0].Set( trans.outer1.x, trans.outer1.y );
  984. drawPts[1].Set( mid2.x, mid2.y );
  985. drawPts[2].Set( mid1.x, mid1.y );
  986. drawPts[3].Set( trans.outer1.z, trans.outer1.w );
  987. drawPts[4].Set( mid2_uv.z, mid2_uv.w );
  988. drawPts[5].Set( mid1_uv.z, mid1_uv.w );
  989. for ( int j = 0; j < 3; j++ ) {
  990. drawPts[j+3].x *= shiftScale.x;
  991. drawPts[j+3].y *= shiftScale.y;
  992. }
  993. renderSystem->DrawStretchTri( drawPts[0], drawPts[1], drawPts[2], drawPts[3], drawPts[4], drawPts[5], material );
  994. // draw [outer1, outer2, mid2]
  995. drawPts[0].Set( trans.outer1.x, trans.outer1.y );
  996. drawPts[1].Set( trans.outer2.x, trans.outer2.y );
  997. drawPts[2].Set( mid2.x, mid2.y );
  998. drawPts[3].Set( trans.outer1.z, trans.outer1.w );
  999. drawPts[4].Set( trans.outer2.z, trans.outer2.w );
  1000. drawPts[5].Set( mid2_uv.z, mid2_uv.w );
  1001. for ( int j = 0; j < 3; j++ ) {
  1002. drawPts[j+3].x *= shiftScale.x;
  1003. drawPts[j+3].y *= shiftScale.y;
  1004. }
  1005. renderSystem->DrawStretchTri( drawPts[0], drawPts[1], drawPts[2], drawPts[3], drawPts[4], drawPts[5], material );
  1006. // draw [mid1, mid2, center]
  1007. drawPts[0].Set( mid1.x, mid1.y );
  1008. drawPts[1].Set( mid2.x, mid2.y );
  1009. drawPts[2].Set( trans.center.x, trans.center.y );
  1010. drawPts[3].Set( mid1_uv.z, mid1_uv.w );
  1011. drawPts[4].Set( mid2_uv.z, mid2_uv.w );
  1012. drawPts[5].Set( trans.center.z, trans.center.w );
  1013. for ( int j = 0; j < 3; j++ ) {
  1014. drawPts[j+3].x *= shiftScale.x;
  1015. drawPts[j+3].y *= shiftScale.y;
  1016. }
  1017. renderSystem->DrawStretchTri( drawPts[0], drawPts[1], drawPts[2], drawPts[3], drawPts[4], drawPts[5], material );
  1018. }
  1019. /*
  1020. ==================
  1021. FullscreenFX_Warp::HighQuality
  1022. ==================
  1023. */
  1024. void FullscreenFX_Warp::HighQuality() {
  1025. float x1, y1, x2, y2, radius, interp;
  1026. idVec2 center;
  1027. int STEP = 9;
  1028. interp = ( idMath::Sin( (float)( gameLocal.slow.time - startWarpTime ) / 1000 ) + 1 ) / 2.f;
  1029. interp = 0.7 * ( 1 - interp ) + 0.3 * ( interp );
  1030. // draw the warps
  1031. center.x = 320;
  1032. center.y = 240;
  1033. radius = 200;
  1034. for ( float i = 0; i < 360; i += STEP ) {
  1035. // compute the values
  1036. x1 = idMath::Sin( DEG2RAD( i ) );
  1037. y1 = idMath::Cos( DEG2RAD( i ) );
  1038. x2 = idMath::Sin( DEG2RAD( i + STEP ) );
  1039. y2 = idMath::Cos( DEG2RAD( i + STEP ) );
  1040. // add warp polygon
  1041. WarpPolygon_t p;
  1042. p.outer1.x = center.x + x1 * radius;
  1043. p.outer1.y = center.y + y1 * radius;
  1044. p.outer1.z = p.outer1.x / 640.f;
  1045. p.outer1.w = 1 - ( p.outer1.y / 480.f );
  1046. p.outer2.x = center.x + x2 * radius;
  1047. p.outer2.y = center.y + y2 * radius;
  1048. p.outer2.z = p.outer2.x / 640.f;
  1049. p.outer2.w = 1 - ( p.outer2.y / 480.f );
  1050. p.center.x = center.x;
  1051. p.center.y = center.y;
  1052. p.center.z = p.center.x / 640.f;
  1053. p.center.w = 1 - ( p.center.y / 480.f );
  1054. // draw it
  1055. DrawWarp( p, interp );
  1056. }
  1057. }
  1058. /*
  1059. ==================
  1060. FullscreenFX_EnviroSuit::Initialize
  1061. ==================
  1062. */
  1063. void FullscreenFX_EnviroSuit::Initialize() {
  1064. material = declManager->FindMaterial( "textures/smf/enviro_suit" );
  1065. }
  1066. /*
  1067. ==================
  1068. FullscreenFX_EnviroSuit::Active
  1069. ==================
  1070. */
  1071. bool FullscreenFX_EnviroSuit::Active() {
  1072. idPlayer *player;
  1073. player = fxman->GetPlayer();
  1074. if ( player->PowerUpActive( ENVIROSUIT ) ) {
  1075. return true;
  1076. }
  1077. return false;
  1078. }
  1079. /*
  1080. ==================
  1081. FullscreenFX_EnviroSuit::HighQuality
  1082. ==================
  1083. */
  1084. void FullscreenFX_EnviroSuit::HighQuality() {
  1085. renderSystem->SetColor4( 1, 1, 1, 1 );
  1086. renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, material );
  1087. }
  1088. /*
  1089. ==================
  1090. FullscreenFX_DoubleVision::Initialize
  1091. ==================
  1092. */
  1093. void FullscreenFX_DoubleVision::Initialize() {
  1094. material = declManager->FindMaterial( "textures/smf/doubleVision" );
  1095. }
  1096. /*
  1097. ==================
  1098. FullscreenFX_DoubleVision::Active
  1099. ==================
  1100. */
  1101. bool FullscreenFX_DoubleVision::Active() {
  1102. if ( gameLocal.fast.time < fxman->GetPlayerView()->dvFinishTime ) {
  1103. return true;
  1104. }
  1105. return false;
  1106. }
  1107. /*
  1108. ==================
  1109. FullscreenFX_DoubleVision::HighQuality
  1110. ==================
  1111. */
  1112. void FullscreenFX_DoubleVision::HighQuality() {
  1113. int offset = fxman->GetPlayerView()->dvFinishTime - gameLocal.fast.time;
  1114. float scale = offset * g_dvAmplitude.GetFloat();
  1115. idPlayer *player;
  1116. idVec2 shiftScale;
  1117. // for testing purposes
  1118. if ( !Active() ) {
  1119. static int test = 0;
  1120. if ( test > 312 ) {
  1121. test = 0;
  1122. }
  1123. offset = test++;
  1124. scale = offset * g_dvAmplitude.GetFloat();
  1125. }
  1126. player = fxman->GetPlayer();
  1127. shiftScale = fxman->GetShiftScale();
  1128. offset *= 2; // crutch up for higher res
  1129. // set the scale and shift
  1130. if ( scale > 0.5f ) {
  1131. scale = 0.5f;
  1132. }
  1133. float shift = scale * sin( sqrtf( (float)offset ) * g_dvFrequency.GetFloat() );
  1134. shift = fabs( shift );
  1135. // carry red tint if in berserk mode
  1136. idVec4 color(1, 1, 1, 1);
  1137. if ( gameLocal.fast.time < player->inventory.powerupEndTime[ BERSERK ] ) {
  1138. color.y = 0;
  1139. color.z = 0;
  1140. }
  1141. if ( !gameLocal.isMultiplayer && gameLocal.fast.time < player->inventory.powerupEndTime[ HELLTIME ] || gameLocal.fast.time < player->inventory.powerupEndTime[ INVULNERABILITY ]) {
  1142. color.y = 0;
  1143. color.z = 0;
  1144. }
  1145. renderSystem->SetColor4( color.x, color.y, color.z, 1.0f );
  1146. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, shift, shiftScale.y, shiftScale.x, 0, material );
  1147. renderSystem->SetColor4( color.x, color.y, color.z, 0.5f );
  1148. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, shiftScale.y, (1-shift) * shiftScale.x, 0, material );
  1149. }
  1150. /*
  1151. ==================
  1152. FullscreenFX_InfluenceVision::Initialize
  1153. ==================
  1154. */
  1155. void FullscreenFX_InfluenceVision::Initialize() {
  1156. }
  1157. /*
  1158. ==================
  1159. FullscreenFX_InfluenceVision::Active
  1160. ==================
  1161. */
  1162. bool FullscreenFX_InfluenceVision::Active() {
  1163. idPlayer *player;
  1164. player = fxman->GetPlayer();
  1165. if ( player->GetInfluenceMaterial() || player->GetInfluenceEntity() ) {
  1166. return true;
  1167. }
  1168. return false;
  1169. }
  1170. /*
  1171. ==================
  1172. FullscreenFX_InfluenceVision::HighQuality
  1173. ==================
  1174. */
  1175. void FullscreenFX_InfluenceVision::HighQuality() {
  1176. float distance = 0.0f;
  1177. float pct = 1.0f;
  1178. idPlayer *player;
  1179. idVec2 shiftScale;
  1180. shiftScale = fxman->GetShiftScale();
  1181. player = fxman->GetPlayer();
  1182. if ( player->GetInfluenceEntity() ) {
  1183. distance = ( player->GetInfluenceEntity()->GetPhysics()->GetOrigin() - player->GetPhysics()->GetOrigin() ).Length();
  1184. if ( player->GetInfluenceRadius() != 0.0f && distance < player->GetInfluenceRadius() ) {
  1185. pct = distance / player->GetInfluenceRadius();
  1186. pct = 1.0f - idMath::ClampFloat( 0.0f, 1.0f, pct );
  1187. }
  1188. }
  1189. if ( player->GetInfluenceMaterial() ) {
  1190. renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, pct );
  1191. renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, player->GetInfluenceMaterial() );
  1192. } else if ( player->GetInfluenceEntity() == NULL ) {
  1193. return;
  1194. } else {
  1195. // int offset = 25 + sinf( gameLocal.slow.time );
  1196. // DoubleVision( hud, view, pct * offset );
  1197. }
  1198. }
  1199. /*
  1200. ==================
  1201. FullscreenFX_Bloom::Initialize
  1202. ==================
  1203. */
  1204. void FullscreenFX_Bloom::Initialize() {
  1205. drawMaterial = declManager->FindMaterial( "textures/smf/bloom2/draw" );
  1206. initMaterial = declManager->FindMaterial( "textures/smf/bloom2/init" );
  1207. currentMaterial = declManager->FindMaterial( "textures/smf/bloom2/currentMaterial" );
  1208. currentIntensity = 0;
  1209. targetIntensity = 0;
  1210. }
  1211. /*
  1212. ==================
  1213. FullscreenFX_Bloom::Active
  1214. ==================
  1215. */
  1216. bool FullscreenFX_Bloom::Active() {
  1217. idPlayer *player;
  1218. player = fxman->GetPlayer();
  1219. if ( player && player->bloomEnabled ) {
  1220. return true;
  1221. }
  1222. return false;
  1223. }
  1224. /*
  1225. ==================
  1226. FullscreenFX_Bloom::HighQuality
  1227. ==================
  1228. */
  1229. void FullscreenFX_Bloom::HighQuality() {
  1230. float shift, delta;
  1231. idVec2 shiftScale;
  1232. idPlayer *player;
  1233. int num;
  1234. shift = 1;
  1235. player = fxman->GetPlayer();
  1236. shiftScale = fxman->GetShiftScale();
  1237. renderSystem->SetColor4( 1, 1, 1, 1 );
  1238. // if intensity value is different, start the blend
  1239. targetIntensity = g_testBloomIntensity.GetFloat();
  1240. if ( player && player->bloomEnabled ) {
  1241. targetIntensity = player->bloomIntensity;
  1242. }
  1243. delta = targetIntensity - currentIntensity;
  1244. float step = 0.001f;
  1245. if ( step < fabs( delta ) ) {
  1246. if ( delta < 0 ) {
  1247. step = -step;
  1248. }
  1249. currentIntensity += step;
  1250. }
  1251. // draw the blends
  1252. num = g_testBloomNumPasses.GetInteger();
  1253. for ( int i = 0; i < num; i++ ) {
  1254. float s1 = 0, t1 = 0, s2 = 1, t2 = 1;
  1255. float alpha;
  1256. // do the center scale
  1257. s1 -= 0.5;
  1258. s1 *= shift;
  1259. s1 += 0.5;
  1260. s1 *= shiftScale.x;
  1261. t1 -= 0.5;
  1262. t1 *= shift;
  1263. t1 += 0.5;
  1264. t1 *= shiftScale.y;
  1265. s2 -= 0.5;
  1266. s2 *= shift;
  1267. s2 += 0.5;
  1268. s2 *= shiftScale.x;
  1269. t2 -= 0.5;
  1270. t2 *= shift;
  1271. t2 += 0.5;
  1272. t2 *= shiftScale.y;
  1273. // draw it
  1274. if ( num == 1 ) {
  1275. alpha = 1;
  1276. }
  1277. else {
  1278. alpha = 1 - (float)i / ( num - 1 );
  1279. }
  1280. renderSystem->SetColor4( alpha, alpha, alpha, 1 );
  1281. renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, s1, t2, s2, t1, drawMaterial );
  1282. shift += currentIntensity;
  1283. }
  1284. }
  1285. /*
  1286. ==================
  1287. FullscreenFX_Bloom::Save
  1288. ==================
  1289. */
  1290. void FullscreenFX_Bloom::Save( idSaveGame *savefile ) {
  1291. FullscreenFX::Save( savefile );
  1292. savefile->WriteFloat( currentIntensity );
  1293. savefile->WriteFloat( targetIntensity );
  1294. }
  1295. /*
  1296. ==================
  1297. FullscreenFX_Bloom::Restore
  1298. ==================
  1299. */
  1300. void FullscreenFX_Bloom::Restore( idRestoreGame *savefile ) {
  1301. FullscreenFX::Restore( savefile );
  1302. savefile->ReadFloat( currentIntensity );
  1303. savefile->ReadFloat( targetIntensity );
  1304. }
  1305. /*
  1306. ==================
  1307. FullscreenFXManager::FullscreenFXManager
  1308. ==================
  1309. */
  1310. FullscreenFXManager::FullscreenFXManager() {
  1311. highQualityMode = false;
  1312. playerView = NULL;
  1313. blendBackMaterial = NULL;
  1314. shiftScale.Set( 0, 0 );
  1315. }
  1316. /*
  1317. ==================
  1318. FullscreenFXManager::~FullscreenFXManager
  1319. ==================
  1320. */
  1321. FullscreenFXManager::~FullscreenFXManager() {
  1322. }
  1323. /*
  1324. ==================
  1325. FullscreenFXManager::FindFX
  1326. ==================
  1327. */
  1328. FullscreenFX* FullscreenFXManager::FindFX( idStr name ) {
  1329. for ( int i = 0; i < fx.Num(); i++ ) {
  1330. if ( fx[i]->GetName() == name ) {
  1331. return fx[i];
  1332. }
  1333. }
  1334. return NULL;
  1335. }
  1336. /*
  1337. ==================
  1338. FullscreenFXManager::CreateFX
  1339. ==================
  1340. */
  1341. void FullscreenFXManager::CreateFX( idStr name, idStr fxtype, int fade ) {
  1342. FullscreenFX *pfx = NULL;
  1343. if ( fxtype == "helltime" ) {
  1344. pfx = new FullscreenFX_Helltime;
  1345. }
  1346. else if ( fxtype == "warp" ) {
  1347. pfx = new FullscreenFX_Warp;
  1348. }
  1349. else if ( fxtype == "envirosuit" ) {
  1350. pfx = new FullscreenFX_EnviroSuit;
  1351. }
  1352. else if ( fxtype == "doublevision" ) {
  1353. pfx = new FullscreenFX_DoubleVision;
  1354. }
  1355. else if ( fxtype == "multiplayer" ) {
  1356. pfx = new FullscreenFX_Multiplayer;
  1357. }
  1358. else if ( fxtype == "influencevision" ) {
  1359. pfx = new FullscreenFX_InfluenceVision;
  1360. }
  1361. else if ( fxtype == "bloom" ) {
  1362. pfx = new FullscreenFX_Bloom;
  1363. }
  1364. else {
  1365. assert( 0 );
  1366. }
  1367. if ( pfx ) {
  1368. pfx->Initialize();
  1369. pfx->SetFXManager( this );
  1370. pfx->SetName( name );
  1371. pfx->SetFadeSpeed( fade );
  1372. fx.Append( pfx );
  1373. }
  1374. }
  1375. /*
  1376. ==================
  1377. FullscreenFXManager::Initialize
  1378. ==================
  1379. */
  1380. void FullscreenFXManager::Initialize( idPlayerView *pv ) {
  1381. // set the playerview
  1382. playerView = pv;
  1383. blendBackMaterial = declManager->FindMaterial( "textures/smf/blendBack" );
  1384. // allocate the fx
  1385. CreateFX( "helltime", "helltime", 1000 );
  1386. CreateFX( "warp", "warp", 0 );
  1387. CreateFX( "envirosuit", "envirosuit", 500 );
  1388. CreateFX( "doublevision", "doublevision", 0 );
  1389. CreateFX( "multiplayer", "multiplayer", 1000 );
  1390. CreateFX( "influencevision", "influencevision", 1000 );
  1391. CreateFX( "bloom", "bloom", 0 );
  1392. // pre-cache the texture grab so we dont hitch
  1393. renderSystem->CropRenderSize( 512, 512, true );
  1394. renderSystem->CaptureRenderToImage( "_accum" );
  1395. renderSystem->UnCrop();
  1396. renderSystem->CropRenderSize( 512, 256, true );
  1397. renderSystem->CaptureRenderToImage( "_scratch" );
  1398. renderSystem->UnCrop();
  1399. renderSystem->CaptureRenderToImage( "_currentRender" );
  1400. }
  1401. /*
  1402. ==================
  1403. FullscreenFXManager::Blendback
  1404. ==================
  1405. */
  1406. void FullscreenFXManager::Blendback( float alpha ) {
  1407. // alpha fade
  1408. if ( alpha < 1.f ) {
  1409. renderSystem->SetColor4( 1, 1, 1, 1 - alpha );
  1410. renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, shiftScale.y, shiftScale.x, 0.f, blendBackMaterial );
  1411. }
  1412. }
  1413. /*
  1414. ==================
  1415. FullscreenFXManager::Save
  1416. ==================
  1417. */
  1418. void FullscreenFXManager::Save( idSaveGame *savefile ) {
  1419. savefile->WriteBool( highQualityMode );
  1420. savefile->WriteVec2( shiftScale );
  1421. for ( int i = 0; i < fx.Num(); i++ ) {
  1422. FullscreenFX *pfx = fx[i];
  1423. pfx->Save( savefile );
  1424. }
  1425. }
  1426. /*
  1427. ==================
  1428. FullscreenFXManager::Restore
  1429. ==================
  1430. */
  1431. void FullscreenFXManager::Restore( idRestoreGame *savefile ) {
  1432. savefile->ReadBool( highQualityMode );
  1433. savefile->ReadVec2( shiftScale );
  1434. for ( int i = 0; i < fx.Num(); i++ ) {
  1435. FullscreenFX *pfx = fx[i];
  1436. pfx->Restore( savefile );
  1437. }
  1438. }
  1439. /*
  1440. ==================
  1441. FullscreenFXManager::CaptureCurrentRender
  1442. ==================
  1443. */
  1444. void FullscreenFXManager::CaptureCurrentRender() {
  1445. renderSystem->CaptureRenderToImage( "_currentRender" );
  1446. }
  1447. /*
  1448. ==================
  1449. FullscreenFXManager::Process
  1450. ==================
  1451. */
  1452. void FullscreenFXManager::Process( const renderView_t *view ) {
  1453. bool allpass = false;
  1454. bool atLeastOneFX = false;
  1455. if ( g_testFullscreenFX.GetInteger() == -2 ) {
  1456. allpass = true;
  1457. }
  1458. if ( g_lowresFullscreenFX.GetBool() ) {
  1459. highQualityMode = false;
  1460. }
  1461. else {
  1462. highQualityMode = true;
  1463. }
  1464. // compute the shift scale
  1465. if ( highQualityMode ) {
  1466. int vidWidth, vidHeight;
  1467. renderSystem->GetGLSettings( vidWidth, vidHeight );
  1468. float pot;
  1469. int w = vidWidth;
  1470. pot = MakePowerOfTwo( w );
  1471. shiftScale.x = (float)w / pot;
  1472. int h = vidHeight;
  1473. pot = MakePowerOfTwo( h );
  1474. shiftScale.y = (float)h / pot;
  1475. }
  1476. else {
  1477. // if we're in low-res mode, shrink view down
  1478. shiftScale.x = 1;
  1479. shiftScale.y = 1;
  1480. renderSystem->CropRenderSize( 512, 512, true );
  1481. }
  1482. // do the first render
  1483. gameRenderWorld->RenderScene( view );
  1484. // do the process
  1485. for ( int i = 0; i < fx.Num(); i++ ) {
  1486. FullscreenFX *pfx = fx[i];
  1487. bool drawIt = false;
  1488. // determine if we need to draw
  1489. if ( pfx->Active() || g_testFullscreenFX.GetInteger() == i || allpass ) {
  1490. drawIt = pfx->SetTriggerState( true );
  1491. }
  1492. else {
  1493. drawIt = pfx->SetTriggerState( false );
  1494. }
  1495. // do the actual drawing
  1496. if ( drawIt ) {
  1497. atLeastOneFX = true;
  1498. // we need to dump to _currentRender
  1499. CaptureCurrentRender();
  1500. // handle the accum pass if we have one
  1501. if ( pfx->HasAccum() ) {
  1502. // if we're in high quality mode, we need to crop the accum pass
  1503. if ( highQualityMode ) {
  1504. renderSystem->CropRenderSize( 512, 512, true );
  1505. pfx->AccumPass( view );
  1506. renderSystem->UnCrop();
  1507. }
  1508. else {
  1509. pfx->AccumPass( view );
  1510. }
  1511. }
  1512. // do the high quality pass
  1513. pfx->HighQuality();
  1514. // do the blendback
  1515. Blendback( pfx->GetFadeAlpha() );
  1516. }
  1517. }
  1518. if ( !highQualityMode ) {
  1519. // we need to dump to _currentRender
  1520. CaptureCurrentRender();
  1521. // uncrop view
  1522. renderSystem->UnCrop();
  1523. // draw the final full-screen image
  1524. renderSystem->SetColor4( 1, 1, 1, 1 );
  1525. renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 1, 1, 0.f, blendBackMaterial );
  1526. }
  1527. }
  1528. #endif