PlayerView.cpp 45 KB

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