Skip to content

Commit

Permalink
Quake4: add view body support in first person viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
glKarin committed Sep 15, 2024
1 parent 5daec39 commit 6d7d4f9
Show file tree
Hide file tree
Showing 8 changed files with 1,393 additions and 0 deletions.
1 change: 1 addition & 0 deletions Q3E/src/main/jni/doom3/neo/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2040,6 +2040,7 @@ if(QUAKE4)
set(q4_compile_definitions "GAME_DLL;_RAVEN;_QUAKE4")
if(Q4_MOD_FULL_BODY_AWARENESS)
set(q4_compile_definitions "${q4_compile_definitions};_MOD_FULL_BODY_AWARENESS")
set(q4_compile_definitions "${q4_compile_definitions};_MOD_VIEW_BODY")
message(STATUS "Build quake4 full body awareness mod support")
endif()
if(Q4_MOD_BOTS)
Expand Down
141 changes: 141 additions & 0 deletions Q3E/src/main/jni/doom3/neo/quake4/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
#include "../sys/xenon/xen_input.h"
#endif
// RAVEN END
#ifdef _MOD_VIEW_BODY
#include "ViewBody.cpp"
#endif

idCVar net_predictionErrorDecay( "net_predictionErrorDecay", "112", CVAR_FLOAT | CVAR_GAME | CVAR_NOCHEAT, "time in milliseconds it takes to fade away prediction errors", 0.0f, 200.0f );
idCVar net_showPredictionError( "net_showPredictionError", "-1", CVAR_INTEGER | CVAR_GAME | CVAR_NOCHEAT, "show prediction errors for the given client", -1, MAX_CLIENTS );
Expand Down Expand Up @@ -1415,6 +1418,10 @@ void idPlayer::SetWeapon( int weaponIndex ) {
if ( !weaponEnabled ) {
Event_DisableWeapon( );
}
#ifdef _MOD_VIEW_BODY
if(viewBody)
viewBody->UpdateWeapon();
#endif
}

