mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-17 11:00:38 +02:00
Initial Prey Game integration support.
This commit is contained in:
@@ -0,0 +1,314 @@
|
||||
#include "precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "prey_local.h"
|
||||
|
||||
// mdl: Only steam this often to keep performance hits when hitting several pipes
|
||||
#define STEAM_DELAY 1000.0f
|
||||
|
||||
|
||||
hhWoundManagerRenderEntity::hhWoundManagerRenderEntity( const idEntity* self ) {
|
||||
this->self = self;
|
||||
}
|
||||
|
||||
hhWoundManagerRenderEntity::~hhWoundManagerRenderEntity() {
|
||||
}
|
||||
|
||||
void hhWoundManagerRenderEntity::DetermineWoundInfo( const trace_t& trace, const idVec3 velocity, jointHandle_t& jointNum, idVec3& origin, idVec3& normal, idVec3& dir ) {
|
||||
jointNum = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id );
|
||||
|
||||
origin = trace.c.point;
|
||||
normal = trace.c.normal;
|
||||
dir = velocity;
|
||||
dir.Normalize();
|
||||
}
|
||||
|
||||
void hhWoundManagerRenderEntity::AddWounds( const idDeclEntityDef *def, surfTypes_t matterType, jointHandle_t jointNum, const idVec3& origin, const idVec3& normal, const idVec3& dir ) {
|
||||
PROFILE_SCOPE("AddWounds", PROFMASK_COMBAT);
|
||||
if( !def ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do a check so we don't spawn too many steam effects at once
|
||||
if( matterType == SURFTYPE_PIPE ) {
|
||||
if ( gameLocal.time > gameLocal.GetSteamTime() ) {
|
||||
// Mark the current steam time
|
||||
gameLocal.SetSteamTime( gameLocal.time + STEAM_DELAY );
|
||||
} else {
|
||||
// Don't steam on this hit
|
||||
matterType = SURFTYPE_METAL;
|
||||
}
|
||||
}
|
||||
|
||||
ApplyWound( def->dict, gameLocal.MatterTypeToMatterKey("fx_wound", matterType), jointNum, origin, normal, dir ); //smoke_wound conflicted with smoke
|
||||
|
||||
const char* impactMarkKey = gameLocal.MatterTypeToMatterKey("mtr", matterType);
|
||||
ApplyMark( def->dict, impactMarkKey, origin, normal, dir );
|
||||
ApplySplatExit( def->dict, impactMarkKey, origin, normal, dir );
|
||||
}
|
||||
|
||||
void hhWoundManagerRenderEntity::ApplyMark( const idDict& damageDict, const char* impactMarkKey, const idVec3 &origin, const idVec3 &normal, const idVec3 &dir ) {
|
||||
PROFILE_SCOPE("ApplyMark", PROFMASK_COMBAT);
|
||||
idList<idStr> strList;
|
||||
|
||||
const idDict* decalDict = gameLocal.FindEntityDefDict( damageDict.GetString("def_entranceMark_decal"), false );
|
||||
if( !decalDict || !self->spawnArgs.GetBool("accepts_decals", "1") ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( !impactMarkKey || !impactMarkKey[0] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
idStr impactMark = decalDict->RandomPrefix( impactMarkKey, gameLocal.random );
|
||||
if( !impactMark.Length() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( self->IsType(idBrittleFracture::Type) ) {
|
||||
static_cast<idBrittleFracture *>( self.GetEntity() )->ProjectDecal( origin, normal, gameLocal.GetTime(), NULL );
|
||||
} else {
|
||||
hhUtils::SplitString( impactMark, strList );
|
||||
|
||||
//bjk: uses normal now
|
||||
float depth = 10.0f;
|
||||
|
||||
for( int ix = strList.Num() - 1; ix >= 0; --ix ) {
|
||||
gameLocal.ProjectDecal( origin, -normal, depth, true, hhMath::Lerp(decalDict->GetVec2("mark_size"), gameLocal.random.RandomFloat()), strList[ix] ); //HUMANHEAD bjk: using normal
|
||||
}
|
||||
}
|
||||
|
||||
//rww - if we were running this code on the server, we could do this:
|
||||
/*
|
||||
idBitMsg msg;
|
||||
byte msgBuf[MAX_EVENT_PARAM_SIZE];
|
||||
idVec2 markSize;
|
||||
|
||||
msg.Init(msgBuf, sizeof(msgBuf));
|
||||
msg.BeginWriting();
|
||||
msg.WriteFloat(origin[0]);
|
||||
msg.WriteFloat(origin[1]);
|
||||
msg.WriteFloat(origin[2]);
|
||||
msg.WriteDir(normal, 24);
|
||||
msg.WriteDir(dir, 24);
|
||||
|
||||
//AGH. rwwFIXME: configstring type system?
|
||||
msg.WriteString(impactMark);
|
||||
|
||||
if (self->IsType(idBrittleFracture::Type))
|
||||
{
|
||||
msg.WriteBool(true);
|
||||
msg.WriteShort(self.GetEntity()->entityNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.WriteBool(false);
|
||||
markSize = damageDict->GetVec2("mark_size");
|
||||
msg.WriteFloat(markSize[0]);
|
||||
msg.WriteFloat(markSize[1]);
|
||||
}
|
||||
|
||||
self.GetEntity()->BroadcastEventReroute(idEntity::EVENT_PROJECT_DECAL, &msg);
|
||||
*/
|
||||
}
|
||||
|
||||
void hhWoundManagerRenderEntity::ApplyWound( const idDict& damageDict, const char* woundKey, jointHandle_t jointNum, const idVec3 &origin, const idVec3 &normal, const idVec3 &dir ) {
|
||||
PROFILE_SCOPE("ApplyWound", PROFMASK_COMBAT);
|
||||
|
||||
if ( !g_bloodEffects.GetBool() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! (self->fl.acceptsWounds && woundKey && *woundKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idDict* woundDict = gameLocal.FindEntityDefDict( damageDict.GetString("def_entranceWound"), false );
|
||||
if( !woundDict ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char* woundName = woundDict->RandomPrefix( woundKey, gameLocal.random );
|
||||
if( !woundName || !woundName[0] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// for steam sound
|
||||
idStr sndKey = "snd_";
|
||||
sndKey += woundKey;
|
||||
const char *sndName = woundDict->GetString(sndKey.c_str());
|
||||
bool bHasSound = idStr::Length(sndName) > 0;
|
||||
|
||||
/* // Optimization: works but it could cause problems in some of our non-euclidean spaces if
|
||||
// a portal destination is less than 1024 units away
|
||||
if (!bHasSound && !gameLocal.isMultiplayer && gameLocal.GetLocalPlayer()) {
|
||||
// Don't spawn purely visual wounds when behind player
|
||||
idVec3 playerOrigin = gameLocal.GetLocalPlayer()->GetOrigin();
|
||||
idMat3 playerView = gameLocal.GetLocalPlayer()->GetAxis();
|
||||
idVec3 toSpot = origin - playerOrigin;
|
||||
float dist = toSpot.Normalize();
|
||||
|
||||
// Only do this optimization when within some distance to avoid problems with the effects being on the
|
||||
// other side of a portal
|
||||
if (dist < 1024.0f) {
|
||||
float dot = toSpot * playerView[0];
|
||||
|
||||
// If spot is behind me and not right on the border, throw it out
|
||||
if (dot < 0.0f && dist > 64.0f) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
hhFxInfo fxInfo;
|
||||
fxInfo.SetNormal( normal );
|
||||
if( !self.GetEntity()->IsType(idStaticEntity::Type) ) {
|
||||
fxInfo.SetEntity( self.GetEntity() );
|
||||
}
|
||||
fxInfo.RemoveWhenDone( true );
|
||||
//correct for server: self->BroadcastFxInfo( woundName, origin, dir.ToMat3(), &fxInfo );
|
||||
//however this function should -only- be called on the client.
|
||||
if (gameLocal.isServer && !gameLocal.GetLocalPlayer()) {
|
||||
gameLocal.Error("hhWoundManagerRenderEntity::ApplyWound called on non-listen server!");
|
||||
}
|
||||
hhEntityFx *fx = self.GetEntity()->SpawnFxLocal( woundName, origin, normal.ToMat3(), &fxInfo, true );
|
||||
if (fx) {
|
||||
fx->fl.neverDormant = true;
|
||||
|
||||
if (bHasSound) {
|
||||
const idSoundShader *shader = declManager->FindSound( sndName );
|
||||
fx->StartSoundShader(shader, SND_CHANNEL_ANY, 0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void hhWoundManagerRenderEntity::ApplySplatExit( const idDict& damageDict, const char* impactMarkKey, const idVec3 &origin, const idVec3 &normal, const idVec3 &dir ) {
|
||||
PROFILE_SCOPE("ApplySplatExit", PROFMASK_COMBAT);
|
||||
|
||||
if ( !g_bloodEffects.GetBool() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( gameLocal.random.RandomFloat() > 0.8f ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idDict *splatDict = gameLocal.FindEntityDefDict( damageDict.GetString("def_exitSplat"), false );
|
||||
if( !splatDict || !self->spawnArgs.GetBool("produces_splats") ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( !impactMarkKey || !impactMarkKey[0] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char* decal = splatDict->RandomPrefix( impactMarkKey, gameLocal.random );
|
||||
if( !decal || !decal[0] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace_t trace;
|
||||
if( gameLocal.clip.TracePoint(trace, origin, origin+dir*200.0f, MASK_SHOT_RENDERMODEL, self.GetEntity() ) ) {
|
||||
|
||||
surfTypes_t matterType = gameLocal.GetMatterType( self.GetEntity(), trace.c.material, "ApplySplatExit" );
|
||||
|
||||
gameLocal.ProjectDecal( trace.endpos,
|
||||
-trace.c.normal,
|
||||
splatDict->GetFloat("splat_dist", "10"),
|
||||
true,
|
||||
hhMath::Lerp(splatDict->GetVec2("mark_size"),
|
||||
gameLocal.random.RandomFloat()), decal );
|
||||
}
|
||||
}
|
||||
|
||||
hhWoundManagerAnimatedEntity::hhWoundManagerAnimatedEntity( const idEntity* self ) : hhWoundManagerRenderEntity(self) {
|
||||
}
|
||||
|
||||
hhWoundManagerAnimatedEntity::~hhWoundManagerAnimatedEntity() {
|
||||
}
|
||||
|
||||
void hhWoundManagerAnimatedEntity::ApplyMark( const idDict& damageDict, const char* impactMarkKey, const idVec3 &origin, const idVec3 &normal, const idVec3 &dir ) {
|
||||
idList<idStr> strList;
|
||||
|
||||
const idDict* overlayDict = gameLocal.FindEntityDefDict( damageDict.GetString("def_entranceMark_overlay"), false );
|
||||
if( !overlayDict || !self->spawnArgs.GetBool("accepts_decals", "1") ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( !impactMarkKey && !impactMarkKey[0] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
idStr impactMark = overlayDict->RandomPrefix( impactMarkKey, gameLocal.random );
|
||||
if( !impactMark.Length() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
hhUtils::SplitString( impactMark, strList );
|
||||
for( int ix = strList.Num() - 1; ix >= 0; --ix ) {
|
||||
self->ProjectOverlay( origin, dir, overlayDict->GetFloat("mark_size"), strList[ix] );
|
||||
}
|
||||
}
|
||||
|
||||
void hhWoundManagerAnimatedEntity::ApplyWound( const idDict& damageDict, const char* woundKey, jointHandle_t jointNum, const idVec3 &origin, const idVec3 &normal, const idVec3 &dir ) {
|
||||
|
||||
if (! (self->fl.acceptsWounds && woundKey && *woundKey && jointNum != INVALID_JOINT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idDict* woundDict = gameLocal.FindEntityDefDict( damageDict.GetString("def_entranceWound"), false );
|
||||
if( !woundDict ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char* woundName = woundDict->RandomPrefix( woundKey, gameLocal.random );
|
||||
if( !woundName || !woundName[0] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if !GOLD
|
||||
//correct for server: self->BroadcastFxInfo( woundName, origin, dir.ToMat3(), &fxInfo );
|
||||
//however this function should -only- be called on the client.
|
||||
if (gameLocal.isServer && !gameLocal.GetLocalPlayer()) {
|
||||
gameLocal.Error("hhWoundManagerRenderEntity::ApplyWound called on non-listen server!");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
hhFxInfo fxInfo;
|
||||
fxInfo.SetNormal( normal );
|
||||
fxInfo.SetEntity( self.GetEntity() );
|
||||
fxInfo.RemoveWhenDone( true );
|
||||
|
||||
hhEntityFx* fx = self.GetEntity()->SpawnFxLocal( woundName, origin, normal.ToMat3(), &fxInfo, true );
|
||||
if (fx) {
|
||||
fx->fl.neverDormant = true;
|
||||
fx->BindToJoint( self.GetEntity(), jointNum, true);
|
||||
}
|
||||
#else //rww - do this in some way that is less hideous and slow (specialcased here, cause this function gets a lot of use)
|
||||
//(avoids binding twice and some other needless logic)
|
||||
if ( !g_skipFX.GetBool() ) {
|
||||
idDict fxArgs;
|
||||
|
||||
fxArgs.Set( "fx", woundName );
|
||||
fxArgs.SetBool( "start", true );
|
||||
fxArgs.SetBool( "removeWhenDone", true );
|
||||
fxArgs.SetVector( "origin", origin );
|
||||
fxArgs.SetMatrix( "rotation", normal.ToMat3() );
|
||||
|
||||
hhEntityFx *fx = (hhEntityFx *)gameLocal.SpawnClientObject( "func_fx", &fxArgs );
|
||||
if (fx) {
|
||||
hhFxInfo fxInfo;
|
||||
fxInfo.SetNormal( normal );
|
||||
fxInfo.SetEntity( self.GetEntity() );
|
||||
fxInfo.RemoveWhenDone( true );
|
||||
fx->SetFxInfo( fxInfo );
|
||||
|
||||
fx->fl.neverDormant = true;
|
||||
fx->BindToJoint( self.GetEntity(), jointNum, true );
|
||||
fx->Show();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user