2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-12-22 15:18:19 +00:00
# include "precompiled.h"
2012-11-26 18:58:24 +00:00
# pragma hdrstop
# include "Game_local.h"
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idMoveable
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
const idEventDef EV_BecomeNonSolid ( " becomeNonSolid " ) ;
const idEventDef EV_SetOwnerFromSpawnArgs ( " <setOwnerFromSpawnArgs> " ) ;
const idEventDef EV_IsAtRest ( " isAtRest " , NULL , ' d ' ) ;
const idEventDef EV_EnableDamage ( " enableDamage " , " f " ) ;
CLASS_DECLARATION ( idEntity , idMoveable )
2012-11-28 15:47:07 +00:00
EVENT ( EV_Activate , idMoveable : : Event_Activate )
EVENT ( EV_BecomeNonSolid , idMoveable : : Event_BecomeNonSolid )
EVENT ( EV_SetOwnerFromSpawnArgs , idMoveable : : Event_SetOwnerFromSpawnArgs )
EVENT ( EV_IsAtRest , idMoveable : : Event_IsAtRest )
EVENT ( EV_EnableDamage , idMoveable : : Event_EnableDamage )
2012-11-26 18:58:24 +00:00
END_CLASS
static const float BOUNCE_SOUND_MIN_VELOCITY = 80.0f ;
static const float BOUNCE_SOUND_MAX_VELOCITY = 200.0f ;
/*
= = = = = = = = = = = = = = = =
idMoveable : : idMoveable
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idMoveable : : idMoveable ( )
{
2012-11-26 18:58:24 +00:00
minDamageVelocity = 100.0f ;
maxDamageVelocity = 200.0f ;
nextCollideFxTime = 0 ;
nextDamageTime = 0 ;
nextSoundTime = 0 ;
initialSpline = NULL ;
initialSplineDir = vec3_zero ;
explode = false ;
unbindOnDeath = false ;
allowStep = false ;
canDamage = false ;
attacker = NULL ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : ~ idMoveable
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idMoveable : : ~ idMoveable ( )
{
2012-11-26 18:58:24 +00:00
delete initialSpline ;
initialSpline = NULL ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Spawn
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Spawn ( )
{
2012-11-26 18:58:24 +00:00
idTraceModel trm ;
float density , friction , bouncyness , mass ;
int clipShrink ;
idStr clipModelName ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if a clip model is set
spawnArgs . GetString ( " clipmodel " , " " , clipModelName ) ;
2012-11-28 15:47:07 +00:00
if ( ! clipModelName [ 0 ] )
{
2012-11-26 18:58:24 +00:00
clipModelName = spawnArgs . GetString ( " model " ) ; // use the visual model
}
2012-11-28 15:47:07 +00:00
if ( ! collisionModelManager - > TrmFromModel ( clipModelName , trm ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " idMoveable '%s': cannot load collision model %s " , name . c_str ( ) , clipModelName . c_str ( ) ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the model should be shrinked
clipShrink = spawnArgs . GetInt ( " clipshrink " ) ;
2012-11-28 15:47:07 +00:00
if ( clipShrink ! = 0 )
{
2012-11-26 18:58:24 +00:00
trm . Shrink ( clipShrink * CM_CLIP_EPSILON ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get rigid body properties
spawnArgs . GetFloat ( " density " , " 0.5 " , density ) ;
density = idMath : : ClampFloat ( 0.001f , 1000.0f , density ) ;
spawnArgs . GetFloat ( " friction " , " 0.05 " , friction ) ;
friction = idMath : : ClampFloat ( 0.0f , 1.0f , friction ) ;
spawnArgs . GetFloat ( " bouncyness " , " 0.6 " , bouncyness ) ;
bouncyness = idMath : : ClampFloat ( 0.0f , 1.0f , bouncyness ) ;
explode = spawnArgs . GetBool ( " explode " ) ;
unbindOnDeath = spawnArgs . GetBool ( " unbindondeath " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fxCollide = spawnArgs . GetString ( " fx_collide " ) ;
nextCollideFxTime = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fl . takedamage = true ;
damage = spawnArgs . GetString ( " def_damage " , " " ) ;
monsterDamage = spawnArgs . GetString ( " monster_damage " , " " ) ;
fl . networkSync = true ;
attacker = NULL ;
canDamage = spawnArgs . GetBool ( " damageWhenActive " ) ? false : true ;
minDamageVelocity = spawnArgs . GetFloat ( " minDamageVelocity " , " 300 " ) ; // _D3XP
maxDamageVelocity = spawnArgs . GetFloat ( " maxDamageVelocity " , " 700 " ) ; // _D3XP
nextDamageTime = 0 ;
nextSoundTime = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
health = spawnArgs . GetInt ( " health " , " 0 " ) ;
spawnArgs . GetString ( " broken " , " " , brokenModel ) ;
2012-11-28 15:47:07 +00:00
if ( health )
{
if ( brokenModel ! = " " & & ! renderModelManager - > CheckModel ( brokenModel ) )
{
gameLocal . Error ( " idMoveable '%s' at (%s): cannot load broken model '%s' " , name . c_str ( ) , GetPhysics ( ) - > GetOrigin ( ) . ToString ( 0 ) , brokenModel . c_str ( ) ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// setup the physics
physicsObj . SetSelf ( this ) ;
2012-11-28 15:47:07 +00:00
physicsObj . SetClipModel ( new ( TAG_PHYSICS_CLIP_MOVER ) idClipModel ( trm ) , density ) ;
2012-11-26 18:58:24 +00:00
physicsObj . GetClipModel ( ) - > SetMaterial ( GetRenderModelMaterial ( ) ) ;
physicsObj . SetOrigin ( GetPhysics ( ) - > GetOrigin ( ) ) ;
physicsObj . SetAxis ( GetPhysics ( ) - > GetAxis ( ) ) ;
physicsObj . SetBouncyness ( bouncyness ) ;
physicsObj . SetFriction ( 0.6f , 0.6f , friction ) ;
physicsObj . SetGravity ( gameLocal . GetGravity ( ) ) ;
physicsObj . SetContents ( CONTENTS_SOLID ) ;
physicsObj . SetClipMask ( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP ) ;
SetPhysics ( & physicsObj ) ;
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetFloat ( " mass " , " 10 " , mass ) )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetMass ( mass ) ;
}
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetBool ( " nodrop " ) )
{
2012-11-26 18:58:24 +00:00
physicsObj . PutToRest ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
physicsObj . DropToFloor ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetBool ( " noimpact " ) | | spawnArgs . GetBool ( " notPushable " ) )
{
2012-11-26 18:58:24 +00:00
physicsObj . DisableImpact ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetBool ( " nonsolid " ) )
{
2012-11-26 18:58:24 +00:00
BecomeNonSolid ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
allowStep = spawnArgs . GetBool ( " allowStep " , " 1 " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_SetOwnerFromSpawnArgs , 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Save
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Save ( idSaveGame * savefile ) const
{
2012-11-26 18:58:24 +00:00
savefile - > WriteString ( brokenModel ) ;
savefile - > WriteString ( damage ) ;
savefile - > WriteString ( monsterDamage ) ;
savefile - > WriteObject ( attacker ) ;
savefile - > WriteString ( fxCollide ) ;
savefile - > WriteInt ( nextCollideFxTime ) ;
savefile - > WriteFloat ( minDamageVelocity ) ;
savefile - > WriteFloat ( maxDamageVelocity ) ;
savefile - > WriteBool ( explode ) ;
savefile - > WriteBool ( unbindOnDeath ) ;
savefile - > WriteBool ( allowStep ) ;
savefile - > WriteBool ( canDamage ) ;
savefile - > WriteInt ( nextDamageTime ) ;
savefile - > WriteInt ( nextSoundTime ) ;
savefile - > WriteInt ( initialSpline ! = NULL ? initialSpline - > GetTime ( 0 ) : - 1 ) ;
savefile - > WriteVec3 ( initialSplineDir ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteStaticObject ( physicsObj ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Restore
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Restore ( idRestoreGame * savefile )
{
2012-11-26 18:58:24 +00:00
int initialSplineTime ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadString ( brokenModel ) ;
savefile - > ReadString ( damage ) ;
savefile - > ReadString ( monsterDamage ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( attacker ) ) ;
2012-11-26 18:58:24 +00:00
savefile - > ReadString ( fxCollide ) ;
savefile - > ReadInt ( nextCollideFxTime ) ;
savefile - > ReadFloat ( minDamageVelocity ) ;
savefile - > ReadFloat ( maxDamageVelocity ) ;
savefile - > ReadBool ( explode ) ;
savefile - > ReadBool ( unbindOnDeath ) ;
savefile - > ReadBool ( allowStep ) ;
savefile - > ReadBool ( canDamage ) ;
savefile - > ReadInt ( nextDamageTime ) ;
savefile - > ReadInt ( nextSoundTime ) ;
savefile - > ReadInt ( initialSplineTime ) ;
savefile - > ReadVec3 ( initialSplineDir ) ;
2012-11-28 15:47:07 +00:00
if ( initialSplineTime ! = - 1 )
{
2012-11-26 18:58:24 +00:00
InitInitialSpline ( initialSplineTime ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
initialSpline = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadStaticObject ( physicsObj ) ;
RestorePhysics ( & physicsObj ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Hide
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Hide ( )
{
2012-11-26 18:58:24 +00:00
idEntity : : Hide ( ) ;
physicsObj . SetContents ( 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Show
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Show ( )
{
2012-11-26 18:58:24 +00:00
idEntity : : Show ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! spawnArgs . GetBool ( " nonsolid " ) )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetContents ( CONTENTS_SOLID ) ;
}
}
/*
= = = = = = = = = = = = = = = = =
idMoveable : : Collide
= = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idMoveable : : Collide ( const trace_t & collision , const idVec3 & velocity )
{
2012-11-26 18:58:24 +00:00
float v , f ;
idVec3 dir ;
2012-11-28 15:47:07 +00:00
idEntity * ent ;
2012-11-26 18:58:24 +00:00
v = - ( velocity * collision . c . normal ) ;
2012-11-28 15:47:07 +00:00
if ( v > BOUNCE_SOUND_MIN_VELOCITY & & gameLocal . time > nextSoundTime )
{
2012-11-26 18:58:24 +00:00
f = v > BOUNCE_SOUND_MAX_VELOCITY ? 1.0f : idMath : : Sqrt ( v - BOUNCE_SOUND_MIN_VELOCITY ) * ( 1.0f / idMath : : Sqrt ( BOUNCE_SOUND_MAX_VELOCITY - BOUNCE_SOUND_MIN_VELOCITY ) ) ;
2012-11-28 15:47:07 +00:00
if ( StartSound ( " snd_bounce " , SND_CHANNEL_ANY , 0 , false , NULL ) )
{
2012-11-26 18:58:24 +00:00
// don't set the volume unless there is a bounce sound as it overrides the entire channel
// which causes footsteps on ai's to not honor their shader parms
SetSoundVolume ( f ) ;
}
nextSoundTime = gameLocal . time + 500 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// _D3XP :: changes relating to the addition of monsterDamage
2012-11-28 15:47:07 +00:00
if ( ! common - > IsClient ( ) & & canDamage & & gameLocal . time > nextDamageTime )
{
2012-11-26 18:58:24 +00:00
bool hasDamage = damage . Length ( ) > 0 ;
bool hasMonsterDamage = monsterDamage . Length ( ) > 0 ;
2012-11-28 15:47:07 +00:00
if ( hasDamage | | hasMonsterDamage )
{
2012-11-26 18:58:24 +00:00
ent = gameLocal . entities [ collision . c . entityNum ] ;
2012-11-28 15:47:07 +00:00
if ( ent & & v > minDamageVelocity )
{
2012-11-26 18:58:24 +00:00
f = v > maxDamageVelocity ? 1.0f : idMath : : Sqrt ( v - minDamageVelocity ) * ( 1.0f / idMath : : Sqrt ( maxDamageVelocity - minDamageVelocity ) ) ;
dir = velocity ;
dir . NormalizeFast ( ) ;
2012-11-28 15:47:07 +00:00
if ( ent - > IsType ( idAI : : Type ) & & hasMonsterDamage )
{
if ( attacker )
{
2012-11-26 18:58:24 +00:00
ent - > Damage ( this , attacker , dir , monsterDamage , f , INVALID_JOINT ) ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
ent - > Damage ( this , GetPhysics ( ) - > GetClipModel ( ) - > GetOwner ( ) , dir , monsterDamage , f , INVALID_JOINT ) ;
}
2012-11-28 15:47:07 +00:00
}
else if ( hasDamage )
{
2012-11-26 18:58:24 +00:00
// in multiplayer, scale damage wrt mass of object
2012-11-28 15:47:07 +00:00
if ( common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
f * = GetPhysics ( ) - > GetMass ( ) * g_moveableDamageScale . GetFloat ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( attacker )
{
2012-11-26 18:58:24 +00:00
ent - > Damage ( this , attacker , dir , damage , f , INVALID_JOINT ) ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
ent - > Damage ( this , GetPhysics ( ) - > GetClipModel ( ) - > GetOwner ( ) , dir , damage , f , INVALID_JOINT ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
nextDamageTime = gameLocal . time + 1000 ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( this - > IsType ( idExplodingBarrel : : Type ) )
{
idExplodingBarrel * ebarrel = static_cast < idExplodingBarrel * > ( this ) ;
if ( ! ebarrel - > IsStable ( ) )
{
2012-11-26 18:58:24 +00:00
PostEventSec ( & EV_Explode , 0.04f ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( fxCollide . Length ( ) & & gameLocal . time > nextCollideFxTime )
{
2012-11-26 18:58:24 +00:00
idEntityFx : : StartFx ( fxCollide , & collision . c . point , NULL , this , false ) ;
nextCollideFxTime = gameLocal . time + 3500 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = =
idMoveable : : Killed
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Killed ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location )
{
if ( unbindOnDeath )
{
2012-11-26 18:58:24 +00:00
Unbind ( ) ;
}
2012-11-28 15:47:07 +00:00
if ( brokenModel ! = " " )
{
2012-11-26 18:58:24 +00:00
SetModel ( brokenModel ) ;
}
2012-11-28 15:47:07 +00:00
if ( explode )
{
if ( brokenModel = = " " )
{
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_Remove , 1000 ) ;
}
}
2012-11-28 15:47:07 +00:00
if ( renderEntity . gui [ 0 ] )
{
2012-11-26 18:58:24 +00:00
renderEntity . gui [ 0 ] = NULL ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ActivateTargets ( this ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fl . takedamage = false ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : AllowStep
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idMoveable : : AllowStep ( ) const
{
2012-11-26 18:58:24 +00:00
return allowStep ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : BecomeNonSolid
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : BecomeNonSolid ( )
{
2012-11-26 18:58:24 +00:00
// set CONTENTS_RENDERMODEL so bullets still collide with the moveable
physicsObj . SetContents ( CONTENTS_CORPSE | CONTENTS_RENDERMODEL ) ;
physicsObj . SetClipMask ( MASK_SOLID | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : EnableDamage
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : EnableDamage ( bool enable , float duration )
{
if ( canDamage = = enable )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
canDamage = enable ;
2012-11-28 15:47:07 +00:00
if ( duration )
{
2012-11-26 18:58:24 +00:00
PostEventSec ( & EV_EnableDamage , duration , ( /*_D3XP*/ enable ) ? 0.0f : 1.0f ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : InitInitialSpline
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : InitInitialSpline ( int startTime )
{
2012-11-26 18:58:24 +00:00
int initialSplineTime ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
initialSpline = GetSpline ( ) ;
initialSplineTime = spawnArgs . GetInt ( " initialSplineTime " , " 300 " ) ;
2012-11-28 15:47:07 +00:00
if ( initialSpline ! = NULL )
{
2012-11-26 18:58:24 +00:00
initialSpline - > MakeUniform ( initialSplineTime ) ;
initialSpline - > ShiftTime ( startTime - initialSpline - > GetTime ( 0 ) ) ;
initialSplineDir = initialSpline - > GetCurrentFirstDerivative ( startTime ) ;
initialSplineDir * = physicsObj . GetAxis ( ) . Transpose ( ) ;
initialSplineDir . Normalize ( ) ;
BecomeActive ( TH_THINK ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : FollowInitialSplinePath
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idMoveable : : FollowInitialSplinePath ( )
{
if ( initialSpline ! = NULL )
{
if ( gameLocal . time < initialSpline - > GetTime ( initialSpline - > GetNumValues ( ) - 1 ) )
{
2012-11-26 18:58:24 +00:00
idVec3 splinePos = initialSpline - > GetCurrentValue ( gameLocal . time ) ;
idVec3 linearVelocity = ( splinePos - physicsObj . GetOrigin ( ) ) * com_engineHz_latched ;
physicsObj . SetLinearVelocity ( linearVelocity ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 splineDir = initialSpline - > GetCurrentFirstDerivative ( gameLocal . time ) ;
idVec3 dir = initialSplineDir * physicsObj . GetAxis ( ) ;
idVec3 angularVelocity = dir . Cross ( splineDir ) ;
angularVelocity . Normalize ( ) ;
angularVelocity * = idMath : : ACos16 ( dir * splineDir / splineDir . Length ( ) ) * com_engineHz_latched ;
physicsObj . SetAngularVelocity ( angularVelocity ) ;
return true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
delete initialSpline ;
initialSpline = NULL ;
}
}
return false ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : ClientThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : ClientThink ( const int curTime , const float fraction , const bool predict )
{
2012-11-26 18:58:24 +00:00
InterpolatePhysicsOnly ( fraction ) ;
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Think
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Think ( )
{
if ( thinkFlags & TH_THINK )
{
if ( ! FollowInitialSplinePath ( ) )
{
2012-11-26 18:58:24 +00:00
BecomeInactive ( TH_THINK ) ;
}
}
idEntity : : Think ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : GetRenderModelMaterial
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idMaterial * idMoveable : : GetRenderModelMaterial ( ) const
{
if ( renderEntity . customShader )
{
2012-11-26 18:58:24 +00:00
return renderEntity . customShader ;
}
2012-11-28 15:47:07 +00:00
if ( renderEntity . hModel & & renderEntity . hModel - > NumSurfaces ( ) )
{
return renderEntity . hModel - > Surface ( 0 ) - > shader ;
2012-11-26 18:58:24 +00:00
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : WriteToSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : WriteToSnapshot ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
physicsObj . WriteToSnapshot ( msg ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : ReadFromSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : ReadFromSnapshot ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
physicsObj . ReadFromSnapshot ( msg ) ;
2012-11-28 15:47:07 +00:00
if ( msg . HasChanged ( ) )
{
2012-11-26 18:58:24 +00:00
UpdateVisuals ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Event_BecomeNonSolid
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Event_BecomeNonSolid ( )
{
2012-11-26 18:58:24 +00:00
BecomeNonSolid ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : SetAttacker
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : SetAttacker ( idEntity * ent )
{
2012-11-26 18:58:24 +00:00
attacker = ent ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Event_Activate
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Event_Activate ( idEntity * activator )
{
2012-11-26 18:58:24 +00:00
float delay ;
idVec3 init_velocity , init_avelocity ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Show ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! spawnArgs . GetInt ( " notPushable " ) )
{
2012-11-26 18:58:24 +00:00
physicsObj . EnableImpact ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . Activate ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spawnArgs . GetVector ( " init_velocity " , " 0 0 0 " , init_velocity ) ;
spawnArgs . GetVector ( " init_avelocity " , " 0 0 0 " , init_avelocity ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delay = spawnArgs . GetFloat ( " init_velocityDelay " , " 0 " ) ;
2012-11-28 15:47:07 +00:00
if ( delay = = 0.0f )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetLinearVelocity ( init_velocity ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
PostEventSec ( & EV_SetLinearVelocity , delay , init_velocity ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
delay = spawnArgs . GetFloat ( " init_avelocityDelay " , " 0 " ) ;
2012-11-28 15:47:07 +00:00
if ( delay = = 0.0f )
{
2012-11-26 18:58:24 +00:00
physicsObj . SetAngularVelocity ( init_avelocity ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
PostEventSec ( & EV_SetAngularVelocity , delay , init_avelocity ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
InitInitialSpline ( gameLocal . time ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Event_SetOwnerFromSpawnArgs
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Event_SetOwnerFromSpawnArgs ( )
{
2012-11-26 18:58:24 +00:00
idStr owner ;
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetString ( " owner " , " " , owner ) )
{
2012-11-26 18:58:24 +00:00
ProcessEvent ( & EV_SetOwner , gameLocal . FindEntity ( owner ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Event_IsAtRest
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Event_IsAtRest ( )
{
2012-11-26 18:58:24 +00:00
idThread : : ReturnInt ( physicsObj . IsAtRest ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Event_EnableDamage
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idMoveable : : Event_EnableDamage ( float enable )
{
2012-11-26 18:58:24 +00:00
// clear out attacker
attacker = NULL ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
canDamage = ( enable ! = 0.0f ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idBarrel
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
CLASS_DECLARATION ( idMoveable , idBarrel )
END_CLASS
/*
= = = = = = = = = = = = = = = =
idBarrel : : idBarrel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idBarrel : : idBarrel ( )
{
2012-11-26 18:58:24 +00:00
radius = 1.0f ;
barrelAxis = 0 ;
lastOrigin . Zero ( ) ;
lastAxis . Identity ( ) ;
additionalRotation = 0.0f ;
additionalAxis . Identity ( ) ;
fl . networkSync = true ;
}
/*
= = = = = = = = = = = = = = = =
idBarrel : : Save
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idBarrel : : Save ( idSaveGame * savefile ) const
{
2012-11-26 18:58:24 +00:00
savefile - > WriteFloat ( radius ) ;
savefile - > WriteInt ( barrelAxis ) ;
savefile - > WriteVec3 ( lastOrigin ) ;
savefile - > WriteMat3 ( lastAxis ) ;
savefile - > WriteFloat ( additionalRotation ) ;
savefile - > WriteMat3 ( additionalAxis ) ;
}
/*
= = = = = = = = = = = = = = = =
idBarrel : : Restore
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idBarrel : : Restore ( idRestoreGame * savefile )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadFloat ( radius ) ;
savefile - > ReadInt ( barrelAxis ) ;
savefile - > ReadVec3 ( lastOrigin ) ;
savefile - > ReadMat3 ( lastAxis ) ;
savefile - > ReadFloat ( additionalRotation ) ;
savefile - > ReadMat3 ( additionalAxis ) ;
}
/*
= = = = = = = = = = = = = = = =
idBarrel : : BarrelThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idBarrel : : BarrelThink ( )
{
2012-11-26 18:58:24 +00:00
bool wasAtRest , onGround ;
float movedDistance , rotatedDistance , angle ;
idVec3 curOrigin , gravityNormal , dir ;
idMat3 curAxis , axis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
wasAtRest = IsAtRest ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// run physics
RunPhysics ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// only need to give the visual model an additional rotation if the physics were run
2012-11-28 15:47:07 +00:00
if ( ! wasAtRest )
{
2012-11-26 18:58:24 +00:00
// current physics state
onGround = GetPhysics ( ) - > HasGroundContacts ( ) ;
curOrigin = GetPhysics ( ) - > GetOrigin ( ) ;
curAxis = GetPhysics ( ) - > GetAxis ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the barrel is on the ground
2012-11-28 15:47:07 +00:00
if ( onGround )
{
2012-11-26 18:58:24 +00:00
gravityNormal = GetPhysics ( ) - > GetGravityNormal ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dir = curOrigin - lastOrigin ;
dir - = gravityNormal * dir * gravityNormal ;
movedDistance = dir . LengthSqr ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the barrel moved and the barrel is not aligned with the gravity direction
2012-11-28 15:47:07 +00:00
if ( movedDistance > 0.0f & & idMath : : Fabs ( gravityNormal * curAxis [ barrelAxis ] ) < 0.7f )
{
2012-11-26 18:58:24 +00:00
// barrel movement since last think frame orthogonal to the barrel axis
movedDistance = idMath : : Sqrt ( movedDistance ) ;
dir * = 1.0f / movedDistance ;
movedDistance = ( 1.0f - idMath : : Fabs ( dir * curAxis [ barrelAxis ] ) ) * movedDistance ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get rotation about barrel axis since last think frame
2012-11-28 15:47:07 +00:00
angle = lastAxis [ ( barrelAxis + 1 ) % 3 ] * curAxis [ ( barrelAxis + 1 ) % 3 ] ;
2012-11-26 18:58:24 +00:00
angle = idMath : : ACos ( angle ) ;
// distance along cylinder hull
rotatedDistance = angle * radius ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the barrel moved further than it rotated about it's axis
2012-11-28 15:47:07 +00:00
if ( movedDistance > rotatedDistance )
{
2012-11-26 18:58:24 +00:00
// additional rotation of the visual model to make it look
// like the barrel rolls instead of slides
2012-11-28 15:47:07 +00:00
angle = 180.0f * ( movedDistance - rotatedDistance ) / ( radius * idMath : : PI ) ;
if ( gravityNormal . Cross ( curAxis [ barrelAxis ] ) * dir < 0.0f )
{
2012-11-26 18:58:24 +00:00
additionalRotation + = angle ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
additionalRotation - = angle ;
}
dir = vec3_origin ;
dir [ barrelAxis ] = 1.0f ;
additionalAxis = idRotation ( vec3_origin , dir , additionalRotation ) . ToMat3 ( ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// save state for next think
lastOrigin = curOrigin ;
lastAxis = curAxis ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idBarrel : : Think
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idBarrel : : Think ( )
{
if ( thinkFlags & TH_THINK )
{
if ( ! FollowInitialSplinePath ( ) )
{
2012-11-26 18:58:24 +00:00
BecomeInactive ( TH_THINK ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
BarrelThink ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idBarrel : : GetPhysicsToVisualTransform
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idBarrel : : GetPhysicsToVisualTransform ( idVec3 & origin , idMat3 & axis )
{
2012-11-26 18:58:24 +00:00
origin = vec3_origin ;
axis = additionalAxis ;
return true ;
}
/*
= = = = = = = = = = = = = = = =
idBarrel : : Spawn
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idBarrel : : Spawn ( )
{
const idBounds & bounds = GetPhysics ( ) - > GetBounds ( ) ;
2012-11-26 18:58:24 +00:00
// radius of the barrel cylinder
radius = ( bounds [ 1 ] [ 0 ] - bounds [ 0 ] [ 0 ] ) * 0.5f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// always a vertical barrel with cylinder axis parallel to the z-axis
barrelAxis = 2 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lastOrigin = GetPhysics ( ) - > GetOrigin ( ) ;
lastAxis = GetPhysics ( ) - > GetAxis ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
additionalRotation = 0.0f ;
additionalAxis . Identity ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
fl . networkSync = true ;
}
/*
= = = = = = = = = = = = = = = =
idBarrel : : ClientThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idBarrel : : ClientThink ( const int curTime , const float fraction , const bool predict )
{
2012-11-26 18:58:24 +00:00
InterpolatePhysics ( fraction ) ;
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idExplodingBarrel
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
const idEventDef EV_Respawn ( " <respawn> " ) ;
const idEventDef EV_TriggerTargets ( " <triggertargets> " ) ;
CLASS_DECLARATION ( idBarrel , idExplodingBarrel )
2012-11-28 15:47:07 +00:00
EVENT ( EV_Activate , idExplodingBarrel : : Event_Activate )
EVENT ( EV_Respawn , idExplodingBarrel : : Event_Respawn )
EVENT ( EV_Explode , idExplodingBarrel : : Event_Explode )
EVENT ( EV_TriggerTargets , idExplodingBarrel : : Event_TriggerTargets )
2012-11-26 18:58:24 +00:00
END_CLASS
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : idExplodingBarrel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idExplodingBarrel : : idExplodingBarrel ( )
{
2012-11-26 18:58:24 +00:00
spawnOrigin . Zero ( ) ;
spawnAxis . Zero ( ) ;
state = NORMAL ;
isStable = true ;
particleModelDefHandle = - 1 ;
lightDefHandle = - 1 ;
memset ( & particleRenderEntity , 0 , sizeof ( particleRenderEntity ) ) ;
memset ( & light , 0 , sizeof ( light ) ) ;
particleTime = 0 ;
lightTime = 0 ;
time = 0.0f ;
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : ~ idExplodingBarrel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idExplodingBarrel : : ~ idExplodingBarrel ( )
{
if ( particleModelDefHandle > = 0 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > FreeEntityDef ( particleModelDefHandle ) ;
}
2012-11-28 15:47:07 +00:00
if ( lightDefHandle > = 0 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > FreeLightDef ( lightDefHandle ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : Save
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : Save ( idSaveGame * savefile ) const
{
2012-11-26 18:58:24 +00:00
savefile - > WriteVec3 ( spawnOrigin ) ;
savefile - > WriteMat3 ( spawnAxis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( state ) ;
savefile - > WriteInt ( particleModelDefHandle ) ;
savefile - > WriteInt ( lightDefHandle ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteRenderEntity ( particleRenderEntity ) ;
savefile - > WriteRenderLight ( light ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( particleTime ) ;
savefile - > WriteInt ( lightTime ) ;
savefile - > WriteFloat ( time ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( isStable ) ;
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : Restore
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : Restore ( idRestoreGame * savefile )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadVec3 ( spawnOrigin ) ;
savefile - > ReadMat3 ( spawnAxis ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadInt ( ( int & ) state ) ;
savefile - > ReadInt ( ( int & ) particleModelDefHandle ) ;
savefile - > ReadInt ( ( int & ) lightDefHandle ) ;
2012-11-26 18:58:24 +00:00
savefile - > ReadRenderEntity ( particleRenderEntity ) ;
savefile - > ReadRenderLight ( light ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( particleTime ) ;
savefile - > ReadInt ( lightTime ) ;
savefile - > ReadFloat ( time ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( isStable ) ;
2012-11-28 15:47:07 +00:00
if ( lightDefHandle ! = - 1 )
{
2012-11-26 18:58:24 +00:00
lightDefHandle = gameRenderWorld - > AddLightDef ( & light ) ;
}
2012-11-28 15:47:07 +00:00
if ( particleModelDefHandle ! = - 1 )
{
2012-11-26 18:58:24 +00:00
particleModelDefHandle = gameRenderWorld - > AddEntityDef ( & particleRenderEntity ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : Spawn
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : Spawn ( )
{
2012-11-26 18:58:24 +00:00
health = spawnArgs . GetInt ( " health " , " 5 " ) ;
fl . takedamage = true ;
isStable = true ;
fl . networkSync = true ;
spawnOrigin = GetPhysics ( ) - > GetOrigin ( ) ;
spawnAxis = GetPhysics ( ) - > GetAxis ( ) ;
state = NORMAL ;
particleModelDefHandle = - 1 ;
lightDefHandle = - 1 ;
lightTime = 0 ;
particleTime = 0 ;
time = spawnArgs . GetFloat ( " time " ) ;
memset ( & particleRenderEntity , 0 , sizeof ( particleRenderEntity ) ) ;
memset ( & light , 0 , sizeof ( light ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : UpdateLight
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : UpdateLight ( )
{
if ( lightDefHandle > = 0 )
{
if ( state = = BURNING )
{
2012-11-26 18:58:24 +00:00
// ramp the color up over 250 ms
2012-11-28 15:47:07 +00:00
float pct = ( gameLocal . serverTime - lightTime ) / 250.f ;
if ( pct > 1.0f )
{
2012-11-26 18:58:24 +00:00
pct = 1.0f ;
}
light . origin = physicsObj . GetAbsBounds ( ) . GetCenter ( ) ;
light . axis = mat3_identity ;
light . shaderParms [ SHADERPARM_RED ] = pct ;
light . shaderParms [ SHADERPARM_GREEN ] = pct ;
light . shaderParms [ SHADERPARM_BLUE ] = pct ;
light . shaderParms [ SHADERPARM_ALPHA ] = pct ;
gameRenderWorld - > UpdateLightDef ( lightDefHandle , & light ) ;
2012-11-28 15:47:07 +00:00
}
else
{
if ( gameLocal . serverTime - lightTime > 250 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > FreeLightDef ( lightDefHandle ) ;
lightDefHandle = - 1 ;
}
return ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : ClientThink
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : ClientThink ( const int curTime , const float fraction , const bool predict )
{
2012-11-26 18:58:24 +00:00
UpdateLight ( ) ;
InterpolatePhysics ( fraction ) ;
Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : Think
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : Think ( )
{
2012-11-26 18:58:24 +00:00
idBarrel : : BarrelThink ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateLight ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! common - > IsClient ( ) & & state ! = BURNING & & state ! = EXPLODING )
{
2012-11-26 18:58:24 +00:00
BecomeInactive ( TH_THINK ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( particleModelDefHandle > = 0 )
{
2012-11-26 18:58:24 +00:00
particleRenderEntity . origin = physicsObj . GetAbsBounds ( ) . GetCenter ( ) ;
particleRenderEntity . axis = mat3_identity ;
gameRenderWorld - > UpdateEntityDef ( particleModelDefHandle , & particleRenderEntity ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : SetStability
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : SetStability ( bool stability )
{
2012-11-26 18:58:24 +00:00
isStable = stability ;
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : IsStable
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idExplodingBarrel : : IsStable ( )
{
2012-11-26 18:58:24 +00:00
return isStable ;
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : StartBurning
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : StartBurning ( )
{
2012-11-26 18:58:24 +00:00
state = BURNING ;
AddParticles ( " barrelfire.prt " , true ) ;
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : StartBurning
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : StopBurning ( )
{
2012-11-26 18:58:24 +00:00
state = NORMAL ;
2012-11-28 15:47:07 +00:00
if ( particleModelDefHandle > = 0 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > FreeEntityDef ( particleModelDefHandle ) ;
particleModelDefHandle = - 1 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
particleTime = 0 ;
memset ( & particleRenderEntity , 0 , sizeof ( particleRenderEntity ) ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : AddParticles
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : AddParticles ( const char * name , bool burn )
{
if ( name & & * name )
{
2012-11-26 18:58:24 +00:00
int explicitTimeGroup = timeGroup ;
SetTimeState explicitTS ( explicitTimeGroup ) ;
2012-11-28 15:47:07 +00:00
if ( particleModelDefHandle > = 0 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > FreeEntityDef ( particleModelDefHandle ) ;
}
2012-11-28 15:47:07 +00:00
memset ( & particleRenderEntity , 0 , sizeof ( particleRenderEntity ) ) ;
2012-11-26 18:58:24 +00:00
idRenderModel * modelDef = renderModelManager - > FindModel ( name ) ;
2012-11-28 15:47:07 +00:00
if ( modelDef )
{
2012-11-26 18:58:24 +00:00
particleRenderEntity . origin = physicsObj . GetAbsBounds ( ) . GetCenter ( ) ;
particleRenderEntity . axis = mat3_identity ;
particleRenderEntity . hModel = modelDef ;
float rgb = ( burn ) ? 0.0f : 1.0f ;
particleRenderEntity . shaderParms [ SHADERPARM_RED ] = rgb ;
particleRenderEntity . shaderParms [ SHADERPARM_GREEN ] = rgb ;
particleRenderEntity . shaderParms [ SHADERPARM_BLUE ] = rgb ;
particleRenderEntity . shaderParms [ SHADERPARM_ALPHA ] = rgb ;
particleRenderEntity . shaderParms [ SHADERPARM_TIMEOFFSET ] = - MS2SEC ( gameLocal . realClientTime ) ;
particleRenderEntity . shaderParms [ SHADERPARM_DIVERSITY ] = ( burn ) ? 1.0f : gameLocal . random . RandomInt ( 90 ) ;
particleRenderEntity . timeGroup = explicitTimeGroup ;
particleModelDefHandle = gameRenderWorld - > AddEntityDef ( & particleRenderEntity ) ;
2012-11-28 15:47:07 +00:00
if ( burn )
{
2012-11-26 18:58:24 +00:00
BecomeActive ( TH_THINK ) ;
}
particleTime = gameLocal . realClientTime ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : AddLight
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : AddLight ( const char * name , bool burn )
{
if ( lightDefHandle > = 0 )
{
2012-11-26 18:58:24 +00:00
gameRenderWorld - > FreeLightDef ( lightDefHandle ) ;
}
2012-11-28 15:47:07 +00:00
memset ( & light , 0 , sizeof ( light ) ) ;
2012-11-26 18:58:24 +00:00
light . axis = mat3_identity ;
light . lightRadius . x = spawnArgs . GetFloat ( " light_radius " ) ;
light . lightRadius . y = light . lightRadius . z = light . lightRadius . x ;
light . origin = physicsObj . GetOrigin ( ) ;
light . origin . z + = 128 ;
light . pointLight = true ;
light . shader = declManager - > FindMaterial ( name ) ;
light . shaderParms [ SHADERPARM_RED ] = 2.0f ;
light . shaderParms [ SHADERPARM_GREEN ] = 2.0f ;
light . shaderParms [ SHADERPARM_BLUE ] = 2.0f ;
light . shaderParms [ SHADERPARM_ALPHA ] = 2.0f ;
lightDefHandle = gameRenderWorld - > AddLightDef ( & light ) ;
lightTime = gameLocal . serverTime ;
BecomeActive ( TH_THINK ) ;
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : ExplodingEffects
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : ExplodingEffects ( )
{
const char * temp ;
2012-11-26 18:58:24 +00:00
StartSound ( " snd_explode " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
temp = spawnArgs . GetString ( " model_damage " ) ;
2012-11-28 15:47:07 +00:00
if ( * temp ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
SetModel ( temp ) ;
Show ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
temp = spawnArgs . GetString ( " model_detonate " ) ;
2012-11-28 15:47:07 +00:00
if ( * temp ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
AddParticles ( temp , false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
temp = spawnArgs . GetString ( " mtr_lightexplode " ) ;
2012-11-28 15:47:07 +00:00
if ( * temp ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
AddLight ( temp , false ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
temp = spawnArgs . GetString ( " mtr_burnmark " ) ;
2012-11-28 15:47:07 +00:00
if ( * temp ! = ' \0 ' )
{
2012-11-26 18:58:24 +00:00
gameLocal . ProjectDecal ( GetPhysics ( ) - > GetOrigin ( ) , GetPhysics ( ) - > GetGravity ( ) , 128.0f , true , 96.0f , temp ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : Killed
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : Killed ( idEntity * inflictor , idEntity * attacker , int damage , const idVec3 & dir , int location )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( IsHidden ( ) | | state = = EXPLODING | | state = = BURNING )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Clients don't process killed
2012-11-28 15:47:07 +00:00
if ( common - > IsClient ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float f = spawnArgs . GetFloat ( " burn " ) ;
2012-11-28 15:47:07 +00:00
if ( f > 0.0f & & state = = NORMAL )
{
2012-11-26 18:58:24 +00:00
state = BURNING ;
PostEventSec ( & EV_Explode , f ) ;
StartSound ( " snd_burn " , SND_CHANNEL_ANY , 0 , false , NULL ) ;
2012-11-28 15:47:07 +00:00
AddParticles ( spawnArgs . GetString ( " model_burn " , " " ) , true ) ;
2012-11-26 18:58:24 +00:00
return ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
state = EXPLODING ;
2012-11-28 15:47:07 +00:00
if ( common - > IsServer ( ) )
{
2012-11-26 18:58:24 +00:00
idBitMsg msg ;
byte msgBuf [ MAX_EVENT_PARAM_SIZE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
msg . InitWrite ( msgBuf , sizeof ( msgBuf ) ) ;
msg . WriteLong ( gameLocal . time ) ;
ServerSendEvent ( EVENT_EXPLODE , & msg , false ) ;
2012-11-28 15:47:07 +00:00
}
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// do this before applying radius damage so the ent can trace to any damagable ents nearby
Hide ( ) ;
physicsObj . SetContents ( 0 ) ;
2012-11-28 15:47:07 +00:00
const char * splash = spawnArgs . GetString ( " def_splash_damage " , " damage_explosion " ) ;
2012-12-11 22:48:55 +00:00
if ( splash ! = NULL & & * splash ! = ' \0 ' )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
gameLocal . RadiusDamage ( GetPhysics ( ) - > GetOrigin ( ) , this , attacker , this , this , splash ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ExplodingEffects ( ) ;
//FIXME: need to precache all the debris stuff here and in the projectiles
2012-11-28 15:47:07 +00:00
const idKeyValue * kv = spawnArgs . MatchPrefix ( " def_debris " ) ;
2012-11-26 18:58:24 +00:00
// bool first = true;
2012-11-28 15:47:07 +00:00
while ( kv ! = NULL )
{
const idDict * debris_args = gameLocal . FindEntityDefDict ( kv - > GetValue ( ) , false ) ;
if ( debris_args )
{
idEntity * ent ;
2012-11-26 18:58:24 +00:00
idVec3 dir ;
2012-11-28 15:47:07 +00:00
idDebris * debris ;
2012-11-26 18:58:24 +00:00
//if ( first ) {
2012-11-28 15:47:07 +00:00
dir = physicsObj . GetAxis ( ) [ 1 ] ;
2012-11-26 18:58:24 +00:00
// first = false;
//} else {
2012-11-28 15:47:07 +00:00
dir . x + = gameLocal . random . CRandomFloat ( ) * 4.0f ;
dir . y + = gameLocal . random . CRandomFloat ( ) * 4.0f ;
//dir.z = gameLocal.random.RandomFloat() * 8.0f;
2012-11-26 18:58:24 +00:00
//}
dir . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLocal . SpawnEntityDef ( * debris_args , & ent , false ) ;
2012-11-28 15:47:07 +00:00
if ( ent = = NULL | | ! ent - > IsType ( idDebris : : Type ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " 'projectile_debris' is not an idDebris " ) ;
break ;
}
2012-11-28 15:47:07 +00:00
debris = static_cast < idDebris * > ( ent ) ;
2012-11-26 18:58:24 +00:00
debris - > Create ( this , physicsObj . GetOrigin ( ) , dir . ToMat3 ( ) ) ;
debris - > Launch ( ) ;
debris - > GetRenderEntity ( ) - > shaderParms [ SHADERPARM_TIME_OF_DEATH ] = ( gameLocal . time + 1500 ) * 0.001f ;
debris - > UpdateVisuals ( ) ;
}
kv = spawnArgs . MatchPrefix ( " def_debris " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . PutToRest ( ) ;
CancelEvents ( & EV_Explode ) ;
CancelEvents ( & EV_Activate ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
f = spawnArgs . GetFloat ( " respawn " ) ;
2012-11-28 15:47:07 +00:00
if ( f > 0.0f )
{
2012-11-26 18:58:24 +00:00
PostEventSec ( & EV_Respawn , f ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_Remove , 5000 ) ;
}
2012-11-28 15:47:07 +00:00
if ( spawnArgs . GetBool ( " triggerTargets " ) )
{
2012-11-26 18:58:24 +00:00
ActivateTargets ( this ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Any time a barrel explodes, attribute it towards the 'Boomtastic' achievement, since there's no way a barrel can explode without player interference
2012-11-28 15:47:07 +00:00
idPlayer * player = gameLocal . GetLocalPlayer ( ) ;
if ( player ! = NULL & & ! common - > IsMultiplayer ( ) )
{
2012-11-26 18:58:24 +00:00
player - > GetAchievementManager ( ) . EventCompletesAchievement ( ACHIEVEMENT_DESTROY_BARRELS ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : Damage
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : Damage ( idEntity * inflictor , idEntity * attacker , const idVec3 & dir ,
const char * damageDefName , const float damageScale , const int location )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
const idDict * damageDef = gameLocal . FindEntityDefDict ( damageDefName ) ;
if ( damageDef = = NULL )
{
2012-11-26 18:58:24 +00:00
gameLocal . Error ( " Unknown damageDef '%s' \n " , damageDefName ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( damageDef - > FindKey ( " radius " ) & & GetPhysics ( ) - > GetContents ( ) ! = 0 & & GetBindMaster ( ) = = NULL )
{
2012-11-26 18:58:24 +00:00
PostEventMS ( & EV_Explode , 400 ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
idEntity : : Damage ( inflictor , attacker , dir , damageDefName , damageScale , location ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : Event_TriggerTargets
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : Event_TriggerTargets ( )
{
2012-11-26 18:58:24 +00:00
ActivateTargets ( this ) ;
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : Event_Explode
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : Event_Explode ( )
{
if ( state = = NORMAL | | state = = BURNING )
{
2012-11-26 18:58:24 +00:00
state = BURNEXPIRED ;
Killed ( NULL , attacker , 0 , vec3_zero , 0 ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : Event_Respawn
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : Event_Respawn ( )
{
2012-11-26 18:58:24 +00:00
int i ;
int minRespawnDist = spawnArgs . GetInt ( " respawn_range " , " 256 " ) ;
2012-11-28 15:47:07 +00:00
if ( minRespawnDist )
{
2012-11-26 18:58:24 +00:00
float minDist = - 1 ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < gameLocal . numClients ; i + + )
{
if ( ! gameLocal . entities [ i ] | | ! gameLocal . entities [ i ] - > IsType ( idPlayer : : Type ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
idVec3 v = gameLocal . entities [ i ] - > GetPhysics ( ) - > GetOrigin ( ) - GetPhysics ( ) - > GetOrigin ( ) ;
float dist = v . Length ( ) ;
2012-11-28 15:47:07 +00:00
if ( minDist < 0 | | dist < minDist )
{
2012-11-26 18:58:24 +00:00
minDist = dist ;
}
}
2012-11-28 15:47:07 +00:00
if ( minDist < minRespawnDist )
{
2012-11-26 18:58:24 +00:00
PostEventSec ( & EV_Respawn , spawnArgs . GetInt ( " respawn_again " , " 10 " ) ) ;
return ;
}
}
2012-11-28 15:47:07 +00:00
const char * temp = spawnArgs . GetString ( " model " ) ;
2012-12-11 22:48:55 +00:00
if ( temp ! = NULL & & * temp ! = ' \0 ' )
2012-11-28 15:47:07 +00:00
{
2012-11-26 18:58:24 +00:00
SetModel ( temp ) ;
}
health = spawnArgs . GetInt ( " health " , " 5 " ) ;
fl . takedamage = true ;
physicsObj . SetOrigin ( spawnOrigin ) ;
physicsObj . SetAxis ( spawnAxis ) ;
physicsObj . SetContents ( CONTENTS_SOLID ) ;
physicsObj . DropToFloor ( ) ;
state = NORMAL ;
Show ( ) ;
UpdateVisuals ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : Event_Activate
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : Event_Activate ( idEntity * activator )
{
2012-11-26 18:58:24 +00:00
Killed ( activator , activator , 0 , vec3_origin , 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : WriteToSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : WriteToSnapshot ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
idMoveable : : WriteToSnapshot ( msg ) ;
msg . WriteBits ( IsHidden ( ) , 1 ) ;
}
/*
= = = = = = = = = = = = = = = =
idMoveable : : ReadFromSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idExplodingBarrel : : ReadFromSnapshot ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
idMoveable : : ReadFromSnapshot ( msg ) ;
2012-11-28 15:47:07 +00:00
if ( msg . ReadBits ( 1 ) )
{
2012-11-26 18:58:24 +00:00
Hide ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
Show ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idExplodingBarrel : : ClientReceiveEvent
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idExplodingBarrel : : ClientReceiveEvent ( int event , int time , const idBitMsg & msg )
{
switch ( event )
{
case EVENT_EXPLODE :
{
if ( gameLocal . realClientTime - msg . ReadLong ( ) < spawnArgs . GetInt ( " explode_lapse " , " 1000 " ) )
{
2012-11-26 18:58:24 +00:00
ExplodingEffects ( ) ;
}
return true ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
return idBarrel : : ClientReceiveEvent ( event , time , msg ) ;
}
}
}