/*
Expand Down Expand Up @@ -1569,6 +1576,9 @@ void idPlayer::Init( void ) {
bobCycle = 0;

SetupWeaponEntity( );
#ifdef _MOD_VIEW_BODY
SetupViewBody();
#endif
currentWeapon = -1;
previousWeapon = -1;

Expand Down Expand Up @@ -1970,6 +1980,9 @@ void idPlayer::Spawn( void ) {
if ( !gameLocal.isClient ) {
// set yourself ready to spawn. idMultiplayerGame will decide when/if appropriate and call SpawnFromSpawnSpot
SetupWeaponEntity( );
#ifdef _MOD_VIEW_BODY
SetupViewBody();
#endif
SpawnFromSpawnSpot( );
spectator = entityNumber;
forceRespawn = true;
Expand All @@ -1980,6 +1993,9 @@ void idPlayer::Spawn( void ) {
{
// set yourself ready to spawn. idMultiplayerGame will decide when/if appropriate and call SpawnFromSpawnSpot
SetupWeaponEntity( );
#ifdef _MOD_VIEW_BODY
SetupViewBody();
#endif
SpawnFromSpawnSpot( );
spectator = entityNumber;
forceRespawn = true;
Expand All @@ -1988,6 +2004,9 @@ void idPlayer::Spawn( void ) {
#endif
} else {
SetupWeaponEntity( );
#ifdef _MOD_VIEW_BODY
SetupViewBody();
#endif
SpawnFromSpawnSpot( );
}

Expand Down Expand Up @@ -2105,6 +2124,9 @@ idPlayer::~idPlayer() {
delete weaponWorldModel;
delete weapon;
delete aasSensor;
#ifdef _MOD_VIEW_BODY
delete viewBody;
#endif

SetPhysics( NULL );
}
Expand Down Expand Up @@ -8187,6 +8209,13 @@ void idPlayer::Spectate( bool spectate, bool force ) {
weaponViewModel = NULL;
delete weaponWorldModel;
weaponWorldModel = NULL;
#ifdef _MOD_VIEW_BODY
if(viewBody)
{
delete viewBody;
viewBody = NULL;
}
#endif
}
} else {
// put everything back together again
Expand Down Expand Up @@ -9734,6 +9763,9 @@ void idPlayer::Think( void ) {
UpdateSpectating();
} else if ( health > 0 && !gameLocal.inCinematic ) {
UpdateWeapon();
#ifdef _MOD_VIEW_BODY
UpdateBody();
#endif
}

UpdateAir();
Expand Down Expand Up @@ -12199,6 +12231,11 @@ void idPlayer::LocalClientPredictionThink( void ) {
if ( !gameLocal.inCinematic && weaponViewModel && ( health > 0 ) && !( gameLocal.isMultiplayer && spectating ) ) {
UpdateWeapon();
}
#ifdef _MOD_VIEW_BODY
if ( !gameLocal.inCinematic && viewBody && ( health > 0 ) && !( gameLocal.isMultiplayer && spectating ) ) {
UpdateBody();
}
#endif

UpdateHud();

Expand Down Expand Up @@ -12380,6 +12417,11 @@ void idPlayer::NonLocalClientPredictionThink( void ) {
if ( !gameLocal.inCinematic && weaponViewModel && ( health > 0 ) && !( gameLocal.isMultiplayer && spectating ) ) {
UpdateWeapon();
}
#ifdef _MOD_VIEW_BODY
if ( !gameLocal.inCinematic && viewBody && ( health > 0 ) && !( gameLocal.isMultiplayer && spectating ) ) {
UpdateBody();
}
#endif

if ( gameLocal.isLastPredictFrame ) {
// this may use firstPersonView, or a thirdPerson / camera view
Expand Down Expand Up @@ -14397,3 +14439,102 @@ int idPlayer::CanSelectWeapon(const char* weaponName)
}

// RITUAL END

#ifdef _MOD_VIEW_BODY
/*
==============
idPlayer::SetupViewBody
==============
*/
void idPlayer::SetupViewBody( void ) {
int w;
const char *weap;
const idDeclEntityDef *decl;
idEntity *spawn;

// don't setup weapons for spectators
#ifdef MOD_BOTS
if ( !IS_BOT() && ( gameLocal.isClient || viewBody || spectating ) )
#else
if ( gameLocal.isClient || viewBody || spectating )
#endif
{
return;
}

idDict args;

#define VIEW_BODY_DEFAULT_CLASSNAME "player_viewbody"
if ( !viewBody ) {
// setup the view model
idStr player_viewbody_classname;
spawnArgs.GetString("player_viewbody", VIEW_BODY_DEFAULT_CLASSNAME, player_viewbody_classname);

if(!player_viewbody_classname.Length())
player_viewbody_classname = VIEW_BODY_DEFAULT_CLASSNAME;

decl = static_cast< const idDeclEntityDef * >( declManager->FindType( DECL_ENTITYDEF, player_viewbody_classname, false, false ) );
if ( !decl ) {
gameLocal.Warning( "entityDef not found: '%s'", player_viewbody_classname.c_str() );
if( idStr::Cmp(player_viewbody_classname, VIEW_BODY_DEFAULT_CLASSNAME) )
{
player_viewbody_classname = VIEW_BODY_DEFAULT_CLASSNAME;
decl = static_cast< const idDeclEntityDef * >( declManager->FindType( DECL_ENTITYDEF, player_viewbody_classname, false, false ) );
}
}
if ( !decl ) {
gameLocal.Warning( "entityDef not found: '%s'", player_viewbody_classname.c_str() );
return;
}

args.Set( "name", va( "%s_viewBody", name.c_str() ) );
args.SetInt( "instance", instance );
args.Set( "classname", decl->GetName() );
spawn = NULL;
gameLocal.SpawnEntityDef( args, &spawn );
if ( !spawn ) {
gameLocal.Warning( "idPlayer::SetupViewBody: failed to spawn viewBody" );
return;
}
viewBody = static_cast<idViewBody*>(spawn);
viewBody->Init( this, true );
viewBody->SetName( va("%s_viewBody", name.c_str() ) );
viewBody->SetInstance( instance );
gameLocal.Printf( "idPlayer::SetupViewBody: spawn viewBody -> %s\n", viewBody->GetName() );
}

viewBody->fl.persistAcrossInstances = true;
}

/*
===============
idPlayer::UpdateBody
===============
*/
void idPlayer::UpdateBody( void ) {
if ( !viewBody ) {
return;
}

if ( health <= 0 ) {
return;
}

assert( !spectating );

// clients need to wait till the weapon and it's world model entity
// are present and synchronized ( weapon.worldModel idEntityPtr to idAnimatedEntity )
if ( gameLocal.isClient && !viewBody ) {
return;
}

// if ( hiddenWeapon )

// update weapon state, particles, dlights, etc
viewBody->PresentBody( harm_ui_showViewBody.GetBool()
#ifdef _MOD_FULL_BODY_AWARENESS
&& !harm_pm_fullBodyAwareness.GetBool()
#endif
);
}
#endif
9 changes: 9 additions & 0 deletions Q3E/src/main/jni/doom3/neo/quake4/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,9 @@ class idInventory {
int secretAreasDiscovered;
};

#ifdef _MOD_VIEW_BODY
class idViewBody;
#endif
class idPlayer : public idActor {
#ifdef MOD_BOTS
friend class botAi;
Expand Down Expand Up @@ -432,6 +435,12 @@ class idPlayer : public idActor {
idVec3 firstPersonViewOrigin_viewWeaponOrigin; // launch
idVec3 fullBodyAwarenessOffset;
#endif
#ifdef _MOD_VIEW_BODY
idEntityPtr<idViewBody> viewBody;
void SetupViewBody( void );
void UpdateBody(void);
friend class idViewBody;
#endif

public:
CLASS_PROTOTYPE( idPlayer );
Expand Down
Loading

0 comments on commit 6d7d4f9

Please sign in to comment.