mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-16 08:10:32 +02:00
749 lines
22 KiB
C++
749 lines
22 KiB
C++
|
|
#include "precompiled.h"
|
|
#pragma hdrstop
|
|
|
|
#include "prey_local.h"
|
|
|
|
#define LETTERBOX_HEIGHT_TOP 50
|
|
#define LETTERBOX_HEIGHT_BOTTOM 50
|
|
|
|
const int IMPULSE_DELAY = 150;
|
|
|
|
//HUMANHEAD rww - render demo madness
|
|
#if _HH_RENDERDEMO_HACKS
|
|
void RENDER_DEMO_VIEWRENDER(const renderView_t *view, const hhPlayerView *pView) {
|
|
if (!view) {
|
|
return;
|
|
}
|
|
|
|
const renderView_t *v = view;
|
|
|
|
if (pView) {
|
|
static renderView_t hackedView = *view;
|
|
hackedView.viewaxis = hackedView.viewaxis * pView->ShakeAxis();
|
|
|
|
v = &hackedView;
|
|
}
|
|
|
|
renderSystem->LogViewRender(v);
|
|
}
|
|
|
|
void RENDER_DEMO_VIEWRENDER_END(void) {
|
|
renderSystem->LogViewRender(NULL);
|
|
}
|
|
#endif
|
|
//HUMANHEAD END
|
|
|
|
hhPlayerView::hhPlayerView() {
|
|
// HUMANHEAD pdm: we don't use the tunnel vision or armor
|
|
bLetterBox = false;
|
|
letterboxMaterial = declManager->FindMaterial( "_black" );
|
|
dirDmgLeftMaterial = declManager->FindMaterial( "textures/interface/directionalDamageLeft" );
|
|
dirDmgFrontMaterial = declManager->FindMaterial( "textures/interface/directionalDamageFront" );
|
|
spiritMaterial = NULL;
|
|
viewOverlayMaterial = NULL;
|
|
viewOverlayColor = colorWhite;
|
|
voTotalTime = -1;
|
|
voRequiresScratchBuffer = false;
|
|
viewOffset.Zero();
|
|
|
|
kickSpeed.Zero();
|
|
kickLastTime = 0;
|
|
hurtValue = 100.f;
|
|
}
|
|
|
|
void hhPlayerView::Save(idSaveGame *savefile) const {
|
|
idPlayerView::Save( savefile );
|
|
|
|
savefile->WriteBool( bLetterBox );
|
|
savefile->WriteFloat( mbAmplitude );
|
|
savefile->WriteInt( mbFinishTime );
|
|
savefile->WriteInt( mbTotalTime );
|
|
savefile->WriteVec3( mbDirection );
|
|
savefile->WriteVec3( viewOffset );
|
|
savefile->WriteMaterial( viewOverlayMaterial );
|
|
savefile->WriteVec4( viewOverlayColor );
|
|
savefile->WriteInt( voFinishTime );
|
|
savefile->WriteInt( voTotalTime );
|
|
savefile->WriteInt( voRequiresScratchBuffer );
|
|
savefile->WriteMaterial( letterboxMaterial );
|
|
savefile->WriteMaterial( dirDmgLeftMaterial );
|
|
savefile->WriteMaterial( dirDmgFrontMaterial );
|
|
savefile->WriteMaterial( spiritMaterial );
|
|
savefile->WriteVec3( lastDamageLocation );
|
|
savefile->WriteInt( kickLastTime - gameLocal.time );
|
|
savefile->WriteAngles( kickSpeed );
|
|
savefile->WriteFloat( hurtValue );
|
|
}
|
|
|
|
void hhPlayerView::Restore( idRestoreGame *savefile ) {
|
|
idPlayerView::Restore( savefile );
|
|
|
|
savefile->ReadBool( bLetterBox );
|
|
savefile->ReadFloat( mbAmplitude );
|
|
savefile->ReadInt( mbFinishTime );
|
|
savefile->ReadInt( mbTotalTime );
|
|
savefile->ReadVec3( mbDirection );
|
|
savefile->ReadVec3( viewOffset );
|
|
savefile->ReadMaterial( viewOverlayMaterial );
|
|
savefile->ReadVec4( viewOverlayColor );
|
|
savefile->ReadInt( voFinishTime );
|
|
savefile->ReadInt( voTotalTime );
|
|
savefile->ReadInt( voRequiresScratchBuffer );
|
|
savefile->ReadMaterial( letterboxMaterial );
|
|
savefile->ReadMaterial( dirDmgLeftMaterial );
|
|
savefile->ReadMaterial( dirDmgFrontMaterial );
|
|
savefile->ReadMaterial( spiritMaterial );
|
|
savefile->ReadVec3( lastDamageLocation );
|
|
savefile->ReadInt( kickLastTime );
|
|
kickLastTime += gameLocal.time;
|
|
savefile->ReadAngles( kickSpeed );
|
|
savefile->ReadFloat( hurtValue );
|
|
}
|
|
|
|
#define MAX_SCREEN_BLOBS_SYNC 2//MAX_SCREEN_BLOBS
|
|
|
|
//rwwFIXME it may be possible to remove a lot of this junk by assuring events happen on the client as they do on the server
|
|
//concerning damage etc.
|
|
void hhPlayerView::WriteToSnapshot( idBitMsgDelta &msg ) const {
|
|
msg.WriteFloat(viewOffset.x);
|
|
msg.WriteFloat(viewOffset.y);
|
|
msg.WriteFloat(viewOffset.z);
|
|
|
|
msg.WriteBits(voTotalTime, 32);
|
|
msg.WriteBits(voFinishTime, 32);
|
|
msg.WriteBits(voRequiresScratchBuffer, 1);
|
|
|
|
if (viewOverlayMaterial) {
|
|
msg.WriteLong(gameLocal.ServerRemapDecl(-1, DECL_MATERIAL, viewOverlayMaterial->Index()));
|
|
}
|
|
else {
|
|
msg.WriteLong(-1);
|
|
}
|
|
|
|
//write screen blobs to snapshot
|
|
for (int i = 0; i < MAX_SCREEN_BLOBS_SYNC; i++) {
|
|
const screenBlob_t *blob = &screenBlobs[i];
|
|
|
|
//i'm disabling this since it might work against delta compression being effective
|
|
/*
|
|
if ( blob->finishTime <= gameLocal.time ) {
|
|
msg.WriteBits(0, 1); //no need to do anymore, continue
|
|
continue;
|
|
}
|
|
|
|
//otherwise continue writing
|
|
msg.WriteBits(1, 1);
|
|
*/
|
|
|
|
if (blob->material) {
|
|
msg.WriteLong(gameLocal.ServerRemapDecl(-1, DECL_MATERIAL, blob->material->Index()));
|
|
}
|
|
else {
|
|
msg.WriteLong(-1);
|
|
}
|
|
|
|
msg.WriteFloat(blob->x);
|
|
msg.WriteFloat(blob->y);
|
|
msg.WriteFloat(blob->w);
|
|
msg.WriteFloat(blob->h);
|
|
|
|
msg.WriteFloat(blob->s1);
|
|
msg.WriteFloat(blob->t1);
|
|
msg.WriteFloat(blob->s2);
|
|
msg.WriteFloat(blob->t2);
|
|
|
|
msg.WriteBits(blob->finishTime, 32);
|
|
msg.WriteBits(blob->startFadeTime, 32);
|
|
|
|
msg.WriteFloat(blob->driftAmount);
|
|
}
|
|
|
|
//motion blur
|
|
msg.WriteFloat(mbAmplitude);
|
|
msg.WriteBits(mbFinishTime, 32);
|
|
msg.WriteBits(mbTotalTime, 32);
|
|
msg.WriteFloat(mbDirection.x);
|
|
msg.WriteFloat(mbDirection.y);
|
|
msg.WriteFloat(mbDirection.z);
|
|
|
|
msg.WriteFloat(viewOverlayColor.w);
|
|
msg.WriteFloat(viewOverlayColor.x);
|
|
msg.WriteFloat(viewOverlayColor.y);
|
|
msg.WriteFloat(viewOverlayColor.z);
|
|
}
|
|
|
|
void hhPlayerView::ReadFromSnapshot( const idBitMsgDelta &msg ) {
|
|
viewOffset.x = msg.ReadFloat();
|
|
viewOffset.y = msg.ReadFloat();
|
|
viewOffset.z = msg.ReadFloat();
|
|
|
|
voTotalTime = msg.ReadBits(32);
|
|
voFinishTime = msg.ReadBits(32);
|
|
voRequiresScratchBuffer = !!msg.ReadBits(1);
|
|
|
|
int matIndex = msg.ReadLong();
|
|
if (matIndex == -1) {
|
|
viewOverlayMaterial = NULL;
|
|
}
|
|
else {
|
|
int mappedIndex;
|
|
|
|
if (voTotalTime != -1 && gameLocal.time >= voFinishTime) { //it's timed out so force it off
|
|
voTotalTime = -1;
|
|
voRequiresScratchBuffer = false;
|
|
viewOverlayMaterial = NULL;
|
|
mappedIndex = -1;
|
|
}
|
|
else {
|
|
mappedIndex = gameLocal.ClientRemapDecl(DECL_MATERIAL, matIndex);
|
|
}
|
|
|
|
if (mappedIndex != -1) {
|
|
viewOverlayMaterial = static_cast<const idMaterial *>(declManager->DeclByIndex(DECL_MATERIAL, mappedIndex));
|
|
}
|
|
else {
|
|
viewOverlayMaterial = NULL;
|
|
}
|
|
}
|
|
|
|
//read screen blobs from snapshot
|
|
for (int i = 0; i < MAX_SCREEN_BLOBS_SYNC; i++) {
|
|
screenBlob_t *blob = &screenBlobs[i];
|
|
|
|
//i'm disabling this since it might work against delta compression being effective
|
|
/*
|
|
bool valid = !!msg.ReadBits(1);
|
|
if (!valid) {
|
|
continue;
|
|
}
|
|
*/
|
|
|
|
int blobMat = msg.ReadLong();
|
|
if (blobMat == -1) {
|
|
blob->material = NULL;
|
|
}
|
|
else {
|
|
int mappedIndex = gameLocal.ClientRemapDecl(DECL_MATERIAL, blobMat);
|
|
if (mappedIndex != -1) {
|
|
blob->material = static_cast<const idMaterial *>(declManager->DeclByIndex(DECL_MATERIAL, mappedIndex));
|
|
}
|
|
else {
|
|
blob->material = NULL;
|
|
}
|
|
}
|
|
|
|
blob->x = msg.ReadFloat();
|
|
blob->y = msg.ReadFloat();
|
|
blob->w = msg.ReadFloat();
|
|
blob->h = msg.ReadFloat();
|
|
|
|
blob->s1 = msg.ReadFloat();
|
|
blob->t1 = msg.ReadFloat();
|
|
blob->s2 = msg.ReadFloat();
|
|
blob->t2 = msg.ReadFloat();
|
|
|
|
blob->finishTime = msg.ReadBits(32);
|
|
blob->startFadeTime = msg.ReadBits(32);
|
|
|
|
blob->driftAmount = msg.ReadFloat();
|
|
}
|
|
|
|
//motion blur
|
|
mbAmplitude = msg.ReadFloat();
|
|
mbFinishTime = msg.ReadBits(32);
|
|
mbTotalTime = msg.ReadBits(32);
|
|
mbDirection.x = msg.ReadFloat();
|
|
mbDirection.y = msg.ReadFloat();
|
|
mbDirection.z = msg.ReadFloat();
|
|
|
|
viewOverlayColor.w = msg.ReadFloat();
|
|
viewOverlayColor.x = msg.ReadFloat();
|
|
viewOverlayColor.y = msg.ReadFloat();
|
|
viewOverlayColor.z = msg.ReadFloat();
|
|
}
|
|
|
|
void hhPlayerView::ClearEffects() {
|
|
idPlayerView::ClearEffects();
|
|
|
|
// HUMANHEAD pdm
|
|
mbFinishTime = gameLocal.time;
|
|
}
|
|
|
|
|
|
void hhPlayerView::SetDamageLoc(const idVec3 &damageLoc) {
|
|
// This called before damageImpulse() so store the location
|
|
lastDamageLocation = damageLoc;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------
|
|
//
|
|
// DamageImpulse
|
|
//
|
|
// LocalKickDir is the direction of force in the player's coordinate system,
|
|
// which will determine the head kick direction
|
|
//------------------------------------------------------
|
|
void hhPlayerView::DamageImpulse( idVec3 localKickDir, const idDict *damageDef ) {
|
|
|
|
// No screen damage effects when in third person
|
|
if (pm_thirdPerson.GetBool()) {
|
|
return;
|
|
}
|
|
|
|
if ( lastDamageTime > 0.0f && SEC2MS( lastDamageTime ) + IMPULSE_DELAY > gameLocal.time ) {
|
|
// keep shotgun from obliterating the view
|
|
return;
|
|
}
|
|
|
|
if (!player->InVehicle()) {
|
|
//
|
|
// Motion Blur effect
|
|
// HUMANHEAD pdm
|
|
float mbTime = damageDef->GetFloat( "mb_time" );
|
|
float severity = damageDef->GetFloat( "mb_amplitude" );
|
|
if ( mbTime ) {
|
|
idVec3 blurDirection;
|
|
blurDirection.y = localKickDir[0]; // forward/back kick will blur vertically
|
|
blurDirection.x = localKickDir[1]; // side kick will blur horizontally
|
|
blurDirection.y += localKickDir[2]; // up/down kick will add to vertical
|
|
MotionBlur(mbTime, severity, blurDirection);
|
|
}
|
|
|
|
//
|
|
// head angle kick
|
|
//
|
|
float kickTime = damageDef->GetFloat( "kick_time" );
|
|
if ( kickTime ) {
|
|
kickFinishTime = gameLocal.time + g_kickTime.GetFloat() * kickTime;
|
|
|
|
// forward / back kick will pitch view
|
|
kickAngles[0] = localKickDir[0];
|
|
|
|
// side kick will yaw view
|
|
kickAngles[1] = localKickDir[1]*0.5f;
|
|
|
|
// up / down kick will pitch view
|
|
kickAngles[0] += localKickDir[2];
|
|
|
|
// roll will come from side
|
|
kickAngles[2] = localKickDir[1];
|
|
|
|
float kickAmplitude = damageDef->GetFloat( "kick_amplitude" );
|
|
if ( kickAmplitude ) {
|
|
kickAngles *= kickAmplitude;
|
|
}
|
|
}
|
|
|
|
//
|
|
// HUMANHEAD: Screen blobs, changed functionality
|
|
//
|
|
float blobTime = damageDef->GetFloat( "blob_time" );
|
|
if ( blobTime ) {
|
|
screenBlob_t *blob = GetScreenBlob();
|
|
blob->startFadeTime = gameLocal.time;
|
|
blob->finishTime = gameLocal.time + blobTime * g_blobTime.GetFloat();
|
|
|
|
const char *materialName = damageDef->GetString( "mtr_blob" );
|
|
blob->material = declManager->FindMaterial( materialName );
|
|
|
|
// Scale blob by 100% +/- blob_devscale%
|
|
float scale = ( 256.0f + ( 256.0f*damageDef->GetFloat("blob_devscale")*gameLocal.random.CRandomFloat() ) ) / 256.0f;
|
|
blob->w = damageDef->GetFloat( "blob_width" ) * g_blobSize.GetFloat() * scale;
|
|
blob->h = damageDef->GetFloat( "blob_height" ) * g_blobSize.GetFloat() * scale;
|
|
blob->s1 = 0;
|
|
blob->t1 = 0;
|
|
blob->s2 = 1;
|
|
blob->t2 = 1;
|
|
|
|
if (damageDef->GetBool("blob_projected") && player->renderView) {
|
|
//rww - renderView null check added. I am not clear on when this may be null, but it apparently was. however, if a player were
|
|
//to take damage before thinking, it seems very possible this would occur. the renderView will not be initialized until after
|
|
//the first think.
|
|
// Project hit location onto screen
|
|
idVec3 localDamageLocation = hhUtils::ProjectOntoScreen(lastDamageLocation, *player->renderView);
|
|
blob->x = localDamageLocation.x - blob->w * 0.5f;
|
|
blob->y = localDamageLocation.y - blob->h * 0.5f;
|
|
}
|
|
else if (damageDef->GetBool("blob_directional")) {
|
|
// Directional blobs to show where damage is coming from (360 degree)
|
|
float dirDist = damageDef->GetFloat("blob_dirdistance");
|
|
blob->x = 320.0f + (dirDist * 320.0f * localKickDir.y) - (blob->w * 0.5f);
|
|
blob->y = 240.0f + (dirDist * 240.0f * localKickDir.x) - (blob->h * 0.5f);
|
|
}
|
|
else {
|
|
// Place blob centered at (blob_x,blob_y)
|
|
blob->x = damageDef->GetFloat( "blob_x" ) - blob->w * 0.5f;
|
|
blob->y = damageDef->GetFloat( "blob_y" ) - blob->h * 0.5f;
|
|
}
|
|
|
|
// Deviate blob +/- (blob_devx,blob_devy)
|
|
blob->x += damageDef->GetFloat( "blob_devx" ) * gameLocal.random.CRandomFloat();
|
|
blob->y += damageDef->GetFloat( "blob_devy" ) * gameLocal.random.CRandomFloat();
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Global directional damage system
|
|
//
|
|
/*
|
|
const int directionDamageTime = 1000;
|
|
screenBlob_t *blob = GetScreenBlob();
|
|
blob->startFadeTime = gameLocal.time;
|
|
blob->finishTime = gameLocal.time + directionDamageTime;
|
|
|
|
blob->s1 = 0;
|
|
blob->t1 = 0;
|
|
blob->s2 = 1;
|
|
blob->t2 = 1;
|
|
if (idMath::Fabs(localKickDir[0]) >= idMath::Fabs(localKickDir[1])) {
|
|
// More in X direction
|
|
blob->material = dirDmgFrontMaterial;
|
|
blob->w = 500.0f;
|
|
blob->h = 80.0f;
|
|
blob->x = 320.0f - blob->w * 0.5f;
|
|
if (localKickDir[0] >= 0.0f) {
|
|
// From Rear
|
|
blob->y = 480.0f - blob->h;
|
|
idSwap(blob->t1, blob->t2);
|
|
}
|
|
else {
|
|
// From Front
|
|
blob->y = 0.0f;
|
|
}
|
|
}
|
|
else {
|
|
// More in Y direction
|
|
blob->material = dirDmgLeftMaterial;
|
|
blob->w = 80.0f;
|
|
blob->h = 400.0f;
|
|
blob->y = 240.0f - blob->h * 0.5f;
|
|
if (localKickDir[1] >= 0.0f) {
|
|
// From Right
|
|
blob->x = 640.0f - blob->w;
|
|
idSwap(blob->s1, blob->s2);
|
|
}
|
|
else {
|
|
// From Left
|
|
blob->x = 0.0f;
|
|
}
|
|
}
|
|
*/
|
|
|
|
//
|
|
// save lastDamageTime for tunnel vision accentuation
|
|
//
|
|
lastDamageTime = MS2SEC( gameLocal.time );
|
|
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// WeaponFireFeedback
|
|
// HUMANHEAD bjk
|
|
//------------------------------------------------------
|
|
void hhPlayerView::WeaponFireFeedback( const idDict *weaponDef ) {
|
|
idAngles angles;
|
|
idVec2 pitch, yaw, viewSpring;
|
|
weaponDef->GetVec2( "recoilPitch", "0 0", pitch );
|
|
weaponDef->GetVec2( "recoilYaw", "0 0", yaw );
|
|
weaponDef->GetVec2( "viewSpring", "150 11", viewSpring );
|
|
|
|
player->kickSpring = viewSpring.x;
|
|
player->kickDamping = viewSpring.y;
|
|
|
|
pitch.x = pitch.x + gameLocal.random.RandomFloat()*(pitch.y - pitch.x);
|
|
yaw.x = yaw.x + gameLocal.random.RandomFloat()*(yaw.y - yaw.x);
|
|
angles=idAngles(-pitch.x,-yaw.x,0);
|
|
kickSpeed+=angles;
|
|
assert(!FLOAT_IS_NAN(kickSpeed.pitch) && !FLOAT_IS_NAN(kickSpeed.yaw) && !FLOAT_IS_NAN(kickSpeed.roll));
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// AngleOffset
|
|
// HUMANHEAD bjk
|
|
//------------------------------------------------------
|
|
idAngles hhPlayerView::AngleOffset(float kickSpring, float kickDamping) {
|
|
//HUMANHEAD rww - for other clients, do not add angle offset, it isn't predicted well
|
|
if (gameLocal.isMultiplayer && !gameLocal.isServer && gameLocal.localClientNum != -1 && player && gameLocal.localClientNum != player->entityNumber) {
|
|
kickSpeed.Zero();
|
|
kickAngles.Zero();
|
|
return kickAngles;
|
|
}
|
|
//HUMANHEAD END
|
|
|
|
float frametime = (gameLocal.time - kickLastTime);
|
|
kickLastTime = gameLocal.time;
|
|
//kickAngles = kickAngles*(1-offset*kickSpeed)+kickBlendTo*offset*kickSpeed;
|
|
//kickBlendTo = kickBlendTo*(1-offset*kickReturnSpeed)+ang*offset*kickReturnSpeed;
|
|
|
|
//HUMANHEAD PCF rww 04/27/06 - these values can get unreasonable at times
|
|
#if 0
|
|
for (int i = 0; i < 3; i++) {
|
|
if (fabsf(kickSpeed[i]) > 9999.0f) {
|
|
kickSpeed[i] = 0.0f;
|
|
}
|
|
if (fabsf(kickAngles[i]) > 9999.0f) {
|
|
kickAngles[i] = 0.0f;
|
|
}
|
|
}
|
|
#endif
|
|
if (frametime > 48.0f) {
|
|
frametime = 48.0f;
|
|
}
|
|
//HUMANHEAD END
|
|
|
|
assert(!FLOAT_IS_NAN(kickSpeed.pitch) && !FLOAT_IS_NAN(kickSpeed.yaw) && !FLOAT_IS_NAN(kickSpeed.roll));
|
|
assert(!FLOAT_IS_NAN(kickAngles.pitch) && !FLOAT_IS_NAN(kickAngles.yaw) && !FLOAT_IS_NAN(kickAngles.roll));
|
|
|
|
kickSpeed-=kickDamping*kickSpeed*frametime/1000;
|
|
kickSpeed-=kickSpring*kickAngles*frametime/1000;
|
|
|
|
if (gameLocal.isNewFrame) { //HUMANHEAD rww
|
|
kickAngles+=kickSpeed*frametime/1000;
|
|
}
|
|
|
|
return kickAngles;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// SingleView
|
|
//------------------------------------------------------
|
|
void hhPlayerView::SingleView( idUserInterface *hud, const renderView_t *view ) {
|
|
// normal rendering
|
|
|
|
if ( !view ) {
|
|
return;
|
|
}
|
|
|
|
// place the sound origin for the player
|
|
gameSoundWorld->PlaceListener( view->vieworg, view->viewaxis, player->entityNumber + 1, gameLocal.time, hud ? hud->State().GetString( "location" ) : "Undefined" );
|
|
|
|
// hack the shake in at the very last moment, so it can't cause any consistency problems
|
|
renderView_t hackedView = *view;
|
|
hackedView.viewaxis = hackedView.viewaxis * ShakeAxis();
|
|
|
|
gameRenderWorld->RenderScene( &hackedView );
|
|
|
|
if ( player->spectating ) {
|
|
return;
|
|
}
|
|
|
|
// draw screen blobs
|
|
if ( !pm_thirdPerson.GetBool() && !g_skipViewEffects.GetBool() ) {
|
|
for ( int i = 0 ; i < MAX_SCREEN_BLOBS ; i++ ) {
|
|
screenBlob_t *blob = &screenBlobs[i];
|
|
if ( blob->finishTime <= gameLocal.time ) {
|
|
continue;
|
|
}
|
|
|
|
blob->y += blob->driftAmount;
|
|
|
|
float fade = (float)( blob->finishTime - gameLocal.time ) / ( blob->finishTime - blob->startFadeTime );
|
|
if ( fade > 1.0f ) {
|
|
fade = 1.0f;
|
|
}
|
|
if ( fade ) {
|
|
renderSystem->SetColor4( 1,1,1,fade );
|
|
renderSystem->DrawStretchPic( blob->x, blob->y, blob->w, blob->h, blob->s1, blob->t1, blob->s2, blob->t2, blob->material );
|
|
}
|
|
}
|
|
|
|
// HUMANHEAD: CJR
|
|
if ( voTotalTime != -1 ) { // Check if the viewOverlay should time out
|
|
if ( gameLocal.time >= voFinishTime ) {
|
|
voTotalTime = -1;
|
|
voRequiresScratchBuffer = false;
|
|
viewOverlayMaterial = NULL; // Remove the overlay
|
|
}
|
|
}
|
|
|
|
//HUMANHEAD: aob
|
|
if( viewOverlayMaterial ) {
|
|
renderSystem->SetColor4( viewOverlayColor[0], viewOverlayColor[1], viewOverlayColor[2], viewOverlayColor[3] );
|
|
renderSystem->DrawStretchPic(0, 0, 640, 480, 0, 1, 1, 0, viewOverlayMaterial);
|
|
}
|
|
//HUMANHEAD END
|
|
|
|
if ( player->health > 0 && player->health < 25 && static_cast<hhPlayer*>(player)->IsSpiritOrDeathwalking()==false ) {
|
|
hurtValue += 0.05f*(player->health - hurtValue);
|
|
if( player->health > 30 )
|
|
hurtValue = player->health;
|
|
|
|
renderSystem->SetColor4( hurtValue/25.0f, 1, 1, 1 );
|
|
renderSystem->DrawStretchPic(0, 0, 640, 480, 0, 1, 1, 0, hurtMaterial);
|
|
}
|
|
}
|
|
|
|
// If this level has a sun corona, then attempt to draw it - CJR
|
|
if ( !g_skipViewEffects.GetBool() && gameLocal.GetSunCorona() ) {
|
|
gameLocal.GetSunCorona()->Draw( (hhPlayer *)player );
|
|
}
|
|
|
|
// test a single material drawn over everything
|
|
if ( g_testPostProcess.GetString()[0] ) {
|
|
const idMaterial *mtr = declManager->FindMaterial( g_testPostProcess.GetString(), false );
|
|
if ( !mtr ) {
|
|
common->Printf( "Material not found.\n" );
|
|
g_testPostProcess.SetString( "" );
|
|
} else {
|
|
renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f );
|
|
renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, mtr );
|
|
}
|
|
}
|
|
}
|
|
|
|
// Hermite()
|
|
// Hermite Interpolator
|
|
// Returns an alpha value [0..1] based on Hermite Parameters N1, N2, S1, S2 and an input alpha 't'
|
|
float Hermite(float t, float N1, float N2, float S1, float S2) {
|
|
float tSquared = t*t;
|
|
float tCubed = tSquared*t;
|
|
return (2*tCubed - 3*tSquared + 1)*N1 +
|
|
(-2*tCubed + 3*tSquared)*N2 +
|
|
(tCubed - 2*tSquared + t)*S1 +
|
|
(tCubed - tSquared)*S2;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------
|
|
// MotionBlurVision
|
|
// HUMANHEAD pdm
|
|
//------------------------------------------------------
|
|
|
|
void hhPlayerView::MotionBlurVision(idUserInterface *hud, const renderView_t *view) {
|
|
if ( !g_doubleVision.GetBool() ) {
|
|
SingleView( hud, view );
|
|
return;
|
|
}
|
|
|
|
float alpha;
|
|
const float N1 = 0.2f;
|
|
const float N2 = 0.0f;
|
|
const float S1 = 1.0f;
|
|
const float S2 = 1.0f;
|
|
|
|
float remainingTime = mbFinishTime - gameLocal.time;
|
|
float elapsedTime = mbTotalTime - remainingTime;
|
|
float scale = remainingTime / mbTotalTime;
|
|
|
|
// Render to a texture
|
|
RENDER_DEMO_VIEWRENDER(view, this); //HUMANHEAD rww
|
|
renderSystem->CropRenderSize( 512, 256, true );
|
|
SingleView( hud, view );
|
|
renderSystem->CaptureRenderToImage( "_scratch" );
|
|
renderSystem->UnCrop();
|
|
RENDER_DEMO_VIEWRENDER_END(); //HUMANHEAD rww
|
|
|
|
// Motion blur
|
|
float xshift, yshift;
|
|
for (int index=0; index<g_mbNumBlurs.GetInteger(); index++) {
|
|
|
|
float curtime = elapsedTime - g_mbFrameSpan.GetFloat()*index*scale;
|
|
float blurfactor = (index+1)/g_mbNumBlurs.GetFloat();
|
|
|
|
// Hermite blend here (N1 is severity (0 - 0.5) )
|
|
alpha = curtime/mbTotalTime;
|
|
alpha = Hermite(alpha, N1, N2, S1, S2); // Hermite parms: N1, N2, S1, S2
|
|
|
|
xshift = blurfactor * scale * mbDirection.x * alpha * mbAmplitude;
|
|
yshift = blurfactor * scale * mbDirection.y * alpha * mbAmplitude;
|
|
|
|
#define CLIP(a) ((a)<0?0:(a)>1?1:(a))
|
|
renderSystem->SetColor4( 1,1,1, index==0 ? 1.0f : 0.2f );
|
|
renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
|
|
CLIP(xshift), CLIP(1+yshift), CLIP(1+xshift), CLIP(yshift), scratchMaterial ); // clipped
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// SpiritVision
|
|
// HUMANHEAD cjr
|
|
//------------------------------------------------------
|
|
|
|
void hhPlayerView::SpiritVision( idUserInterface *hud, const renderView_t *view ) {
|
|
int oldTime = voTotalTime;
|
|
const idMaterial *oldMaterial = viewOverlayMaterial;
|
|
|
|
voTotalTime = -1;
|
|
viewOverlayMaterial = NULL;
|
|
|
|
SingleView( hud, view );
|
|
|
|
// Draw the spiritwalk image over the top
|
|
if ( player && !spiritMaterial ) {
|
|
spiritMaterial = declManager->FindMaterial( player->spawnArgs.GetString( "mtr_spiritwalk" ) );
|
|
}
|
|
|
|
renderSystem->SetColor4( 1, 1, 1, 1 );
|
|
renderSystem->DrawStretchPic(0, 0, 640, 480, 0, 1, 1, 0, spiritMaterial );
|
|
|
|
voTotalTime = oldTime;
|
|
viewOverlayMaterial = oldMaterial;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// ApplyLetterbox
|
|
// HUMANHEAD pdm
|
|
//------------------------------------------------------
|
|
void hhPlayerView::ApplyLetterBox(const renderView_t *view) {
|
|
if (bLetterBox) {
|
|
renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f );
|
|
renderSystem->DrawStretchPic(0, 0, 640, LETTERBOX_HEIGHT_TOP, 0, 0, 1, 1, letterboxMaterial);
|
|
renderSystem->DrawStretchPic(0, 480-LETTERBOX_HEIGHT_BOTTOM, 640, LETTERBOX_HEIGHT_BOTTOM, 0, 0, 1, 1, letterboxMaterial);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// MotionBlur
|
|
// HUMANHEAD pdm
|
|
//------------------------------------------------------
|
|
void hhPlayerView::MotionBlur(int mbTime, float severity, idVec3 &direction) {
|
|
mbTotalTime = mbTime;
|
|
mbFinishTime = gameLocal.time + mbTotalTime;
|
|
mbAmplitude = severity;
|
|
mbDirection = direction;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// SetLetterBox
|
|
// HUMANHEAD pdm
|
|
//------------------------------------------------------
|
|
void hhPlayerView::SetLetterBox(bool on) {
|
|
bLetterBox = on;
|
|
}
|
|
|
|
//------------------------------------------------------
|
|
// RenderPlayerView
|
|
//------------------------------------------------------
|
|
void hhPlayerView::RenderPlayerView( idUserInterface *hud ) {
|
|
const renderView_t *view = player->GetRenderView();
|
|
|
|
if ( g_skipViewEffects.GetBool() ) {
|
|
SingleView( hud, view );
|
|
} else {
|
|
if (gameLocal.time < mbFinishTime) {
|
|
MotionBlurVision(hud, view);
|
|
} else if ( ((hhPlayer *)player)->IsSpiritWalking() ) {
|
|
SpiritVision( hud, view );
|
|
} else {
|
|
SingleView(hud, view);
|
|
}
|
|
ScreenFade();
|
|
|
|
// HUMANHEAD pdm: letterbox
|
|
ApplyLetterBox(view);
|
|
}
|
|
|
|
// HUMANHEAD: Draw the HUD after all over overlay effects.
|
|
if (hud) {
|
|
hud->SetStateBool("letterbox", bLetterBox);
|
|
player->DrawHUD( hud );
|
|
}
|
|
|
|
if ( net_clientLagOMeter.GetBool() && lagoMaterial && gameLocal.isClient ) {
|
|
renderSystem->SetColor4( 1.0f, 1.0f, 1.0f, 1.0f );
|
|
renderSystem->DrawStretchPic( 10.0f, 380.0f, 64.0f, 64.0f, 0.0f, 0.0f, 1.0f, 1.0f, lagoMaterial );
|
|
}
|
|
}
|