diff --git a/game/AFEntity.cpp b/game/AFEntity.cpp index 8b422b6..bb8ad58 100644 --- a/game/AFEntity.cpp +++ b/game/AFEntity.cpp @@ -1104,6 +1104,8 @@ idAFEntity_Gibbable::SpawnGibs */ void idAFEntity_Gibbable::SpawnGibs( const idVec3 &dir, const char *damageDefName ) { int i; + float gibTime; // darknar + float gibPower; // darknar bool gibNonSolid; idVec3 entityCenter, velocity; idList list; @@ -1115,6 +1117,9 @@ void idAFEntity_Gibbable::SpawnGibs( const idVec3 &dir, const char *damageDefNam gameLocal.Error( "Unknown damageDef '%s'", damageDefName ); } + gibTime = g_gib_remove_time.GetFloat(); // darknar + gibPower = g_gib_power.GetFloat(); // darknar + // spawn gib articulated figures idAFEntity_Base::DropAFs( this, "gib", &list ); @@ -1131,16 +1136,32 @@ void idAFEntity_Gibbable::SpawnGibs( const idVec3 &dir, const char *damageDefNam list[i]->GetPhysics()->UnlinkClip(); list[i]->GetPhysics()->PutToRest(); } else { - list[i]->GetPhysics()->SetContents( CONTENTS_CORPSE ); + //list[i]->GetPhysics()->SetContents( CONTENTS_CORPSE ); + list[i]->GetPhysics()->SetContents(0); // darknar list[i]->GetPhysics()->SetClipMask( CONTENTS_SOLID ); velocity = list[i]->GetPhysics()->GetAbsBounds().GetCenter() - entityCenter; velocity.NormalizeFast(); velocity += ( i & 1 ) ? dir : -dir; - list[i]->GetPhysics()->SetLinearVelocity( velocity * 75.0f ); + // list[i]->GetPhysics()->SetLinearVelocity( velocity * 75.0f ); + list[i]->GetPhysics()->SetLinearVelocity(velocity * gibPower); // darknar gib power } - list[i]->GetRenderEntity()->noShadow = true; - list[i]->GetRenderEntity()->shaderParms[ SHADERPARM_TIME_OF_DEATH ] = gameLocal.time * 0.001f; - list[i]->PostEventSec(&EV_Remove, 90000.0f); // Blood Mod 4.0 to 90000 Increases the time until gibs disappear. This is probably not enough to fully customize the disappearance since all gibs still disappear after exactly 5 minutes. + + // darknar start change + /* + list[i]->GetRenderEntity()->noShadow = true; + list[i]->GetRenderEntity()->shaderParms[ SHADERPARM_TIME_OF_DEATH ] = gameLocal.time * 0.001f; + list[i]->PostEventSec(&EV_Remove, 4.0f); + */ + + if (!g_gib_shadows.GetBool()) { + list[i]->GetRenderEntity()->noShadow = true; // shadows can be optional, 1 = enable shadows, 0 = no shadows ( default ) + } + + //list[i]->GetRenderEntity()->shaderParms[SHADERPARM_TIME_OF_DEATH] = gameLocal.time * 0.001f; // disable burn effect for now + if (gibTime > 0.0f) { // darknar, if the float is > to 0, do the remove after x seconds + list[i]->PostEventSec(&EV_Remove, gibTime); // darknar, define a float in Cvar, gibs are removed after thes time + } + // darknar end change } } @@ -1173,7 +1194,7 @@ void idAFEntity_Gibbable::Gib( const idVec3 &dir, const char *damageDefName ) { UnlinkCombat(); if ( g_bloodEffects.GetBool() ) { - // Blood Mod. Taken from the repository (https://github.com/RobertBeckebans/Sikkpin-Feedback) + // Blood Mod - Taken from the repository (https://github.com/RobertBeckebans/Sikkpin-Feedback) // sikk - Since "nextGibTime" is a member of idGameLocal and not idAFEntity||idAFEntity_Gibbable // the folloing if statement is only true once per damage event instead of per entity being damaged. // This is why only one entity will get gibbed while the rest just disappear after a few seconds. diff --git a/game/Actor.cpp b/game/Actor.cpp index a141111..7c3c5a6 100644 --- a/game/Actor.cpp +++ b/game/Actor.cpp @@ -2191,7 +2191,7 @@ void idActor::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir health = -999; } Killed( inflictor, attacker, damage, dir, location ); - if ( ( health <= 0 ) && spawnArgs.GetBool( "gib" ) && damageDef->GetBool( "gib" ) ) { // Blood Mod change "< -20" to "<= 0". Makes zombies drop gibs immediately after death + if ( ( health <= spawnArgs.GetInt( va( "health_gib" ), "0" ) ) && spawnArgs.GetBool( "gib" ) && damageDef->GetBool( "gib" ) ) { // Blood Mod - Uses a custom value for gibbing, 0 = default Gib( dir, damageDefName ); } } else { diff --git a/game/Entity.cpp b/game/Entity.cpp index c631a43..26f4bac 100644 --- a/game/Entity.cpp +++ b/game/Entity.cpp @@ -4902,6 +4902,8 @@ idAnimatedEntity::idAnimatedEntity idAnimatedEntity::idAnimatedEntity() { animator.SetEntity( this ); damageEffects = NULL; + nextBloodPoolTime = 0; // Blood Mod + nextSplatTime = 0; // Blood Mod } /* @@ -5168,21 +5170,12 @@ int idAnimatedEntity::GetDefaultSurfaceType( void ) const { idAnimatedEntity::AddLocalDamageEffect ============== */ -// FIXME: the code behind _DENTONMOD_ENTITY_CPP is not used, or can't be used, because the calls to this function all -// use the old signature without soundEnt (which isn't used at all in the implementation of this function?!) -// and because TH_UPDATEWOUNDPARTICLES isn't defined anywhere -#ifdef _DENTONMOD_ENTITY_CPP -void idAnimatedEntity::AddLocalDamageEffect( jointHandle_t jointNum, const idVec3 &origin, const idVec3 &normal, const idVec3 &dir, const idDeclEntityDef *def, const idMaterial *collisionMaterial /*, idEntity *soundEnt */ ) { -#else void idAnimatedEntity::AddLocalDamageEffect( jointHandle_t jointNum, const idVec3 &localOrigin, const idVec3 &localNormal, const idVec3 &localDir, const idDeclEntityDef *def, const idMaterial *collisionMaterial ) { -#endif const char *sound, *splat, *decal, *bleed, *key; damageEffect_t *de; idVec3 gravDir; idPhysics *phys; -#ifdef _DENTONMOD_ENTITY_CPP -#else idMat3 axis; idVec3 origin, dir; axis = renderEntity.joints[jointNum].ToMat3() * renderEntity.axis; @@ -5190,7 +5183,6 @@ void idAnimatedEntity::AddLocalDamageEffect( jointHandle_t jointNum, const idVec origin = origin + localOrigin * axis; dir = localDir * axis; -#endif int type = collisionMaterial->GetSurfaceType(); @@ -5213,19 +5205,32 @@ void idAnimatedEntity::AddLocalDamageEffect( jointHandle_t jointNum, const idVec StartSoundShader( declManager->FindSound( sound ), SND_CHANNEL_BODY, 0, false, NULL ); } - // blood splats are thrown onto nearby surfaces - key = va( "mtr_splat_%s", materialType ); - splat = spawnArgs.RandomPrefix( key, gameLocal.random ); + //if (health > 0) { + int splatTime; - if ( *splat == '\0' ) { - splat = def->dict.RandomPrefix( key, gameLocal.random ); + if (gameLocal.time > nextSplatTime) { + // blood splats are thrown onto nearby surfaces + key = va("mtr_splat_%s", materialType); + splat = spawnArgs.RandomPrefix(key, gameLocal.random); + + if (*splat == '\0') { + splat = def->dict.RandomPrefix(key, gameLocal.random); + } + + if (*splat != '\0') { + //gameLocal.BloodSplat(origin, dir, 64.0f, splat); + gameLocal.BloodSplat( origin, dir, def->dict.GetFloat( va("size_splat_%s", materialType), "64.0f"), splat ); // Blood Mod - Set blood splat size, 64 = default + } + + // Blood Mod - Set a delay for the next blood splat to appear, 300 = default + if (!spawnArgs.GetInt("next_splat_time", "300", splatTime)) { + splatTime = def->dict.GetInt( va("next_splat_time"), "300"); + } + nextSplatTime = gameLocal.time + splatTime; } + //} - if ( *splat != '\0' ) { - gameLocal.BloodSplat( origin, dir, 64.0f, splat ); - } - - //Create blood pools at feet, Only when alive - By Clone JCD + //Create blood pools at feet, Only when alive - By Clone JCD if (health > 0){ int bloodpoolTime; @@ -5246,22 +5251,21 @@ void idAnimatedEntity::AddLocalDamageEffect( jointHandle_t jointNum, const idVec gameLocal.BloodSplat( origin, gravDir, def->dict.GetFloat ( va ("size_bloodPool_%s", materialType), "64.0f"), splat ); } } - /* Blood Mod deleted this + // This condition makes sure that we dont spawn overlapping bloodpools in a single frame. - if(!spawnArgs.GetInt( "next_bloodpool_time", "050", bloodpoolTime) ){ - bloodpoolTime = def->dict.GetInt( "next_bloodpool_time", "050"); + if(!spawnArgs.GetInt( "next_bloodpool_time", "500", bloodpoolTime) ){ + bloodpoolTime = def->dict.GetInt( va("next_bloodpool_time"), "500"); } nextBloodPoolTime = gameLocal.time + bloodpoolTime; // This avoids excessive bloodpool overlapping - */ } } // can't see wounds on the player model in single player mode. - // Blood Mod deleted this. Needed for the Full Body Awareness mod so that wounds from zombie shots appear on the player\92s body + // Blood Mod deleted this. Needed for the Full Body Awareness mod so that wounds from zombie shots appear on the player body //if ( !( IsType( idPlayer::Type ) && !gameLocal.isMultiplayer ) ) { - // blood splats can be thrown on the body itself two - By Clone JC Denton + // blood splats can be thrown on the body itself two - By Clone JC Denton key = va( "mtr_splatSelf_%s", materialType ); splat = spawnArgs.RandomPrefix( key, gameLocal.random ); if ( *splat == '\0' ) { @@ -5310,24 +5314,9 @@ void idAnimatedEntity::AddLocalDamageEffect( jointHandle_t jointNum, const idVec de->jointNum = jointNum; de->type = static_cast(declManager->FindType(DECL_PARTICLE, bleed)); -#ifdef _DENTONMOD_ENTITY_CPP - idVec3 boneOrigin; - idMat3 boneAxis; - - boneAxis = renderEntity.joints[jointNum].ToMat3() * renderEntity.axis; - boneOrigin = renderEntity.origin + renderEntity.joints[jointNum].ToVec3() * renderEntity.axis; - - de->localOrigin = ( origin - boneOrigin ) * boneAxis.Transpose(); - de->localNormal = normal * boneAxis.Transpose(); - de->time = -1; // used as flag, notifies UpdateDamageEffects that this effect is just started - - if (!(thinkFlags & TH_UPDATEWOUNDPARTICLES)) // if flag was not set before set it now - BecomeActive( TH_UPDATEWOUNDPARTICLES ); -#else de->localOrigin = localOrigin; de->localNormal = localNormal; de->time = gameLocal.time; -#endif } } diff --git a/game/Entity.h b/game/Entity.h index 871cb06..36f988d 100644 --- a/game/Entity.h +++ b/game/Entity.h @@ -39,13 +39,6 @@ If you have questions concerning this license or the applicable additional terms #include "gamesys/Event.h" #include "Game_local.h" -// the following is from bloodmod -#ifdef _DENTONMOD -#ifndef _DENTONMOD_ENTITY_CPP -#define _DENTONMOD_ENTITY_CPP -#endif -#endif - /* =============================================================================== @@ -530,6 +523,7 @@ protected: private: int nextBloodPoolTime; // Blood Mod + int nextSplatTime; // Blood Mod void Event_GetJointHandle( const char *jointname ); void Event_ClearAllJoints( void ); diff --git a/game/Item.cpp b/game/Item.cpp index 97ae952..a230a92 100644 --- a/game/Item.cpp +++ b/game/Item.cpp @@ -870,6 +870,7 @@ idMoveableItem::idMoveableItem() { trigger = NULL; smoke = NULL; smokeTime = 0; + nextSoundTime = 0; // darknar collide data } /* @@ -895,6 +896,8 @@ void idMoveableItem::Save( idSaveGame *savefile ) const { savefile->WriteParticle( smoke ); savefile->WriteInt( smokeTime ); + savefile->WriteString(fxCollide); // darknar collide data + savefile->WriteInt(nextSoundTime); // darknar collide data } /* @@ -910,6 +913,8 @@ void idMoveableItem::Restore( idRestoreGame *savefile ) { savefile->ReadParticle( smoke ); savefile->ReadInt( smokeTime ); + savefile->ReadString(fxCollide); // darknar collide data + savefile->ReadInt(nextSoundTime); // darknar collide data } /* @@ -946,6 +951,7 @@ void idMoveableItem::Spawn( void ) { trm.Shrink( CM_CLIP_EPSILON ); } + fxCollide = spawnArgs.GetString("fx_collide"); // darknar collide data // get rigid body properties spawnArgs.GetFloat( "density", "0.5", density ); density = idMath::ClampFloat( 0.001f, 1000.0f, density ); @@ -968,6 +974,7 @@ void idMoveableItem::Spawn( void ) { smoke = NULL; smokeTime = 0; + nextSoundTime = 0; // darknar collide data const char *smokeName = spawnArgs.GetString( "smoke_trail" ); if ( *smokeName != '\0' ) { smoke = static_cast( declManager->FindType( DECL_PARTICLE, smokeName ) ); @@ -1000,6 +1007,32 @@ void idMoveableItem::Think( void ) { Present(); } +/* +================= +idMoveableItem::Collide // darknar collide data, allows idMoveableGibItem and idMoveableItem spawn a collide fx when collides. I was using a idMoveable to make the gib splats, if that was causing lag, this can help to make the blood decals. +================= +*/ + +bool idMoveableItem::Collide(const trace_t& collision, const idVec3& velocity) { + float v, f; + + v = -(velocity * collision.c.normal); + if (v > 80 && gameLocal.time > nextSoundTime) { + if (fxCollide.Length()) { + idEntityFx::StartFx(fxCollide, &collision.c.point, NULL, this, false); + } + f = v > 200 ? 1.0f : idMath::Sqrt(v - 80) * 0.091f; + if (StartSound("snd_bounce", SND_CHANNEL_ANY, 0, false, NULL)) { + // don't set the volume unless there is a bounce sound as it overrides the entire channel + // which causes footsteps on ai's to not honor their shader parms + SetSoundVolume(f); + } + nextSoundTime = gameLocal.time + 500; + } + + return false; +} + /* ================ idMoveableItem::Pickup @@ -1039,14 +1072,19 @@ idEntity *idMoveableItem::DropItem( const char *classname, const idVec3 &origin, item->GetPhysics()->SetAxis( axis ); item->GetPhysics()->SetLinearVelocity( velocity ); item->UpdateVisuals(); + + // Blood Mod + /* if ( activateDelay ) { item->PostEventMS( &EV_Activate, activateDelay, item ); } + if ( !removeDelay ) { removeDelay = 5 * 60 * 1000; } // always remove a dropped item after 5 minutes in case it dropped to an unreachable location item->PostEventMS( &EV_Remove, removeDelay ); + */ } return item; } @@ -1356,3 +1394,16 @@ void idObjectiveComplete::Event_HideObjective( idEntity *e ) { } } } + +// darknar start change + +/* +================ +idMoveableGibItem +================ +*/ + +CLASS_DECLARATION(idMoveableItem, idMoveableGibItem) +END_CLASS + +// darknar end change diff --git a/game/Item.h b/game/Item.h index acf7c0c..b232167 100644 --- a/game/Item.h +++ b/game/Item.h @@ -161,6 +161,7 @@ public: void Spawn( void ); virtual void Think( void ); + virtual bool Collide(const trace_t& collision, const idVec3& velocity); // darknar, probably this can be useful if the splat fx moveable gib was causing lag. Allow idMoveableItem class spawn fx on collision virtual bool Pickup( idPlayer *player ); static void DropItems( idAnimatedEntity *ent, const char *type, idList *list ); @@ -174,7 +175,8 @@ private: idClipModel * trigger; const idDeclParticle * smoke; int smokeTime; - + int nextSoundTime; // darknar, fx collide data + idStr fxCollide; // darknar, fx collide data void Gib( const idVec3 &dir, const char *damageDefName ); void Event_DropToFloor( void ); @@ -226,4 +228,18 @@ private: void Event_GetPlayerPos(); }; +// darknar start change + +/* +=============================================================================== +idMoveableGibItem +=============================================================================== +*/ +class idMoveableGibItem : public idMoveableItem { +public: + CLASS_PROTOTYPE(idMoveableGibItem); +}; + +// darknar end change + #endif /* !__GAME_ITEM_H__ */ diff --git a/game/Mover.cpp b/game/Mover.cpp index 9f1a819..608300f 100644 --- a/game/Mover.cpp +++ b/game/Mover.cpp @@ -1004,6 +1004,12 @@ void idMover::Event_PartBlocked( idEntity *blockingEntity ) { if ( g_debugMover.GetBool() ) { gameLocal.Printf( "%d: '%s' blocked by '%s'\n", gameLocal.time, name.c_str(), blockingEntity->name.c_str() ); } + if (blockingEntity->IsType(idMoveableItem::Type)) { // Blood Mod + blockingEntity->PostEventMS(&EV_Remove, 0); + } + if (blockingEntity->IsType(idMoveableGibItem::Type)) { // darknar, remove gib if is blocking the mover. + blockingEntity->PostEventMS(&EV_Remove, 0); + } } /* @@ -3790,6 +3796,12 @@ void idDoor::Event_PartBlocked( idEntity *blockingEntity ) { if ( damage > 0.0f ) { blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT ); } + if (blockingEntity->IsType(idMoveableItem::Type)) { // Blood Mod + blockingEntity->PostEventMS(&EV_Remove, 0); + } + if (blockingEntity->IsType(idMoveableItem::Type)) { // darknar, remove gib if is blocking the mover. + blockingEntity->PostEventMS(&EV_Remove, 0); + } } /* @@ -4227,6 +4239,12 @@ void idPlat::Event_PartBlocked( idEntity *blockingEntity ) { if ( damage > 0.0f ) { blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT ); } + if (blockingEntity->IsType(idMoveableItem::Type)) { // Blood Mod + blockingEntity->PostEventMS(&EV_Remove, 0); + } + if (blockingEntity->IsType(idMoveableItem::Type)) { // darknar, remove gib if is blocking the mover. + blockingEntity->PostEventMS(&EV_Remove, 0); + } } @@ -4318,6 +4336,12 @@ void idMover_Periodic::Event_PartBlocked( idEntity *blockingEntity ) { if ( damage > 0.0f ) { blockingEntity->Damage( this, this, vec3_origin, "damage_moverCrush", damage, INVALID_JOINT ); } + if (blockingEntity->IsType(idMoveableItem::Type)) { // Blood Mod + blockingEntity->PostEventMS(&EV_Remove, 0); + } + if (blockingEntity->IsType(idMoveableItem::Type)) { // darknar, remove gib if is blocking the mover. + blockingEntity->PostEventMS(&EV_Remove, 0); + } } /* diff --git a/game/gamesys/SysCmds.cpp b/game/gamesys/SysCmds.cpp index 105ff57..4c3834b 100644 --- a/game/gamesys/SysCmds.cpp +++ b/game/gamesys/SysCmds.cpp @@ -261,6 +261,21 @@ void Cmd_KillMovables_f( const idCmdArgs &args ) { KillEntities( args, idMoveable::Type ); } +// darknar start change +/* +================== +Cmd_ClearGibs_f +Kill all gib moveable in a level. +================== +*/ +void Cmd_ClearGibs_f(const idCmdArgs& args) { + if (!gameLocal.GetLocalPlayer()) { + return; + } + KillEntities(args, idMoveableGibItem::Type); +} +// darknar end change + /* ================== Cmd_KillRagdolls_f @@ -2334,6 +2349,13 @@ void idGameLocal::InitConsoleCommands( void ) { cmdSystem->AddCommand( "remove", Cmd_Remove_f, CMD_FL_GAME|CMD_FL_CHEAT, "removes an entity", idGameLocal::ArgCompletion_EntityName ); cmdSystem->AddCommand( "killMonsters", Cmd_KillMonsters_f, CMD_FL_GAME|CMD_FL_CHEAT, "removes all monsters" ); cmdSystem->AddCommand( "killMoveables", Cmd_KillMovables_f, CMD_FL_GAME|CMD_FL_CHEAT, "removes all moveables" ); + + // darlnar start change + + cmdSystem->AddCommand( "ClearGibs", Cmd_ClearGibs_f, CMD_FL_GAME | CMD_FL_CHEAT, "removes all gibs spawned" ); + + // darknar end change + cmdSystem->AddCommand( "killRagdolls", Cmd_KillRagdolls_f, CMD_FL_GAME|CMD_FL_CHEAT, "removes all ragdolls" ); cmdSystem->AddCommand( "addline", Cmd_AddDebugLine_f, CMD_FL_GAME|CMD_FL_CHEAT, "adds a debug line" ); cmdSystem->AddCommand( "addarrow", Cmd_AddDebugLine_f, CMD_FL_GAME|CMD_FL_CHEAT, "adds a debug arrow" ); diff --git a/game/gamesys/SysCvar.cpp b/game/gamesys/SysCvar.cpp index e2d64e7..8181e09 100644 --- a/game/gamesys/SysCvar.cpp +++ b/game/gamesys/SysCvar.cpp @@ -335,3 +335,8 @@ idCVar mod_validSkins( "mod_validSkins", "skins/characters/player/marine_mp idCVar net_serverDownload( "net_serverDownload", "0", CVAR_GAME | CVAR_INTEGER | CVAR_ARCHIVE, "enable server download redirects. 0: off 1: redirect to si_serverURL 2: use builtin download. see net_serverDl cvars for configuration" ); idCVar net_serverDlBaseURL( "net_serverDlBaseURL", "", CVAR_GAME | CVAR_ARCHIVE, "base URL for the download redirection" ); idCVar net_serverDlTable( "net_serverDlTable", "", CVAR_GAME | CVAR_ARCHIVE, "pak names for which download is provided, separated by ;" ); + +// darknar add +idCVar g_gib_power( "g_gib_power", "75.0", CVAR_GAME | CVAR_NOCHEAT | CVAR_ARCHIVE | CVAR_FLOAT, "gibs are launched with this force when the monster gibs" ); +idCVar g_gib_shadows( "g_gib_shadows", "0", CVAR_GAME | CVAR_NOCHEAT | CVAR_ARCHIVE | CVAR_BOOL, "enable shadows for spawned gibs, 0 = no shadows" ); +idCVar g_gib_remove_time( "g_gib_remove_time", "0.0", CVAR_GAME | CVAR_NOCHEAT | CVAR_ARCHIVE | CVAR_FLOAT, "remove the gibs after x seconds, 0.0 = unlimited" ); diff --git a/game/gamesys/SysCvar.h b/game/gamesys/SysCvar.h index da8e26e..b39f385 100644 --- a/game/gamesys/SysCvar.h +++ b/game/gamesys/SysCvar.h @@ -250,6 +250,11 @@ extern idCVar si_spectators; extern idCVar net_clientSelfSmoothing; extern idCVar net_clientLagOMeter; +// darknar add +extern idCVar g_gib_power; +extern idCVar g_gib_shadows; +extern idCVar g_gib_remove_time; + extern const char *si_gameTypeArgs[]; extern const char *ui_skinArgs[];