mirror of
https://github.com/dhewm/dhewm3-sdk.git
synced 2025-02-24 20:52:02 +00:00
mostly by fixing missing includes and some other compiler errors, also fixed some compiler warnings (mostly uninitialized variables)
304 lines
8.9 KiB
C++
304 lines
8.9 KiB
C++
#ifdef _WATER_PHYSICS
|
|
|
|
#include "Game_local.h"
|
|
|
|
#include "physics/Physics_Actor.h"
|
|
#include "physics/Physics_AF.h"
|
|
#include "SmokeParticles.h"
|
|
|
|
#include "Liquid.h"
|
|
|
|
// We do these splashes if the mass of the colliding object is less than these values.
|
|
// Anything large than MEDIUM_SPLASH does a large splash. (get it?)
|
|
const int SMALL_SPLASH = 25;
|
|
const int MEDIUM_SPLASH = 1000;
|
|
|
|
/*
|
|
===============================================================================
|
|
|
|
idLiquid
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
CLASS_DECLARATION( idEntity, idLiquid )
|
|
EVENT( EV_Touch, idLiquid::Event_Touch )
|
|
END_CLASS
|
|
|
|
/*
|
|
================
|
|
idLiquid::Save
|
|
================
|
|
*/
|
|
void idLiquid::Save( idSaveGame *savefile ) const {
|
|
|
|
int i;
|
|
|
|
savefile->WriteStaticObject( this->physicsObj );
|
|
|
|
//savefile->WriteString(smokeName.c_str());
|
|
//savefile->WriteString(soundName.c_str());
|
|
//bool skipSound //ivan - don't waste space to save this
|
|
|
|
for( i = 0; i < 3; i++ ){
|
|
savefile->WriteParticle(this->splash[i]);
|
|
}
|
|
savefile->WriteParticle(this->waves);
|
|
}
|
|
|
|
/*
|
|
================
|
|
idLiquid::Restore
|
|
================
|
|
*/
|
|
void idLiquid::Restore( idRestoreGame *savefile ) {
|
|
|
|
int i;
|
|
|
|
savefile->ReadStaticObject( this->physicsObj );
|
|
RestorePhysics( &this->physicsObj );
|
|
|
|
//savefile->ReadString(this->smokeName);
|
|
//savefile->ReadString(this->soundName);
|
|
//bool skipSound //ivan - don't waste space to save this
|
|
skipSound = false;
|
|
|
|
for( i = 0; i < 3; i++ ){
|
|
savefile->ReadParticle(this->splash[i]);
|
|
}
|
|
savefile->ReadParticle(this->waves);
|
|
}
|
|
|
|
/*
|
|
================
|
|
idLiquid::Spawn
|
|
================
|
|
*/
|
|
void idLiquid::Spawn() {
|
|
/*
|
|
model = dynamic_cast<idRenderModelLiquid *>( renderEntity.hModel );
|
|
if ( !model ) {
|
|
gameLocal.Error( "Entity '%s' must have liquid model", name.c_str() );
|
|
}
|
|
model->Reset();
|
|
*/
|
|
float liquidDensity;
|
|
float liquidViscosity;
|
|
//float liquidFriction;
|
|
idVec3 minSplash;
|
|
idVec3 minWave;
|
|
idStr temp;
|
|
const char *splashName;
|
|
idStr tempName; //ivan
|
|
|
|
// getters
|
|
spawnArgs.GetFloat("density","0.01043",liquidDensity); //changes the gravity (>density --> > upward push)
|
|
spawnArgs.GetFloat("viscosity","3.0",liquidViscosity); //changes the friction (>viscosity --> > friction)
|
|
//spawnArgs.GetFloat("friction","3.0",liquidFriction);
|
|
spawnArgs.GetString("liquid_name","water",temp);
|
|
spawnArgs.GetVector("minSplashVelocity","100 100 100",minSplash);
|
|
spawnArgs.GetVector("minWaveVelocity","60 60 60",minWave);
|
|
|
|
// setters
|
|
/*
|
|
this->smokeName = "smoke_";
|
|
this->smokeName.Append(temp);
|
|
*/
|
|
|
|
/*
|
|
this->soundName = "snd_";
|
|
this->soundName.Append(temp);
|
|
*/
|
|
|
|
|
|
//sndshader = declManager->FindSound( spawnArgs.GetString( "snd_water", "water/water_splash" ) ); //ivan
|
|
|
|
//ivan start
|
|
skipSound = false; //init
|
|
|
|
sprintf( tempName, "%s_splash_tiny", temp.c_str() );
|
|
splashName = spawnArgs.GetString("smoke_small", tempName.c_str() );
|
|
this->splash[0] = static_cast<const idDeclParticle *>(declManager->FindType(DECL_PARTICLE,splashName));
|
|
|
|
sprintf( tempName, "%s_splash", temp.c_str() );
|
|
splashName = spawnArgs.GetString("smoke_medium", tempName.c_str() );
|
|
this->splash[1] = static_cast<const idDeclParticle *>(declManager->FindType(DECL_PARTICLE,splashName));
|
|
|
|
sprintf( tempName, "%s_splash_large", temp.c_str() );
|
|
splashName = spawnArgs.GetString("smoke_large", tempName.c_str() );
|
|
this->splash[2] = static_cast<const idDeclParticle *>(declManager->FindType(DECL_PARTICLE,splashName));
|
|
|
|
sprintf( tempName, "%s_waves", temp.c_str() );
|
|
splashName = spawnArgs.GetString("smoke_waves", tempName.c_str() );
|
|
this->waves = static_cast<const idDeclParticle *>(declManager->FindType(DECL_PARTICLE,splashName));
|
|
|
|
/*
|
|
splashName = spawnArgs.GetString("smoke_small","water_splash_tiny");
|
|
this->splash[0] = static_cast<const idDeclParticle *>(declManager->FindType(DECL_PARTICLE,splashName));
|
|
|
|
splashName = spawnArgs.GetString("smoke_medium","water_splash");
|
|
this->splash[1] = static_cast<const idDeclParticle *>(declManager->FindType(DECL_PARTICLE,splashName));
|
|
|
|
splashName = spawnArgs.GetString("smoke_large","water_splash_large");
|
|
this->splash[2] = static_cast<const idDeclParticle *>(declManager->FindType(DECL_PARTICLE,splashName));
|
|
|
|
splashName = spawnArgs.GetString("smoke_waves","water_waves");
|
|
this->waves = static_cast<const idDeclParticle *>(declManager->FindType(DECL_PARTICLE,splashName));
|
|
*/
|
|
//ivan end
|
|
|
|
// setup physics
|
|
this->physicsObj.SetSelf(this);
|
|
this->physicsObj.SetClipModel( new idClipModel(this->GetPhysics()->GetClipModel()), liquidDensity );
|
|
this->physicsObj.SetOrigin(this->GetPhysics()->GetOrigin());
|
|
this->physicsObj.SetAxis(this->GetPhysics()->GetAxis());
|
|
this->physicsObj.SetGravity( gameLocal.GetGravity() );
|
|
this->physicsObj.SetContents( CONTENTS_WATER | CONTENTS_TRIGGER );
|
|
|
|
this->physicsObj.SetDensity(liquidDensity);
|
|
this->physicsObj.SetViscosity(liquidViscosity);
|
|
this->physicsObj.SetMinSplashVelocity(minSplash);
|
|
this->physicsObj.SetMinWaveVelocity(minWave);
|
|
|
|
this->SetPhysics( &this->physicsObj );
|
|
|
|
BecomeActive( TH_THINK );
|
|
}
|
|
|
|
/*
|
|
================
|
|
idLiquid::Event_Touch
|
|
|
|
This is mainly used for actors who touch the liquid, it spawns a splash
|
|
near they're feet if they're moving fast enough.
|
|
================
|
|
*/
|
|
void idLiquid::Event_Touch( idEntity *other, trace_t *trace ) {
|
|
//idPhysics_Liquid *liquid;
|
|
idPhysics_Actor *phys;
|
|
|
|
//only for actors!
|
|
if( !other->GetPhysics()->IsType(idPhysics_Actor::Type) ){
|
|
return;
|
|
}
|
|
|
|
//only if enough in the water
|
|
phys = static_cast<idPhysics_Actor *>(other->GetPhysics());
|
|
if( phys->GetWaterLevel() != WATERLEVEL_FEET ){
|
|
return;
|
|
}
|
|
|
|
//ivan start - stop actors from constantly splashing when they're in the water
|
|
|
|
//nextWaterSplash can be reset by the player if its walking in order to force this random behaviour
|
|
if ( phys->nextWaterSplash == 0 ) { //someone reset this (or it's the first time)
|
|
if( gameLocal.random.RandomFloat() > 0.5f ){ return; }
|
|
}
|
|
|
|
//default behaviour
|
|
if ( phys->nextWaterSplash < gameLocal.time ) {
|
|
phys->nextWaterSplash = gameLocal.time + 50 + gameLocal.random.RandomInt(50);
|
|
if( phys->nextWaterSnd < gameLocal.time ){
|
|
phys->nextWaterSnd = gameLocal.time + 300 + gameLocal.random.RandomInt(100);
|
|
}else{
|
|
skipSound = true;
|
|
}
|
|
}else{
|
|
return;
|
|
}
|
|
//ivan end
|
|
|
|
impactInfo_t info;
|
|
other->GetImpactInfo(this,trace->c.id,trace->c.point,&info);
|
|
//liquid = &this->physicsObj;
|
|
|
|
trace->c.point = info.position + other->GetPhysics()->GetOrigin();
|
|
trace->c.entityNum = other->entityNumber;
|
|
|
|
this->Collide(*trace,info.velocity);
|
|
}
|
|
|
|
/*
|
|
================
|
|
idLiquid::Collide
|
|
Spawns a splash particle and attaches a sound to the colliding entity.
|
|
================
|
|
*/
|
|
bool idLiquid::Collide( const trace_t &collision, const idVec3 &velocity ) {
|
|
idEntity *e = gameLocal.entities[collision.c.entityNum];
|
|
const idDeclParticle *splash;
|
|
float eMass;
|
|
idVec3 splashSpot;
|
|
float velSquare = velocity.LengthSqr();
|
|
//ivan start - why did he do this? We can directly use our physicsObj :|
|
|
//was: idPhysics_Liquid *phys = static_cast<idPhysics_Liquid *>( this->GetPhysics() );
|
|
//was: const char *sName;
|
|
int customType;
|
|
|
|
//avoid too many spashes for AFs!
|
|
if( e->GetPhysics()->IsType(idPhysics_AF::Type) ){
|
|
idPhysics_AF *phys = static_cast<idPhysics_AF *>(e->GetPhysics());
|
|
|
|
if ( phys->nextWaterSplash < gameLocal.time ) {
|
|
phys->nextWaterSplash = gameLocal.time + 30 + gameLocal.random.RandomInt(50);
|
|
}else{
|
|
return true;
|
|
}
|
|
}
|
|
//ivan end
|
|
|
|
eMass = e->GetPhysics()->GetMass();
|
|
splashSpot = collision.c.point;
|
|
|
|
if( velSquare > physicsObj.GetMinSplashVelocity().LengthSqr() ) { //ivan - was: phys
|
|
//ivan start
|
|
/*
|
|
// pick which splash particle to spawn
|
|
// first we check the entity, if it's not defined we use
|
|
// one defined for this liquid.
|
|
sName = e->spawnArgs.GetString(this->smokeName.c_str());
|
|
if( *sName != '\0' ) {
|
|
// load entity particle
|
|
splash = static_cast<const idDeclParticle *>(declManager->FindType(DECL_PARTICLE,sName));
|
|
}
|
|
else {
|
|
*/
|
|
|
|
customType = e->spawnArgs.GetInt( "water_size" , "-1"); //default is invalid
|
|
if( customType >= 0 && customType < 3 ){
|
|
splash = this->splash[customType];
|
|
}else{
|
|
//ivan end
|
|
// load a liquid particle based on the mass of the splashing entity
|
|
if( eMass < SMALL_SPLASH )
|
|
splash = this->splash[0];
|
|
else if( eMass < MEDIUM_SPLASH )
|
|
splash = this->splash[1];
|
|
else
|
|
splash = this->splash[2];
|
|
}
|
|
|
|
//ivan start
|
|
// only play the sound for a splash
|
|
//was: e->StartSound( this->soundName.c_str(), SND_CHANNEL_ANY, 0, false, NULL);
|
|
if( skipSound ){
|
|
skipSound = false;
|
|
}else{
|
|
e->StartSound( "snd_water", SND_CHANNEL_ANY, 0, false, NULL);
|
|
}
|
|
//ivan end
|
|
}
|
|
else if( velSquare > physicsObj.GetMinWaveVelocity().LengthSqr() ) { //ivan - was: phys
|
|
splash = this->waves;
|
|
}
|
|
else {
|
|
// the object is moving too slow so we abort
|
|
return true;
|
|
}
|
|
|
|
// spawn the particle
|
|
gameLocal.smokeParticles->EmitSmoke(splash,gameLocal.time,gameLocal.random.RandomFloat(),splashSpot,mat3_identity);
|
|
return true;
|
|
}
|
|
|
|
#endif // _WATER_PHYSICS
|