mirror of
https://github.com/dhewm/dhewm3-sdk.git
synced 2025-04-04 16:41:31 +00:00
Merge code of Desolated - The Crying Fate mod
This commit is contained in:
parent
5fcabc8f6a
commit
3f720956db
35 changed files with 3595 additions and 233 deletions
|
@ -81,6 +81,13 @@ const int IMPULSE_26 = 26; // <unused>
|
|||
const int IMPULSE_27 = 27; // <unused>
|
||||
const int IMPULSE_28 = 28; // vote yes
|
||||
const int IMPULSE_29 = 29; // vote no
|
||||
//###// by MacX
|
||||
const int IMPULSE_35 = 35; // slowmotion - by Cameron
|
||||
const int IMPULSE_36 = 36; // toggle xp - by Cameron
|
||||
const int IMPULSE_37 = 37; // toggle diary
|
||||
const int IMPULSE_38 = 38; // toggle questlog
|
||||
const int IMPULSE_39 = 39; // toggle thirdperson
|
||||
//###//
|
||||
const int IMPULSE_40 = 40; // use vehicle
|
||||
|
||||
// usercmd_t->flags
|
||||
|
|
10
game/AF.cpp
10
game/AF.cpp
|
@ -928,6 +928,16 @@ bool idAF::Load( idEntity *ent, const char *fileName ) {
|
|||
}
|
||||
}
|
||||
|
||||
// load how the body will be floated in liquid
|
||||
bool isFixedDensity;
|
||||
if( ent->spawnArgs.GetBool( "fixedDensityBuoyancy", "1", isFixedDensity ) )
|
||||
physicsObj.SetFixedDensityBuoyancy( isFixedDensity );
|
||||
|
||||
// load liquid density from file
|
||||
float liquidDensity;
|
||||
if( ent->spawnArgs.GetFloat( "liquidDensity", "", liquidDensity ) )
|
||||
physicsObj.SetLiquidDensity( liquidDensity );
|
||||
|
||||
physicsObj.SetMass( file->totalMass );
|
||||
physicsObj.SetChanged();
|
||||
|
||||
|
|
|
@ -120,6 +120,8 @@ const idEventDef EV_StartFx( "startFx", "s" );
|
|||
const idEventDef EV_HasFunction( "hasFunction", "s", 'd' );
|
||||
const idEventDef EV_CallFunction( "callFunction", "s" );
|
||||
const idEventDef EV_SetNeverDormant( "setNeverDormant", "d" );
|
||||
const idEventDef EV_GetMass("getMass","d",'f');
|
||||
const idEventDef EV_IsInLiquid("isInLiquid",NULL,'d');
|
||||
|
||||
ABSTRACT_DECLARATION( idClass, idEntity )
|
||||
EVENT( EV_GetName, idEntity::Event_GetName )
|
||||
|
@ -185,6 +187,8 @@ ABSTRACT_DECLARATION( idClass, idEntity )
|
|||
EVENT( EV_HasFunction, idEntity::Event_HasFunction )
|
||||
EVENT( EV_CallFunction, idEntity::Event_CallFunction )
|
||||
EVENT( EV_SetNeverDormant, idEntity::Event_SetNeverDormant )
|
||||
EVENT( EV_GetMass, idEntity::Event_GetMass )
|
||||
EVENT( EV_IsInLiquid, idEntity::Event_IsInLiquid )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
|
@ -432,6 +436,8 @@ idEntity::idEntity() {
|
|||
|
||||
memset( &renderEntity, 0, sizeof( renderEntity ) );
|
||||
modelDefHandle = -1;
|
||||
modelDefHandlePost = -1; // new 6th venom
|
||||
shaderPost = NULL; // new
|
||||
memset( &refSound, 0, sizeof( refSound ) );
|
||||
|
||||
mpGUIState = -1;
|
||||
|
@ -478,6 +484,13 @@ void idEntity::Spawn( void ) {
|
|||
// parse static models the same way the editor display does
|
||||
gameEdit->ParseSpawnArgsToRenderEntity( &spawnArgs, &renderEntity );
|
||||
|
||||
//new 6th venom
|
||||
temp = spawnArgs.GetString( "shader_post" );
|
||||
|
||||
if( temp[0] != '\0' )
|
||||
shaderPost = (idMaterial *)declManager->FindMaterial( temp );
|
||||
|
||||
|
||||
renderEntity.entityNum = entityNumber;
|
||||
|
||||
// go dormant within 5 frames so that when the map starts most monsters are dormant
|
||||
|
@ -663,6 +676,8 @@ void idEntity::Save( idSaveGame *savefile ) const {
|
|||
|
||||
savefile->WriteRenderEntity( renderEntity );
|
||||
savefile->WriteInt( modelDefHandle );
|
||||
savefile->WriteInt( modelDefHandlePost ); // new 6th venom
|
||||
savefile->WriteMaterial( shaderPost ); // new
|
||||
savefile->WriteRefSound( refSound );
|
||||
|
||||
savefile->WriteObject( bindMaster );
|
||||
|
@ -738,6 +753,8 @@ void idEntity::Restore( idRestoreGame *savefile ) {
|
|||
|
||||
savefile->ReadRenderEntity( renderEntity );
|
||||
savefile->ReadInt( modelDefHandle );
|
||||
savefile->ReadInt( modelDefHandlePost ); // new 6th venom
|
||||
savefile->ReadMaterial( shaderPost ); // new
|
||||
savefile->ReadRefSound( refSound );
|
||||
|
||||
savefile->ReadObject( reinterpret_cast<idClass *&>( bindMaster ) );
|
||||
|
@ -778,6 +795,17 @@ void idEntity::Restore( idRestoreGame *savefile ) {
|
|||
if ( modelDefHandle != -1 ) {
|
||||
modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
|
||||
}
|
||||
|
||||
// new 6th venom
|
||||
if( shaderPost )
|
||||
{
|
||||
renderEntity_t post = renderEntity;
|
||||
post.customShader = shaderPost;
|
||||
|
||||
if( modelDefHandlePost != -1 )
|
||||
modelDefHandlePost = gameRenderWorld->AddEntityDef( &post );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1144,6 +1172,14 @@ void idEntity::FreeModelDef( void ) {
|
|||
gameRenderWorld->FreeEntityDef( modelDefHandle );
|
||||
modelDefHandle = -1;
|
||||
}
|
||||
|
||||
//new 6th venom
|
||||
if( modelDefHandlePost != -1 )
|
||||
{
|
||||
gameRenderWorld->FreeEntityDef( modelDefHandlePost );
|
||||
modelDefHandlePost = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1422,6 +1458,18 @@ void idEntity::Present( void ) {
|
|||
} else {
|
||||
gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
|
||||
}
|
||||
|
||||
//new 6th venom
|
||||
if( shaderPost )
|
||||
{
|
||||
renderEntity_t post = renderEntity;
|
||||
post.customShader = shaderPost;
|
||||
|
||||
if( modelDefHandlePost == -1 )
|
||||
modelDefHandlePost = gameRenderWorld->AddEntityDef( &post );
|
||||
else
|
||||
gameRenderWorld->UpdateEntityDef( modelDefHandlePost, &post );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4569,6 +4617,24 @@ void idEntity::Event_CallFunction( const char *funcname ) {
|
|||
thread->CallFunction( this, func, false );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idEntity::Event_GetMass
|
||||
================
|
||||
*/
|
||||
void idEntity::Event_GetMass( int id ) {
|
||||
idThread::ReturnFloat(physics->GetMass(id));
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idEntity::Event_IsInLiquid
|
||||
================
|
||||
*/
|
||||
void idEntity::Event_IsInLiquid( void ) {
|
||||
idThread::ReturnInt(physics->GetWater() != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idEntity::Event_SetNeverDormant
|
||||
|
|
|
@ -68,6 +68,8 @@ extern const idEventDef EV_SetSkin;
|
|||
extern const idEventDef EV_StartSoundShader;
|
||||
extern const idEventDef EV_StopSound;
|
||||
extern const idEventDef EV_CacheSoundShader;
|
||||
extern const idEventDef EV_GetMass;
|
||||
extern const idEventDef EV_IsInLiquid;
|
||||
|
||||
// Think flags
|
||||
enum {
|
||||
|
@ -364,6 +366,8 @@ public:
|
|||
protected:
|
||||
renderEntity_t renderEntity; // used to present a model to the renderer
|
||||
int modelDefHandle; // handle to static renderer model
|
||||
int modelDefHandlePost; // new 6th venom
|
||||
const idMaterial *shaderPost; // new
|
||||
refSound_t refSound; // used to present sound to the audio engine
|
||||
|
||||
private:
|
||||
|
@ -465,6 +469,8 @@ private:
|
|||
void Event_HasFunction( const char *name );
|
||||
void Event_CallFunction( const char *name );
|
||||
void Event_SetNeverDormant( int enable );
|
||||
void Event_GetMass( int body );
|
||||
void Event_IsInLiquid( void );
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -656,4 +656,19 @@ extern const float DEFAULT_GRAVITY;
|
|||
extern const idVec3 DEFAULT_GRAVITY_VEC3;
|
||||
extern const int CINEMATIC_SKIP_DELAY;
|
||||
|
||||
#include "physics/Physics_Parametric.h"
|
||||
#include "physics/Physics_RigidBody.h"
|
||||
#include "physics/Physics_AF.h"
|
||||
#include "physics/Physics_Liquid.h"
|
||||
|
||||
#include "SmokeParticles.h"
|
||||
|
||||
#include "AF.h"
|
||||
#include "IK.h"
|
||||
#include "AFEntity.h"
|
||||
#include "Liquid.h"
|
||||
#include "Misc.h"
|
||||
#include "Actor.h"
|
||||
#include "Projectile.h"
|
||||
|
||||
#endif /* !__GAME_LOCAL_H__ */
|
||||
|
|
226
game/Liquid.cpp
Normal file
226
game/Liquid.cpp
Normal file
|
@ -0,0 +1,226 @@
|
|||
#include "../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "Game_local.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());
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
// getters
|
||||
spawnArgs.GetFloat("density","0.01043f",liquidDensity);
|
||||
spawnArgs.GetFloat("viscosity","3.0f",liquidViscosity);
|
||||
spawnArgs.GetFloat("friction","3.0f",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);
|
||||
|
||||
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));
|
||||
|
||||
// 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 ) {
|
||||
// FIXME: for QuakeCon
|
||||
/*
|
||||
idVec3 pos;
|
||||
|
||||
pos = other->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
|
||||
model->IntersectBounds( other->GetPhysics()->GetBounds().Translate( pos ), -10.0f );
|
||||
*/
|
||||
|
||||
idPhysics_Liquid *liquid;
|
||||
idPhysics_Actor *phys;
|
||||
|
||||
if( !other->GetPhysics()->IsType(idPhysics_Actor::Type) )
|
||||
return;
|
||||
|
||||
phys = static_cast<idPhysics_Actor *>(other->GetPhysics());
|
||||
if( phys->GetWaterLevel() != WATERLEVEL_FEET )
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
// stop actors from constantly splashing when they're in the water
|
||||
// (this is such a bad thing to do!!!)
|
||||
// TODO: Fixme...
|
||||
// 1) Probably the best way to fix this is put a wait timer inside the actor and have this
|
||||
// function set/reset that timer for when the actor should spawn particles at it's feet.
|
||||
// 2) Actors don't spawn particles at their feet, it's usually at the origin, for some
|
||||
// reason info.position is (null), needs a fix so that splash position is correct
|
||||
if( gameLocal.random.RandomFloat() > 0.5f )
|
||||
return;
|
||||
|
||||
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];
|
||||
idPhysics_Liquid *phys = static_cast<idPhysics_Liquid *>( this->GetPhysics() );
|
||||
const idDeclParticle *splash;
|
||||
const char *sName;
|
||||
float eMass;
|
||||
idVec3 splashSpot;
|
||||
float velSquare = velocity.LengthSqr();
|
||||
|
||||
eMass = e->GetPhysics()->GetMass();
|
||||
splashSpot = collision.c.point;
|
||||
|
||||
if( velSquare > phys->GetMinSplashVelocity().LengthSqr() ) {
|
||||
// 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 {
|
||||
// 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];
|
||||
}
|
||||
|
||||
// only play the sound for a splash
|
||||
e->StartSound( this->soundName.c_str(), SND_CHANNEL_ANY, 0, false, NULL);
|
||||
}
|
||||
else if( velSquare > phys->GetMinWaveVelocity().LengthSqr() ) {
|
||||
splash = this->waves;
|
||||
}
|
||||
else {
|
||||
// the object is moving to slow so we abort
|
||||
return true;
|
||||
}
|
||||
|
||||
// spawn the particle
|
||||
gameLocal.smokeParticles->EmitSmoke(splash,gameLocal.time,gameLocal.random.RandomFloat(),splashSpot,mat3_identity);
|
||||
return true;
|
||||
}
|
43
game/Liquid.h
Normal file
43
game/Liquid.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef __LIQUID_H__
|
||||
#define __LIQUID_H__
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
idLiquid
|
||||
|
||||
Base class for all liquid object. The entity part of the liquid is
|
||||
responsible for spawning splashes and sounds to match.
|
||||
|
||||
The physics portion is as usual, responsible for the physics.
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idRenderModelLiquid;
|
||||
|
||||
class idLiquid : public idEntity {
|
||||
public:
|
||||
CLASS_PROTOTYPE( idLiquid );
|
||||
|
||||
void Spawn( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
virtual bool Collide( const trace_t &collision, const idVec3 &velocity );
|
||||
|
||||
private:
|
||||
void Event_Touch( idEntity *other, trace_t *trace );
|
||||
|
||||
idPhysics_Liquid physicsObj;
|
||||
|
||||
idRenderModelLiquid *model;
|
||||
|
||||
const idDeclParticle *splash[3];
|
||||
const idDeclParticle *waves;
|
||||
|
||||
idStr smokeName;
|
||||
idStr soundName;
|
||||
};
|
||||
|
||||
#endif // __LIQUID_H__
|
|
@ -1465,6 +1465,26 @@ void idStaticEntity::Think( void ) {
|
|||
renderEntity.gui[2]->StateChanged( gameLocal.time, true );
|
||||
}
|
||||
}
|
||||
//###// by MacX - using code by Cameron
|
||||
if( !player->diaryUIOpen ) {
|
||||
renderEntity.gui[0]->StateChanged( gameLocal.time, true );
|
||||
if ( renderEntity.gui[1] ) {
|
||||
renderEntity.gui[1]->StateChanged( gameLocal.time, true );
|
||||
}
|
||||
if ( renderEntity.gui[2] ) {
|
||||
renderEntity.gui[2]->StateChanged( gameLocal.time, true );
|
||||
}
|
||||
}
|
||||
if( !player->questlogUIOpen ) {
|
||||
renderEntity.gui[0]->StateChanged( gameLocal.time, true );
|
||||
if ( renderEntity.gui[1] ) {
|
||||
renderEntity.gui[1]->StateChanged( gameLocal.time, true );
|
||||
}
|
||||
if ( renderEntity.gui[2] ) {
|
||||
renderEntity.gui[2]->StateChanged( gameLocal.time, true );
|
||||
}
|
||||
}
|
||||
//###//
|
||||
}
|
||||
}
|
||||
if ( fadeEnd > 0 ) {
|
||||
|
@ -2293,69 +2313,6 @@ void idBeam::ReadFromSnapshot( const idBitMsgDelta &msg ) {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
idLiquid
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
CLASS_DECLARATION( idEntity, idLiquid )
|
||||
EVENT( EV_Touch, idLiquid::Event_Touch )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
================
|
||||
idLiquid::Save
|
||||
================
|
||||
*/
|
||||
void idLiquid::Save( idSaveGame *savefile ) const {
|
||||
// Nothing to save
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idLiquid::Restore
|
||||
================
|
||||
*/
|
||||
void idLiquid::Restore( idRestoreGame *savefile ) {
|
||||
//FIXME: NO!
|
||||
Spawn();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
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();
|
||||
GetPhysics()->SetContents( CONTENTS_TRIGGER );
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idLiquid::Event_Touch
|
||||
================
|
||||
*/
|
||||
void idLiquid::Event_Touch( idEntity *other, trace_t *trace ) {
|
||||
// FIXME: for QuakeCon
|
||||
/*
|
||||
idVec3 pos;
|
||||
|
||||
pos = other->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
|
||||
model->IntersectBounds( other->GetPhysics()->GetBounds().Translate( pos ), -10.0f );
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
|
27
game/Misc.h
27
game/Misc.h
|
@ -534,33 +534,6 @@ private:
|
|||
};
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
idLiquid
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idRenderModelLiquid;
|
||||
|
||||
class idLiquid : public idEntity {
|
||||
public:
|
||||
CLASS_PROTOTYPE( idLiquid );
|
||||
|
||||
void Spawn( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
private:
|
||||
void Event_Touch( idEntity *other, trace_t *trace );
|
||||
|
||||
|
||||
idRenderModelLiquid *model;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
|
|
669
game/Player.cpp
669
game/Player.cpp
|
@ -128,6 +128,7 @@ idVec3 idPlayer::colorBarTable[ 5 ] = {
|
|||
idVec3( 1.00f, 0.80f, 0.10f )
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
idInventory::Clear
|
||||
|
@ -139,6 +140,34 @@ void idInventory::Clear( void ) {
|
|||
powerups = 0;
|
||||
armor = 0;
|
||||
maxarmor = 0;
|
||||
|
||||
//###// by MacX
|
||||
|
||||
money = 0;
|
||||
diary.Clear();
|
||||
quest.Clear();
|
||||
questState.Clear();
|
||||
|
||||
enemiesKilled = 0;
|
||||
|
||||
testVarGui1 = 0;
|
||||
testVarGui2 = 0;
|
||||
testVarGui3 = 0;
|
||||
testVarGui4 = 0;
|
||||
testVarGui5 = 0;
|
||||
testVar1 = 0;
|
||||
testVar2 = 0;
|
||||
testVar3 = 0;
|
||||
testVar4 = 0;
|
||||
testVar5 = 0;
|
||||
testVar6 = 0;
|
||||
testVar7 = 0;
|
||||
testVar8 = 0;
|
||||
testVar9 = 0;
|
||||
testVar10 = 0;
|
||||
|
||||
//###//
|
||||
|
||||
deplete_armor = 0;
|
||||
deplete_rate = 0.0f;
|
||||
deplete_ammount = 0;
|
||||
|
@ -239,6 +268,46 @@ void idInventory::GetPersistantData( idDict &dict ) {
|
|||
// armor
|
||||
dict.SetInt( "armor", armor );
|
||||
|
||||
//###// by MacX
|
||||
dict.SetInt( "money", money );
|
||||
|
||||
for ( i = 0; i < diary.Num(); i++ ) {
|
||||
sprintf( key, "diary_%i", i );
|
||||
dict.Set( key, diary[ i ].c_str() );
|
||||
}
|
||||
dict.SetInt( "diary", diary.Num() );
|
||||
|
||||
for ( i = 0; i < quest.Num(); i++ ) {
|
||||
sprintf( key, "quest_%i", i );
|
||||
dict.Set( key, quest[ i ].c_str() );
|
||||
}
|
||||
dict.SetInt( "quest", quest.Num() );
|
||||
|
||||
for ( i = 0; i < questState.Num(); i++ ) {
|
||||
sprintf( key, "questState_%i", i );
|
||||
dict.Set( key, questState[ i ].c_str() );
|
||||
}
|
||||
dict.SetInt( "questState", questState.Num() );
|
||||
|
||||
dict.SetInt( "enemiesKilled", enemiesKilled );
|
||||
|
||||
dict.SetInt( "testVarGui1", testVarGui1 );
|
||||
dict.SetInt( "testVarGui2", testVarGui2 );
|
||||
dict.SetInt( "testVarGui3", testVarGui3 );
|
||||
dict.SetInt( "testVarGui4", testVarGui4 );
|
||||
dict.SetInt( "testVarGui5", testVarGui5 );
|
||||
dict.SetInt( "testVar1", testVar1 );
|
||||
dict.SetInt( "testVar2", testVar2 );
|
||||
dict.SetInt( "testVar3", testVar3 );
|
||||
dict.SetInt( "testVar4", testVar4 );
|
||||
dict.SetInt( "testVar5", testVar5 );
|
||||
dict.SetInt( "testVar6", testVar6 );
|
||||
dict.SetInt( "testVar7", testVar7 );
|
||||
dict.SetInt( "testVar8", testVar8 );
|
||||
dict.SetInt( "testVar9", testVar9 );
|
||||
dict.SetInt( "testVar10", testVar10 );
|
||||
//###//
|
||||
|
||||
// don't bother with powerups, maxhealth, maxarmor, or the clip
|
||||
|
||||
// ammo
|
||||
|
@ -332,6 +401,52 @@ void idInventory::RestoreInventory( idPlayer *owner, const idDict &dict ) {
|
|||
maxHealth = dict.GetInt( "maxhealth", "100" );
|
||||
armor = dict.GetInt( "armor", "50" );
|
||||
maxarmor = dict.GetInt( "maxarmor", "100" );
|
||||
|
||||
//###// by MacX
|
||||
money = dict.GetInt( "money", "0" );
|
||||
|
||||
// diary
|
||||
num = dict.GetInt( "diary" );
|
||||
diary.SetNum( num );
|
||||
for ( i = 0; i < num; i++ ) {
|
||||
sprintf( itemname, "diary_%i", i );
|
||||
diary[i] = dict.GetString( itemname, "default" );
|
||||
}
|
||||
|
||||
//quest
|
||||
num = dict.GetInt( "quest" );
|
||||
quest.SetNum( num );
|
||||
for ( i = 0; i < num; i++ ) {
|
||||
sprintf( itemname, "quest_%i", i );
|
||||
quest[i] = dict.GetString( itemname, "default" );
|
||||
}
|
||||
|
||||
// questState
|
||||
num = dict.GetInt( "questState" );
|
||||
questState.SetNum( num );
|
||||
for ( i = 0; i < num; i++ ) {
|
||||
sprintf( itemname, "questState_%i", i );
|
||||
questState[i] = dict.GetString( itemname, "default" );
|
||||
}
|
||||
|
||||
enemiesKilled = dict.GetInt( "enemiesKilled", "0" );
|
||||
|
||||
testVarGui1 = dict.GetInt( "testVarGui1", "0" );
|
||||
testVarGui2 = dict.GetInt( "testVarGui2", "0" );
|
||||
testVarGui3 = dict.GetInt( "testVarGui3", "0" );
|
||||
testVarGui4 = dict.GetInt( "testVarGui4", "0" );
|
||||
testVarGui5 = dict.GetInt( "testVarGui5", "0" );
|
||||
testVar1 = dict.GetInt( "testVar1", "0" );
|
||||
testVar2 = dict.GetInt( "testVar2", "0" );
|
||||
testVar3 = dict.GetInt( "testVar3", "0" );
|
||||
testVar4 = dict.GetInt( "testVar4", "0" );
|
||||
testVar5 = dict.GetInt( "testVar5", "0" );
|
||||
testVar6 = dict.GetInt( "testVar6", "0" );
|
||||
testVar7 = dict.GetInt( "testVar7", "0" );
|
||||
testVar8 = dict.GetInt( "testVar8", "0" );
|
||||
testVar9 = dict.GetInt( "testVar9", "0" );
|
||||
//###//
|
||||
|
||||
deplete_armor = dict.GetInt( "deplete_armor", "0" );
|
||||
deplete_rate = dict.GetFloat( "deplete_rate", "2.0" );
|
||||
deplete_ammount = dict.GetInt( "deplete_ammount", "1" );
|
||||
|
@ -432,6 +547,44 @@ void idInventory::Save( idSaveGame *savefile ) const {
|
|||
savefile->WriteInt( powerups );
|
||||
savefile->WriteInt( armor );
|
||||
savefile->WriteInt( maxarmor );
|
||||
|
||||
//###// by MacX
|
||||
savefile->WriteInt( money );
|
||||
|
||||
savefile->WriteInt( diary.Num() );
|
||||
for( i = 0; i < diary.Num(); i++ ) {
|
||||
savefile->WriteString( diary[ i ] );
|
||||
}
|
||||
|
||||
savefile->WriteInt( quest.Num() );
|
||||
for( i = 0; i < quest.Num(); i++ ) {
|
||||
savefile->WriteString( quest[ i ] );
|
||||
}
|
||||
|
||||
savefile->WriteInt( questState.Num() );
|
||||
for( i = 0; i < questState.Num(); i++ ) {
|
||||
savefile->WriteString( questState[ i ] );
|
||||
}
|
||||
|
||||
savefile->WriteInt( enemiesKilled );
|
||||
|
||||
savefile->WriteInt( testVarGui1 );
|
||||
savefile->WriteInt( testVarGui2 );
|
||||
savefile->WriteInt( testVarGui3 );
|
||||
savefile->WriteInt( testVarGui4 );
|
||||
savefile->WriteInt( testVarGui5 );
|
||||
savefile->WriteInt( testVar1 );
|
||||
savefile->WriteInt( testVar2 );
|
||||
savefile->WriteInt( testVar3 );
|
||||
savefile->WriteInt( testVar4 );
|
||||
savefile->WriteInt( testVar5 );
|
||||
savefile->WriteInt( testVar6 );
|
||||
savefile->WriteInt( testVar7 );
|
||||
savefile->WriteInt( testVar8 );
|
||||
savefile->WriteInt( testVar9 );
|
||||
savefile->WriteInt( testVar10 );
|
||||
//###//
|
||||
|
||||
savefile->WriteInt( ammoPredictTime );
|
||||
savefile->WriteInt( deplete_armor );
|
||||
savefile->WriteFloat( deplete_rate );
|
||||
|
@ -528,6 +681,50 @@ void idInventory::Restore( idRestoreGame *savefile ) {
|
|||
savefile->ReadInt( powerups );
|
||||
savefile->ReadInt( armor );
|
||||
savefile->ReadInt( maxarmor );
|
||||
|
||||
//###// by MacX
|
||||
savefile->ReadInt( money );
|
||||
|
||||
savefile->ReadInt( num );
|
||||
for( i = 0; i < num; i++ ) {
|
||||
idStr strDiary;
|
||||
savefile->ReadString( strDiary );
|
||||
diary.Append( strDiary );
|
||||
}
|
||||
|
||||
savefile->ReadInt( num );
|
||||
for( i = 0; i < num; i++ ) {
|
||||
idStr strQuest;
|
||||
savefile->ReadString( strQuest );
|
||||
quest.Append( strQuest );
|
||||
}
|
||||
|
||||
savefile->ReadInt( num );
|
||||
for( i = 0; i < num; i++ ) {
|
||||
idStr strQuest;
|
||||
savefile->ReadString( strQuest );
|
||||
questState.Append( strQuest );
|
||||
}
|
||||
|
||||
savefile->ReadInt( enemiesKilled );
|
||||
|
||||
savefile->ReadInt( testVarGui1 );
|
||||
savefile->ReadInt( testVarGui2 );
|
||||
savefile->ReadInt( testVarGui3 );
|
||||
savefile->ReadInt( testVarGui4 );
|
||||
savefile->ReadInt( testVarGui5 );
|
||||
savefile->ReadInt( testVar1 );
|
||||
savefile->ReadInt( testVar2 );
|
||||
savefile->ReadInt( testVar3 );
|
||||
savefile->ReadInt( testVar4 );
|
||||
savefile->ReadInt( testVar5 );
|
||||
savefile->ReadInt( testVar6 );
|
||||
savefile->ReadInt( testVar7 );
|
||||
savefile->ReadInt( testVar8 );
|
||||
savefile->ReadInt( testVar9 );
|
||||
savefile->ReadInt( testVar10 );
|
||||
//###//
|
||||
|
||||
savefile->ReadInt( ammoPredictTime );
|
||||
savefile->ReadInt( deplete_armor );
|
||||
savefile->ReadFloat( deplete_rate );
|
||||
|
@ -762,7 +959,22 @@ bool idInventory::Give( idPlayer *owner, const idDict &spawnArgs, const char *st
|
|||
AddPickupName( name, "" );
|
||||
}
|
||||
}
|
||||
} else if ( !idStr::Icmp( statname, "armor" ) ) {
|
||||
}
|
||||
//###// by MacX
|
||||
|
||||
else if ( !idStr::Icmp( statname, "money" ) ) {
|
||||
amount = atoi( value );
|
||||
if ( amount ) {
|
||||
money += amount;
|
||||
if ( money > 999999 ) {
|
||||
money = 999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//###//
|
||||
|
||||
else if ( !idStr::Icmp( statname, "armor" ) ) {
|
||||
if ( armor >= maxarmor ) {
|
||||
return false; // can't hold any more, so leave the item
|
||||
}
|
||||
|
@ -977,6 +1189,14 @@ idPlayer::idPlayer() {
|
|||
objectiveSystem = NULL;
|
||||
objectiveSystemOpen = false;
|
||||
|
||||
//###//by MacX
|
||||
diaryUI = NULL;
|
||||
diaryUIOpen = false;
|
||||
|
||||
questlogUI = NULL;
|
||||
questlogUIOpen = false;
|
||||
//###//
|
||||
|
||||
heartRate = BASE_HEARTRATE;
|
||||
heartInfo.Init( 0, 0, 0, 0 );
|
||||
lastHeartAdjust = 0;
|
||||
|
@ -1133,6 +1353,8 @@ idPlayer::idPlayer() {
|
|||
isChatting = false;
|
||||
|
||||
selfSmooth = false;
|
||||
|
||||
bIsZoomed = false; // sikk - Zoom DoF Fullscreen PostProcess Effect
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1286,6 +1508,11 @@ void idPlayer::Init( void ) {
|
|||
}
|
||||
}
|
||||
|
||||
//###// by MacX
|
||||
slowmotion = pm_slowmotion.GetFloat();
|
||||
startslow = 0;
|
||||
//###//
|
||||
|
||||
// disable stamina on hell levels
|
||||
if ( gameLocal.world && gameLocal.world->spawnArgs.GetBool( "no_stamina" ) ) {
|
||||
pm_stamina.SetFloat( 0.0f );
|
||||
|
@ -1469,6 +1696,14 @@ void idPlayer::Spawn( void ) {
|
|||
|
||||
objectiveSystem = uiManager->FindGui( "guis/pda.gui", true, false, true );
|
||||
objectiveSystemOpen = false;
|
||||
|
||||
//###// by MacX
|
||||
diaryUI = uiManager->FindGui( "guis/diary.gui", true, false, true );
|
||||
diaryUIOpen = false;
|
||||
|
||||
questlogUI = uiManager->FindGui( "guis/questlog.gui", true, false, true );
|
||||
questlogUIOpen = false;
|
||||
//###//
|
||||
}
|
||||
|
||||
SetLastHitTime( 0 );
|
||||
|
@ -1642,6 +1877,18 @@ void idPlayer::Save( idSaveGame *savefile ) const {
|
|||
savefile->WriteUserInterface( objectiveSystem, false );
|
||||
savefile->WriteBool( objectiveSystemOpen );
|
||||
|
||||
//Cameron Law START - edited by MacX
|
||||
savefile->WriteFloat( slowmotion );
|
||||
savefile->WriteInt( startslow );
|
||||
//Cameron Law END
|
||||
|
||||
//###// by MacX
|
||||
savefile->WriteUserInterface( diaryUI, false );
|
||||
savefile->WriteBool( diaryUIOpen );
|
||||
savefile->WriteUserInterface( questlogUI, false );
|
||||
savefile->WriteBool( questlogUIOpen );
|
||||
//###//
|
||||
|
||||
savefile->WriteInt( weapon_soulcube );
|
||||
savefile->WriteInt( weapon_pda );
|
||||
savefile->WriteInt( weapon_fists );
|
||||
|
@ -1811,6 +2058,11 @@ void idPlayer::Save( idSaveGame *savefile ) const {
|
|||
|
||||
savefile->WriteFloat( pm_stamina.GetFloat() );
|
||||
|
||||
//###// by MacX
|
||||
savefile->WriteFloat( pm_slowmotion.GetFloat() );
|
||||
savefile->WriteFloat( pm_slowmotionrate.GetFloat() );
|
||||
//###//
|
||||
|
||||
if ( hud ) {
|
||||
hud->SetStateString( "message", common->GetLanguageDict()->GetString( "#str_02916" ) );
|
||||
hud->HandleNamedEvent( "Message" );
|
||||
|
@ -1865,6 +2117,16 @@ void idPlayer::Restore( idRestoreGame *savefile ) {
|
|||
savefile->ReadUserInterface( hud );
|
||||
savefile->ReadUserInterface( objectiveSystem );
|
||||
savefile->ReadBool( objectiveSystemOpen );
|
||||
//Cameron Law START - edited by MacX
|
||||
savefile->ReadFloat( slowmotion );
|
||||
savefile->ReadInt( startslow );
|
||||
//Cameron Law END
|
||||
//###// by MacX
|
||||
savefile->ReadUserInterface( diaryUI );
|
||||
savefile->ReadBool( diaryUIOpen );
|
||||
savefile->ReadUserInterface( questlogUI );
|
||||
savefile->ReadBool( questlogUIOpen );
|
||||
//###//
|
||||
|
||||
savefile->ReadInt( weapon_soulcube );
|
||||
savefile->ReadInt( weapon_pda );
|
||||
|
@ -2061,6 +2323,13 @@ void idPlayer::Restore( idRestoreGame *savefile ) {
|
|||
savefile->ReadFloat( set );
|
||||
pm_stamina.SetFloat( set );
|
||||
|
||||
//###// by MacX
|
||||
savefile->ReadFloat( set );
|
||||
pm_slowmotion.SetFloat( set );
|
||||
savefile->ReadFloat( set );
|
||||
pm_slowmotionrate.SetFloat( set );
|
||||
//###//
|
||||
|
||||
// create combat collision hull for exact collision detection
|
||||
SetCombatModel();
|
||||
|
||||
|
@ -2533,6 +2802,29 @@ void idPlayer::UpdateHudStats( idUserInterface *_hud ) {
|
|||
_hud->SetStateInt( "player_hr", heartRate );
|
||||
_hud->SetStateInt( "player_nostamina", ( max_stamina == 0 ) ? 1 : 0 );
|
||||
|
||||
//###// by MacX
|
||||
|
||||
_hud->SetStateInt( "player_money", inventory.money );
|
||||
|
||||
if( pm_thirdPerson.GetBool() == true ) {
|
||||
_hud->SetStateInt( "thirdperson", 1 );
|
||||
} else {
|
||||
_hud->SetStateInt( "thirdperson", 0 );
|
||||
}
|
||||
|
||||
int slowmopercentage = idMath::FtoiFast( 100.0f * slowmotion / pm_slowmotion.GetFloat() );
|
||||
_hud->SetStateInt( "player_slowmotion", slowmopercentage );
|
||||
|
||||
_hud->SetStateInt( "player_enemiesKilled", inventory.enemiesKilled );
|
||||
|
||||
_hud->SetStateInt( "player_testVarGui1", inventory.testVarGui1 );
|
||||
_hud->SetStateInt( "player_testVarGui2", inventory.testVarGui2 );
|
||||
_hud->SetStateInt( "player_testVarGui3", inventory.testVarGui3 );
|
||||
_hud->SetStateInt( "player_testVarGui4", inventory.testVarGui4 );
|
||||
_hud->SetStateInt( "player_testVarGui5", inventory.testVarGui5 );
|
||||
|
||||
//###//
|
||||
|
||||
_hud->HandleNamedEvent( "updateArmorHealthAir" );
|
||||
|
||||
if ( healthPulse ) {
|
||||
|
@ -3804,9 +4096,17 @@ idPlayer::ActiveGui
|
|||
===============
|
||||
*/
|
||||
idUserInterface *idPlayer::ActiveGui( void ) {
|
||||
if ( objectiveSystemOpen ) {
|
||||
//###// by MacX
|
||||
if ( objectiveSystemOpen || diaryUIOpen || questlogUIOpen ) {
|
||||
if ( diaryUIOpen ) {
|
||||
return diaryUI;
|
||||
}
|
||||
if ( questlogUIOpen ) {
|
||||
return questlogUI;
|
||||
}
|
||||
return objectiveSystem;
|
||||
}
|
||||
//###//
|
||||
|
||||
return focusUI;
|
||||
}
|
||||
|
@ -3977,7 +4277,9 @@ idPlayer::Weapon_GUI
|
|||
*/
|
||||
void idPlayer::Weapon_GUI( void ) {
|
||||
|
||||
if ( !objectiveSystemOpen ) {
|
||||
//###// by MacX
|
||||
if ( !objectiveSystemOpen && !diaryUIOpen && !questlogUIOpen ) {
|
||||
//###//
|
||||
if ( idealWeapon != currentWeapon ) {
|
||||
Weapon_Combat();
|
||||
}
|
||||
|
@ -4488,6 +4790,12 @@ void idPlayer::UpdateFocus( void ) {
|
|||
focusGUIent = ent;
|
||||
focusUI = ui;
|
||||
|
||||
//###// by MacX
|
||||
|
||||
focusUI->SetStateString( "player_money", va( "%i%", inventory.money ) );
|
||||
|
||||
//###//
|
||||
|
||||
if ( oldFocus != ent ) {
|
||||
// new activation
|
||||
// going to see if we have anything in inventory a gui might be interested in
|
||||
|
@ -4873,7 +5181,10 @@ void idPlayer::UpdateViewAngles( void ) {
|
|||
int i;
|
||||
idAngles delta;
|
||||
|
||||
if ( !noclip && ( gameLocal.inCinematic || privateCameraView || gameLocal.GetCamera() || influenceActive == INFLUENCE_LEVEL2 || objectiveSystemOpen ) ) {
|
||||
//###// by MacX
|
||||
if ( !noclip && ( gameLocal.inCinematic || privateCameraView || gameLocal.GetCamera() || influenceActive == INFLUENCE_LEVEL2 || objectiveSystemOpen ||
|
||||
diaryUIOpen || questlogUIOpen ) ) {
|
||||
//###//
|
||||
// no view changes at all, but we still want to update the deltas or else when
|
||||
// we get out of this mode, our view will snap to a kind of random angle
|
||||
UpdateDeltaViewAngles( viewAngles );
|
||||
|
@ -5053,6 +5364,10 @@ void idPlayer::UpdateAir( void ) {
|
|||
return;
|
||||
}
|
||||
|
||||
//###// by MacX - using code of water physics Mod
|
||||
idPhysics_Player *phys = dynamic_cast<idPhysics_Player *>(this->GetPhysics());
|
||||
//###//
|
||||
|
||||
// see if the player is connected to the info_vacuum
|
||||
bool newAirless = false;
|
||||
|
||||
|
@ -5073,6 +5388,14 @@ void idPlayer::UpdateAir( void ) {
|
|||
}
|
||||
}
|
||||
|
||||
//###// by MacX - using code of water physics Mod
|
||||
|
||||
// check if the player is in water
|
||||
if( phys != NULL && phys->GetWaterLevel() >= WATERLEVEL_HEAD )
|
||||
newAirless = true;
|
||||
|
||||
//###//
|
||||
|
||||
if ( newAirless ) {
|
||||
if ( !airless ) {
|
||||
StartSound( "snd_decompress", SND_CHANNEL_ANY, SSF_GLOBAL, false, NULL );
|
||||
|
@ -5430,6 +5753,222 @@ void idPlayer::TogglePDA( void ) {
|
|||
objectiveSystemOpen ^= 1;
|
||||
}
|
||||
|
||||
//###// by MacX
|
||||
|
||||
/*
|
||||
==============
|
||||
idPlayer::ToggleDiary
|
||||
==============
|
||||
*/
|
||||
void idPlayer::ToggleDiary( void ) {
|
||||
if ( diaryUI == NULL ) {
|
||||
return;
|
||||
}
|
||||
assert( hud );
|
||||
|
||||
if( !diaryUIOpen )
|
||||
{
|
||||
idStrList diary = inventory.diary;
|
||||
|
||||
inventory.diaryInfo.currentPage = 0;
|
||||
inventory.diaryInfo.diaryText = "";
|
||||
inventory.diaryInfo.diaryText2 = "";
|
||||
inventory.diaryInfo.diaryText3 = "";
|
||||
inventory.diaryInfo.diaryText4 = "";
|
||||
inventory.diaryInfo.pageLeft = "";
|
||||
inventory.diaryInfo.pageRight = "";
|
||||
|
||||
int i = 0;
|
||||
|
||||
if( diary.Num() > 0 && diary.Num() < 1000 /* something goes wrong */ ) {
|
||||
|
||||
i = diary.Num();
|
||||
if( i == 1 ) {
|
||||
inventory.diaryInfo.diaryText = diary[i-1];
|
||||
inventory.diaryInfo.pageLeft = va( "-%i-", i );
|
||||
inventory.diaryInfo.pageRight = va( "-%i-", i+1 );
|
||||
inventory.diaryInfo.currentPage = (( i+1 ) / 2 );
|
||||
}
|
||||
else {
|
||||
if( ( i % 2 ) == 1 ) {
|
||||
inventory.diaryInfo.diaryText = diary[i-1];
|
||||
inventory.diaryInfo.pageLeft = va( "-%i-", i );
|
||||
inventory.diaryInfo.pageRight = va( "-%i-", i+1 );
|
||||
inventory.diaryInfo.currentPage = (( i+1 ) / 2 );
|
||||
}
|
||||
else {
|
||||
inventory.diaryInfo.diaryText = diary[i-2];
|
||||
inventory.diaryInfo.diaryText2 = diary[i-1];
|
||||
inventory.diaryInfo.pageLeft = va( "-%i-", i-1 );
|
||||
inventory.diaryInfo.pageRight = va( "-%i-", i );
|
||||
inventory.diaryInfo.currentPage = ( i / 2 );
|
||||
}
|
||||
}
|
||||
|
||||
if( inventory.diaryInfo.currentPage > 1 ) {
|
||||
diaryUI->HandleNamedEvent( "prevPageOn" );
|
||||
diaryUI->HandleNamedEvent( "nextPageOff" );
|
||||
}
|
||||
|
||||
diaryUI->SetStateString( "pageLeft", inventory.diaryInfo.pageLeft );
|
||||
diaryUI->SetStateString( "pageRight", inventory.diaryInfo.pageRight );
|
||||
diaryUI->SetStateString( "diaryText", inventory.diaryInfo.diaryText );
|
||||
diaryUI->SetStateString( "diaryText2", inventory.diaryInfo.diaryText2 );
|
||||
}
|
||||
else {
|
||||
diaryUI->SetStateString( "pageLeft", "-1-" );
|
||||
diaryUI->SetStateString( "pageRight", "-2-" );
|
||||
}
|
||||
|
||||
diaryUI->Activate( true, gameLocal.time );
|
||||
}
|
||||
else {
|
||||
diaryUI->Activate( false, gameLocal.time );
|
||||
}
|
||||
|
||||
diaryUIOpen ^= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
==============
|
||||
idPlayer::ToggleQuestlog
|
||||
==============
|
||||
*/
|
||||
void idPlayer::ToggleQuestlog( void ) {
|
||||
if ( questlogUI == NULL ) {
|
||||
return;
|
||||
}
|
||||
assert( hud );
|
||||
|
||||
if( !questlogUIOpen )
|
||||
{
|
||||
idStrList quest = inventory.quest;
|
||||
|
||||
inventory.diaryInfo.currentPage = 0;
|
||||
inventory.diaryInfo.diaryText = "";
|
||||
inventory.diaryInfo.diaryText2 = "";
|
||||
inventory.diaryInfo.diaryText3 = "";
|
||||
inventory.diaryInfo.diaryText4 = "";
|
||||
inventory.diaryInfo.pageLeft = "";
|
||||
inventory.diaryInfo.pageRight = "";
|
||||
|
||||
int i = 0;
|
||||
|
||||
questlogUI->HandleNamedEvent( "StateLeftTopBoxOff" );
|
||||
questlogUI->HandleNamedEvent( "StateLeftBottomBoxOff" );
|
||||
questlogUI->HandleNamedEvent( "StateRightTopBoxOff" );
|
||||
questlogUI->HandleNamedEvent( "StateRightBottomBoxOff" );
|
||||
questlogUI->HandleNamedEvent( "StateLeftTopDoneOff" );
|
||||
questlogUI->HandleNamedEvent( "StateLeftBottomDoneOff" );
|
||||
questlogUI->HandleNamedEvent( "StateRightTopDoneOff" );
|
||||
questlogUI->HandleNamedEvent( "StateRightBottomDoneOff" );
|
||||
|
||||
if( quest.Num() > 0 && quest.Num() < 1000 /* something goes wrong */ ) {
|
||||
i = quest.Num();
|
||||
|
||||
if( (i % 4) == 1 ) {
|
||||
inventory.diaryInfo.diaryText = quest[i-1];
|
||||
inventory.diaryInfo.pageLeft = va( "-%i-", (i / 2) + 1 );
|
||||
inventory.diaryInfo.pageRight = va( "-%i-", (i / 2) + 2 );
|
||||
inventory.diaryInfo.currentPage = ((i + 3) / 4 );
|
||||
questlogUI->HandleNamedEvent( "StateLeftTopBoxOn" );
|
||||
if( inventory.questState[i-1] == "solved" ) {
|
||||
questlogUI->HandleNamedEvent( "StateLeftTopDoneOn" );
|
||||
}
|
||||
}
|
||||
else if( (i % 4) == 2 ) {
|
||||
inventory.diaryInfo.diaryText = quest[i-2];
|
||||
inventory.diaryInfo.diaryText2 = quest[i-1];
|
||||
inventory.diaryInfo.pageLeft = va( "-%i-", (i / 2) );
|
||||
inventory.diaryInfo.pageRight = va( "-%i-", (i / 2) + 1 );
|
||||
inventory.diaryInfo.currentPage = ((i + 2) / 4 );
|
||||
questlogUI->HandleNamedEvent( "StateLeftTopBoxOn" );
|
||||
questlogUI->HandleNamedEvent( "StateLeftBottomBoxOn" );
|
||||
if( inventory.questState[i-2] == "solved" ) {
|
||||
questlogUI->HandleNamedEvent( "StateLeftTopDoneOn" );
|
||||
}
|
||||
if( inventory.questState[i-1] == "solved" ) {
|
||||
questlogUI->HandleNamedEvent( "StateLeftBottomDoneOn" );
|
||||
}
|
||||
}
|
||||
else if( (i % 4) == 3 ) {
|
||||
inventory.diaryInfo.diaryText = quest[i-3];
|
||||
inventory.diaryInfo.diaryText2 = quest[i-2];
|
||||
inventory.diaryInfo.diaryText3 = quest[i-1];
|
||||
inventory.diaryInfo.pageLeft = va( "-%i-", (i / 2) );
|
||||
inventory.diaryInfo.pageRight = va( "-%i-", (i / 2) + 1 );
|
||||
inventory.diaryInfo.currentPage = ((i + 1) / 4 );
|
||||
|
||||
questlogUI->HandleNamedEvent( "StateLeftTopBoxOn" );
|
||||
questlogUI->HandleNamedEvent( "StateLeftBottomBoxOn" );
|
||||
questlogUI->HandleNamedEvent( "StateRightTopBoxOn" );
|
||||
|
||||
if( inventory.questState[i-3] == "solved" ) {
|
||||
questlogUI->HandleNamedEvent( "StateLeftTopDoneOn" );
|
||||
}
|
||||
if( inventory.questState[i-2] == "solved" ) {
|
||||
questlogUI->HandleNamedEvent( "StateLeftBottomDoneOn" );
|
||||
}
|
||||
if( inventory.questState[i-1] == "solved" ) {
|
||||
questlogUI->HandleNamedEvent( "StateRightTopDoneOn" );
|
||||
}
|
||||
}
|
||||
else if( (i % 4) == 0 ) {
|
||||
inventory.diaryInfo.diaryText = quest[i-4];
|
||||
inventory.diaryInfo.diaryText2 = quest[i-3];
|
||||
inventory.diaryInfo.diaryText3 = quest[i-2];
|
||||
inventory.diaryInfo.diaryText4 = quest[i-1];
|
||||
inventory.diaryInfo.pageLeft = va( "-%i-", (i / 2) - 1 );
|
||||
inventory.diaryInfo.pageRight = va( "-%i-", (i / 2) );
|
||||
inventory.diaryInfo.currentPage = ( i / 4 );
|
||||
|
||||
questlogUI->HandleNamedEvent( "StateLeftTopBoxOn" );
|
||||
questlogUI->HandleNamedEvent( "StateLeftBottomBoxOn" );
|
||||
questlogUI->HandleNamedEvent( "StateRightTopBoxOn" );
|
||||
questlogUI->HandleNamedEvent( "StateRightBottomBoxOn" );
|
||||
|
||||
if( inventory.questState[i-4] == "solved" ) {
|
||||
questlogUI->HandleNamedEvent( "StateLeftTopDoneOn" );
|
||||
}
|
||||
if( inventory.questState[i-3] == "solved" ) {
|
||||
questlogUI->HandleNamedEvent( "StateLeftBottomDoneOn" );
|
||||
}
|
||||
if( inventory.questState[i-2] == "solved" ) {
|
||||
questlogUI->HandleNamedEvent( "StateRightTopDoneOn" );
|
||||
}
|
||||
if( inventory.questState[i-1] == "solved" ) {
|
||||
questlogUI->HandleNamedEvent( "StateRightBottomDoneOn" );
|
||||
}
|
||||
}
|
||||
|
||||
if( inventory.diaryInfo.currentPage > 1 ) {
|
||||
questlogUI->HandleNamedEvent( "prevPageOn" );
|
||||
questlogUI->HandleNamedEvent( "nextPageOff" );
|
||||
}
|
||||
|
||||
questlogUI->SetStateString( "pageLeft", inventory.diaryInfo.pageLeft );
|
||||
questlogUI->SetStateString( "pageRight", inventory.diaryInfo.pageRight );
|
||||
questlogUI->SetStateString( "diaryText", inventory.diaryInfo.diaryText );
|
||||
questlogUI->SetStateString( "diaryText2", inventory.diaryInfo.diaryText2 );
|
||||
questlogUI->SetStateString( "diaryText3", inventory.diaryInfo.diaryText3 );
|
||||
questlogUI->SetStateString( "diaryText4", inventory.diaryInfo.diaryText4 );
|
||||
}
|
||||
else {
|
||||
questlogUI->SetStateString( "pageLeft", "-1-" );
|
||||
questlogUI->SetStateString( "pageRight", "-2-" );
|
||||
}
|
||||
|
||||
questlogUI->Activate( true, gameLocal.time );
|
||||
}
|
||||
else {
|
||||
questlogUI->Activate( false, gameLocal.time );
|
||||
}
|
||||
|
||||
questlogUIOpen ^= 1;
|
||||
}
|
||||
|
||||
//###//
|
||||
|
||||
/*
|
||||
==============
|
||||
idPlayer::ToggleScoreboard
|
||||
|
@ -5565,7 +6104,9 @@ void idPlayer::PerformImpulse( int impulse ) {
|
|||
SelectWeapon( impulse, false );
|
||||
return;
|
||||
}
|
||||
|
||||
//Cameron Law START
|
||||
idPlayer *player=gameLocal.GetLocalPlayer();
|
||||
//Cameron Law END
|
||||
switch( impulse ) {
|
||||
case IMPULSE_13: {
|
||||
Reload();
|
||||
|
@ -5625,6 +6166,47 @@ void idPlayer::PerformImpulse( int impulse ) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
//Cameron Law START
|
||||
case IMPULSE_35: {
|
||||
if ( cvarSystem->GetCVarFloat( "timeScale" ) == 1 ) {
|
||||
idLib::common->DPrintf( "pm_slowmotion (20%): %f\n", pm_slowmotion.GetFloat() );
|
||||
idLib::common->DPrintf( "Slowmotion: %f\n", player->slowmotion );
|
||||
if ( player->slowmotion > ( pm_slowmotion.GetFloat() * 0.2f ) ) {
|
||||
cvarSystem->SetCVarFloat( "timeScale", 0.5 );
|
||||
player->startslow = gameLocal.time;
|
||||
}
|
||||
} else {
|
||||
cvarSystem->SetCVarFloat( "timeScale", 1 );
|
||||
player->startslow = gameLocal.time;
|
||||
}
|
||||
break;
|
||||
}
|
||||
//Cameron Law End
|
||||
//###// by MacX
|
||||
case IMPULSE_37: {
|
||||
ToggleDiary();
|
||||
break;
|
||||
}
|
||||
case IMPULSE_38: {
|
||||
ToggleQuestlog();
|
||||
break;
|
||||
}
|
||||
//###//
|
||||
//Cameron Law START (Toggle thirdperson)
|
||||
//###// by MacX
|
||||
case IMPULSE_39: { // 39 -> IMPULSE_39 ( defined in framework/usercmdgen.h )
|
||||
//###//
|
||||
if ( pm_thirdPerson.GetBool() == 1 )
|
||||
{
|
||||
pm_thirdPerson.SetBool(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pm_thirdPerson.SetBool(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//Cameron Law END
|
||||
case IMPULSE_40: {
|
||||
UseVehicle();
|
||||
break;
|
||||
|
@ -5641,6 +6223,16 @@ bool idPlayer::HandleESC( void ) {
|
|||
TogglePDA();
|
||||
return true;
|
||||
}
|
||||
//###// by MacX
|
||||
if( diaryUIOpen ) {
|
||||
ToggleDiary();
|
||||
return true;
|
||||
}
|
||||
if( questlogUIOpen ) {
|
||||
ToggleQuestlog();
|
||||
return true;
|
||||
}
|
||||
//###//
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -5737,7 +6329,14 @@ void idPlayer::AdjustSpeed( void ) {
|
|||
speed *= 0.33f;
|
||||
}
|
||||
|
||||
physicsObj.SetSpeed( speed, pm_crouchspeed.GetFloat() );
|
||||
//###// by MacX
|
||||
if ( cvarSystem->GetCVarFloat( "timeScale" ) == 1 ) {
|
||||
physicsObj.SetSpeed( speed, pm_crouchspeed.GetFloat() );
|
||||
}
|
||||
else {
|
||||
physicsObj.SetSpeed( speed + 100, pm_crouchspeed.GetFloat() + 80 );
|
||||
}
|
||||
//###//
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -6197,6 +6796,33 @@ void idPlayer::Think( void ) {
|
|||
|
||||
UpdatePlayerIcons();
|
||||
|
||||
//Cameron Law END - edited by MacX
|
||||
if ( cvarSystem->GetCVarFloat( "timeScale" ) != 1 ) {
|
||||
if ( slowmotion <= 0 ) {
|
||||
slowmotion = 0.0f;
|
||||
cvarSystem->SetCVarFloat( "timeScale", 1 );
|
||||
startslow = gameLocal.time;
|
||||
} else {
|
||||
if ( ( startslow + 250 ) < gameLocal.time ) {
|
||||
slowmotion -= 2.0f;
|
||||
startslow = gameLocal.time;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Cameron Law END
|
||||
//###// by MacX
|
||||
else {
|
||||
if ( slowmotion >= pm_slowmotion.GetFloat() ) {
|
||||
slowmotion = pm_slowmotion.GetFloat();
|
||||
} else {
|
||||
if ( ( startslow + 1000 ) < gameLocal.time ) {
|
||||
slowmotion += pm_slowmotionrate.GetFloat();
|
||||
startslow = gameLocal.time;
|
||||
}
|
||||
}
|
||||
}
|
||||
//###//
|
||||
|
||||
// latch button actions
|
||||
oldButtons = usercmd.buttons;
|
||||
|
||||
|
@ -6221,10 +6847,20 @@ void idPlayer::Think( void ) {
|
|||
oldFlags = usercmd.flags;
|
||||
}
|
||||
|
||||
if ( objectiveSystemOpen || gameLocal.inCinematic || influenceActive ) {
|
||||
//###// by MacX - using code by Cameron
|
||||
if ( objectiveSystemOpen || gameLocal.inCinematic || influenceActive ||
|
||||
diaryUIOpen || questlogUIOpen ) {
|
||||
|
||||
if ( objectiveSystemOpen && AI_PAIN ) {
|
||||
TogglePDA();
|
||||
}
|
||||
if( diaryUIOpen && AI_PAIN ) {
|
||||
ToggleDiary();
|
||||
}
|
||||
if( questlogUIOpen && AI_PAIN ) {
|
||||
ToggleQuestlog();
|
||||
}
|
||||
//###//
|
||||
usercmd.forwardmove = 0;
|
||||
usercmd.rightmove = 0;
|
||||
usercmd.upmove = 0;
|
||||
|
@ -6256,8 +6892,10 @@ void idPlayer::Think( void ) {
|
|||
if ( ( usercmd.buttons ^ oldCmd.buttons ) & BUTTON_ZOOM ) {
|
||||
if ( ( usercmd.buttons & BUTTON_ZOOM ) && weapon.GetEntity() ) {
|
||||
zoomFov.Init( gameLocal.time, 200.0f, CalcFov( false ), weapon.GetEntity()->GetZoomFov() );
|
||||
bIsZoomed = true; // sikk - Zoom DoF Fullscreen PostProcess Effect
|
||||
} else {
|
||||
zoomFov.Init( gameLocal.time, 200.0f, zoomFov.GetCurrentValue( gameLocal.time ), DefaultFov() );
|
||||
bIsZoomed = false; // sikk - Zoom DoF Fullscreen PostProcess Effect
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7167,6 +7805,19 @@ void idPlayer::OffsetThirdPersonView( float angle, float range, float height, bo
|
|||
angles = viewAngles;
|
||||
GetViewPos( origin, axis );
|
||||
|
||||
//Cameron Law START (Zoom camera in and out)
|
||||
if( usercmd.buttons & BUTTON_5 && range < MAX_PLAYER_CAM )
|
||||
{
|
||||
range++;
|
||||
}
|
||||
else if( usercmd.buttons & BUTTON_6 && range > MIN_PLAYER_CAM )
|
||||
{
|
||||
range--;
|
||||
}
|
||||
//save range
|
||||
pm_thirdPersonRange.SetFloat(range);
|
||||
//Cameron Law END
|
||||
|
||||
if ( angle ) {
|
||||
angles.pitch = 0.0f;
|
||||
}
|
||||
|
@ -7812,11 +8463,13 @@ void idPlayer::ClientPredictionThink( void ) {
|
|||
buttonMask &= usercmd.buttons;
|
||||
usercmd.buttons &= ~buttonMask;
|
||||
|
||||
if ( objectiveSystemOpen ) {
|
||||
//###// by MacX - using code by Cameron
|
||||
if ( objectiveSystemOpen || diaryUIOpen || questlogUIOpen ) {
|
||||
usercmd.forwardmove = 0;
|
||||
usercmd.rightmove = 0;
|
||||
usercmd.upmove = 0;
|
||||
}
|
||||
//###//
|
||||
|
||||
// clear the ik before we do anything else so the skeleton doesn't get updated twice
|
||||
walkIK.ClearJointMods();
|
||||
|
|
|
@ -31,6 +31,11 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "idlib/math/Interpolate.h"
|
||||
|
||||
//Cameron Law START Max and Min camera settings
|
||||
const float MIN_PLAYER_CAM=20;
|
||||
const float MAX_PLAYER_CAM=300;
|
||||
//Cameron Law END
|
||||
|
||||
#include "physics/Physics_Player.h"
|
||||
#include "Item.h"
|
||||
#include "Actor.h"
|
||||
|
@ -122,6 +127,20 @@ enum {
|
|||
INFLUENCE_LEVEL3, // slow player movement
|
||||
};
|
||||
|
||||
//###// by MacX
|
||||
|
||||
struct idDiaryInfo{
|
||||
int currentPage;
|
||||
idStr diaryText;
|
||||
idStr diaryText2;
|
||||
idStr diaryText3;
|
||||
idStr diaryText4;
|
||||
idStr pageLeft; // page number, i.e. "-1-"
|
||||
idStr pageRight; // page number, i.e. "-2-"
|
||||
};
|
||||
|
||||
//###//
|
||||
|
||||
class idInventory {
|
||||
public:
|
||||
int maxHealth;
|
||||
|
@ -129,6 +148,33 @@ public:
|
|||
int powerups;
|
||||
int armor;
|
||||
int maxarmor;
|
||||
|
||||
//###// by MacX
|
||||
int money;
|
||||
idStrList diary;
|
||||
idStrList quest;
|
||||
idStrList questState;
|
||||
idDiaryInfo diaryInfo;
|
||||
|
||||
int enemiesKilled;
|
||||
|
||||
int testVarGui1;
|
||||
int testVarGui2;
|
||||
int testVarGui3;
|
||||
int testVarGui4;
|
||||
int testVarGui5;
|
||||
int testVar1;
|
||||
int testVar2;
|
||||
int testVar3;
|
||||
int testVar4;
|
||||
int testVar5;
|
||||
int testVar6;
|
||||
int testVar7;
|
||||
int testVar8;
|
||||
int testVar9;
|
||||
int testVar10;
|
||||
//###//
|
||||
|
||||
int ammo[ AMMO_NUMTYPES ];
|
||||
int clip[ MAX_WEAPONS ];
|
||||
int powerupEndTime[ MAX_POWERUPS ];
|
||||
|
@ -265,6 +311,15 @@ public:
|
|||
idUserInterface * objectiveSystem;
|
||||
bool objectiveSystemOpen;
|
||||
|
||||
//###// by MacX
|
||||
|
||||
idUserInterface* diaryUI;
|
||||
bool diaryUIOpen;
|
||||
idUserInterface* questlogUI;
|
||||
bool questlogUIOpen;
|
||||
|
||||
//###//
|
||||
|
||||
int weapon_soulcube;
|
||||
int weapon_pda;
|
||||
int weapon_fists;
|
||||
|
@ -320,6 +375,11 @@ public:
|
|||
int minRespawnTime; // can respawn when time > this, force after g_forcerespawn
|
||||
int maxRespawnTime; // force respawn after this time
|
||||
|
||||
//Cameron Law Start - edited by MacX
|
||||
float slowmotion;
|
||||
int startslow;
|
||||
//Cameron Law End
|
||||
|
||||
// the first person view values are always calculated, even
|
||||
// if a third person view is used
|
||||
idVec3 firstPersonViewOrigin;
|
||||
|
@ -327,6 +387,7 @@ public:
|
|||
|
||||
idDragEntity dragEntity;
|
||||
|
||||
bool bIsZoomed; // sikk - Zoom DoF Fullscreen PostProcess Effect
|
||||
public:
|
||||
CLASS_PROTOTYPE( idPlayer );
|
||||
|
||||
|
@ -460,6 +521,12 @@ public:
|
|||
void PerformImpulse( int impulse );
|
||||
void Spectate( bool spectate );
|
||||
void TogglePDA( void );
|
||||
|
||||
//###// by MacX
|
||||
void ToggleDiary( void );
|
||||
void ToggleQuestlog( void );
|
||||
//###//
|
||||
|
||||
void ToggleScoreboard( void );
|
||||
void RouteGuiMouse( idUserInterface *gui );
|
||||
void UpdateHud( void );
|
||||
|
|
|
@ -54,6 +54,16 @@ idPlayerView::idPlayerView() {
|
|||
bloodSprayMaterial = declManager->FindMaterial( "textures/decals/bloodspray" );
|
||||
bfgMaterial = declManager->FindMaterial( "textures/decals/bfgvision" );
|
||||
lagoMaterial = declManager->FindMaterial( LAGO_MATERIAL, false );
|
||||
|
||||
// sikk---> Brilliant Bloom/Motion Blur/DoF/Scene Effect PostProcess
|
||||
bloomAddMaterial = declManager->FindMaterial( "textures/AFX/AFXadd" );
|
||||
bloomBlurMaterial = declManager->FindMaterial( "textures/AFX/AFXblurB" );
|
||||
bloomWeightMaterial = declManager->FindMaterial( "textures/AFX/AFXweight" );
|
||||
motionblurMaterial = declManager->FindMaterial( "textures/sfx/motionblur" );
|
||||
dofMaterial = declManager->FindMaterial( "textures/sfx/zoomDoF" );
|
||||
celMaterial = declManager->FindMaterial( "textures/sfx/cel" );
|
||||
// <---sikk
|
||||
|
||||
bfgVision = false;
|
||||
dvFinishTime = 0;
|
||||
kickFinishTime = 0;
|
||||
|
@ -448,6 +458,17 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view )
|
|||
return;
|
||||
}
|
||||
|
||||
//###// by MacX - using code by Cameron
|
||||
if( player->diaryUIOpen ) {
|
||||
player->diaryUI->Redraw( gameLocal.time );
|
||||
return;
|
||||
}
|
||||
if( player->questlogUIOpen ) {
|
||||
player->questlogUI->Redraw( gameLocal.time );
|
||||
return;
|
||||
}
|
||||
//###//
|
||||
|
||||
// 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();
|
||||
|
@ -458,8 +479,13 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view )
|
|||
return;
|
||||
}
|
||||
|
||||
//###// by MacX
|
||||
|
||||
// draw screen blobs
|
||||
if ( !pm_thirdPerson.GetBool() && !g_skipViewEffects.GetBool() ) {
|
||||
//if ( !pm_thirdPerson.GetBool() && !g_skipViewEffects.GetBool() ) {
|
||||
if ( !g_skipViewEffects.GetBool() ) {
|
||||
|
||||
//###//
|
||||
for ( int i = 0 ; i < MAX_SCREEN_BLOBS ; i++ ) {
|
||||
screenBlob_t *blob = &screenBlobs[i];
|
||||
if ( blob->finishTime <= gameLocal.time ) {
|
||||
|
@ -477,7 +503,8 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view )
|
|||
renderSystem->DrawStretchPic( blob->x, blob->y, blob->w, blob->h,blob->s1, blob->t1, blob->s2, blob->t2, blob->material );
|
||||
}
|
||||
}
|
||||
player->DrawHUD( hud );
|
||||
|
||||
// player->DrawHUD( hud ); // sikk - Draw the hud after postprocessing effects
|
||||
|
||||
// armor impulse feedback
|
||||
float armorPulse = ( gameLocal.time - player->lastArmorPulse ) / 250.0f;
|
||||
|
@ -487,7 +514,6 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view )
|
|||
renderSystem->DrawStretchPic( 0, 0, 640, 480, 0, 0, 1, 1, armorMaterial );
|
||||
}
|
||||
|
||||
|
||||
// tunnel vision
|
||||
float health = 0.0f;
|
||||
if ( g_testHealthVision.GetFloat() != 0.0f ) {
|
||||
|
@ -523,6 +549,27 @@ void idPlayerView::SingleView( idUserInterface *hud, const renderView_t *view )
|
|||
renderSystem->DrawStretchPic( 0.0f, 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 1.0f, 1.0f, bfgMaterial );
|
||||
}
|
||||
|
||||
// sikk---> Brilliant Bloom/Filmgrain/Motion Blur/DoF/Cel Shading PostProcessing Effects
|
||||
if( z_bloom.GetBool() &&
|
||||
!player->PowerUpActive( BERSERK ) &&
|
||||
//###// by MacX
|
||||
( cvarSystem->GetCVarFloat( "timeScale" ) == 1 ) ) {
|
||||
//###//
|
||||
|
||||
PostprocessBloom();
|
||||
}
|
||||
if ( r_useCelShading.GetBool() ) {
|
||||
PostprocessCelShading();
|
||||
}
|
||||
if ( r_useMotionBlur.GetBool() ) {
|
||||
PostprocessMotionBlur();
|
||||
}
|
||||
if ( r_useZoomDoF.GetBool() ) {
|
||||
PostprocessZoomDoF();
|
||||
}
|
||||
// <---sikk
|
||||
|
||||
player->DrawHUD( hud ); // sikk - Draw the hud after postprocessing effects
|
||||
}
|
||||
|
||||
// test a single material drawn over everything
|
||||
|
@ -711,7 +758,10 @@ void idPlayerView::RenderPlayerView( idUserInterface *hud ) {
|
|||
InfluenceVision( hud, view );
|
||||
} else if ( gameLocal.time < dvFinishTime ) {
|
||||
DoubleVision( hud, view, dvFinishTime - gameLocal.time );
|
||||
} else if ( player->PowerUpActive( BERSERK ) ) {
|
||||
//CAMERON LAW START
|
||||
// } else if ( player->PowerUpActive( BERSERK ) ) {
|
||||
} else if ( player->PowerUpActive( BERSERK ) || cvarSystem->GetCVarFloat("timeScale") !=1) {
|
||||
//CAMERON LAW END
|
||||
BerserkVision( hud, view );
|
||||
} else {
|
||||
SingleView( hud, view );
|
||||
|
@ -724,3 +774,121 @@ void idPlayerView::RenderPlayerView( idUserInterface *hud ) {
|
|||
renderSystem->DrawStretchPic( 10.0f, 380.0f, 64.0f, 64.0f, 0.0f, 0.0f, 1.0f, 1.0f, lagoMaterial );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sikk---> Brilliant Bloom Fullscreen PostProcess Effect
|
||||
/*
|
||||
===================
|
||||
idPlayerView::PostprocessBloom
|
||||
|
||||
- original code by mahaX
|
||||
===================
|
||||
*/
|
||||
void idPlayerView::PostprocessBloom() {
|
||||
int bW, bH, rbW, rbH; // buffer and renderBuffer (currentRender)
|
||||
float rbMx, rbMy; // renderBuffer margin
|
||||
|
||||
// notes: outside the source code I might have mixed the bloom buffer as "render buffer"...
|
||||
|
||||
// determine AFX buffer size
|
||||
switch ( z_bloomBufferSize.GetInteger() ) {
|
||||
case 0:
|
||||
bW = 64; bH = 32; break;
|
||||
case 1:
|
||||
bW = 128; bH = 64; break;
|
||||
case 2:
|
||||
bW = 256; bH = 128; break;
|
||||
case 3:
|
||||
bW = 512; bH = 256; break;
|
||||
case 4:
|
||||
bW = 1024; bH = 512; break;
|
||||
default:
|
||||
bW = 256; bH = 128; break;
|
||||
}
|
||||
|
||||
// determine currentRender buffer size
|
||||
if ( renderSystem->GetScreenWidth() > 1024 )
|
||||
rbW = 2048;
|
||||
else
|
||||
rbW = 1024;
|
||||
|
||||
if ( renderSystem->GetScreenHeight() > 1024 )
|
||||
rbH = 2048;
|
||||
else if ( renderSystem->GetScreenHeight() < 512 )
|
||||
rbH = 512;
|
||||
else
|
||||
rbH = 1024;
|
||||
|
||||
rbMx = renderSystem->GetScreenWidth() / (float)rbW;
|
||||
rbMy = renderSystem->GetScreenHeight() / (float)rbH;
|
||||
|
||||
// capture original
|
||||
renderSystem->CaptureRenderToImage( "_currentRender" );
|
||||
|
||||
// create weight map
|
||||
renderSystem->CropRenderSize( 2, 2, true, true );
|
||||
renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, bloomWeightMaterial );
|
||||
renderSystem->CaptureRenderToImage( "_zweight" );
|
||||
renderSystem->UnCrop();
|
||||
|
||||
// create lower res map
|
||||
renderSystem->CropRenderSize( bW, bH, true, true );
|
||||
renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, rbMy, rbMx, 0, declManager->FindMaterial( "_currentRender" ) );
|
||||
renderSystem->CaptureRenderToImage( "_zbloom" );
|
||||
|
||||
// loop iterations
|
||||
for ( int i = 0; i < z_bloomIterations.GetInteger(); i++ ) {
|
||||
renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, bloomBlurMaterial );
|
||||
renderSystem->CaptureRenderToImage( "_zbloom" );
|
||||
}
|
||||
renderSystem->UnCrop();
|
||||
|
||||
// blend original and bloom
|
||||
renderSystem->DrawStretchPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1, 1, 0, bloomAddMaterial );
|
||||
}
|
||||
// <---sikk
|
||||
|
||||
// sikk---> Motion Blur Fullscreen PostProcess Effect
|
||||
/*
|
||||
===================
|
||||
idPlayerView::PostprocessMotionBlur
|
||||
===================
|
||||
*/
|
||||
void idPlayerView::PostprocessMotionBlur() {
|
||||
if ( ( player->viewAngles.pitch >= mbPrevAngles.pitch + 5 ) ||
|
||||
( player->viewAngles.pitch <= mbPrevAngles.pitch - 5 ) ||
|
||||
( player->viewAngles.yaw >= mbPrevAngles.yaw + 5 ) ||
|
||||
( player->viewAngles.yaw <= mbPrevAngles.yaw - 5 ) ) {
|
||||
|
||||
renderSystem->CaptureRenderToImage( "_currentRender" );
|
||||
renderSystem->DrawStretchPic( 0, 0, 640, 480, 0, 0, 1, 1, motionblurMaterial );
|
||||
}
|
||||
|
||||
mbPrevAngles = player->viewAngles;
|
||||
}
|
||||
// <---sikk
|
||||
|
||||
// sikk---> Zoom DoF Fullscreen PostProcess Effect
|
||||
/*
|
||||
===================
|
||||
idPlayerView::PostprocessZoomDoF
|
||||
===================
|
||||
*/
|
||||
void idPlayerView::PostprocessZoomDoF() {
|
||||
if ( player->bIsZoomed ) {
|
||||
renderSystem->CaptureRenderToImage( "_currentRender" );
|
||||
renderSystem->DrawStretchPic( 0, 0, 640, 480, 0, 0, 1, 1, dofMaterial );
|
||||
}
|
||||
}
|
||||
|
||||
// sikk---> Cel-Shading Fullscreen PostProcess Effect
|
||||
/*
|
||||
===================
|
||||
idPlayerView::PostprocessCelShading
|
||||
===================
|
||||
*/
|
||||
void idPlayerView::PostprocessCelShading() {
|
||||
renderSystem->CaptureRenderToImage( "_currentRender" );
|
||||
renderSystem->DrawStretchPic( 0, 0, 640, 480, 0, 0, 1, 1, celMaterial);
|
||||
}
|
||||
// <---sikk
|
||||
|
|
|
@ -98,6 +98,13 @@ private:
|
|||
void InfluenceVision( idUserInterface *hud, const renderView_t *view );
|
||||
void ScreenFade();
|
||||
|
||||
// sikk---> Brilliant Bloom/Motion Blur/DoF PostProcessing Effects
|
||||
void PostprocessBloom();
|
||||
void PostprocessMotionBlur();
|
||||
void PostprocessZoomDoF();
|
||||
void PostprocessCelShading();
|
||||
// <---sikk
|
||||
|
||||
screenBlob_t * GetScreenBlob();
|
||||
|
||||
screenBlob_t screenBlobs[MAX_SCREEN_BLOBS];
|
||||
|
@ -117,6 +124,18 @@ private:
|
|||
const idMaterial * bloodSprayMaterial; // blood spray
|
||||
const idMaterial * bfgMaterial; // when targeted with BFG
|
||||
const idMaterial * lagoMaterial; // lagometer drawing
|
||||
|
||||
// sikk---> Brilliant Bloom/Filmgrain/Motion Blur/DoF/Scene Effect PostProcess
|
||||
const idMaterial * bloomAddMaterial; // Bloom Add material
|
||||
const idMaterial * bloomBlurMaterial; // Bloom Blur material
|
||||
const idMaterial * bloomWeightMaterial; // Bloom Weight material
|
||||
const idMaterial * dofMaterial; // DoF material
|
||||
const idMaterial * motionblurMaterial; // Motion Blur material
|
||||
const idMaterial * celMaterial; // Cel Shading
|
||||
|
||||
idAngles mbPrevAngles; // sikk - Holds previous frame's player view angle for motion blur
|
||||
// <---sikk
|
||||
|
||||
float lastDamageTime; // accentuate the tunnel effect for a while
|
||||
|
||||
idVec4 fadeColor; // fade color
|
||||
|
|
|
@ -287,6 +287,14 @@ void idTrigger_Multi::Save( idSaveGame *savefile ) const {
|
|||
savefile->WriteBool( touchOther );
|
||||
savefile->WriteBool( triggerFirst );
|
||||
savefile->WriteBool( triggerWithSelf );
|
||||
|
||||
//###// by MacX
|
||||
savefile->WriteString( diaryTextKey );
|
||||
savefile->WriteString( questlogTextKey );
|
||||
savefile->WriteString( questDone );
|
||||
savefile->WriteString( subtitle );
|
||||
//###//
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -306,6 +314,14 @@ void idTrigger_Multi::Restore( idRestoreGame *savefile ) {
|
|||
savefile->ReadBool( touchOther );
|
||||
savefile->ReadBool( triggerFirst );
|
||||
savefile->ReadBool( triggerWithSelf );
|
||||
|
||||
//###// by MacX
|
||||
savefile->ReadString( diaryTextKey );
|
||||
savefile->ReadString( questlogTextKey );
|
||||
savefile->ReadString( questDone );
|
||||
savefile->ReadString( subtitle );
|
||||
//###//
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -341,6 +357,13 @@ void idTrigger_Multi::Spawn( void ) {
|
|||
spawnArgs.GetBool( "triggerFirst", "0", triggerFirst );
|
||||
spawnArgs.GetBool( "triggerWithSelf", "0", triggerWithSelf );
|
||||
|
||||
//###// by MacX
|
||||
spawnArgs.GetString( "diaryTextKey", "", diaryTextKey );
|
||||
spawnArgs.GetString( "questlogTextKey", "", questlogTextKey );
|
||||
spawnArgs.GetString( "questDone", "", questDone );
|
||||
spawnArgs.GetString( "subtitle", "", subtitle );
|
||||
//###//
|
||||
|
||||
if ( spawnArgs.GetBool( "anyTouch" ) ) {
|
||||
touchClient = true;
|
||||
touchOther = true;
|
||||
|
@ -402,6 +425,72 @@ void idTrigger_Multi::TriggerAction( idEntity *activator ) {
|
|||
nextTriggerTime = gameLocal.time + 1;
|
||||
PostEventMS( &EV_Remove, 0 );
|
||||
}
|
||||
|
||||
//###// by MacX
|
||||
|
||||
idStr str;
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idStr diaryString = "";
|
||||
if( !diaryTextKey.IsEmpty() ) {
|
||||
diaryString = "#str_";
|
||||
diaryString += diaryTextKey;
|
||||
}
|
||||
|
||||
if ( idStr::Cmpn( diaryString, STRTABLE_ID, STRTABLE_ID_LENGTH ) == 0 ) {
|
||||
str = common->GetLanguageDict()->GetString( diaryString.c_str() );
|
||||
player->inventory.diary.Append( str );
|
||||
}
|
||||
|
||||
idStr questlogString = "";
|
||||
if( !questlogTextKey.IsEmpty() ) {
|
||||
questlogString = "#str_";
|
||||
questlogString += questlogTextKey;
|
||||
}
|
||||
|
||||
if ( idStr::Cmpn( questlogString, STRTABLE_ID, STRTABLE_ID_LENGTH ) == 0 ) {
|
||||
str = common->GetLanguageDict()->GetString( questlogString.c_str() );
|
||||
player->inventory.quest.Append( str );
|
||||
player->hud->HandleNamedEvent( "InfoNewQuest" );
|
||||
player->inventory.questState.Append( "unsolved" );
|
||||
}
|
||||
|
||||
idStr strDone = "";
|
||||
if( !questDone.IsEmpty() ) {
|
||||
strDone = "#str_";
|
||||
strDone += questDone;
|
||||
}
|
||||
|
||||
if ( idStr::Cmpn( strDone, STRTABLE_ID, STRTABLE_ID_LENGTH ) == 0 ) {
|
||||
str = common->GetLanguageDict()->GetString( strDone.c_str() );
|
||||
questDone = str;
|
||||
|
||||
if( !questDone.IsEmpty() ) {
|
||||
for( int i = 0; i < player->inventory.quest.Num(); i++ ) {
|
||||
if( questDone == player->inventory.quest[i] ) {
|
||||
player->inventory.questState[i] = "solved";
|
||||
player->hud->HandleNamedEvent( "InfoQuestDone" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( g_showSubtitle.GetBool() ) {
|
||||
idStr strSubtitle = "";
|
||||
if( !subtitle.IsEmpty() ) {
|
||||
strSubtitle = "#str_";
|
||||
strSubtitle += subtitle;
|
||||
}
|
||||
|
||||
if( idStr::Cmpn( strSubtitle, STRTABLE_ID, STRTABLE_ID_LENGTH ) == 0 ) {
|
||||
str = common->GetLanguageDict()->GetString( strSubtitle.c_str() );
|
||||
player->hud->SetStateString( "player_subtitle", str.c_str() );
|
||||
player->hud->HandleNamedEvent( "ShowSubtitle" );
|
||||
}
|
||||
}
|
||||
|
||||
//###//
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -102,6 +102,13 @@ private:
|
|||
bool triggerFirst;
|
||||
bool triggerWithSelf;
|
||||
|
||||
//###// by MacX
|
||||
idStr diaryTextKey;
|
||||
idStr questlogTextKey;
|
||||
idStr questDone;
|
||||
idStr subtitle;
|
||||
//###//
|
||||
|
||||
bool CheckFacing( idEntity *activator );
|
||||
void TriggerAction( idEntity *activator );
|
||||
void Event_TriggerAction( idEntity *activator );
|
||||
|
|
|
@ -3398,6 +3398,28 @@ void idAI::Killed( idEntity *inflictor, idEntity *attacker, int damage, const id
|
|||
if ( ( attacker && attacker->IsType( idPlayer::Type ) ) && ( inflictor && !inflictor->IsType( idSoulCubeMissile::Type ) ) ) {
|
||||
static_cast< idPlayer* >( attacker )->AddAIKill();
|
||||
}
|
||||
|
||||
//###// by MacX
|
||||
srand( (unsigned)time( NULL ) );
|
||||
|
||||
int randMoney = 50 + ( rand() % ( 100 - 50 + 1 ) ); // random value between 50 and 100
|
||||
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
if( player->inventory.money < 999999 ) {
|
||||
player->inventory.money += randMoney;
|
||||
if( player->inventory.money > 999999 ) {
|
||||
player->inventory.money = 999999;
|
||||
}
|
||||
}
|
||||
|
||||
if( player->inventory.enemiesKilled < INT_MAX ) {
|
||||
player->inventory.enemiesKilled += 1;
|
||||
}
|
||||
if( player->inventory.enemiesKilled < 0 ) {
|
||||
player->inventory.enemiesKilled = 0;
|
||||
}
|
||||
|
||||
//###//
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -302,18 +302,26 @@ void Cmd_Give_f( const idCmdArgs &args ) {
|
|||
give_all = false;
|
||||
}
|
||||
|
||||
if ( give_all || ( idStr::Cmpn( name, "weapon", 6 ) == 0 ) ) {
|
||||
if ( gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) ) {
|
||||
gameLocal.world->spawnArgs.SetBool( "no_Weapons", false );
|
||||
for( i = 0; i < gameLocal.numClients; i++ ) {
|
||||
if ( gameLocal.entities[ i ] ) {
|
||||
gameLocal.entities[ i ]->PostEventSec( &EV_Player_SelectWeapon, 0.5f, gameLocal.entities[ i ]->spawnArgs.GetString( "def_weapon1" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//###// by MacX
|
||||
//if ( give_all || ( idStr::Cmpn( name, "weapon", 6 ) == 0 ) ) {
|
||||
// if ( gameLocal.world->spawnArgs.GetBool( "no_Weapons" ) ) {
|
||||
// gameLocal.world->spawnArgs.SetBool( "no_Weapons", false );
|
||||
// for( i = 0; i < gameLocal.numClients; i++ ) {
|
||||
// if ( gameLocal.entities[ i ] ) {
|
||||
// gameLocal.entities[ i ]->PostEventSec( &EV_Player_SelectWeapon, 0.5f, gameLocal.entities[ i ]->spawnArgs.GetString( "def_weapon1" ) );
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//###//
|
||||
|
||||
if ( ( idStr::Cmpn( name, "weapon_", 7 ) == 0 ) || ( idStr::Cmpn( name, "item_", 5 ) == 0 ) || ( idStr::Cmpn( name, "ammo_", 5 ) == 0 ) ) {
|
||||
if ( ( ( idStr::Cmpn( name, "weapon_", 7 ) == 0 ) &&
|
||||
//###// by MacX
|
||||
( idStr::Cmpn( name, "weapon_soulcube", 15 ) != 0 ) &&
|
||||
( idStr::Cmpn( name, "weapon_bfg", 10 ) != 0 ) &&
|
||||
( idStr::Cmpn( name, "weapon_handgrenade", 18 ) != 0 ) ) ||
|
||||
//###//
|
||||
( idStr::Cmpn( name, "item_", 5 ) == 0 ) || ( idStr::Cmpn( name, "ammo_", 5 ) == 0 ) ) {
|
||||
player->GiveItem( name );
|
||||
return;
|
||||
}
|
||||
|
@ -325,14 +333,16 @@ void Cmd_Give_f( const idCmdArgs &args ) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( give_all || idStr::Icmp( name, "weapons" ) == 0 ) {
|
||||
player->inventory.weapons = BIT( MAX_WEAPONS ) - 1;
|
||||
player->CacheWeapons();
|
||||
//###// by MacX
|
||||
//if ( give_all || idStr::Icmp( name, "weapons" ) == 0 ) {
|
||||
// player->inventory.weapons = BIT( MAX_WEAPONS ) - 1;
|
||||
// player->CacheWeapons();
|
||||
|
||||
if ( !give_all ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// if ( !give_all ) {
|
||||
// return;
|
||||
// }
|
||||
//}
|
||||
//###//
|
||||
|
||||
if ( give_all || idStr::Icmp( name, "ammo" ) == 0 ) {
|
||||
for ( i = 0 ; i < AMMO_NUMTYPES; i++ ) {
|
||||
|
@ -343,12 +353,16 @@ void Cmd_Give_f( const idCmdArgs &args ) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( give_all || idStr::Icmp( name, "armor" ) == 0 ) {
|
||||
player->inventory.armor = player->inventory.maxarmor;
|
||||
if ( !give_all ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
//###// by MacX
|
||||
|
||||
//if ( give_all || idStr::Icmp( name, "armor" ) == 0 ) {
|
||||
// player->inventory.armor = player->inventory.maxarmor;
|
||||
// if ( !give_all ) {
|
||||
// return;
|
||||
// }
|
||||
//}
|
||||
|
||||
//###//
|
||||
|
||||
if ( idStr::Icmp( name, "berserk" ) == 0 ) {
|
||||
player->GivePowerUp( BERSERK, SEC2MS( 30.0f ) );
|
||||
|
|
|
@ -146,6 +146,10 @@ idCVar g_showTestModelFrame( "g_showTestModelFrame", "0", CVAR_GAME | CVAR_B
|
|||
idCVar g_showActiveEntities( "g_showActiveEntities", "0", CVAR_GAME | CVAR_BOOL, "draws boxes around thinking entities. dormant entities (outside of pvs) are drawn yellow. non-dormant are green." );
|
||||
idCVar g_showEnemies( "g_showEnemies", "0", CVAR_GAME | CVAR_BOOL, "draws boxes around monsters that have targeted the the player" );
|
||||
|
||||
//###// by MacX
|
||||
idCVar g_showSubtitle( "g_showSubtitle", "0", CVAR_GAME | CVAR_BOOL, "displays subtitle 1=on/0=off" );
|
||||
//###//
|
||||
|
||||
idCVar g_frametime( "g_frametime", "0", CVAR_GAME | CVAR_BOOL, "displays timing information for each game frame" );
|
||||
idCVar g_timeentities( "g_timeEntities", "0", CVAR_GAME | CVAR_FLOAT, "when non-zero, shows entities whose think functions exceeded the # of milliseconds specified" );
|
||||
|
||||
|
@ -196,6 +200,12 @@ idCVar af_useLinearTime( "af_useLinearTime", "1", CVAR_GAME | CVAR_BOOL, "
|
|||
idCVar af_useImpulseFriction( "af_useImpulseFriction", "0", CVAR_GAME | CVAR_BOOL, "use impulse based contact friction" );
|
||||
idCVar af_useJointImpulseFriction( "af_useJointImpulseFriction","0", CVAR_GAME | CVAR_BOOL, "use impulse based joint friction" );
|
||||
idCVar af_useSymmetry( "af_useSymmetry", "1", CVAR_GAME | CVAR_BOOL, "use constraint matrix symmetry" );
|
||||
|
||||
//###// by MacX - using code of water physics mod
|
||||
idCVar af_useBodyDensityBuoyancy( "af_useBodyDensityBuoyancy","0", CVAR_GAME | CVAR_BOOL, "uses density of each body to calculate buoyancy");
|
||||
idCVar af_useFixedDensityBuoyancy( "af_useFixedDensityBuoyancy","1", CVAR_GAME | CVAR_BOOL, "if set, use liquidDensity as a fixed density for each body when calculating buoyancy. If clear, bodies are floated uniformly by a scalar liquidDensity as defined in the decls." );
|
||||
//###//
|
||||
|
||||
idCVar af_skipSelfCollision( "af_skipSelfCollision", "0", CVAR_GAME | CVAR_BOOL, "skip self collision detection" );
|
||||
idCVar af_skipLimits( "af_skipLimits", "0", CVAR_GAME | CVAR_BOOL, "skip joint limits" );
|
||||
idCVar af_skipFriction( "af_skipFriction", "0", CVAR_GAME | CVAR_BOOL, "skip friction" );
|
||||
|
@ -230,6 +240,10 @@ idCVar rb_showInertia( "rb_showInertia", "0", CVAR_GAME | CVAR_BOOL, "sho
|
|||
idCVar rb_showVelocity( "rb_showVelocity", "0", CVAR_GAME | CVAR_BOOL, "show the velocity of each rigid body" );
|
||||
idCVar rb_showActive( "rb_showActive", "0", CVAR_GAME | CVAR_BOOL, "show rigid bodies that are not at rest" );
|
||||
|
||||
//###// by MacX - using code of water physics mod
|
||||
idCVar rb_showBuoyancy( "rb_showBuoyancy", "0", CVAR_GAME | CVAR_BOOL, "show rigid body buoyancy information" );
|
||||
//###//
|
||||
|
||||
// The default values for player movement cvars are set in def/player.def
|
||||
idCVar pm_jumpheight( "pm_jumpheight", "48", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_FLOAT, "approximate height the player can jump" );
|
||||
idCVar pm_stepsize( "pm_stepsize", "16", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_FLOAT, "maximum height the player can step up without jumping" );
|
||||
|
@ -245,6 +259,12 @@ idCVar pm_maxviewpitch( "pm_maxviewpitch", "89", CVAR_GAME | CVAR_NETWORK
|
|||
idCVar pm_stamina( "pm_stamina", "24", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_FLOAT, "length of time player can run" );
|
||||
idCVar pm_staminathreshold( "pm_staminathreshold", "45", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_FLOAT, "when stamina drops below this value, player gradually slows to a walk" );
|
||||
idCVar pm_staminarate( "pm_staminarate", "0.75", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_FLOAT, "rate that player regains stamina. divide pm_stamina by this value to determine how long it takes to fully recharge." );
|
||||
|
||||
//###// by MacX
|
||||
idCVar pm_slowmotion( "pm_slowmotion", "60", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_FLOAT, "length of time in slow motion" );
|
||||
idCVar pm_slowmotionrate( "pm_slowmotionrate", "1", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_FLOAT, "rate to regain slow motion time" );
|
||||
//###//
|
||||
|
||||
idCVar pm_crouchheight( "pm_crouchheight", "38", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_FLOAT, "height of player's bounding box while crouched" );
|
||||
idCVar pm_crouchviewheight( "pm_crouchviewheight", "32", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_FLOAT, "height of player's view while crouched" );
|
||||
idCVar pm_normalheight( "pm_normalheight", "74", CVAR_GAME | CVAR_NETWORKSYNC | CVAR_FLOAT, "height of player's bounding box while standing" );
|
||||
|
@ -335,3 +355,17 @@ 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 ;" );
|
||||
|
||||
// ### z_mod ###
|
||||
|
||||
idCVar z_bloom("z_bloom", "1", CVAR_GAME | CVAR_BOOL, "Enable bloom" );
|
||||
idCVar z_bloomBufferSize("z_bloomBufferSize", "2", CVAR_GAME | CVAR_INTEGER | CVAR_ARCHIVE, "bloom render to texture size: \n0 = 64x32\n1 = 128x64\n2 = 256x128\n3 = 512x256\n4 = 1024x512" );
|
||||
idCVar z_bloomIterations("z_bloomIterations", "12", CVAR_GAME | CVAR_INTEGER | CVAR_ARCHIVE, "Number of times the blur filter is applied" );
|
||||
|
||||
//idCVar z_decalPP("z_decalPP", "1", CVAR_GAME | CVAR_BOOL, "Enable decal post processing effects" );
|
||||
|
||||
// sikk---> Motion Blur/DoF post processing effects
|
||||
idCVar r_useMotionBlur( "r_useMotionBlur", "0", CVAR_GAME | CVAR_NOCHEAT | CVAR_BOOL | CVAR_ARCHIVE, "Enable motion blur postprocessing effect." );
|
||||
idCVar r_useZoomDoF( "r_useZoomDoF", "0", CVAR_GAME | CVAR_NOCHEAT | CVAR_BOOL | CVAR_ARCHIVE, "Enable fake depth of field postprocessing effect when zoomed." );
|
||||
idCVar r_useCelShading( "r_useCelShading", "1", CVAR_GAME | CVAR_NOCHEAT | CVAR_BOOL | CVAR_ARCHIVE, "Enable cel shading." );
|
||||
// <---sikk
|
||||
|
|
|
@ -83,6 +83,10 @@ extern idCVar g_showTestModelFrame;
|
|||
extern idCVar g_showActiveEntities;
|
||||
extern idCVar g_showEnemies;
|
||||
|
||||
//###// by MacX
|
||||
extern idCVar g_showSubtitle;
|
||||
//###//
|
||||
|
||||
extern idCVar g_frametime;
|
||||
extern idCVar g_timeentities;
|
||||
|
||||
|
@ -126,6 +130,12 @@ extern idCVar af_useLinearTime;
|
|||
extern idCVar af_useImpulseFriction;
|
||||
extern idCVar af_useJointImpulseFriction;
|
||||
extern idCVar af_useSymmetry;
|
||||
|
||||
//###// by MacX - using code of water physics mod
|
||||
extern idCVar af_useBodyDensityBuoyancy;
|
||||
extern idCVar af_useFixedDensityBuoyancy;
|
||||
//###//
|
||||
|
||||
extern idCVar af_skipSelfCollision;
|
||||
extern idCVar af_skipLimits;
|
||||
extern idCVar af_skipFriction;
|
||||
|
@ -160,6 +170,10 @@ extern idCVar rb_showInertia;
|
|||
extern idCVar rb_showVelocity;
|
||||
extern idCVar rb_showActive;
|
||||
|
||||
//###// by MacX - using code of water physics mod
|
||||
extern idCVar rb_showBuoyancy;
|
||||
//###//
|
||||
|
||||
extern idCVar pm_jumpheight;
|
||||
extern idCVar pm_stepsize;
|
||||
extern idCVar pm_crouchspeed;
|
||||
|
@ -174,6 +188,12 @@ extern idCVar pm_maxviewpitch;
|
|||
extern idCVar pm_stamina;
|
||||
extern idCVar pm_staminathreshold;
|
||||
extern idCVar pm_staminarate;
|
||||
|
||||
//###// by MacX
|
||||
extern idCVar pm_slowmotion;
|
||||
extern idCVar pm_slowmotionrate;
|
||||
//###//
|
||||
|
||||
extern idCVar pm_crouchheight;
|
||||
extern idCVar pm_crouchviewheight;
|
||||
extern idCVar pm_normalheight;
|
||||
|
@ -254,4 +274,18 @@ extern const char *si_gameTypeArgs[];
|
|||
|
||||
extern const char *ui_skinArgs[];
|
||||
|
||||
// ### z_mod ###
|
||||
extern idCVar z_bloom;
|
||||
extern idCVar z_bloomBufferSize;
|
||||
extern idCVar z_bloomIterations;
|
||||
|
||||
//extern idCVar z_decalPP; // decal post process
|
||||
|
||||
// sikk---> Motion Blur/DoF/Cel Shading PostProcessing Effects
|
||||
extern idCVar r_useMotionBlur;
|
||||
extern idCVar r_useZoomDoF;
|
||||
extern idCVar r_useCelShading;
|
||||
// <---sikk
|
||||
|
||||
|
||||
#endif /* !__SYS_CVAR_H__ */
|
||||
|
|
|
@ -70,6 +70,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
#define CONTACT_EPSILON 0.25f // maximum contact seperation distance
|
||||
|
||||
class idEntity;
|
||||
class idPhysics_Liquid;
|
||||
|
||||
typedef struct impactInfo_s {
|
||||
float invMass; // inverse mass
|
||||
|
@ -184,6 +185,12 @@ public: // common physics interface
|
|||
// networking
|
||||
virtual void WriteToSnapshot( idBitMsgDelta &msg ) const = 0;
|
||||
virtual void ReadFromSnapshot( const idBitMsgDelta &msg ) = 0;
|
||||
|
||||
// gets/sets the water
|
||||
// these should be pure virtual but I would've had to change 10 or so other classes
|
||||
// so this was a better solution
|
||||
virtual idPhysics_Liquid *GetWater() { return NULL; }
|
||||
virtual void SetWater( idPhysics_Liquid *e ) {}
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_H__ */
|
||||
|
|
|
@ -47,16 +47,22 @@ const float LCP_EPSILON = 1e-7f;
|
|||
const float LIMIT_LCP_EPSILON = 1e-4f;
|
||||
const float CONTACT_LCP_EPSILON = 1e-6f;
|
||||
const float CENTER_OF_MASS_EPSILON = 1e-4f;
|
||||
const float NO_MOVE_TIME = 1.0f;
|
||||
const float NO_MOVE_TIME = 2.0f;
|
||||
const float NO_MOVE_TRANSLATION_TOLERANCE = 10.0f;
|
||||
const float NO_MOVE_ROTATION_TOLERANCE = 10.0f;
|
||||
const float MIN_MOVE_TIME = -1.0f;
|
||||
const float MAX_MOVE_TIME = -1.0f;
|
||||
const float IMPULSE_THRESHOLD = 500.0f;
|
||||
const float IMPULSE_THRESHOLD = 1500.0f;
|
||||
const float SUSPEND_LINEAR_VELOCITY = 10.0f;
|
||||
const float SUSPEND_ANGULAR_VELOCITY = 15.0f;
|
||||
const float SUSPEND_LINEAR_ACCELERATION = 20.0f;
|
||||
const float SUSPEND_ANGULAR_ACCELERATION = 30.0f;
|
||||
|
||||
const float WATER_FRICTION = 0.0f; // we need AF friction to be a little bigger than RB water friction, we add this value
|
||||
const float DEFAULT_LIQUID_SCALAR = -0.28f;
|
||||
const float DEFAULT_LIQUID_DENSITY = 0.005f;
|
||||
const float LIQUID_MASS_MUL = 3.0f; // I'm not sure how to explain this, without it body bob way too quickly
|
||||
|
||||
const idVec6 vec6_lcp_epsilon = idVec6( LCP_EPSILON, LCP_EPSILON, LCP_EPSILON,
|
||||
LCP_EPSILON, LCP_EPSILON, LCP_EPSILON );
|
||||
|
||||
|
@ -4205,6 +4211,10 @@ void idAFBody::Init( void ) {
|
|||
centerOfMass = vec3_zero;
|
||||
inertiaTensor = mat3_identity;
|
||||
inverseInertiaTensor = mat3_identity;
|
||||
this->volume = 1.0f;
|
||||
this->liquidMass = 1.0f;
|
||||
this->invLiquidMass = 1.0f;
|
||||
this->waterLevel = 0.0f;
|
||||
|
||||
current = &state[0];
|
||||
next = &state[1];
|
||||
|
@ -4317,6 +4327,11 @@ void idAFBody::SetDensity( float density, const idMat3 &inertiaScale ) {
|
|||
else {
|
||||
inverseInertiaTensor = inertiaTensor.Inverse();
|
||||
}
|
||||
|
||||
// stuff for water
|
||||
this->volume = mass / density;
|
||||
this->liquidMass = this->mass;
|
||||
this->invLiquidMass = this->invMass;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4425,6 +4440,9 @@ void idAFBody::Save( idSaveGame *saveFile ) {
|
|||
saveFile->WriteFloat( contactMotorVelocity );
|
||||
saveFile->WriteFloat( contactMotorForce );
|
||||
|
||||
saveFile->WriteFloat( volume );
|
||||
saveFile->WriteFloat( liquidMass );
|
||||
saveFile->WriteFloat( invLiquidMass );
|
||||
saveFile->WriteFloat( mass );
|
||||
saveFile->WriteFloat( invMass );
|
||||
saveFile->WriteVec3( centerOfMass );
|
||||
|
@ -4455,6 +4473,9 @@ void idAFBody::Restore( idRestoreGame *saveFile ) {
|
|||
saveFile->ReadFloat( contactMotorVelocity );
|
||||
saveFile->ReadFloat( contactMotorForce );
|
||||
|
||||
saveFile->ReadFloat( volume );
|
||||
saveFile->ReadFloat( liquidMass );
|
||||
saveFile->ReadFloat( invLiquidMass );
|
||||
saveFile->ReadFloat( mass );
|
||||
saveFile->ReadFloat( invMass );
|
||||
saveFile->ReadVec3( centerOfMass );
|
||||
|
@ -4470,6 +4491,89 @@ void idAFBody::Restore( idRestoreGame *saveFile ) {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
idAFBody::GetWaterLevel
|
||||
returns the percent of the body in water (set by SetWaterLevel)
|
||||
================
|
||||
*/
|
||||
float idAFBody::GetWaterLevel() const {
|
||||
return this->waterLevel;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idAFBody::SetWaterLevel
|
||||
returns the percent of the body in water
|
||||
0.0f if out of water
|
||||
|
||||
Note we use the liquid's gravity normal for
|
||||
floating because the idPhysics_AF gravity normal
|
||||
is really hard to get a hold of!
|
||||
================
|
||||
*/
|
||||
float idAFBody::SetWaterLevel( idPhysics_Liquid *l, const idVec3 &gravityNormal, bool fixedDensityBuoyancy ) {
|
||||
if( l == NULL ) {
|
||||
this->waterLevel = 0.0f;
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if( !fixedDensityBuoyancy ) {
|
||||
const idBounds &bounds = this->clipModel->GetBounds();
|
||||
idVec3 depth,point;
|
||||
float height, d;
|
||||
|
||||
//
|
||||
// check if physics object is under water
|
||||
// and return the percentage of the object under water
|
||||
//
|
||||
point = this->GetWorldOrigin();
|
||||
|
||||
depth = l->GetDepth(point);
|
||||
// height = abs( (bounds[0] - bounds[1]) * gravityNormal ) * 0.5f;
|
||||
// d = abs( depth * gravityNormal );
|
||||
height = abs( bounds[0].z - bounds[1].z ) * 0.5f;
|
||||
d = depth.z;
|
||||
|
||||
if( d < 0 )
|
||||
this->waterLevel = 0.0f;
|
||||
else if( d > height )
|
||||
this->waterLevel = 1.0f;
|
||||
else
|
||||
this->waterLevel = d / height;
|
||||
}
|
||||
else {
|
||||
idVec3 depth,bottom(this->current->worldOrigin);
|
||||
idBounds bounds = this->clipModel->GetBounds();
|
||||
float height,d;
|
||||
|
||||
// offset and rotate the bounding box
|
||||
bounds += -centerOfMass;
|
||||
bounds *= this->current->worldAxis.Transpose();
|
||||
|
||||
// gets the position of the object relative to the surface of the water
|
||||
height = abs(bounds[1] * gravityNormal * 2);
|
||||
|
||||
// calculates the depth of the bottom of the object
|
||||
bottom += (height * 0.5f) * gravityNormal;
|
||||
depth = l->GetDepth(bottom);
|
||||
d = abs(depth * gravityNormal);
|
||||
|
||||
if( d > height ) {
|
||||
// the body is totally submerged
|
||||
this->waterLevel = 1.0f;
|
||||
}
|
||||
else if( depth.x == -1 && depth.y == -1 && depth.z == -1 ) {
|
||||
this->waterLevel = 0.0f;
|
||||
}
|
||||
else {
|
||||
// the body is partly submerged
|
||||
this->waterLevel = d / height;
|
||||
}
|
||||
}
|
||||
return this->waterLevel;
|
||||
}
|
||||
|
||||
|
||||
//===============================================================
|
||||
// M
|
||||
|
@ -4905,11 +5009,21 @@ idPhysics_AF::EvaluateBodies
|
|||
void idPhysics_AF::EvaluateBodies( float timeStep ) {
|
||||
int i;
|
||||
idAFBody *body;
|
||||
float bMass, invbMass;
|
||||
idMat3 axis;
|
||||
|
||||
for ( i = 0; i < bodies.Num(); i++ ) {
|
||||
body = bodies[i];
|
||||
|
||||
if( this->water != NULL && body->GetWaterLevel() > 0.0f ) {
|
||||
bMass = body->liquidMass;
|
||||
invbMass = body->invLiquidMass;
|
||||
}
|
||||
else {
|
||||
bMass = body->mass;
|
||||
invbMass = body->invMass;
|
||||
}
|
||||
|
||||
// we transpose the axis before using it because idMat3 is column-major
|
||||
axis = body->current->worldAxis.Transpose();
|
||||
|
||||
|
@ -4917,20 +5031,20 @@ void idPhysics_AF::EvaluateBodies( float timeStep ) {
|
|||
if ( body->centerOfMass.Compare( vec3_origin, CENTER_OF_MASS_EPSILON ) ) {
|
||||
|
||||
// spatial inertia in world space
|
||||
body->I.Set( body->mass * mat3_identity, mat3_zero,
|
||||
body->I.Set( bMass * mat3_identity, mat3_zero,
|
||||
mat3_zero, axis * body->inertiaTensor * axis.Transpose() );
|
||||
|
||||
// inverse spatial inertia in world space
|
||||
body->inverseWorldSpatialInertia.Set( body->invMass * mat3_identity, mat3_zero,
|
||||
body->inverseWorldSpatialInertia.Set( invbMass * mat3_identity, mat3_zero,
|
||||
mat3_zero, axis * body->inverseInertiaTensor * axis.Transpose() );
|
||||
|
||||
body->fl.spatialInertiaSparse = true;
|
||||
}
|
||||
else {
|
||||
idMat3 massMoment = body->mass * SkewSymmetric( body->centerOfMass );
|
||||
idMat3 massMoment = bMass * SkewSymmetric( body->centerOfMass );
|
||||
|
||||
// spatial inertia in world space
|
||||
body->I.Set( body->mass * mat3_identity, massMoment,
|
||||
body->I.Set( bMass * mat3_identity, massMoment,
|
||||
massMoment.Transpose(), axis * body->inertiaTensor * axis.Transpose() );
|
||||
|
||||
// inverse spatial inertia in world space
|
||||
|
@ -5337,7 +5451,7 @@ idPhysics_AF::Evolve
|
|||
*/
|
||||
void idPhysics_AF::Evolve( float timeStep ) {
|
||||
int i;
|
||||
float angle;
|
||||
float angle,waterLevel;
|
||||
idVec3 vec;
|
||||
idAFBody *body;
|
||||
idVec6 force;
|
||||
|
@ -5392,7 +5506,15 @@ void idPhysics_AF::Evolve( float timeStep ) {
|
|||
body->next->worldAxis.OrthoNormalizeSelf();
|
||||
|
||||
// linear and angular friction
|
||||
body->next->spatialVelocity.SubVec3(0) -= body->linearFriction * body->next->spatialVelocity.SubVec3(0);
|
||||
// apply a higher friction value if the AF is underwater
|
||||
waterLevel = body->GetWaterLevel();
|
||||
if( waterLevel == 0.0f || this->water == NULL ) {
|
||||
body->next->spatialVelocity.SubVec3(0) -= body->linearFriction * body->next->spatialVelocity.SubVec3(0);
|
||||
}
|
||||
else {
|
||||
body->next->spatialVelocity.SubVec3(0) -= (body->linearFriction * (this->water->GetViscosity()+WATER_FRICTION) * waterLevel) * body->next->spatialVelocity.SubVec3(0);
|
||||
}
|
||||
|
||||
body->next->spatialVelocity.SubVec3(1) -= body->angularFriction * body->next->spatialVelocity.SubVec3(1);
|
||||
}
|
||||
}
|
||||
|
@ -5410,6 +5532,7 @@ bool idPhysics_AF::CollisionImpulse( float timeStep, idAFBody *body, trace_t &co
|
|||
idVec3 r, velocity, impulse;
|
||||
idMat3 inverseWorldInertiaTensor;
|
||||
float impulseNumerator, impulseDenominator;
|
||||
float invMass;
|
||||
impactInfo_t info;
|
||||
idEntity *ent;
|
||||
|
||||
|
@ -5418,6 +5541,13 @@ bool idPhysics_AF::CollisionImpulse( float timeStep, idAFBody *body, trace_t &co
|
|||
return false;
|
||||
}
|
||||
|
||||
if( this->water != NULL ) {
|
||||
invMass = body->invLiquidMass;
|
||||
}
|
||||
else {
|
||||
invMass = body->invMass;
|
||||
}
|
||||
|
||||
// get info from other entity involved
|
||||
ent->GetImpactInfo( self, collision.c.id, collision.c.point, &info );
|
||||
// collision point relative to the body center of mass
|
||||
|
@ -5432,7 +5562,7 @@ bool idPhysics_AF::CollisionImpulse( float timeStep, idAFBody *body, trace_t &co
|
|||
}
|
||||
inverseWorldInertiaTensor = body->current->worldAxis.Transpose() * body->inverseInertiaTensor * body->current->worldAxis;
|
||||
impulseNumerator = -( 1.0f + body->bouncyness ) * ( velocity * collision.c.normal );
|
||||
impulseDenominator = body->invMass + ( ( inverseWorldInertiaTensor * r.Cross( collision.c.normal ) ).Cross( r ) * collision.c.normal );
|
||||
impulseDenominator = invMass + ( ( inverseWorldInertiaTensor * r.Cross( collision.c.normal ) ).Cross( r ) * collision.c.normal );
|
||||
if ( info.invMass ) {
|
||||
impulseDenominator += info.invMass + ( ( info.invInertiaTensor * info.position.Cross( collision.c.normal ) ).Cross( info.position ) * collision.c.normal );
|
||||
}
|
||||
|
@ -5549,6 +5679,7 @@ void idPhysics_AF::CheckForCollisions( float timeStep ) {
|
|||
idRotation rotation;
|
||||
trace_t collision;
|
||||
idEntity *passEntity;
|
||||
impactInfo_t info;
|
||||
|
||||
// clear list with collisions
|
||||
collisions.SetNum( 0, false );
|
||||
|
@ -5591,6 +5722,25 @@ void idPhysics_AF::CheckForCollisions( float timeStep ) {
|
|||
collisions[index].body = body;
|
||||
}
|
||||
|
||||
// Check for water collision
|
||||
// ideally we could do this check in one step but if a body moves quickly in shallow water
|
||||
// they will occasionally clip through a solid entity (ie. fall through the floor)
|
||||
if ( gameLocal.clip.Motion( collision, body->current->worldOrigin, body->next->worldOrigin, rotation,
|
||||
body->clipModel, body->current->worldAxis, MASK_WATER, passEntity ) ) {
|
||||
idEntity *ent = gameLocal.entities[collision.c.entityNum];
|
||||
|
||||
// if the object collides with something with a physics_liquid
|
||||
if( ent->GetPhysics()->IsType( idPhysics_Liquid::Type ) ) {
|
||||
idPhysics_Liquid *liquid = static_cast<idPhysics_Liquid *>(ent->GetPhysics());
|
||||
impactInfo_t info;
|
||||
|
||||
this->self->GetImpactInfo(ent,collision.c.id,collision.c.point,&info);
|
||||
|
||||
this->SetWater(liquid);
|
||||
this->water->Splash(this->self,body->GetVolume(),info,collision);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST_COLLISION_DETECTION
|
||||
if ( gameLocal.clip.Contents( body->next->worldOrigin, body->clipModel,
|
||||
body->next->worldAxis, body->clipMask, passEntity ) ) {
|
||||
|
@ -5764,14 +5914,53 @@ idPhysics_AF::AddGravity
|
|||
================
|
||||
*/
|
||||
void idPhysics_AF::AddGravity( void ) {
|
||||
int i;
|
||||
idAFBody *body;
|
||||
idVec3 grav( this->liquidDensity * this->gravityVector );
|
||||
float waterLevel,wDensity;
|
||||
bool inWater,bodyBuoyancy;
|
||||
int i;
|
||||
|
||||
if( this->SetWaterLevelf() == 1.0f ) {
|
||||
wDensity = this->water->GetDensity();
|
||||
bodyBuoyancy = af_useBodyDensityBuoyancy.GetBool();
|
||||
}
|
||||
|
||||
inWater = false;
|
||||
for ( i = 0; i < bodies.Num(); i++ ) {
|
||||
body = bodies[i];
|
||||
|
||||
// add gravitational force
|
||||
body->current->externalForce.SubVec3( 0 ) += body->mass * gravityVector;
|
||||
waterLevel = body->SetWaterLevel(this->water,this->gravityNormal,this->fixedDensityBuoyancy);
|
||||
if( waterLevel > 0.0f ) {
|
||||
if( !this->fixedDensityBuoyancy && !bodyBuoyancy )
|
||||
{
|
||||
body->liquidMass = body->mass;
|
||||
body->invLiquidMass = body->invMass;
|
||||
}
|
||||
else {
|
||||
body->liquidMass = body->volume * this->liquidDensity * LIQUID_MASS_MUL;
|
||||
body->invLiquidMass = 1 / body->liquidMass;
|
||||
}
|
||||
|
||||
// we float the body in water
|
||||
if( bodyBuoyancy )
|
||||
body->current->externalForce.SubVec3( 0 ) += (body->mass - (body->volume * wDensity * waterLevel)) * gravityVector;
|
||||
else if( this->fixedDensityBuoyancy )
|
||||
body->current->externalForce.SubVec3( 0 ) += body->volume * ( this->liquidDensity - (wDensity * waterLevel) ) * gravityVector;
|
||||
else
|
||||
body->current->externalForce.SubVec3( 0 ) += body->mass * grav * waterLevel;
|
||||
|
||||
inWater = true;
|
||||
}
|
||||
else {
|
||||
body->current->externalForce.SubVec3( 0 ) += body->mass * gravityVector;
|
||||
}
|
||||
}
|
||||
|
||||
// if all AFBodies are not in the water, we assume the whole entity is not in water so
|
||||
// we clear the water flag
|
||||
if( !inWater )
|
||||
this->water = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5919,6 +6108,11 @@ bool idPhysics_AF::TestIfAtRest( float timeStep ) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// prevent bodies from going in active after floating. You don't really want bodies to
|
||||
// go inactive if they're in water (sometimes they just have a long way to go before surfacing)
|
||||
if( this->water != NULL )
|
||||
current.activateTime = 0.0f;
|
||||
|
||||
current.activateTime += timeStep;
|
||||
|
||||
// if the simulation should never be suspended before a certaint amount of time passed
|
||||
|
@ -5966,20 +6160,41 @@ bool idPhysics_AF::TestIfAtRest( float timeStep ) {
|
|||
}
|
||||
|
||||
// test if the velocity or acceleration of any body is still too large to come to rest
|
||||
for ( i = 0; i < bodies.Num(); i++ ) {
|
||||
body = bodies[i];
|
||||
// we do seperates tests for if we're in water or not
|
||||
if( this->water == NULL ) {
|
||||
for ( i = 0; i < bodies.Num(); i++ ) {
|
||||
body = bodies[i];
|
||||
|
||||
if ( body->current->spatialVelocity.SubVec3(0).LengthSqr() > Square( suspendVelocity[0] ) ) {
|
||||
return false;
|
||||
if ( body->current->spatialVelocity.SubVec3(0).LengthSqr() > ( suspendVelocity[0] ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( body->current->spatialVelocity.SubVec3(1).LengthSqr() > ( suspendVelocity[1] ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( body->acceleration.SubVec3(0).LengthSqr() > Square( suspendAcceleration[0] ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( body->acceleration.SubVec3(1).LengthSqr() > Square( suspendAcceleration[1] ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( body->current->spatialVelocity.SubVec3(1).LengthSqr() > Square( suspendVelocity[1] ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( body->acceleration.SubVec3(0).LengthSqr() > Square( suspendAcceleration[0] ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( body->acceleration.SubVec3(1).LengthSqr() > Square( suspendAcceleration[1] ) ) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
for ( i = 0; i < bodies.Num(); i++ ) {
|
||||
body = bodies[i];
|
||||
|
||||
if ( body->current->spatialVelocity.SubVec3(0).LengthSqr() > Square( suspendVelocity[0] ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( body->current->spatialVelocity.SubVec3(1).LengthSqr() > Square( suspendVelocity[1] ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( body->acceleration.SubVec3(0).LengthSqr() > Square( suspendAcceleration[0] ) ) {
|
||||
return false;
|
||||
}
|
||||
if ( body->acceleration.SubVec3(1).LengthSqr() > Square( suspendAcceleration[1] ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6118,8 +6333,24 @@ idPhysics_AF::GetMass
|
|||
*/
|
||||
float idPhysics_AF::GetMass( int id ) const {
|
||||
if ( id >= 0 && id < bodies.Num() ) {
|
||||
return bodies[id]->mass;
|
||||
if( bodies[id]->GetWaterLevel() > 0.0f )
|
||||
return bodies[id]->liquidMass;
|
||||
else
|
||||
return bodies[id]->mass;
|
||||
}
|
||||
|
||||
// if body in water, we have to recompute the total mass
|
||||
if( this->water != NULL ) {
|
||||
int i;
|
||||
float waterMass = 0.0f;
|
||||
|
||||
for( i = 0; i < this->bodies.Num(); i++ ) {
|
||||
waterMass += this->bodies[i]->liquidMass;
|
||||
}
|
||||
|
||||
return waterMass;
|
||||
}
|
||||
|
||||
return totalMass;
|
||||
}
|
||||
|
||||
|
@ -6524,13 +6755,16 @@ void idPhysics_AF::DebugDraw( void ) {
|
|||
if ( af_showMass.GetBool() ) {
|
||||
for ( i = 0; i < bodies.Num(); i++ ) {
|
||||
body = bodies[i];
|
||||
gameRenderWorld->DrawText( va( "\n%1.2f", 1.0f / body->GetInverseMass() ), body->GetWorldOrigin(), 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
|
||||
if( body->GetWaterLevel() > 0.0f )
|
||||
gameRenderWorld->DrawText( va( "\n%1.2f", body->liquidMass ), body->GetWorldOrigin(), 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
|
||||
else
|
||||
gameRenderWorld->DrawText( va( "\n%1.2f", body->mass ), body->GetWorldOrigin(), 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
if ( af_showTotalMass.GetBool() ) {
|
||||
axis = gameLocal.GetLocalPlayer()->viewAngles.ToMat3();
|
||||
gameRenderWorld->DrawText( va( "\n%1.2f", totalMass ), bodies[0]->GetWorldOrigin() + axis[2] * 8.0f, 0.15f, colorCyan, axis, 1 );
|
||||
gameRenderWorld->DrawText( va( "\n%1.2f", this->GetMass() ), bodies[0]->GetWorldOrigin() + axis[2] * 8.0f, 0.15f, colorCyan, axis, 1 );
|
||||
}
|
||||
|
||||
if ( af_showInertia.GetBool() ) {
|
||||
|
@ -6617,6 +6851,17 @@ idPhysics_AF::idPhysics_AF( void ) {
|
|||
totalMass = 0.0f;
|
||||
forceTotalMass = -1.0f;
|
||||
|
||||
// sets default buoyancy property based on CVar
|
||||
if( af_useFixedDensityBuoyancy.GetBool() ) {
|
||||
this->fixedDensityBuoyancy = true;
|
||||
this->liquidDensity = DEFAULT_LIQUID_DENSITY;
|
||||
}
|
||||
else {
|
||||
this->fixedDensityBuoyancy = false;
|
||||
this->liquidDensity = DEFAULT_LIQUID_SCALAR;
|
||||
}
|
||||
this->water = NULL;
|
||||
|
||||
suspendVelocity.Set( SUSPEND_LINEAR_VELOCITY, SUSPEND_ANGULAR_VELOCITY );
|
||||
suspendAcceleration.Set( SUSPEND_LINEAR_ACCELERATION, SUSPEND_LINEAR_ACCELERATION );
|
||||
noMoveTime = NO_MOVE_TIME;
|
||||
|
@ -6749,6 +6994,9 @@ void idPhysics_AF::Save( idSaveGame *saveFile ) const {
|
|||
saveFile->WriteFloat( totalMass );
|
||||
saveFile->WriteFloat( forceTotalMass );
|
||||
|
||||
saveFile->WriteBool( this->fixedDensityBuoyancy );
|
||||
saveFile->WriteFloat( this->liquidDensity );
|
||||
|
||||
saveFile->WriteVec2( suspendVelocity );
|
||||
saveFile->WriteVec2( suspendAcceleration );
|
||||
saveFile->WriteFloat( noMoveTime );
|
||||
|
@ -6823,6 +7071,9 @@ void idPhysics_AF::Restore( idRestoreGame *saveFile ) {
|
|||
saveFile->ReadFloat( totalMass );
|
||||
saveFile->ReadFloat( forceTotalMass );
|
||||
|
||||
saveFile->ReadBool( this->fixedDensityBuoyancy );
|
||||
saveFile->ReadFloat( this->liquidDensity );
|
||||
|
||||
saveFile->ReadVec2( suspendVelocity );
|
||||
saveFile->ReadVec2( suspendAcceleration );
|
||||
saveFile->ReadFloat( noMoveTime );
|
||||
|
@ -7399,7 +7650,11 @@ void idPhysics_AF::GetImpactInfo( const int id, const idVec3 &point, impactInfo_
|
|||
memset( info, 0, sizeof( *info ) );
|
||||
return;
|
||||
}
|
||||
info->invMass = 1.0f / bodies[id]->mass;
|
||||
if( this->water != NULL )
|
||||
info->invMass = bodies[id]->invLiquidMass;
|
||||
else
|
||||
info->invMass = bodies[id]->invMass;
|
||||
|
||||
info->invInertiaTensor = bodies[id]->current->worldAxis.Transpose() * bodies[id]->inverseInertiaTensor * bodies[id]->current->worldAxis;
|
||||
info->position = point - bodies[id]->current->worldOrigin;
|
||||
info->velocity = bodies[id]->current->spatialVelocity.SubVec3(0) + bodies[id]->current->spatialVelocity.SubVec3(1).Cross( info->position );
|
||||
|
@ -7418,7 +7673,11 @@ void idPhysics_AF::ApplyImpulse( const int id, const idVec3 &point, const idVec3
|
|||
return;
|
||||
}
|
||||
idMat3 invWorldInertiaTensor = bodies[id]->current->worldAxis.Transpose() * bodies[id]->inverseInertiaTensor * bodies[id]->current->worldAxis;
|
||||
bodies[id]->current->spatialVelocity.SubVec3(0) += bodies[id]->invMass * impulse;
|
||||
if( this->water != NULL )
|
||||
bodies[id]->current->spatialVelocity.SubVec3(0) += bodies[id]->invLiquidMass * impulse;
|
||||
else
|
||||
bodies[id]->current->spatialVelocity.SubVec3(0) += bodies[id]->invMass * impulse;
|
||||
|
||||
bodies[id]->current->spatialVelocity.SubVec3(1) += invWorldInertiaTensor * (point - bodies[id]->current->worldOrigin).Cross( impulse );
|
||||
Activate();
|
||||
}
|
||||
|
@ -8011,3 +8270,48 @@ void idPhysics_AF::ReadFromSnapshot( const idBitMsgDelta &msg ) {
|
|||
|
||||
UpdateClipModels();
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_AF::SetLiquidDensity
|
||||
================
|
||||
*/
|
||||
void idPhysics_AF::SetLiquidDensity( float density )
|
||||
{
|
||||
this->liquidDensity = density;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_AF::GetLiquidDensity
|
||||
================
|
||||
*/
|
||||
float idPhysics_AF::GetLiquidDensity() const
|
||||
{
|
||||
return this->liquidDensity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_AF::SetFixedDensityBuoyancy
|
||||
This will reset the liquid density to the default value depending on the mode.
|
||||
================
|
||||
*/
|
||||
void idPhysics_AF::SetFixedDensityBuoyancy( bool fixed )
|
||||
{
|
||||
this->fixedDensityBuoyancy = fixed;
|
||||
if( this->fixedDensityBuoyancy )
|
||||
this->liquidDensity = DEFAULT_LIQUID_DENSITY;
|
||||
else
|
||||
this->liquidDensity = DEFAULT_LIQUID_SCALAR;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_AF::GetFixedDensityBuoyancy
|
||||
================
|
||||
*/
|
||||
bool idPhysics_AF::GetFixedDensityBuoyancy() const
|
||||
{
|
||||
return this->fixedDensityBuoyancy;
|
||||
}
|
|
@ -689,6 +689,7 @@ public:
|
|||
float GetContactFriction( void ) const { return contactFriction; }
|
||||
void SetBouncyness( float bounce );
|
||||
float GetBouncyness( void ) const { return bouncyness; }
|
||||
float GetVolume( void ) const { return volume; }
|
||||
void SetDensity( float density, const idMat3 &inertiaScale = mat3_identity );
|
||||
float GetInverseMass( void ) const { return invMass; }
|
||||
idMat3 GetInverseWorldInertia( void ) const { return current->worldAxis.Transpose() * inverseInertiaTensor * current->worldAxis; }
|
||||
|
@ -696,6 +697,11 @@ public:
|
|||
void SetFrictionDirection( const idVec3 &dir );
|
||||
bool GetFrictionDirection( idVec3 &dir ) const;
|
||||
|
||||
// returns the depth of the object in the water
|
||||
// 0.0f if out of water
|
||||
float GetWaterLevel() const;
|
||||
float SetWaterLevel( idPhysics_Liquid *l, const idVec3 &gravityNormal, bool fixedDensityBuoyancy );
|
||||
|
||||
void SetContactMotorDirection( const idVec3 &dir );
|
||||
bool GetContactMotorDirection( idVec3 &dir ) const;
|
||||
void SetContactMotorVelocity( float vel ) { contactMotorVelocity = vel; }
|
||||
|
@ -723,6 +729,7 @@ private:
|
|||
float angularFriction; // rotational friction
|
||||
float contactFriction; // friction with contact surfaces
|
||||
float bouncyness; // bounce
|
||||
float volume; // volume of body
|
||||
int clipMask; // contents this body collides with
|
||||
idVec3 frictionDir; // specifies a single direction of friction in body space
|
||||
idVec3 contactMotorDir; // contact motor direction
|
||||
|
@ -732,6 +739,9 @@ private:
|
|||
// derived properties
|
||||
float mass; // mass of body
|
||||
float invMass; // inverse mass
|
||||
float liquidMass; // mass of object in a liquid
|
||||
float invLiquidMass; // inverse liquid mass
|
||||
float waterLevel; // percent of body in water
|
||||
idVec3 centerOfMass; // center of mass of body
|
||||
idMat3 inertiaTensor; // inertia tensor
|
||||
idMat3 inverseInertiaTensor; // inverse inertia tensor
|
||||
|
@ -893,6 +903,14 @@ public:
|
|||
// update the clip model positions
|
||||
void UpdateClipModels( void );
|
||||
|
||||
// buoyancy stuff
|
||||
void SetLiquidDensity( float density );
|
||||
float GetLiquidDensity() const;
|
||||
|
||||
// this will reset liquidDensity so be careful when using it
|
||||
void SetFixedDensityBuoyancy( bool fixed );
|
||||
bool GetFixedDensityBuoyancy() const;
|
||||
|
||||
public: // common physics interface
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
|
@ -1016,6 +1034,9 @@ private:
|
|||
// physics state
|
||||
AFPState_t current;
|
||||
AFPState_t saved;
|
||||
bool fixedDensityBuoyancy; // treats liquid Density as THE density for each body when the AF is in liquid.
|
||||
// otherwise liquidDensity is just a gravity scalar for the AF in any liquid.
|
||||
float liquidDensity; // explained above.
|
||||
|
||||
idAFBody * masterBody; // master body
|
||||
idLCP * lcp; // linear complementarity problem solver
|
||||
|
|
|
@ -48,6 +48,9 @@ idPhysics_Actor::idPhysics_Actor( void ) {
|
|||
masterYaw = 0.0f;
|
||||
masterDeltaYaw = 0.0f;
|
||||
groundEntityPtr = NULL;
|
||||
|
||||
waterLevel = WATERLEVEL_NONE;
|
||||
waterType = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -79,6 +82,9 @@ void idPhysics_Actor::Save( idSaveGame *savefile ) const {
|
|||
savefile->WriteFloat( masterYaw );
|
||||
savefile->WriteFloat( masterDeltaYaw );
|
||||
|
||||
savefile->WriteInt( (int)waterLevel );
|
||||
savefile->WriteInt( waterType );
|
||||
|
||||
groundEntityPtr.Save( savefile );
|
||||
}
|
||||
|
||||
|
@ -99,6 +105,9 @@ void idPhysics_Actor::Restore( idRestoreGame *savefile ) {
|
|||
savefile->ReadFloat( masterYaw );
|
||||
savefile->ReadFloat( masterDeltaYaw );
|
||||
|
||||
savefile->ReadInt( (int &)waterLevel );
|
||||
savefile->ReadInt( waterType );
|
||||
|
||||
groundEntityPtr.Restore( savefile );
|
||||
}
|
||||
|
||||
|
@ -380,3 +389,71 @@ bool idPhysics_Actor::EvaluateContacts( void ) {
|
|||
|
||||
return ( contacts.Num() != 0 );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=============
|
||||
idPhysics_Actor::SetWaterLevel
|
||||
=============
|
||||
*/
|
||||
void idPhysics_Actor::SetWaterLevel( void ) {
|
||||
idVec3 point;
|
||||
idVec3 origin;
|
||||
idBounds bounds;
|
||||
int contents;
|
||||
|
||||
//
|
||||
// get waterlevel, accounting for ducking
|
||||
//
|
||||
waterLevel = WATERLEVEL_NONE;
|
||||
waterType = 0;
|
||||
|
||||
origin = this->GetOrigin();
|
||||
bounds = clipModel->GetBounds();
|
||||
|
||||
// check at feet level
|
||||
point = origin - ( bounds[0][2] + 1.0f ) * gravityNormal;
|
||||
contents = gameLocal.clip.Contents( point, NULL, mat3_identity, -1, self );
|
||||
if ( contents & MASK_WATER ) {
|
||||
// sets water entity
|
||||
this->SetWaterLevelf();
|
||||
|
||||
waterType = contents;
|
||||
waterLevel = WATERLEVEL_FEET;
|
||||
|
||||
// check at waist level
|
||||
point = origin - ( bounds[1][2] - bounds[0][2] ) * 0.5f * gravityNormal;
|
||||
contents = gameLocal.clip.Contents( point, NULL, mat3_identity, -1, self );
|
||||
if ( contents & MASK_WATER ) {
|
||||
|
||||
waterLevel = WATERLEVEL_WAIST;
|
||||
|
||||
// check at head level
|
||||
point = origin - ( bounds[1][2] - 1.0f ) * gravityNormal;
|
||||
contents = gameLocal.clip.Contents( point, NULL, mat3_identity, -1, self );
|
||||
if ( contents & MASK_WATER ) {
|
||||
waterLevel = WATERLEVEL_HEAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
this->SetWater(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetWaterLevel
|
||||
================
|
||||
*/
|
||||
waterLevel_t idPhysics_Actor::GetWaterLevel( void ) const {
|
||||
return waterLevel;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Actor::GetWaterType
|
||||
================
|
||||
*/
|
||||
int idPhysics_Actor::GetWaterType( void ) const {
|
||||
return waterType;
|
||||
}
|
|
@ -43,6 +43,14 @@ If you have questions concerning this license or the applicable additional terms
|
|||
===================================================================================
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
WATERLEVEL_NONE,
|
||||
WATERLEVEL_FEET,
|
||||
WATERLEVEL_WAIST,
|
||||
WATERLEVEL_HEAD
|
||||
} waterLevel_t;
|
||||
|
||||
|
||||
class idPhysics_Actor : public idPhysics_Base {
|
||||
|
||||
public:
|
||||
|
@ -61,6 +69,10 @@ public:
|
|||
// align the clip model with the gravity direction
|
||||
void SetClipModelAxis( void );
|
||||
|
||||
// water stuff
|
||||
virtual waterLevel_t GetWaterLevel( void ) const;
|
||||
virtual int GetWaterType( void ) const;
|
||||
|
||||
public: // common physics interface
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
|
@ -96,6 +108,8 @@ public: // common physics interface
|
|||
bool EvaluateContacts( void );
|
||||
|
||||
protected:
|
||||
virtual void SetWaterLevel( void );
|
||||
|
||||
idClipModel * clipModel; // clip model used for collision detection
|
||||
idMat3 clipModelAxis; // axis of clip model aligned with gravity direction
|
||||
|
||||
|
@ -109,6 +123,8 @@ protected:
|
|||
float masterDeltaYaw;
|
||||
|
||||
// results of last evaluate
|
||||
waterLevel_t waterLevel;
|
||||
int waterType;
|
||||
idEntityPtr<idEntity> groundEntityPtr;
|
||||
};
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ idPhysics_Base::idPhysics_Base
|
|||
*/
|
||||
idPhysics_Base::idPhysics_Base( void ) {
|
||||
self = NULL;
|
||||
water = NULL;
|
||||
clipMask = 0;
|
||||
SetGravity( gameLocal.GetGravity() );
|
||||
ClearContacts();
|
||||
|
@ -836,3 +837,76 @@ idPhysics_Base::ReadFromSnapshot
|
|||
*/
|
||||
void idPhysics_Base::ReadFromSnapshot( const idBitMsgDelta &msg ) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetWater
|
||||
================
|
||||
*/
|
||||
void idPhysics_Base::SetWater( idPhysics_Liquid *e ) {
|
||||
this->water = e;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetWater
|
||||
================
|
||||
*/
|
||||
idPhysics_Liquid *idPhysics_Base::GetWater()
|
||||
{
|
||||
return this->water;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::SetWaterLevelf
|
||||
|
||||
Returns 1.0f if the object is in a liquid, 0.0f otherwise.
|
||||
|
||||
If the object's not in a liquid it double checks to make sure it's really not.
|
||||
Normally we only set this->water when an object collides with a water material but
|
||||
what happens if an object spawns inside a liquid or something? Nothing, it'll just sit
|
||||
there. This function sets the water level for an object that's already inside the water.
|
||||
|
||||
This was most noticeable when I had monsters walking into the water and of course, they'd
|
||||
sink to the bottom. After I'd kill them they'd die normally and not float. After adding
|
||||
this function they float after they're killed.
|
||||
|
||||
================
|
||||
*/
|
||||
float idPhysics_Base::SetWaterLevelf() {
|
||||
if( this->water == NULL ) {
|
||||
idEntity *e[2];
|
||||
trace_t result;
|
||||
idBounds bounds = this->GetBounds();
|
||||
|
||||
bounds += this->GetOrigin();
|
||||
|
||||
// trace for a water contact
|
||||
if( gameLocal.clip.EntitiesTouchingBounds(bounds,MASK_WATER,e,2) ) {
|
||||
if( e[0]->GetPhysics()->IsType(idPhysics_Liquid::Type) ) {
|
||||
this->water = static_cast<idPhysics_Liquid *>(e[0]->GetPhysics());
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
else
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Base::GetWaterLevelf
|
||||
|
||||
The water level for this object, 0.0f if not in the water, 1.0f if in water
|
||||
================
|
||||
*/
|
||||
float idPhysics_Base::GetWaterLevelf() const {
|
||||
if( this->water == NULL )
|
||||
return 0.0f;
|
||||
else
|
||||
return 1.0f;
|
||||
}
|
|
@ -56,6 +56,7 @@ public:
|
|||
public: // common physics interface
|
||||
|
||||
void SetSelf( idEntity *e );
|
||||
inline const idEntity *GetSelf() { return this->self; }
|
||||
|
||||
void SetClipModel( idClipModel *model, float density, int id = 0, bool freeOld = true );
|
||||
idClipModel * GetClipModel( int id = 0 ) const;
|
||||
|
@ -144,6 +145,12 @@ public: // common physics interface
|
|||
void WriteToSnapshot( idBitMsgDelta &msg ) const;
|
||||
void ReadFromSnapshot( const idBitMsgDelta &msg );
|
||||
|
||||
// water level stuff
|
||||
idPhysics_Liquid * GetWater();
|
||||
void SetWater( idPhysics_Liquid *e );
|
||||
float SetWaterLevelf();
|
||||
float GetWaterLevelf() const;
|
||||
|
||||
protected:
|
||||
idEntity * self; // entity using this physics object
|
||||
int clipMask; // contents the physics object collides with
|
||||
|
@ -151,6 +158,7 @@ protected:
|
|||
idVec3 gravityNormal; // normalized direction of gravity
|
||||
idList<contactInfo_t> contacts; // contacts with other physics objects
|
||||
idList<contactEntity_t> contactEntities; // entities touching this physics object
|
||||
idPhysics_Liquid *water; // the water object the object is in, we use this to check density/viscosity
|
||||
|
||||
protected:
|
||||
// add ground contacts for the clip model
|
||||
|
|
194
game/physics/Physics_Liquid.cpp
Normal file
194
game/physics/Physics_Liquid.cpp
Normal file
|
@ -0,0 +1,194 @@
|
|||
|
||||
#include "../../idlib/precompiled.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
|
||||
CLASS_DECLARATION( idPhysics_Static, idPhysics_Liquid )
|
||||
END_CLASS
|
||||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
idPhysics_Liquid
|
||||
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::idPhysics_Liquid
|
||||
================
|
||||
*/
|
||||
idPhysics_Liquid::idPhysics_Liquid() {
|
||||
|
||||
// initializes to a water-like liquid
|
||||
this->density = 0.001043f;
|
||||
this->viscosity = 3.0f;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::~idPhysics_Liquid
|
||||
================
|
||||
*/
|
||||
idPhysics_Liquid::~idPhysics_Liquid() {
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::Save
|
||||
================
|
||||
*/
|
||||
void idPhysics_Liquid::Save( idSaveGame *savefile ) const
|
||||
{
|
||||
savefile->WriteFloat(this->density);
|
||||
savefile->WriteFloat(this->viscosity);
|
||||
savefile->WriteVec3(this->minSplashVelocity);
|
||||
savefile->WriteVec3(this->minWaveVelocity);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::Restore
|
||||
================
|
||||
*/
|
||||
void idPhysics_Liquid::Restore( idRestoreGame *savefile )
|
||||
{
|
||||
savefile->ReadFloat(this->density);
|
||||
savefile->ReadFloat(this->viscosity);
|
||||
savefile->ReadVec3(this->minSplashVelocity);
|
||||
savefile->ReadVec3(this->minWaveVelocity);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::GetDepth
|
||||
Gets the depth of a point in the liquid. Returns -1 -1 -1 if the object is not in the liquid
|
||||
================
|
||||
*/
|
||||
idVec3 idPhysics_Liquid::GetDepth( const idVec3 &point ) const {
|
||||
const idBounds &bounds = this->GetBounds();
|
||||
idVec3 gravityNormal = this->GetGravityNormal();
|
||||
idVec3 depth(-1.0f,-1.0f,-1.0f);
|
||||
|
||||
if( !this->isInLiquid(point) )
|
||||
return depth;
|
||||
depth = (((bounds[1] + this->GetOrigin()) - point) * gravityNormal) * gravityNormal;
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::Splash
|
||||
Causes the liquid to splash but only if the velocity is greater than minSplashVelocity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Liquid::Splash( idEntity *other, float volume, impactInfo_t &info, trace_t &collision ) {
|
||||
collision.c.entityNum = other->entityNumber;
|
||||
self->Collide(collision,info.velocity);
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::isInLiquid
|
||||
Returns true if a point is in the liquid
|
||||
================
|
||||
*/
|
||||
bool idPhysics_Liquid::isInLiquid( const idVec3 &point ) const {
|
||||
bool result;
|
||||
|
||||
result = (gameLocal.clip.Contents(point,NULL,mat3_identity,MASK_WATER,NULL) != 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::GetPressure
|
||||
Returns the amount of pressure the liquid applies to the given point
|
||||
================
|
||||
*/
|
||||
idVec3 idPhysics_Liquid::GetPressure( const idVec3 &point ) const {
|
||||
idVec3 pressure;
|
||||
idVec3 &depth = this->GetDepth(point);
|
||||
|
||||
pressure = depth * this->density;
|
||||
|
||||
return pressure;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::GetDensity
|
||||
================
|
||||
*/
|
||||
float idPhysics_Liquid::GetDensity() const {
|
||||
return this->density;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::SetDensity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Liquid::SetDensity( float density ) {
|
||||
if( density > 0.0f )
|
||||
this->density = density;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::GetViscosity
|
||||
================
|
||||
*/
|
||||
float idPhysics_Liquid::GetViscosity() const {
|
||||
return this->viscosity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::SetViscosity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Liquid::SetViscosity( float viscosity ) {
|
||||
if( viscosity >= 0.0f )
|
||||
this->viscosity = viscosity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::GetMinSplashVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Liquid::GetMinSplashVelocity() const {
|
||||
return this->minSplashVelocity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::SetMinSplashVelocity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Liquid::SetMinSplashVelocity( const idVec3 &m ) {
|
||||
this->minSplashVelocity = m;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::GetMinWaveVelocity
|
||||
================
|
||||
*/
|
||||
const idVec3 &idPhysics_Liquid::GetMinWaveVelocity() const {
|
||||
return this->minWaveVelocity;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Liquid::SetMinWaveVelocity
|
||||
================
|
||||
*/
|
||||
void idPhysics_Liquid::SetMinWaveVelocity( const idVec3 &w ) {
|
||||
this->minWaveVelocity = w;
|
||||
}
|
60
game/physics/Physics_Liquid.h
Normal file
60
game/physics/Physics_Liquid.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
|
||||
/*
|
||||
===============================================================================
|
||||
|
||||
Physics object for a liquid. This class contains physics properties for a
|
||||
given liquid. Note: Liquid does not necessarily imply water.
|
||||
|
||||
This class does very little functionally as it relies on the other physics
|
||||
classes to do the bouoyancy calculations. It simply holds information and
|
||||
allows the other object to deal with that information however they please.
|
||||
|
||||
As a side note, the difference between minSplashVelocity and
|
||||
minWaveVelocity is that min splash is the minimum amount of velocity
|
||||
before the liquid spawns a splash particle. minWaveVelocity is to generate
|
||||
a wave on the surface, not a splash. It should be lower than min splash
|
||||
velocity. It's the reason some things won't splash but will still cause
|
||||
ripples in the water (especially when surfacing)
|
||||
===============================================================================
|
||||
*/
|
||||
|
||||
class idPhysics_Liquid : public idPhysics_Static {
|
||||
public:
|
||||
CLASS_PROTOTYPE( idPhysics_Liquid );
|
||||
|
||||
idPhysics_Liquid( void );
|
||||
~idPhysics_Liquid( void );
|
||||
|
||||
void Save( idSaveGame *savefile ) const;
|
||||
void Restore( idRestoreGame *savefile );
|
||||
|
||||
public:
|
||||
// Creates a splash on the liquid
|
||||
virtual void Splash( idEntity *other, float volume, impactInfo_t &info, trace_t &collision );
|
||||
|
||||
// Derived information
|
||||
virtual bool isInLiquid( const idVec3 &point ) const;
|
||||
virtual idVec3 GetDepth( const idVec3 &point ) const;
|
||||
virtual idVec3 GetPressure( const idVec3 &point ) const;
|
||||
|
||||
// Physical properties
|
||||
virtual float GetDensity() const;
|
||||
virtual void SetDensity( float density );
|
||||
|
||||
virtual float GetViscosity() const;
|
||||
virtual void SetViscosity( float viscosity );
|
||||
|
||||
virtual const idVec3 &GetMinSplashVelocity() const;
|
||||
virtual void SetMinSplashVelocity( const idVec3 &m );
|
||||
|
||||
virtual const idVec3 &GetMinWaveVelocity() const;
|
||||
virtual void SetMinWaveVelocity( const idVec3 &w );
|
||||
|
||||
private:
|
||||
// STATE
|
||||
float density;
|
||||
float viscosity;
|
||||
|
||||
idVec3 minWaveVelocity;
|
||||
idVec3 minSplashVelocity;
|
||||
};
|
|
@ -451,6 +451,9 @@ bool idPhysics_Monster::Evaluate( int timeStepMSec, int endTimeMSec ) {
|
|||
idMat3 masterAxis;
|
||||
float timeStep;
|
||||
|
||||
waterLevel = WATERLEVEL_NONE;
|
||||
waterType = 0;
|
||||
|
||||
timeStep = MS2SEC( timeStepMSec );
|
||||
|
||||
moveResult = MM_OK;
|
||||
|
@ -481,6 +484,9 @@ bool idPhysics_Monster::Evaluate( int timeStepMSec, int endTimeMSec ) {
|
|||
|
||||
clipModel->Unlink();
|
||||
|
||||
// check water level / type
|
||||
idPhysics_Monster::SetWaterLevel();
|
||||
|
||||
// check if on the ground
|
||||
idPhysics_Monster::CheckGround( current );
|
||||
|
||||
|
|
|
@ -1216,6 +1216,8 @@ bool idPhysics_Player::CheckWaterJump( void ) {
|
|||
idVec3 spot;
|
||||
int cont;
|
||||
idVec3 flatforward;
|
||||
const idBounds &bounds = this->GetBounds();
|
||||
idVec3 offset = ( ((bounds[0] + bounds[1]) * 0.5f) * gravityNormal) * gravityNormal;
|
||||
|
||||
if ( current.movementTime ) {
|
||||
return false;
|
||||
|
@ -1229,25 +1231,80 @@ bool idPhysics_Player::CheckWaterJump( void ) {
|
|||
flatforward = viewForward - (viewForward * gravityNormal) * gravityNormal;
|
||||
flatforward.Normalize();
|
||||
|
||||
spot = current.origin + 30.0f * flatforward;
|
||||
spot -= 4.0f * gravityNormal;
|
||||
spot = current.origin + ((bounds[1].x + 1.0f) * flatforward);
|
||||
spot += offset;
|
||||
cont = gameLocal.clip.Contents( spot, NULL, mat3_identity, -1, self );
|
||||
if ( !(cont & CONTENTS_SOLID) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
spot -= 16.0f * gravityNormal;
|
||||
spot += 0.75f * offset;
|
||||
cont = gameLocal.clip.Contents( spot, NULL, mat3_identity, -1, self );
|
||||
if ( cont ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// jump out of water
|
||||
current.velocity = 200.0f * viewForward - 350.0f * gravityNormal;
|
||||
current.velocity = (300.0f * viewForward) - (300.0f * gravityNormal);
|
||||
current.movementFlags |= PMF_TIME_WATERJUMP;
|
||||
current.movementTime = 2000;
|
||||
|
||||
return true;
|
||||
/* idVec3 spot;
|
||||
int cont;
|
||||
idVec3 flatforward;
|
||||
// inolen
|
||||
idBounds bounds;
|
||||
|
||||
if ( current.movementTime ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for water jump
|
||||
if ( waterLevel != WATERLEVEL_WAIST ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// inolen
|
||||
bounds = clipModel->GetBounds();
|
||||
|
||||
flatforward = viewForward - (viewForward * gravityNormal) * gravityNormal;
|
||||
flatforward.Normalize();
|
||||
|
||||
// inolen
|
||||
spot = current.origin + (bounds[1][0]+1.0f) * flatforward;
|
||||
spot -= 4.0f * gravityNormal;
|
||||
|
||||
// debugging
|
||||
//gameRenderWorld->DebugBox( colorGreen, idBox( idBounds( idVec3( -2.0f, -2.0f, -2.0f ), idVec3( 2.0f, 2.0f, 2.0f ) ), spot, mat3_identity ) );
|
||||
|
||||
cont = gameLocal.clip.Contents( spot, NULL, mat3_identity, -1, self );
|
||||
|
||||
if ( !(cont & CONTENTS_SOLID) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// inolen
|
||||
spot -= (bounds[1][2] + 4.0f) * gravityNormal;
|
||||
cont = gameLocal.clip.Contents( spot, NULL, mat3_identity, -1, self );
|
||||
|
||||
// debugging
|
||||
//gameRenderWorld->DebugArrow( colorRed, current.origin, spot, 2 );
|
||||
|
||||
if( cont ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// jump out of water
|
||||
// inolen
|
||||
current.velocity = ((flatforward + -gravityNormal)/2.0f);
|
||||
current.velocity.Normalize();
|
||||
current.velocity *= 650.0f;
|
||||
|
||||
current.movementFlags |= PMF_TIME_WATERJUMP;
|
||||
current.movementTime = 2000;
|
||||
|
||||
return true;*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1255,43 +1312,6 @@ bool idPhysics_Player::CheckWaterJump( void ) {
|
|||
idPhysics_Player::SetWaterLevel
|
||||
=============
|
||||
*/
|
||||
void idPhysics_Player::SetWaterLevel( void ) {
|
||||
idVec3 point;
|
||||
idBounds bounds;
|
||||
int contents;
|
||||
|
||||
//
|
||||
// get waterlevel, accounting for ducking
|
||||
//
|
||||
waterLevel = WATERLEVEL_NONE;
|
||||
waterType = 0;
|
||||
|
||||
bounds = clipModel->GetBounds();
|
||||
|
||||
// check at feet level
|
||||
point = current.origin - ( bounds[0][2] + 1.0f ) * gravityNormal;
|
||||
contents = gameLocal.clip.Contents( point, NULL, mat3_identity, -1, self );
|
||||
if ( contents & MASK_WATER ) {
|
||||
|
||||
waterType = contents;
|
||||
waterLevel = WATERLEVEL_FEET;
|
||||
|
||||
// check at waist level
|
||||
point = current.origin - ( bounds[1][2] - bounds[0][2] ) * 0.5f * gravityNormal;
|
||||
contents = gameLocal.clip.Contents( point, NULL, mat3_identity, -1, self );
|
||||
if ( contents & MASK_WATER ) {
|
||||
|
||||
waterLevel = WATERLEVEL_WAIST;
|
||||
|
||||
// check at head level
|
||||
point = current.origin - ( bounds[1][2] - 1.0f ) * gravityNormal;
|
||||
contents = gameLocal.clip.Contents( point, NULL, mat3_identity, -1, self );
|
||||
if ( contents & MASK_WATER ) {
|
||||
waterLevel = WATERLEVEL_HEAD;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -1432,18 +1452,12 @@ void idPhysics_Player::MovePlayer( int msec ) {
|
|||
idPhysics_Player::GetWaterLevel
|
||||
================
|
||||
*/
|
||||
waterLevel_t idPhysics_Player::GetWaterLevel( void ) const {
|
||||
return waterLevel;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_Player::GetWaterType
|
||||
================
|
||||
*/
|
||||
int idPhysics_Player::GetWaterType( void ) const {
|
||||
return waterType;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -1518,8 +1532,6 @@ idPhysics_Player::idPhysics_Player( void ) {
|
|||
groundMaterial = NULL;
|
||||
ladder = false;
|
||||
ladderNormal.Zero();
|
||||
waterLevel = WATERLEVEL_NONE;
|
||||
waterType = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1586,9 +1598,6 @@ void idPhysics_Player::Save( idSaveGame *savefile ) const {
|
|||
|
||||
savefile->WriteBool( ladder );
|
||||
savefile->WriteVec3( ladderNormal );
|
||||
|
||||
savefile->WriteInt( (int)waterLevel );
|
||||
savefile->WriteInt( waterType );
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1624,9 +1633,6 @@ void idPhysics_Player::Restore( idRestoreGame *savefile ) {
|
|||
savefile->ReadBool( ladder );
|
||||
savefile->ReadVec3( ladderNormal );
|
||||
|
||||
savefile->ReadInt( (int &)waterLevel );
|
||||
savefile->ReadInt( waterType );
|
||||
|
||||
/* DG: It can apparently happen that the player saves while the clipModel's axis are
|
||||
* modified by idPush::TryRotatePushEntity() -> idPhysics_Player::Rotate() -> idClipModel::Link()
|
||||
* Normally idPush seems to reset them to the identity matrix in the next frame,
|
||||
|
|
|
@ -51,13 +51,6 @@ typedef enum {
|
|||
PM_NOCLIP // flying without collision detection nor gravity
|
||||
} pmtype_t;
|
||||
|
||||
typedef enum {
|
||||
WATERLEVEL_NONE,
|
||||
WATERLEVEL_FEET,
|
||||
WATERLEVEL_WAIST,
|
||||
WATERLEVEL_HEAD
|
||||
} waterLevel_t;
|
||||
|
||||
#define MAXTOUCH 32
|
||||
|
||||
typedef struct playerPState_s {
|
||||
|
@ -91,8 +84,6 @@ public:
|
|||
void SetKnockBack( const int knockBackTime );
|
||||
void SetDebugLevel( bool set );
|
||||
// feed back from last physics frame
|
||||
waterLevel_t GetWaterLevel( void ) const;
|
||||
int GetWaterType( void ) const;
|
||||
bool HasJumped( void ) const;
|
||||
bool HasSteppedUp( void ) const;
|
||||
float GetStepUp( void ) const;
|
||||
|
@ -165,10 +156,6 @@ private:
|
|||
bool ladder;
|
||||
idVec3 ladderNormal;
|
||||
|
||||
// results of last evaluate
|
||||
waterLevel_t waterLevel;
|
||||
int waterType;
|
||||
|
||||
private:
|
||||
float CmdScale( const usercmd_t &cmd ) const;
|
||||
void Accelerate( const idVec3 &wishdir, const float wishspeed, const float accel );
|
||||
|
@ -189,7 +176,6 @@ private:
|
|||
void CheckLadder( void );
|
||||
bool CheckJump( void );
|
||||
bool CheckWaterJump( void );
|
||||
void SetWaterLevel( void );
|
||||
void DropTimers( void );
|
||||
void MovePlayer( int msec );
|
||||
};
|
||||
|
|
|
@ -38,8 +38,13 @@ If you have questions concerning this license or the applicable additional terms
|
|||
CLASS_DECLARATION( idPhysics_Base, idPhysics_RigidBody )
|
||||
END_CLASS
|
||||
|
||||
const float STOP_SPEED = 10.0f;
|
||||
const int STOP_SPEED = 10.0f;
|
||||
|
||||
// if linearVelocity < WATER_STOP_LINEAR && angularVelocity < WATER_STOP_ANGULAR then set the RB to rest
|
||||
// and we need this->noMoveTime + NO_MOVE_TIME < gameLocal.getTime()
|
||||
const idVec3 WATER_STOP_LINEAR(10.0f,10.0f,10.0f);
|
||||
const idVec3 WATER_STOP_ANGULAR(500000.0f,500000.0f,500000.0f);
|
||||
const int NO_MOVE_TIME = 200;
|
||||
|
||||
#undef RB_TIMINGS
|
||||
|
||||
|
@ -73,10 +78,128 @@ void RigidBodyDerivatives( const float t, const void *clientData, const float *s
|
|||
// derivatives
|
||||
d->linearVelocity = p->inverseMass * s->linearMomentum;
|
||||
d->angularMatrix = SkewSymmetric( angularVelocity ) * s->orientation;
|
||||
d->force = - p->linearFriction * s->linearMomentum + p->current.externalForce;
|
||||
d->torque = - p->angularFriction * s->angularMomentum + p->current.externalTorque;
|
||||
|
||||
// underwater we have a higher friction
|
||||
if( p->GetWaterLevelf() == 0.0f ) {
|
||||
|
||||
d->force = - p->linearFriction * s->linearMomentum + p->current.externalForce;
|
||||
d->torque = - p->angularFriction * s->angularMomentum + p->current.externalTorque;
|
||||
}
|
||||
else {
|
||||
// don't let water friction go less than 25% of the water viscosity
|
||||
float percent = Max(0.25f,p->GetSubmergedPercent(s->position,s->orientation.Transpose()));
|
||||
|
||||
d->force = (-p->linearFriction * p->water->GetViscosity() * percent) * s->linearMomentum + p->current.externalForce;
|
||||
d->torque = (-p->angularFriction * p->water->GetViscosity()) * s->angularMomentum + p->current.externalTorque;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_RigidBody::GetSubmergedPercent
|
||||
|
||||
Approximates the percentage of the body that is submerged
|
||||
================
|
||||
*/
|
||||
float idPhysics_RigidBody::GetSubmergedPercent( const idVec3 &pos, const idMat3 &rotation ) const
|
||||
{
|
||||
idVec3 depth,bottom(pos);
|
||||
idBounds bounds = this->GetBounds();
|
||||
float height,d;
|
||||
|
||||
if( this->water == NULL )
|
||||
return 0.0f;
|
||||
|
||||
// offset and rotate the bounding box
|
||||
bounds += -centerOfMass;
|
||||
bounds *= rotation;
|
||||
|
||||
// gets the position of the object relative to the surface of the water
|
||||
height = abs(bounds[1] * gravityNormal * 2);
|
||||
|
||||
// calculates the depth of the bottom of the object
|
||||
bottom += (height * 0.5f) * gravityNormal;
|
||||
depth = this->water->GetDepth(bottom);
|
||||
d = abs(depth * gravityNormal);
|
||||
|
||||
if( d > height ) {
|
||||
// the body is totally submerged
|
||||
return 1.0f;
|
||||
}
|
||||
else if( d <= 0 ) {
|
||||
return 0.0f;
|
||||
}
|
||||
else {
|
||||
// the body is partly submerged
|
||||
return d / height;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_RigidBody::GetBuoyancy
|
||||
|
||||
Gets buoyancy information for this RB
|
||||
================
|
||||
*/
|
||||
bool idPhysics_RigidBody::GetBuoyancy( const idVec3 &pos, const idMat3 &rotation, idVec3 &bCenter, float &percent ) const
|
||||
{
|
||||
// pos - position of the RB
|
||||
// rotation - axis for the RB
|
||||
// bCenter - after the function is called this is an approximation for the center of buoyancy
|
||||
// percent - rough percentage of the body that is under water
|
||||
// used to calculate the volume of the submersed object (volume * percent) to give
|
||||
// the body somewhat realistic bobbing.
|
||||
//
|
||||
// return true if the body is in water, false otherwise
|
||||
|
||||
idVec3 tbCenter(pos);
|
||||
idBounds bounds = this->GetBounds();
|
||||
idTraceModel tm = *this->GetClipModel()->GetTraceModel();
|
||||
int i,count;
|
||||
|
||||
percent = this->GetSubmergedPercent(pos,rotation);
|
||||
bCenter = pos;
|
||||
|
||||
if( percent == 1.0f ) {
|
||||
// the body is totally submerged
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
// the body is partly submerged (or not in the water)
|
||||
//
|
||||
// We do a rough approximation for center of buoyancy.
|
||||
// Normally this is done by calculating the volume of the submersed part of the body
|
||||
// so the center of buoyancy is the center of mass of the submersed volume. This is
|
||||
// probably a slow computation so what I do is take an average of the submersed
|
||||
// vertices of the trace model.
|
||||
//
|
||||
// I was suprized when this first worked but you can use rb_showBuoyancy to see
|
||||
// what the approximation looks like.
|
||||
|
||||
// set up clip model for approximation of center of buoyancy
|
||||
tm.Translate(-centerOfMass);
|
||||
tm.Rotate(rotation);
|
||||
tm.Translate(pos);
|
||||
|
||||
// calculate which vertices are under water
|
||||
for( i = 0, count = 1; i < tm.numVerts; i++ ) {
|
||||
if( gameLocal.clip.Contents(tm.verts[i],NULL,this->GetAxis(),MASK_WATER,NULL) ) {
|
||||
tbCenter += tm.verts[i];
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( count == 1 )
|
||||
bCenter = pos;
|
||||
else
|
||||
bCenter = tbCenter / count;
|
||||
return (count != 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
idPhysics_RigidBody::Integrate
|
||||
|
@ -95,8 +218,39 @@ void idPhysics_RigidBody::Integrate( float deltaTime, rigidBodyPState_t &next )
|
|||
integrator->Evaluate( (float *) ¤t.i, (float *) &next.i, 0, deltaTime );
|
||||
next.i.orientation.OrthoNormalizeSelf();
|
||||
|
||||
// apply gravity
|
||||
next.i.linearMomentum += deltaTime * gravityVector * mass;
|
||||
// apply a water gravity if the body is out of water
|
||||
if( this->SetWaterLevelf() != 0.0f ) {
|
||||
idVec3 bCenter;
|
||||
idVec3 bForce(gravityVector),rForce(-gravityVector);
|
||||
float bMass,fraction,liquidMass;
|
||||
bool inWater;
|
||||
|
||||
inWater = this->GetBuoyancy(next.i.position,next.i.orientation.Transpose(),bCenter,fraction);
|
||||
|
||||
// calculate water mass
|
||||
liquidMass = this->volume * this->water->GetDensity() * fraction;
|
||||
// don't let liquid mass get too high
|
||||
liquidMass = Min( liquidMass, 3 * this->mass );
|
||||
|
||||
bMass = this->mass - liquidMass;
|
||||
|
||||
// calculate buoyancy force
|
||||
bForce *= deltaTime * bMass;
|
||||
rForce *= deltaTime * liquidMass;
|
||||
|
||||
// apply water force
|
||||
// basically here we do a ::ApplyImpulse() but we apply it to next, not current
|
||||
next.i.linearMomentum += bForce;
|
||||
next.i.angularMomentum += (bCenter - next.i.position).Cross(rForce);
|
||||
|
||||
// take the body out of water if it's not in water.
|
||||
if( !inWater )
|
||||
this->SetWater(NULL);
|
||||
}
|
||||
else {
|
||||
// apply normal gravity
|
||||
next.i.linearMomentum += deltaTime * gravityVector * mass;
|
||||
}
|
||||
|
||||
current.i.orientation.TransposeSelf();
|
||||
next.i.orientation.TransposeSelf();
|
||||
|
@ -177,6 +331,8 @@ bool idPhysics_RigidBody::CheckForCollisions( const float deltaTime, rigidBodyPS
|
|||
//#define TEST_COLLISION_DETECTION
|
||||
idMat3 axis;
|
||||
idRotation rotation;
|
||||
idVec3 pos;
|
||||
trace_t waterCollision;
|
||||
bool collided = false;
|
||||
|
||||
#ifdef TEST_COLLISION_DETECTION
|
||||
|
@ -189,9 +345,10 @@ bool idPhysics_RigidBody::CheckForCollisions( const float deltaTime, rigidBodyPS
|
|||
TransposeMultiply( current.i.orientation, next.i.orientation, axis );
|
||||
rotation = axis.ToRotation();
|
||||
rotation.SetOrigin( current.i.position );
|
||||
pos = next.i.position;
|
||||
|
||||
// if there was a collision
|
||||
if ( gameLocal.clip.Motion( collision, current.i.position, next.i.position, rotation, clipModel, current.i.orientation, clipMask, self ) ) {
|
||||
if ( collided || gameLocal.clip.Motion( collision, current.i.position, next.i.position, rotation, clipModel, current.i.orientation, clipMask, self ) ) {
|
||||
// set the next state to the state at the moment of impact
|
||||
next.i.position = collision.endpos;
|
||||
next.i.orientation = collision.endAxis;
|
||||
|
@ -200,6 +357,43 @@ bool idPhysics_RigidBody::CheckForCollisions( const float deltaTime, rigidBodyPS
|
|||
collided = true;
|
||||
}
|
||||
|
||||
// Check for water collision
|
||||
// ideally we could do this check in one step but if a body moves quickly in shallow water
|
||||
// they will occasionally clip through a solid entity (ie. fall through the floor)
|
||||
if ( gameLocal.clip.Motion( waterCollision, current.i.position, pos, rotation, clipModel, current.i.orientation, MASK_WATER, self ) ) {
|
||||
idEntity *ent = gameLocal.entities[waterCollision.c.entityNum];
|
||||
|
||||
// make sure the object didn't collide with something before hitting the water (we don't splash for that case)
|
||||
if( !collided || waterCollision.fraction < collision.fraction ) {
|
||||
|
||||
// if the object collides with something with a physics_liquid
|
||||
if( ent->GetPhysics()->IsType( idPhysics_Liquid::Type ) ) {
|
||||
idPhysics_Liquid *liquid = static_cast<idPhysics_Liquid *>(ent->GetPhysics());
|
||||
impactInfo_t info;
|
||||
|
||||
self->GetImpactInfo(ent,waterCollision.c.id,waterCollision.c.point,&info);
|
||||
|
||||
// apply water splash friction
|
||||
if( this->water == NULL ) {
|
||||
idVec3 impulse = -info.velocity * this->volume * liquid->GetDensity() * 0.25f;
|
||||
impulse = (impulse * gravityNormal) * gravityNormal;
|
||||
|
||||
if( next.i.linearMomentum.LengthSqr() < impulse.LengthSqr() ) {
|
||||
// cancel falling, maintain sideways movement (lateral?)
|
||||
next.i.linearMomentum -= (next.i.linearMomentum * gravityNormal) * gravityNormal;
|
||||
}
|
||||
else {
|
||||
next.i.angularMomentum += ( waterCollision.c.point - ( next.i.position + centerOfMass * next.i.orientation ) ).Cross( impulse );
|
||||
next.i.linearMomentum += impulse * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
this->SetWater(liquid);
|
||||
this->water->Splash(this->self,this->volume,info,waterCollision);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TEST_COLLISION_DETECTION
|
||||
if ( gameLocal.clip.Contents( next.i.position, clipModel, next.i.orientation, clipMask, self ) ) {
|
||||
if ( !startsolid ) {
|
||||
|
@ -275,7 +469,7 @@ idPhysics_RigidBody::TestIfAtRest
|
|||
Does not catch all cases where the body is at rest but is generally good enough.
|
||||
================
|
||||
*/
|
||||
bool idPhysics_RigidBody::TestIfAtRest( void ) const {
|
||||
bool idPhysics_RigidBody::TestIfAtRest( void ) {
|
||||
int i;
|
||||
float gv;
|
||||
idVec3 v, av, normal, point;
|
||||
|
@ -286,6 +480,25 @@ bool idPhysics_RigidBody::TestIfAtRest( void ) const {
|
|||
return true;
|
||||
}
|
||||
|
||||
// do some special checks if the body is in water
|
||||
if( this->water != NULL )
|
||||
{
|
||||
if( this->current.i.linearMomentum.LengthSqr() < WATER_STOP_LINEAR.LengthSqr() &&
|
||||
this->current.i.angularMomentum.LengthSqr() < WATER_STOP_ANGULAR.LengthSqr() ) {
|
||||
|
||||
if( this->noMoveTime == 0 ) {
|
||||
this->noMoveTime = gameLocal.GetTime();
|
||||
}
|
||||
else if( this->noMoveTime+NO_MOVE_TIME < gameLocal.GetTime() ) {
|
||||
this->noMoveTime = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->noMoveTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// need at least 3 contact points to come to rest
|
||||
if ( contacts.Num() < 3 ) {
|
||||
return false;
|
||||
|
@ -414,7 +627,19 @@ void idPhysics_RigidBody::DebugDraw( void ) {
|
|||
}
|
||||
|
||||
if ( rb_showMass.GetBool() ) {
|
||||
gameRenderWorld->DrawText( va( "\n%1.2f", mass ), current.i.position, 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
|
||||
if( this->water != NULL ) {
|
||||
idVec3 pos;
|
||||
float percent, liquidMass;
|
||||
|
||||
pos = this->current.i.position + this->centerOfMass*this->current.i.orientation;
|
||||
percent = this->GetSubmergedPercent(pos,this->current.i.orientation.Transpose());
|
||||
|
||||
liquidMass = this->mass - ( this->volume * this->water->GetDensity() * percent );
|
||||
|
||||
gameRenderWorld->DrawText( va( "\n%1.2f", liquidMass), current.i.position, 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
|
||||
}
|
||||
else
|
||||
gameRenderWorld->DrawText( va( "\n%1.2f", mass ), current.i.position, 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), 1 );
|
||||
}
|
||||
|
||||
if ( rb_showInertia.GetBool() ) {
|
||||
|
@ -429,6 +654,18 @@ void idPhysics_RigidBody::DebugDraw( void ) {
|
|||
if ( rb_showVelocity.GetBool() ) {
|
||||
DrawVelocity( clipModel->GetId(), 0.1f, 4.0f );
|
||||
}
|
||||
|
||||
if( rb_showBuoyancy.GetBool() && this->water != NULL ) {
|
||||
idVec3 pos;
|
||||
idVec3 bCenter;
|
||||
float percent;
|
||||
|
||||
pos = this->current.i.position + this->centerOfMass*this->current.i.orientation;
|
||||
this->GetBuoyancy(pos,this->current.i.orientation.Transpose(),bCenter,percent);
|
||||
|
||||
gameRenderWorld->DebugArrow(colorGreen,pos,bCenter,1);
|
||||
gameRenderWorld->DrawText( va( "%1.2f",percent), pos, 0.08f, colorCyan, gameLocal.GetLocalPlayer()->viewAngles.ToMat3());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -463,6 +700,8 @@ idPhysics_RigidBody::idPhysics_RigidBody( void ) {
|
|||
inertiaTensor.Identity();
|
||||
inverseInertiaTensor.Identity();
|
||||
|
||||
this->water = NULL;
|
||||
|
||||
// use the least expensive euler integrator
|
||||
integrator = new idODE_Euler( sizeof(rigidBodyIState_t) / sizeof(float), RigidBodyDerivatives, this );
|
||||
|
||||
|
@ -473,6 +712,8 @@ idPhysics_RigidBody::idPhysics_RigidBody( void ) {
|
|||
hasMaster = false;
|
||||
isOrientated = false;
|
||||
|
||||
this->noMoveTime = 0.0f;
|
||||
|
||||
#ifdef RB_TIMINGS
|
||||
lastTimerReset = 0;
|
||||
#endif
|
||||
|
@ -548,6 +789,7 @@ void idPhysics_RigidBody::Save( idSaveGame *savefile ) const {
|
|||
savefile->WriteClipModel( clipModel );
|
||||
|
||||
savefile->WriteFloat( mass );
|
||||
savefile->WriteFloat( volume );
|
||||
savefile->WriteFloat( inverseMass );
|
||||
savefile->WriteVec3( centerOfMass );
|
||||
savefile->WriteMat3( inertiaTensor );
|
||||
|
@ -579,6 +821,7 @@ void idPhysics_RigidBody::Restore( idRestoreGame *savefile ) {
|
|||
savefile->ReadClipModel( clipModel );
|
||||
|
||||
savefile->ReadFloat( mass );
|
||||
savefile->ReadFloat( volume );
|
||||
savefile->ReadFloat( inverseMass );
|
||||
savefile->ReadVec3( centerOfMass );
|
||||
savefile->ReadMat3( inertiaTensor );
|
||||
|
@ -627,6 +870,8 @@ void idPhysics_RigidBody::SetClipModel( idClipModel *model, const float density,
|
|||
inertiaTensor.Identity();
|
||||
}
|
||||
|
||||
this->volume = mass / density;
|
||||
|
||||
// check whether or not the inertia tensor is balanced
|
||||
minIndex = Min3Index( inertiaTensor[0][0], inertiaTensor[1][1], inertiaTensor[2][2] );
|
||||
inertiaScale.Identity();
|
||||
|
@ -687,7 +932,18 @@ idPhysics_RigidBody::GetMass
|
|||
================
|
||||
*/
|
||||
float idPhysics_RigidBody::GetMass( int id ) const {
|
||||
return mass;
|
||||
if( this->water != NULL ) {
|
||||
idVec3 pos;
|
||||
float percent,bMass;
|
||||
|
||||
pos = this->current.i.position + this->centerOfMass*this->current.i.orientation;
|
||||
percent = this->GetSubmergedPercent(pos,this->current.i.orientation);
|
||||
bMass = mass - (this->volume * this->water->GetDensity() * percent);
|
||||
|
||||
return bMass;
|
||||
}
|
||||
else
|
||||
return mass;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -166,6 +166,7 @@ private:
|
|||
float angularFriction; // rotational friction
|
||||
float contactFriction; // friction with contact surfaces
|
||||
float bouncyness; // bouncyness
|
||||
float volume; // object volume
|
||||
idClipModel * clipModel; // clip model used for collision detection
|
||||
|
||||
// derived properties
|
||||
|
@ -185,6 +186,9 @@ private:
|
|||
bool hasMaster;
|
||||
bool isOrientated;
|
||||
|
||||
// buoyancy
|
||||
int noMoveTime; // suspend simulation if hardly any movement for this many seconds
|
||||
|
||||
private:
|
||||
friend void RigidBodyDerivatives( const float t, const void *clientData, const float *state, float *derivatives );
|
||||
void Integrate( const float deltaTime, rigidBodyPState_t &next );
|
||||
|
@ -192,9 +196,15 @@ private:
|
|||
bool CollisionImpulse( const trace_t &collision, idVec3 &impulse );
|
||||
void ContactFriction( float deltaTime );
|
||||
void DropToFloorAndRest( void );
|
||||
bool TestIfAtRest( void ) const;
|
||||
bool TestIfAtRest( void );
|
||||
void Rest( void );
|
||||
void DebugDraw( void );
|
||||
|
||||
// Buoyancy stuff
|
||||
// Approximates the center of mass of the submerged portion of the rigid body.
|
||||
virtual bool GetBuoyancy( const idVec3 &pos, const idMat3 &rotation, idVec3 &bCenter, float &percent ) const;
|
||||
// Returns rough a percentage of which percent of the body is in water.
|
||||
virtual float GetSubmergedPercent( const idVec3 &pos, const idMat3 &rotation ) const;
|
||||
};
|
||||
|
||||
#endif /* !__PHYSICS_RIGIDBODY_H__ */
|
||||
|
|
|
@ -102,6 +102,55 @@ const idEventDef EV_Thread_StrRight( "strRight", "sd", 's' );
|
|||
const idEventDef EV_Thread_StrSkip( "strSkip", "sd", 's' );
|
||||
const idEventDef EV_Thread_StrMid( "strMid", "sdd", 's' );
|
||||
const idEventDef EV_Thread_StrToFloat( "strToFloat", "s", 'f' );
|
||||
|
||||
//###// by MacX
|
||||
|
||||
const idEventDef EV_Thread_GetMoney( "getMoney", NULL, 'f' );
|
||||
const idEventDef EV_Thread_DecreaseMoney( "decreaseMoney", "f" );
|
||||
const idEventDef EV_Thread_LooseMoney( "looseMoney", NULL );
|
||||
const idEventDef EV_Thread_SetPlayerHealth( "setPlayerHealth", NULL );
|
||||
const idEventDef EV_Thread_DecreasePlayerHealth( "decreasePlayerHealth", "f" );
|
||||
const idEventDef EV_Thread_PreviousPageDiary( "previousPageDiary", NULL );
|
||||
const idEventDef EV_Thread_NextPageDiary( "nextPageDiary", NULL );
|
||||
const idEventDef EV_Thread_PreviousPageQuestlog( "previousPageQuestlog", NULL );
|
||||
const idEventDef EV_Thread_NextPageQuestlog( "nextPageQuestlog", NULL );
|
||||
|
||||
const idEventDef EV_Thread_GetEnemiesKilled( "getEnemiesKilled", NULL, 'f' );
|
||||
|
||||
const idEventDef EV_Thread_GetTestVarGui1( "getTestVarGui1", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVarGui2( "getTestVarGui2", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVarGui3( "getTestVarGui3", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVarGui4( "getTestVarGui4", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVarGui5( "getTestVarGui5", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVar1( "getTestVar1", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVar2( "getTestVar2", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVar3( "getTestVar3", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVar4( "getTestVar4", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVar5( "getTestVar5", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVar6( "getTestVar6", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVar7( "getTestVar7", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVar8( "getTestVar8", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVar9( "getTestVar9", NULL, 'f' );
|
||||
const idEventDef EV_Thread_GetTestVar10( "getTestVar10", NULL, 'f' );
|
||||
|
||||
const idEventDef EV_Thread_SetTestVarGui1( "setTestVarGui1", "f" );
|
||||
const idEventDef EV_Thread_SetTestVarGui2( "setTestVarGui2", "f" );
|
||||
const idEventDef EV_Thread_SetTestVarGui3( "setTestVarGui3", "f" );
|
||||
const idEventDef EV_Thread_SetTestVarGui4( "setTestVarGui4", "f" );
|
||||
const idEventDef EV_Thread_SetTestVarGui5( "setTestVarGui5", "f" );
|
||||
const idEventDef EV_Thread_SetTestVar1( "setTestVar1", "f" );
|
||||
const idEventDef EV_Thread_SetTestVar2( "setTestVar2", "f" );
|
||||
const idEventDef EV_Thread_SetTestVar3( "setTestVar3", "f" );
|
||||
const idEventDef EV_Thread_SetTestVar4( "setTestVar4", "f" );
|
||||
const idEventDef EV_Thread_SetTestVar5( "setTestVar5", "f" );
|
||||
const idEventDef EV_Thread_SetTestVar6( "setTestVar6", "f" );
|
||||
const idEventDef EV_Thread_SetTestVar7( "setTestVar7", "f" );
|
||||
const idEventDef EV_Thread_SetTestVar8( "setTestVar8", "f" );
|
||||
const idEventDef EV_Thread_SetTestVar9( "setTestVar9", "f" );
|
||||
const idEventDef EV_Thread_SetTestVar10( "setTestVar10", "f" );
|
||||
|
||||
//###//
|
||||
|
||||
const idEventDef EV_Thread_RadiusDamage( "radiusDamage", "vEEEsf" );
|
||||
const idEventDef EV_Thread_IsClient( "isClient", NULL, 'f' );
|
||||
const idEventDef EV_Thread_IsMultiplayer( "isMultiplayer", NULL, 'f' );
|
||||
|
@ -181,6 +230,55 @@ CLASS_DECLARATION( idClass, idThread )
|
|||
EVENT( EV_Thread_StrSkip, idThread::Event_StrSkip )
|
||||
EVENT( EV_Thread_StrMid, idThread::Event_StrMid )
|
||||
EVENT( EV_Thread_StrToFloat, idThread::Event_StrToFloat )
|
||||
|
||||
//###// by MacX
|
||||
|
||||
EVENT( EV_Thread_GetMoney, idThread::Event_GetMoney )
|
||||
EVENT( EV_Thread_DecreaseMoney, idThread::Event_DecreaseMoney )
|
||||
EVENT( EV_Thread_LooseMoney, idThread::Event_LooseMoney )
|
||||
EVENT( EV_Thread_SetPlayerHealth, idThread::Event_SetPlayerHealth )
|
||||
EVENT( EV_Thread_DecreasePlayerHealth, idThread::Event_DecreasePlayerHealth )
|
||||
EVENT( EV_Thread_PreviousPageDiary, idThread::Event_PreviousPageDiary )
|
||||
EVENT( EV_Thread_NextPageDiary, idThread::Event_NextPageDiary )
|
||||
EVENT( EV_Thread_PreviousPageQuestlog, idThread::Event_PreviousPageQuestlog )
|
||||
EVENT( EV_Thread_NextPageQuestlog, idThread::Event_NextPageQuestlog )
|
||||
|
||||
EVENT( EV_Thread_GetEnemiesKilled, idThread::Event_GetEnemiesKilled )
|
||||
|
||||
EVENT( EV_Thread_GetTestVarGui1, idThread::Event_GetTestVarGui1 )
|
||||
EVENT( EV_Thread_GetTestVarGui2, idThread::Event_GetTestVarGui2 )
|
||||
EVENT( EV_Thread_GetTestVarGui3, idThread::Event_GetTestVarGui3 )
|
||||
EVENT( EV_Thread_GetTestVarGui4, idThread::Event_GetTestVarGui4 )
|
||||
EVENT( EV_Thread_GetTestVarGui5, idThread::Event_GetTestVarGui5 )
|
||||
EVENT( EV_Thread_GetTestVar1, idThread::Event_GetTestVar1 )
|
||||
EVENT( EV_Thread_GetTestVar2, idThread::Event_GetTestVar2 )
|
||||
EVENT( EV_Thread_GetTestVar3, idThread::Event_GetTestVar3 )
|
||||
EVENT( EV_Thread_GetTestVar4, idThread::Event_GetTestVar4 )
|
||||
EVENT( EV_Thread_GetTestVar5, idThread::Event_GetTestVar5 )
|
||||
EVENT( EV_Thread_GetTestVar6, idThread::Event_GetTestVar6 )
|
||||
EVENT( EV_Thread_GetTestVar7, idThread::Event_GetTestVar7 )
|
||||
EVENT( EV_Thread_GetTestVar8, idThread::Event_GetTestVar8 )
|
||||
EVENT( EV_Thread_GetTestVar9, idThread::Event_GetTestVar9 )
|
||||
EVENT( EV_Thread_GetTestVar10, idThread::Event_GetTestVar10 )
|
||||
|
||||
EVENT( EV_Thread_SetTestVarGui1, idThread::Event_SetTestVarGui1 )
|
||||
EVENT( EV_Thread_SetTestVarGui2, idThread::Event_SetTestVarGui2 )
|
||||
EVENT( EV_Thread_SetTestVarGui3, idThread::Event_SetTestVarGui3 )
|
||||
EVENT( EV_Thread_SetTestVarGui4, idThread::Event_SetTestVarGui4 )
|
||||
EVENT( EV_Thread_SetTestVarGui5, idThread::Event_SetTestVarGui5 )
|
||||
EVENT( EV_Thread_SetTestVar1, idThread::Event_SetTestVar1 )
|
||||
EVENT( EV_Thread_SetTestVar2, idThread::Event_SetTestVar2 )
|
||||
EVENT( EV_Thread_SetTestVar3, idThread::Event_SetTestVar3 )
|
||||
EVENT( EV_Thread_SetTestVar4, idThread::Event_SetTestVar4 )
|
||||
EVENT( EV_Thread_SetTestVar5, idThread::Event_SetTestVar5 )
|
||||
EVENT( EV_Thread_SetTestVar6, idThread::Event_SetTestVar6 )
|
||||
EVENT( EV_Thread_SetTestVar7, idThread::Event_SetTestVar7 )
|
||||
EVENT( EV_Thread_SetTestVar8, idThread::Event_SetTestVar8 )
|
||||
EVENT( EV_Thread_SetTestVar9, idThread::Event_SetTestVar9 )
|
||||
EVENT( EV_Thread_SetTestVar10, idThread::Event_SetTestVar10 )
|
||||
|
||||
//###//
|
||||
|
||||
EVENT( EV_Thread_RadiusDamage, idThread::Event_RadiusDamage )
|
||||
EVENT( EV_Thread_IsClient, idThread::Event_IsClient )
|
||||
EVENT( EV_Thread_IsMultiplayer, idThread::Event_IsMultiplayer )
|
||||
|
@ -1727,6 +1825,786 @@ void idThread::Event_StrToFloat( const char *string ) {
|
|||
idThread::ReturnFloat( result );
|
||||
}
|
||||
|
||||
|
||||
//###// by MacX
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetMoney( void )
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetMoney( void ) {
|
||||
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.money );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_DecreaseMoney( float value )
|
||||
================
|
||||
*/
|
||||
void idThread::Event_DecreaseMoney( float value ) {
|
||||
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
if( player->inventory.money > 0 ) {
|
||||
player->inventory.money -= value;
|
||||
if( player->inventory.money < 0 ) {
|
||||
player->inventory.money = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_LooseMoney()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_LooseMoney( void ) {
|
||||
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.money = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetPlayerHealth()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetPlayerHealth( void ) {
|
||||
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
player->hud->HandleNamedEvent( "hideHealth" );
|
||||
|
||||
int newPlayerHealth;
|
||||
|
||||
if ( g_skill.GetInteger() == 0 ) {
|
||||
newPlayerHealth = 4;
|
||||
} else if ( g_skill.GetInteger() == 1 ) {
|
||||
newPlayerHealth = 2;
|
||||
} else {
|
||||
newPlayerHealth = 1;
|
||||
}
|
||||
|
||||
if( !(player->health > player->inventory.maxHealth) &&
|
||||
!( player->health <= 0 ) ) {
|
||||
|
||||
player->health += newPlayerHealth;
|
||||
|
||||
if( player->health > player->inventory.maxHealth ) {
|
||||
player->health = player->inventory.maxHealth;
|
||||
}
|
||||
}
|
||||
if( player->inventory.armor > 0 ) {
|
||||
player->inventory.armor -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_DecreasePlayerHealth()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_DecreasePlayerHealth( float hp ) {
|
||||
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
if( player->health > 0 ) {
|
||||
player->health -= hp;
|
||||
|
||||
if( player->health <= 0 ) {
|
||||
player->health = 0;
|
||||
player->Damage( player, player, vec3_origin, "damage_suicide", 1.0f, INVALID_JOINT );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetEnemiesKilled
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetEnemiesKilled( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
idThread::ReturnFloat( player->inventory.enemiesKilled );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVarGui1()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVarGui1( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVarGui1 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVarGui2()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVarGui2( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVarGui2 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVarGui3()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVarGui3( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVarGui3 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVarGui4()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVarGui4( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVarGui4 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVarGui5()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVarGui5( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVarGui5 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVar1()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVar1( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVar1 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVar2()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVar2( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVar2 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVar3()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVar3( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVar3 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVar4()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVar4( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVar4 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVar5()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVar5( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVar5 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVar6()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVar6( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVar6 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVar7()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVar7( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVar7 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVar8()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVar8( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVar8 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVar9()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVar9( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVar9 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_GetTestVar10()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_GetTestVar10( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
idThread::ReturnFloat( player->inventory.testVar10 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVarGui1()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVarGui1( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVarGui1 = value;
|
||||
|
||||
if( player->inventory.testVarGui1 < 0 ||
|
||||
player->inventory.testVarGui1 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVarGui1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVarGui2()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVarGui2( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVarGui2 = value;
|
||||
|
||||
if( player->inventory.testVarGui2 < 0 ||
|
||||
player->inventory.testVarGui2 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVarGui2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVarGui3()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVarGui3( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVarGui3 = value;
|
||||
|
||||
if( player->inventory.testVarGui3 < 0 ||
|
||||
player->inventory.testVarGui3 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVarGui3 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVarGui4()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVarGui4( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVarGui4 = value;
|
||||
|
||||
if( player->inventory.testVarGui4 < 0 ||
|
||||
player->inventory.testVarGui4 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVarGui4 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVarGui5()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVarGui5( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVarGui5 = value;
|
||||
|
||||
if( player->inventory.testVarGui5 < 0 ||
|
||||
player->inventory.testVarGui5 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVarGui5 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVar1()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVar1( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVar1 = value;
|
||||
|
||||
if( player->inventory.testVar1 < 0 ||
|
||||
player->inventory.testVar1 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVar1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVar2()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVar2( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVar2 = value;
|
||||
|
||||
if( player->inventory.testVar2 < 0 ||
|
||||
player->inventory.testVar2 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVar2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVar3()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVar3( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVar3 = value;
|
||||
|
||||
if( player->inventory.testVar3 < 0 ||
|
||||
player->inventory.testVar3 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVar3 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVar4()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVar4( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVar4 = value;
|
||||
|
||||
if( player->inventory.testVar4 < 0 ||
|
||||
player->inventory.testVar4 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVar4 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVar5()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVar5( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVar5 = value;
|
||||
|
||||
if( player->inventory.testVar5 < 0 ||
|
||||
player->inventory.testVar5 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVar5 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVar6()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVar6( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVar6 = value;
|
||||
|
||||
if( player->inventory.testVar6 < 0 ||
|
||||
player->inventory.testVar6 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVar6 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVar7()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVar7( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVar7 = value;
|
||||
|
||||
if( player->inventory.testVar7 < 0 ||
|
||||
player->inventory.testVar7 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVar7 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVar8()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVar8( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVar8 = value;
|
||||
|
||||
if( player->inventory.testVar8 < 0 ||
|
||||
player->inventory.testVar8 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVar8 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVar9()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVar9( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVar9 = value;
|
||||
|
||||
if( player->inventory.testVar9 < 0 ||
|
||||
player->inventory.testVar9 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVar9 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_SetTestVar10()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_SetTestVar10( float value ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
|
||||
player->inventory.testVar10 = value;
|
||||
|
||||
if( player->inventory.testVar10 < 0 ||
|
||||
player->inventory.testVar10 > INT_MAX ) {
|
||||
|
||||
player->inventory.testVar10 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_PreviousPageDiary()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_PreviousPageDiary( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
idStrList diary = player->inventory.diary;
|
||||
|
||||
player->inventory.diaryInfo.currentPage--;
|
||||
|
||||
if( player->inventory.diaryInfo.currentPage == 1 ) {
|
||||
player->diaryUI->HandleNamedEvent( "prevPageOff" );
|
||||
}
|
||||
|
||||
player->diaryUI->HandleNamedEvent( "nextPageOn" );
|
||||
|
||||
int i = ( player->inventory.diaryInfo.currentPage * 2 );
|
||||
|
||||
player->inventory.diaryInfo.diaryText = diary[i-2];
|
||||
player->inventory.diaryInfo.diaryText2 = diary[i-1];
|
||||
player->inventory.diaryInfo.pageLeft = va( "-%i-", i-1 );
|
||||
player->inventory.diaryInfo.pageRight = va( "-%i-", i );
|
||||
|
||||
player->diaryUI->SetStateString(
|
||||
"pageLeft", player->inventory.diaryInfo.pageLeft );
|
||||
player->diaryUI->SetStateString(
|
||||
"pageRight", player->inventory.diaryInfo.pageRight );
|
||||
player->diaryUI->SetStateString(
|
||||
"diaryText", player->inventory.diaryInfo.diaryText );
|
||||
player->diaryUI->SetStateString(
|
||||
"diaryText2", player->inventory.diaryInfo.diaryText2 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_NextPageDiary()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_NextPageDiary( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
idStrList diary = player->inventory.diary;
|
||||
|
||||
player->inventory.diaryInfo.currentPage++;
|
||||
int i = ( player->inventory.diaryInfo.currentPage * 2 );
|
||||
|
||||
if( i >= diary.Num() ) {
|
||||
player->diaryUI->HandleNamedEvent( "nextPageOff" );
|
||||
}
|
||||
player->diaryUI->HandleNamedEvent( "prevPageOn" );
|
||||
|
||||
player->inventory.diaryInfo.diaryText = diary[i-2];
|
||||
player->inventory.diaryInfo.pageLeft = va( "-%i-", i-1 );
|
||||
player->inventory.diaryInfo.pageRight = va( "-%i-", i );
|
||||
|
||||
if( (i-1) == diary.Num() && i > diary.Num() ) {
|
||||
player->inventory.diaryInfo.diaryText2 = "";
|
||||
}
|
||||
else {
|
||||
player->inventory.diaryInfo.diaryText2 = diary[i-1];
|
||||
}
|
||||
|
||||
player->diaryUI->SetStateString(
|
||||
"pageLeft", player->inventory.diaryInfo.pageLeft );
|
||||
player->diaryUI->SetStateString(
|
||||
"pageRight", player->inventory.diaryInfo.pageRight );
|
||||
player->diaryUI->SetStateString(
|
||||
"diaryText", player->inventory.diaryInfo.diaryText );
|
||||
player->diaryUI->SetStateString(
|
||||
"diaryText2", player->inventory.diaryInfo.diaryText2 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_PreviousPageQuestlog()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_PreviousPageQuestlog( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
idStrList quest = player->inventory.quest;
|
||||
|
||||
player->inventory.diaryInfo.currentPage--;
|
||||
|
||||
player->inventory.diaryInfo.diaryText = "";
|
||||
player->inventory.diaryInfo.diaryText2 = "";
|
||||
player->inventory.diaryInfo.diaryText3 = "";
|
||||
player->inventory.diaryInfo.diaryText4 = "";
|
||||
|
||||
if( player->inventory.diaryInfo.currentPage == 1 ) {
|
||||
player->questlogUI->HandleNamedEvent( "prevPageOff" );
|
||||
}
|
||||
|
||||
player->questlogUI->HandleNamedEvent( "nextPageOn" );
|
||||
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftTopBoxOn" );
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomBoxOn" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightTopBoxOn" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightBottomBoxOn" );
|
||||
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftTopDoneOff" );
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomDoneOff" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightTopDoneOff" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightBottomDoneOff" );
|
||||
|
||||
int i = ( player->inventory.diaryInfo.currentPage * 4 );
|
||||
|
||||
player->inventory.diaryInfo.diaryText = quest[i-4];
|
||||
player->inventory.diaryInfo.diaryText2 = quest[i-3];
|
||||
player->inventory.diaryInfo.diaryText3 = quest[i-2];
|
||||
player->inventory.diaryInfo.diaryText4 = quest[i-1];
|
||||
player->inventory.diaryInfo.pageLeft = va( "-%i-", (i / 2) - 1 );
|
||||
player->inventory.diaryInfo.pageRight = va( "-%i-", (i / 2) );
|
||||
|
||||
if( player->inventory.questState[i-4] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftTopDoneOn" );
|
||||
}
|
||||
if( player->inventory.questState[i-3] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomDoneOn" );
|
||||
}
|
||||
if( player->inventory.questState[i-2] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateRightTopDoneOn" );
|
||||
}
|
||||
if( player->inventory.questState[i-1] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateRightBottomDoneOn" );
|
||||
}
|
||||
|
||||
player->questlogUI->SetStateString(
|
||||
"pageLeft", player->inventory.diaryInfo.pageLeft );
|
||||
player->questlogUI->SetStateString(
|
||||
"pageRight", player->inventory.diaryInfo.pageRight );
|
||||
player->questlogUI->SetStateString(
|
||||
"diaryText", player->inventory.diaryInfo.diaryText );
|
||||
player->questlogUI->SetStateString(
|
||||
"diaryText2", player->inventory.diaryInfo.diaryText2 );
|
||||
player->questlogUI->SetStateString(
|
||||
"diaryText3", player->inventory.diaryInfo.diaryText3 );
|
||||
player->questlogUI->SetStateString(
|
||||
"diaryText4", player->inventory.diaryInfo.diaryText4 );
|
||||
}
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_NextPageQuestlog()
|
||||
================
|
||||
*/
|
||||
void idThread::Event_NextPageQuestlog( void ) {
|
||||
idPlayer* player = gameLocal.GetLocalPlayer();
|
||||
idStrList quest = player->inventory.quest;
|
||||
|
||||
player->inventory.diaryInfo.currentPage++;
|
||||
|
||||
player->inventory.diaryInfo.diaryText = "";
|
||||
player->inventory.diaryInfo.diaryText2 = "";
|
||||
player->inventory.diaryInfo.diaryText3 = "";
|
||||
player->inventory.diaryInfo.diaryText4 = "";
|
||||
|
||||
int i = ( player->inventory.diaryInfo.currentPage * 4 );
|
||||
|
||||
if( i >= quest.Num() ) {
|
||||
player->questlogUI->HandleNamedEvent( "nextPageOff" );
|
||||
}
|
||||
player->questlogUI->HandleNamedEvent( "prevPageOn" );
|
||||
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftTopBoxOff" );
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomBoxOff" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightTopBoxOff" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightBottomBoxOff" );
|
||||
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftTopDoneOff" );
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomDoneOff" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightTopDoneOff" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightBottomDoneOff" );
|
||||
|
||||
int diff = 0;
|
||||
|
||||
if( i <= quest.Num() ) {
|
||||
diff = i;
|
||||
} else {
|
||||
diff = quest.Num();
|
||||
}
|
||||
|
||||
player->inventory.diaryInfo.diaryText = quest[i-4];
|
||||
player->inventory.diaryInfo.pageLeft = va( "-%i-", (i / 2) - 1 );
|
||||
player->inventory.diaryInfo.pageRight = va( "-%i-", (i / 2) );
|
||||
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftTopBoxOn" );
|
||||
|
||||
if( player->inventory.questState[i-4] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftTopDoneOn" );
|
||||
}
|
||||
|
||||
if( (diff % 4) == 1 ) {
|
||||
player->inventory.diaryInfo.diaryText2 = "";
|
||||
player->inventory.diaryInfo.diaryText3 = "";
|
||||
player->inventory.diaryInfo.diaryText4 = "";
|
||||
}
|
||||
else if( (diff % 4) == 2 ) {
|
||||
player->inventory.diaryInfo.diaryText2 = quest[i-3];
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomBoxOn" );
|
||||
if( player->inventory.questState[i-3] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomDoneOn" );
|
||||
}
|
||||
player->inventory.diaryInfo.diaryText3 = "";
|
||||
player->inventory.diaryInfo.diaryText4 = "";
|
||||
}
|
||||
else if( (diff % 4) == 3 ) {
|
||||
player->inventory.diaryInfo.diaryText2 = quest[i-3];
|
||||
player->inventory.diaryInfo.diaryText3 = quest[i-2];
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomBoxOn" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightTopBoxOn" );
|
||||
if( player->inventory.questState[i-3] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomDoneOn" );
|
||||
}
|
||||
if( player->inventory.questState[i-2] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateRightTopDoneOn" );
|
||||
}
|
||||
player->inventory.diaryInfo.diaryText4 = "";
|
||||
}
|
||||
else {
|
||||
player->inventory.diaryInfo.diaryText2 = quest[i-3];
|
||||
player->inventory.diaryInfo.diaryText3 = quest[i-2];
|
||||
player->inventory.diaryInfo.diaryText4 = quest[i-1];
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomBoxOn" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightTopBoxOn" );
|
||||
player->questlogUI->HandleNamedEvent( "StateRightBottomBoxOn" );
|
||||
if( player->inventory.questState[i-3] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateLeftBottomDoneOn" );
|
||||
}
|
||||
if( player->inventory.questState[i-2] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateRightTopDoneOn" );
|
||||
}
|
||||
if( player->inventory.questState[i-1] == "solved" ) {
|
||||
player->questlogUI->HandleNamedEvent( "StateRightBottomDoneOn" );
|
||||
}
|
||||
}
|
||||
|
||||
player->questlogUI->SetStateString(
|
||||
"pageLeft", player->inventory.diaryInfo.pageLeft );
|
||||
player->questlogUI->SetStateString(
|
||||
"pageRight", player->inventory.diaryInfo.pageRight );
|
||||
player->questlogUI->SetStateString(
|
||||
"diaryText", player->inventory.diaryInfo.diaryText );
|
||||
player->questlogUI->SetStateString(
|
||||
"diaryText2", player->inventory.diaryInfo.diaryText2 );
|
||||
player->questlogUI->SetStateString(
|
||||
"diaryText3", player->inventory.diaryInfo.diaryText3 );
|
||||
player->questlogUI->SetStateString(
|
||||
"diaryText4", player->inventory.diaryInfo.diaryText4 );
|
||||
}
|
||||
|
||||
//###//
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
idThread::Event_RadiusDamage
|
||||
|
|
|
@ -175,6 +175,55 @@ private:
|
|||
void Event_StrSkip( const char *string, int num );
|
||||
void Event_StrMid( const char *string, int start, int num );
|
||||
void Event_StrToFloat( const char *string );
|
||||
|
||||
//###// by MacX
|
||||
|
||||
void Event_GetMoney( void );
|
||||
void Event_DecreaseMoney( float value );
|
||||
void Event_LooseMoney( void );
|
||||
void Event_SetPlayerHealth( void );
|
||||
void Event_DecreasePlayerHealth( float hp );
|
||||
void Event_PreviousPageDiary( void );
|
||||
void Event_NextPageDiary( void );
|
||||
void Event_PreviousPageQuestlog( void );
|
||||
void Event_NextPageQuestlog( void );
|
||||
|
||||
void Event_GetEnemiesKilled( void );
|
||||
|
||||
void Event_GetTestVarGui1( void );
|
||||
void Event_GetTestVarGui2( void );
|
||||
void Event_GetTestVarGui3( void );
|
||||
void Event_GetTestVarGui4( void );
|
||||
void Event_GetTestVarGui5( void );
|
||||
void Event_GetTestVar1( void );
|
||||
void Event_GetTestVar2( void );
|
||||
void Event_GetTestVar3( void );
|
||||
void Event_GetTestVar4( void );
|
||||
void Event_GetTestVar5( void );
|
||||
void Event_GetTestVar6( void );
|
||||
void Event_GetTestVar7( void );
|
||||
void Event_GetTestVar8( void );
|
||||
void Event_GetTestVar9( void );
|
||||
void Event_GetTestVar10( void );
|
||||
|
||||
void Event_SetTestVarGui1( float value );
|
||||
void Event_SetTestVarGui2( float value );
|
||||
void Event_SetTestVarGui3( float value );
|
||||
void Event_SetTestVarGui4( float value );
|
||||
void Event_SetTestVarGui5( float value );
|
||||
void Event_SetTestVar1( float value );
|
||||
void Event_SetTestVar2( float value );
|
||||
void Event_SetTestVar3( float value );
|
||||
void Event_SetTestVar4( float value );
|
||||
void Event_SetTestVar5( float value );
|
||||
void Event_SetTestVar6( float value );
|
||||
void Event_SetTestVar7( float value );
|
||||
void Event_SetTestVar8( float value );
|
||||
void Event_SetTestVar9( float value );
|
||||
void Event_SetTestVar10( float value );
|
||||
|
||||
//###//
|
||||
|
||||
void Event_RadiusDamage( const idVec3 &origin, idEntity *inflictor, idEntity *attacker, idEntity *ignore, const char *damageDefName, float dmgPower );
|
||||
void Event_IsClient( void );
|
||||
void Event_IsMultiplayer( void );
|
||||
|
|
Loading…
Reference in a new issue