12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 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 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 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 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 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.
- ===========================================================================
- */
- #include "../idlib/precompiled.h"
- #pragma hdrstop
- #include "Game_local.h"
- /*
- ===============================================================================
- idMoveable
-
- ===============================================================================
- */
- const idEventDef EV_BecomeNonSolid( "becomeNonSolid" );
- const idEventDef EV_SetOwnerFromSpawnArgs( "<setOwnerFromSpawnArgs>" );
- const idEventDef EV_IsAtRest( "isAtRest", NULL, 'd' );
- const idEventDef EV_EnableDamage( "enableDamage", "f" );
- const idEventDef EV_GetOriginalPosition("GetOriginalPosition", NULL, 'v');
- const idEventDef EV_GetOriginalAngle("GetOriginalAngle", NULL, 'v');
- CLASS_DECLARATION( idEntity, idMoveable )
- 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 )
- EVENT( EV_GetOriginalPosition, idMoveable::Event_GetOriginalPosition )
- EVENT( EV_GetOriginalAngle, idMoveable::Event_GetOriginalAngle )
- END_CLASS
- static const float BOUNCE_SOUND_MIN_VELOCITY = 80.0f;
- static const float BOUNCE_SOUND_MAX_VELOCITY = 200.0f;
- /*
- ================
- idMoveable::idMoveable
- ================
- */
- idMoveable::idMoveable( void ) {
- minDamageVelocity = 100.0f;
- maxDamageVelocity = 200.0f;
- nextCollideFxTime = 0;
- nextDamageTime = 0;
- nextSoundTime = 0;
- nextPushTime = 0;
- initialSpline = NULL;
- initialSplineDir = vec3_zero;
- explode = false;
- unbindOnDeath = false;
- allowStep = false;
- canDamage = false;
- #ifdef _D3XP
- attacker = NULL;
- #endif
- }
- /*
- ================
- idMoveable::~idMoveable
- ================
- */
- idMoveable::~idMoveable( void ) {
- delete initialSpline;
- initialSpline = NULL;
- }
- /*
- ================
- idMoveable::Spawn
- ================
- */
- void idMoveable::Spawn( void ) {
- idTraceModel trm;
- float density, friction, bouncyness, mass;
- int clipShrink;
- idStr clipModelName;
- // check if a clip model is set
- spawnArgs.GetString( "clipmodel", "", clipModelName );
- if ( !clipModelName[0] ) {
- clipModelName = spawnArgs.GetString( "model" ); // use the visual model
- }
- if ( !collisionModelManager->TrmFromModel( clipModelName, trm ) ) {
- gameLocal.Error( "idMoveable '%s': cannot load collision model %s", name.c_str(), clipModelName.c_str() );
- return;
- }
- // if the model should be shrinked
- clipShrink = spawnArgs.GetInt( "clipshrink" );
- if ( clipShrink != 0 ) {
- trm.Shrink( clipShrink * CM_CLIP_EPSILON );
- }
- // 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" );
- fxCollide = spawnArgs.GetString( "fx_collide" );
- nextCollideFxTime = 0;
- fl.takedamage = true;
- damage = spawnArgs.GetString( "def_damage", "" );
- #ifdef _D3XP
- monsterDamage = spawnArgs.GetString( "monster_damage", "" );
- fl.networkSync = true;
- attacker = NULL;
- #endif
- canDamage = spawnArgs.GetBool( "damageWhenActive" ) ? false : true;
- minDamageVelocity = spawnArgs.GetFloat( "minDamageVelocity", "300" ); // _D3XP
- maxDamageVelocity = spawnArgs.GetFloat( "maxDamageVelocity", "700" ); // _D3XP
- nextDamageTime = 0;
- nextSoundTime = 0;
- nextPushTime = 0;
- health = spawnArgs.GetInt( "health", "0" );
- spawnArgs.GetString( "broken", "", brokenModel );
- 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() );
- }
- }
- // setup the physics
- physicsObj.SetSelf( this );
- physicsObj.SetClipModel( new idClipModel( trm ), density );
- 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 );
- if ( spawnArgs.GetFloat( "mass", "1", mass ) ) {
- physicsObj.SetMass( mass );
- }
- if ( spawnArgs.GetBool( "nodrop" ) ) {
- physicsObj.PutToRest();
- } else {
- physicsObj.DropToFloor();
- }
- if ( spawnArgs.GetBool( "noimpact" ) || spawnArgs.GetBool( "notPushable" ) ) {
- physicsObj.DisableImpact();
- }
- if ( spawnArgs.GetBool( "nonsolid" ) ) {
- BecomeNonSolid();
- }
- allowStep = spawnArgs.GetBool( "allowStep", "1" );
-
- //bc
- this->originalPosition = this->GetPhysics()->GetOrigin();
- this->originalAngle = this->GetPhysics()->GetAxis();
- PostEventMS( &EV_SetOwnerFromSpawnArgs, 0 );
- }
- /*
- ================
- idMoveable::Save
- ================
- */
- void idMoveable::Save( idSaveGame *savefile ) const {
- savefile->WriteString( brokenModel );
- savefile->WriteString( damage );
- #ifdef _D3XP
- savefile->WriteString( monsterDamage );
- savefile->WriteObject( attacker );
- #endif
- 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 );
- savefile->WriteStaticObject( physicsObj );
- //bc
- savefile->WriteVec3(originalPosition);
- savefile->WriteMat3(originalAngle);
- }
- /*
- ================
- idMoveable::Restore
- ================
- */
- void idMoveable::Restore( idRestoreGame *savefile ) {
- int initialSplineTime;
- savefile->ReadString( brokenModel );
- savefile->ReadString( damage );
- #ifdef _D3XP
- savefile->ReadString( monsterDamage );
- savefile->ReadObject( reinterpret_cast<idClass *&>( attacker ) );
- #endif
- 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 );
- if ( initialSplineTime != -1 ) {
- InitInitialSpline( initialSplineTime );
- } else {
- initialSpline = NULL;
- }
- savefile->ReadStaticObject( physicsObj );
- RestorePhysics( &physicsObj );
- //bc
- savefile->ReadVec3(originalPosition);
- savefile->ReadMat3(originalAngle);
- }
- /*
- ================
- idMoveable::Hide
- ================
- */
- void idMoveable::Hide( void ) {
- idEntity::Hide();
- physicsObj.SetContents( 0 );
- }
- /*
- ================
- idMoveable::Show
- ================
- */
- void idMoveable::Show( void ) {
- idEntity::Show();
- if ( !spawnArgs.GetBool( "nonsolid" ) ) {
- physicsObj.SetContents( CONTENTS_SOLID );
- }
- }
- /*
- =================
- idMoveable::Collide
- =================
- */
- bool idMoveable::Collide( const trace_t &collision, const idVec3 &velocity ) {
- float v, f;
- idVec3 dir;
- idEntity *ent;
- if ( gameLocal.time > nextPushTime && idMath::Fabs(collision.c.normal[0]) < 0.1 && idMath::Fabs(collision.c.normal[1]) < 0.1 && collision.c.normal[2] > 0.9 )
- {
- nextPushTime = gameLocal.time + 400;
- StartSound( "snd_push", SND_CHANNEL_ANY, 0, false, NULL );
- }
- v = -( velocity * collision.c.normal );
- if ( v > BOUNCE_SOUND_MIN_VELOCITY && gameLocal.time > nextSoundTime && !this->IsGrabbed())
- {
- 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 ) );
- if (gameLocal.time >= 2000)
- {
- if ( StartSound( "snd_bounce", SND_CHANNEL_ANY, 0, false, NULL ) )
- {
- // don't set the volume unless there is a bounce sound as it overrides the entire channel
- // which causes footsteps on ai's to not honor their shader parms
- //SetSoundVolume( f );
- if ( developer.GetBool() )
- {
- gameRenderWorld->DebugLine(idVec4(1,1,0,1), collision.endpos, collision.endpos + idVec3(0,0,512), 5000);
- }
- }
- }
- nextSoundTime = gameLocal.time + 500;
- //BC smoke effect.
- const char *smokeName = spawnArgs.GetString( "smoke_bounce" );
- if ( *smokeName != '\0' )
- {
- const idDeclParticle *smokeFly = NULL;
- smokeFly = static_cast<const idDeclParticle *>( declManager->FindType( DECL_PARTICLE, smokeName ) );
- if (smokeFly)
- {
- gameLocal.smokeParticles->EmitSmoke( smokeFly, gameLocal.time, 0,
- collision.endpos, collision.endAxis, timeGroup );
- }
- }
- //damage the player if the moveable smacks the player.
- //ent = thing that is hit.
- ent = gameLocal.entities[ collision.c.entityNum ];
- if ( ent )
- {
- //prevent held items from smacking player or destroying glass.
- idPlayer *localplayer = gameLocal.GetLocalPlayer();
- int frobnum = -1;
- if (localplayer->pickerState >= 2)
- {
- frobnum = localplayer->pickerWeapon.dragEnt.GetEntity()->entityNumber;
- }
- if (frobnum != this->entityNumber)
- {
- if ( ent->IsType( idPlayer::Type ) )
- {
- //Play the doublevision fullscreen FX.
- const idDict *damageDef = gameLocal.FindEntityDefDict( "damage_vaultsmack" );
- static_cast< idPlayer * >( ent )->playerView.DamageImpulse( idVec3(1,0,0), damageDef );
- //Play sound effect.
- const idKeyValue *kv = damageDef->FindKey( "snd_flesh" );
- if ( kv )
- {
- ent->StartSoundShader( declManager->FindSound(kv->GetValue()), SND_CHANNEL_ANY, 0, false, NULL );
- }
- }
- //check if hit a brittle glass.
- if (ent->IsType( idBrittleFracture::Type ))
- {
- ent->AddForce(this, this->entityNumber, collision.endpos, collision.c.normal);
- }
- else if (ent->IsType( idQGlass::Type ))
- {
- ent->AddForce(this, this->entityNumber, collision.endpos, collision.c.normal);
- }
- else if (ent->IsType( idTrembler::Type))
- {
- static_cast< idTrembler * >( ent )->Event_Touch(NULL, NULL);
- }
- }
- }
- }
- //bc
-
- // _D3XP :: changes relating to the addition of monsterDamage
- if ( !gameLocal.isClient && canDamage && gameLocal.time > nextDamageTime ) {
- bool hasDamage = damage.Length() > 0;
- bool hasMonsterDamage = monsterDamage.Length() > 0;
- if ( hasDamage || hasMonsterDamage ) {
- ent = gameLocal.entities[ collision.c.entityNum ];
- if ( ent && v > minDamageVelocity ) {
- f = v > maxDamageVelocity ? 1.0f : idMath::Sqrt( v - minDamageVelocity ) * ( 1.0f / idMath::Sqrt( maxDamageVelocity - minDamageVelocity ) );
- dir = velocity;
- dir.NormalizeFast();
- if ( ent->IsType( idAI::Type ) && hasMonsterDamage ) {
- #ifdef _D3XP
- if ( attacker ) {
- ent->Damage( this, attacker, dir, monsterDamage, f, INVALID_JOINT );
- }
- else {
- ent->Damage( this, GetPhysics()->GetClipModel()->GetOwner(), dir, monsterDamage, f, INVALID_JOINT );
- }
- #else
- ent->Damage( this, GetPhysics()->GetClipModel()->GetOwner(), dir, monsterDamage, f, INVALID_JOINT );
- #endif
- } else if ( hasDamage ) {
- #ifdef _D3XP
- // in multiplayer, scale damage wrt mass of object
- if ( gameLocal.isMultiplayer ) {
- f *= GetPhysics()->GetMass() * g_moveableDamageScale.GetFloat();
- }
- if ( attacker ) {
- ent->Damage( this, attacker, dir, damage, f, INVALID_JOINT );
- }
- else {
- //bc when vault smacks player.
- ent->Damage( this, GetPhysics()->GetClipModel()->GetOwner(), dir, damage, f, INVALID_JOINT );
- }
- #else
- ent->Damage( this, GetPhysics()->GetClipModel()->GetOwner(), dir, damage, f, INVALID_JOINT );
- #endif
- }
- nextDamageTime = gameLocal.time + 1000;
- }
- }
- }
- #ifdef _D3XP
- if ( this->IsType( idExplodingBarrel::Type ) ) {
- idExplodingBarrel *ebarrel = static_cast<idExplodingBarrel*>(this);
- if ( !ebarrel->IsStable() ) {
- PostEventSec( &EV_Explode, 0.04f );
- }
- }
- #endif
- if ( fxCollide.Length() && gameLocal.time > nextCollideFxTime ) {
- idEntityFx::StartFx( fxCollide, &collision.c.point, NULL, this, false );
- nextCollideFxTime = gameLocal.time + 3500;
- }
- return false;
- }
- /*
- ============
- idMoveable::Killed
- ============
- */
- void idMoveable::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
- if ( unbindOnDeath ) {
- Unbind();
- }
- if ( brokenModel != "" ) {
- SetModel( brokenModel );
- }
- if ( explode ) {
- if ( brokenModel == "" ) {
- PostEventMS( &EV_Remove, 1000 );
- }
- }
- if ( renderEntity.gui[ 0 ] ) {
- renderEntity.gui[ 0 ] = NULL;
- }
- ActivateTargets( this );
- fl.takedamage = false;
- }
- /*
- ================
- idMoveable::AllowStep
- ================
- */
- bool idMoveable::AllowStep( void ) const {
- return allowStep;
- }
- /*
- ================
- idMoveable::BecomeNonSolid
- ================
- */
- void idMoveable::BecomeNonSolid( void ) {
- // 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
- ================
- */
- void idMoveable::EnableDamage( bool enable, float duration ) {
- #ifdef _D3XP
- if ( canDamage == enable ) {
- return;
- }
- #endif
- canDamage = enable;
- if ( duration ) {
- PostEventSec( &EV_EnableDamage, duration, ( /*_D3XP*/enable ) ? 0.0f : 1.0f );
- }
- }
- /*
- ================
- idMoveable::InitInitialSpline
- ================
- */
- void idMoveable::InitInitialSpline( int startTime ) {
- int initialSplineTime;
- initialSpline = GetSpline();
- initialSplineTime = spawnArgs.GetInt( "initialSplineTime", "300" );
- if ( initialSpline != NULL ) {
- initialSpline->MakeUniform( initialSplineTime );
- initialSpline->ShiftTime( startTime - initialSpline->GetTime( 0 ) );
- initialSplineDir = initialSpline->GetCurrentFirstDerivative( startTime );
- initialSplineDir *= physicsObj.GetAxis().Transpose();
- initialSplineDir.Normalize();
- BecomeActive( TH_THINK );
- }
- }
- /*
- ================
- idMoveable::FollowInitialSplinePath
- ================
- */
- bool idMoveable::FollowInitialSplinePath( void ) {
- if ( initialSpline != NULL ) {
- if ( gameLocal.time < initialSpline->GetTime( initialSpline->GetNumValues() - 1 ) ) {
- idVec3 splinePos = initialSpline->GetCurrentValue( gameLocal.time );
- idVec3 linearVelocity = ( splinePos - physicsObj.GetOrigin() ) * USERCMD_HZ;
- physicsObj.SetLinearVelocity( linearVelocity );
- 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() ) * USERCMD_HZ;
- physicsObj.SetAngularVelocity( angularVelocity );
- return true;
- } else {
- delete initialSpline;
- initialSpline = NULL;
- }
- }
- return false;
- }
- /*
- ================
- idMoveable::Think
- ================
- */
- void idMoveable::Think( void ) {
- if ( thinkFlags & TH_THINK ) {
- if ( !FollowInitialSplinePath() ) {
- BecomeInactive( TH_THINK );
- }
- }
- idEntity::Think();
- }
- /*
- ================
- idMoveable::GetRenderModelMaterial
- ================
- */
- const idMaterial *idMoveable::GetRenderModelMaterial( void ) const {
- if ( renderEntity.customShader ) {
- return renderEntity.customShader;
- }
- if ( renderEntity.hModel && renderEntity.hModel->NumSurfaces() ) {
- return renderEntity.hModel->Surface( 0 )->shader;
- }
- return NULL;
- }
- /*
- ================
- idMoveable::WriteToSnapshot
- ================
- */
- void idMoveable::WriteToSnapshot( idBitMsgDelta &msg ) const {
- physicsObj.WriteToSnapshot( msg );
- }
- /*
- ================
- idMoveable::ReadFromSnapshot
- ================
- */
- void idMoveable::ReadFromSnapshot( const idBitMsgDelta &msg ) {
- physicsObj.ReadFromSnapshot( msg );
- if ( msg.HasChanged() ) {
- UpdateVisuals();
- }
- }
- void idMoveable::Event_GetOriginalPosition( void )
- {
- idThread::ReturnVector(this->originalPosition);
- }
- void idMoveable::Event_GetOriginalAngle( void )
- {
- idThread::ReturnVector(idVec3(this->originalAngle.ToAngles().pitch, this->originalAngle.ToAngles().yaw, this->originalAngle.ToAngles().roll));
- }
- /*
- ================
- idMoveable::Event_BecomeNonSolid
- ================
- */
- void idMoveable::Event_BecomeNonSolid( void ) {
- BecomeNonSolid();
- }
- #ifdef _D3XP
- /*
- ================
- idMoveable::SetAttacker
- ================
- */
- void idMoveable::SetAttacker( idEntity *ent ) {
- attacker = ent;
- }
- #endif
- /*
- ================
- idMoveable::Event_Activate
- ================
- */
- void idMoveable::Event_Activate( idEntity *activator ) {
- float delay;
- idVec3 init_velocity, init_avelocity;
- Show();
- if ( !spawnArgs.GetInt( "notPushable" ) ) {
- physicsObj.EnableImpact();
- }
- physicsObj.Activate();
- spawnArgs.GetVector( "init_velocity", "0 0 0", init_velocity );
- spawnArgs.GetVector( "init_avelocity", "0 0 0", init_avelocity );
- delay = spawnArgs.GetFloat( "init_velocityDelay", "0" );
- if ( delay == 0.0f ) {
- physicsObj.SetLinearVelocity( init_velocity );
- } else {
- PostEventSec( &EV_SetLinearVelocity, delay, init_velocity );
- }
- delay = spawnArgs.GetFloat( "init_avelocityDelay", "0" );
- if ( delay == 0.0f ) {
- physicsObj.SetAngularVelocity( init_avelocity );
- } else {
- PostEventSec( &EV_SetAngularVelocity, delay, init_avelocity );
- }
- InitInitialSpline( gameLocal.time );
- }
- /*
- ================
- idMoveable::Event_SetOwnerFromSpawnArgs
- ================
- */
- void idMoveable::Event_SetOwnerFromSpawnArgs( void ) {
- idStr owner;
- if ( spawnArgs.GetString( "owner", "", owner ) ) {
- ProcessEvent( &EV_SetOwner, gameLocal.FindEntity( owner ) );
- }
- }
- /*
- ================
- idMoveable::Event_IsAtRest
- ================
- */
- void idMoveable::Event_IsAtRest( void ) {
- idThread::ReturnInt( physicsObj.IsAtRest() );
- }
- /*
- ================
- idMoveable::Event_EnableDamage
- ================
- */
- void idMoveable::Event_EnableDamage( float enable ) {
- #ifdef _D3XP
- // clear out attacker
- attacker = NULL;
- #endif
- canDamage = ( enable != 0.0f );
- }
- /*
- ===============================================================================
- idBarrel
-
- ===============================================================================
- */
- CLASS_DECLARATION( idMoveable, idBarrel )
- END_CLASS
- /*
- ================
- idBarrel::idBarrel
- ================
- */
- idBarrel::idBarrel() {
- radius = 1.0f;
- barrelAxis = 0;
- lastOrigin.Zero();
- lastAxis.Identity();
- additionalRotation = 0.0f;
- additionalAxis.Identity();
- fl.networkSync = true;
- }
- /*
- ================
- idBarrel::Save
- ================
- */
- void idBarrel::Save( idSaveGame *savefile ) const {
- savefile->WriteFloat( radius );
- savefile->WriteInt( barrelAxis );
- savefile->WriteVec3( lastOrigin );
- savefile->WriteMat3( lastAxis );
- savefile->WriteFloat( additionalRotation );
- savefile->WriteMat3( additionalAxis );
- }
- /*
- ================
- idBarrel::Restore
- ================
- */
- void idBarrel::Restore( idRestoreGame *savefile ) {
- savefile->ReadFloat( radius );
- savefile->ReadInt( barrelAxis );
- savefile->ReadVec3( lastOrigin );
- savefile->ReadMat3( lastAxis );
- savefile->ReadFloat( additionalRotation );
- savefile->ReadMat3( additionalAxis );
- }
- /*
- ================
- idBarrel::BarrelThink
- ================
- */
- void idBarrel::BarrelThink( void ) {
- bool wasAtRest, onGround;
- float movedDistance, rotatedDistance, angle;
- idVec3 curOrigin, gravityNormal, dir;
- idMat3 curAxis, axis;
- wasAtRest = IsAtRest();
- // run physics
- RunPhysics();
- // only need to give the visual model an additional rotation if the physics were run
- if ( !wasAtRest ) {
- // current physics state
- onGround = GetPhysics()->HasGroundContacts();
- curOrigin = GetPhysics()->GetOrigin();
- curAxis = GetPhysics()->GetAxis();
- // if the barrel is on the ground
- if ( onGround ) {
- gravityNormal = GetPhysics()->GetGravityNormal();
- dir = curOrigin - lastOrigin;
- dir -= gravityNormal * dir * gravityNormal;
- movedDistance = dir.LengthSqr();
- // if the barrel moved and the barrel is not aligned with the gravity direction
- if ( movedDistance > 0.0f && idMath::Fabs( gravityNormal * curAxis[barrelAxis] ) < 0.7f ) {
- // 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;
- // get rotation about barrel axis since last think frame
- angle = lastAxis[(barrelAxis+1)%3] * curAxis[(barrelAxis+1)%3];
- angle = idMath::ACos( angle );
- // distance along cylinder hull
- rotatedDistance = angle * radius;
- // if the barrel moved further than it rotated about it's axis
- if ( movedDistance > rotatedDistance ) {
- // additional rotation of the visual model to make it look
- // like the barrel rolls instead of slides
- angle = 180.0f * (movedDistance - rotatedDistance) / (radius * idMath::PI);
- if ( gravityNormal.Cross( curAxis[barrelAxis] ) * dir < 0.0f ) {
- additionalRotation += angle;
- } else {
- additionalRotation -= angle;
- }
- dir = vec3_origin;
- dir[barrelAxis] = 1.0f;
- additionalAxis = idRotation( vec3_origin, dir, additionalRotation ).ToMat3();
- }
- }
- }
- // save state for next think
- lastOrigin = curOrigin;
- lastAxis = curAxis;
- }
- Present();
- }
- /*
- ================
- idBarrel::Think
- ================
- */
- void idBarrel::Think( void ) {
- if ( thinkFlags & TH_THINK ) {
- if ( !FollowInitialSplinePath() ) {
- BecomeInactive( TH_THINK );
- }
- }
- BarrelThink();
- }
- /*
- ================
- idBarrel::GetPhysicsToVisualTransform
- ================
- */
- bool idBarrel::GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis ) {
- origin = vec3_origin;
- axis = additionalAxis;
- return true;
- }
- /*
- ================
- idBarrel::Spawn
- ================
- */
- void idBarrel::Spawn( void ) {
- const idBounds &bounds = GetPhysics()->GetBounds();
- // radius of the barrel cylinder
- radius = ( bounds[1][0] - bounds[0][0] ) * 0.5f;
- // always a vertical barrel with cylinder axis parallel to the z-axis
- barrelAxis = 2;
- lastOrigin = GetPhysics()->GetOrigin();
- lastAxis = GetPhysics()->GetAxis();
- additionalRotation = 0.0f;
- additionalAxis.Identity();
- #ifdef _D3XP
- fl.networkSync = true;
- #endif
- }
- /*
- ================
- idBarrel::ClientPredictionThink
- ================
- */
- void idBarrel::ClientPredictionThink( void ) {
- Think();
- }
- /*
- ===============================================================================
- idExplodingBarrel
- ===============================================================================
- */
- const idEventDef EV_Respawn( "<respawn>" );
- const idEventDef EV_TriggerTargets( "<triggertargets>" );
- CLASS_DECLARATION( idBarrel, idExplodingBarrel )
- EVENT( EV_Activate, idExplodingBarrel::Event_Activate )
- EVENT( EV_Respawn, idExplodingBarrel::Event_Respawn )
- EVENT( EV_Explode, idExplodingBarrel::Event_Explode )
- EVENT( EV_TriggerTargets, idExplodingBarrel::Event_TriggerTargets )
- END_CLASS
- /*
- ================
- idExplodingBarrel::idExplodingBarrel
- ================
- */
- idExplodingBarrel::idExplodingBarrel() {
- spawnOrigin.Zero();
- spawnAxis.Zero();
- state = NORMAL;
- #ifdef _D3XP
- isStable = true;
- #endif
- particleModelDefHandle = -1;
- lightDefHandle = -1;
- memset( &particleRenderEntity, 0, sizeof( particleRenderEntity ) );
- memset( &light, 0, sizeof( light ) );
- particleTime = 0;
- lightTime = 0;
- time = 0.0f;
- }
- /*
- ================
- idExplodingBarrel::~idExplodingBarrel
- ================
- */
- idExplodingBarrel::~idExplodingBarrel() {
- if ( particleModelDefHandle >= 0 ){
- gameRenderWorld->FreeEntityDef( particleModelDefHandle );
- }
- if ( lightDefHandle >= 0 ) {
- gameRenderWorld->FreeLightDef( lightDefHandle );
- }
- }
- /*
- ================
- idExplodingBarrel::Save
- ================
- */
- void idExplodingBarrel::Save( idSaveGame *savefile ) const {
- savefile->WriteVec3( spawnOrigin );
- savefile->WriteMat3( spawnAxis );
- savefile->WriteInt( state );
- savefile->WriteInt( particleModelDefHandle );
- savefile->WriteInt( lightDefHandle );
- savefile->WriteRenderEntity( particleRenderEntity );
- savefile->WriteRenderLight( light );
- savefile->WriteInt( particleTime );
- savefile->WriteInt( lightTime );
- savefile->WriteFloat( time );
- #ifdef _D3XP
- savefile->WriteBool( isStable );
- #endif
- }
- /*
- ================
- idExplodingBarrel::Restore
- ================
- */
- void idExplodingBarrel::Restore( idRestoreGame *savefile ) {
- savefile->ReadVec3( spawnOrigin );
- savefile->ReadMat3( spawnAxis );
- savefile->ReadInt( (int &)state );
- savefile->ReadInt( (int &)particleModelDefHandle );
- savefile->ReadInt( (int &)lightDefHandle );
- savefile->ReadRenderEntity( particleRenderEntity );
- savefile->ReadRenderLight( light );
- savefile->ReadInt( particleTime );
- savefile->ReadInt( lightTime );
- savefile->ReadFloat( time );
- #ifdef _D3XP
- savefile->ReadBool( isStable );
- if ( lightDefHandle != -1 ) {
- lightDefHandle = gameRenderWorld->AddLightDef( &light );
- }
- if ( particleModelDefHandle != -1 ) {
- particleModelDefHandle = gameRenderWorld->AddEntityDef( &particleRenderEntity );
- }
- #endif
- }
- /*
- ================
- idExplodingBarrel::Spawn
- ================
- */
- void idExplodingBarrel::Spawn( void ) {
- health = spawnArgs.GetInt( "health", "5" );
- fl.takedamage = true;
- #ifdef _D3XP
- isStable = true;
- fl.networkSync = true;
- #endif
- 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 ) );
- //bc
- if (spawnArgs.GetBool("autoexplode", "0"))
- {
- Killed(NULL, NULL, 100, vec3_zero, 0);
- }
- }
- /*
- ================
- idExplodingBarrel::Think
- ================
- */
- void idExplodingBarrel::Think( void ) {
- idBarrel::BarrelThink();
- if ( lightDefHandle >= 0 ){
- if ( state == BURNING ) {
- // ramp the color up over 250 ms
- float pct = (gameLocal.time - lightTime) / 250.f;
- if ( pct > 1.0f ) {
- 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 );
- } else {
- if ( gameLocal.time - lightTime > 250 ) {
- gameRenderWorld->FreeLightDef( lightDefHandle );
- lightDefHandle = -1;
- }
- return;
- }
- }
- if ( !gameLocal.isClient && state != BURNING && state != EXPLODING ) {
- BecomeInactive( TH_THINK );
- return;
- }
- if ( particleModelDefHandle >= 0 ){
- particleRenderEntity.origin = physicsObj.GetAbsBounds().GetCenter();
- particleRenderEntity.axis = mat3_identity;
- gameRenderWorld->UpdateEntityDef( particleModelDefHandle, &particleRenderEntity );
- }
- }
- #ifdef _D3XP
- /*
- ================
- idExplodingBarrel::SetStability
- ================
- */
- void idExplodingBarrel::SetStability( bool stability ) {
- isStable = stability;
- }
- /*
- ================
- idExplodingBarrel::IsStable
- ================
- */
- bool idExplodingBarrel::IsStable( void ) {
- return isStable;
- }
- /*
- ================
- idExplodingBarrel::StartBurning
- ================
- */
- void idExplodingBarrel::StartBurning( void ) {
- state = BURNING;
- AddParticles( "barrelfire.prt", true );
- }
- /*
- ================
- idExplodingBarrel::StartBurning
- ================
- */
- void idExplodingBarrel::StopBurning( void ) {
- state = NORMAL;
- if ( particleModelDefHandle >= 0 ){
- gameRenderWorld->FreeEntityDef( particleModelDefHandle );
- particleModelDefHandle = -1;
- particleTime = 0;
- memset( &particleRenderEntity, 0, sizeof( particleRenderEntity ) );
- }
- }
- #endif
- /*
- ================
- idExplodingBarrel::AddParticles
- ================
- */
- void idExplodingBarrel::AddParticles( const char *name, bool burn ) {
- if ( name && *name ) {
- #ifdef _D3XP
- int explicitTimeGroup = timeGroup;
- SetTimeState explicitTS( explicitTimeGroup );
- #endif
- if ( particleModelDefHandle >= 0 ){
- gameRenderWorld->FreeEntityDef( particleModelDefHandle );
- }
- memset( &particleRenderEntity, 0, sizeof ( particleRenderEntity ) );
- const idDeclModelDef *modelDef = static_cast<const idDeclModelDef *>( declManager->FindType( DECL_MODELDEF, name ) );
- if ( modelDef ) {
- particleRenderEntity.origin = physicsObj.GetAbsBounds().GetCenter();
- particleRenderEntity.axis = mat3_identity;
- particleRenderEntity.hModel = modelDef->ModelHandle();
- 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 );
- #ifdef _D3XP
- particleRenderEntity.timeGroup = explicitTimeGroup;
- #endif
- if ( !particleRenderEntity.hModel ) {
- particleRenderEntity.hModel = renderModelManager->FindModel( name );
- }
- particleModelDefHandle = gameRenderWorld->AddEntityDef( &particleRenderEntity );
- if ( burn ) {
- BecomeActive( TH_THINK );
- }
- particleTime = gameLocal.realClientTime;
- }
- }
- }
- /*
- ================
- idExplodingBarrel::AddLight
- ================
- */
- void idExplodingBarrel::AddLight( const char *name, bool burn ) {
- if ( lightDefHandle >= 0 ){
- gameRenderWorld->FreeLightDef( lightDefHandle );
- }
- memset( &light, 0, sizeof ( light ) );
- 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.realClientTime;
- BecomeActive( TH_THINK );
- }
- /*
- ================
- idExplodingBarrel::ExplodingEffects
- ================
- */
- void idExplodingBarrel::ExplodingEffects( void ) {
- const char *temp;
- StartSound( "snd_explode", SND_CHANNEL_ANY, 0, false, NULL );
- temp = spawnArgs.GetString( "model_damage" );
- if ( *temp != '\0' ) {
- SetModel( temp );
- Show();
- }
- temp = spawnArgs.GetString( "model_detonate" );
- if ( *temp != '\0' ) {
- AddParticles( temp, false );
- }
- temp = spawnArgs.GetString( "mtr_lightexplode" );
- if ( *temp != '\0' ) {
- AddLight( temp, false );
- }
- temp = spawnArgs.GetString( "mtr_burnmark" );
- if ( *temp != '\0' ) {
- gameLocal.ProjectDecal( GetPhysics()->GetOrigin(), GetPhysics()->GetGravity(), 128.0f, true, 96.0f, temp );
- }
- }
- /*
- ================
- idExplodingBarrel::Killed
- ================
- */
- void idExplodingBarrel::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
- if ( IsHidden() || state == EXPLODING || state == BURNING ) {
- return;
- }
- float f = spawnArgs.GetFloat( "burn" );
- if ( f > 0.0f && state == NORMAL ) {
- state = BURNING;
- PostEventSec( &EV_Explode, f );
- StartSound( "snd_burn", SND_CHANNEL_ANY, 0, false, NULL );
- AddParticles( spawnArgs.GetString ( "model_burn", "" ), true );
- return;
- } else {
- state = EXPLODING;
- if ( gameLocal.isServer ) {
- idBitMsg msg;
- byte msgBuf[MAX_EVENT_PARAM_SIZE];
- msg.Init( msgBuf, sizeof( msgBuf ) );
- msg.WriteLong( gameLocal.time );
- ServerSendEvent( EVENT_EXPLODE, &msg, false, -1 );
- }
- }
- // do this before applying radius damage so the ent can trace to any damagable ents nearby
- Hide();
- physicsObj.SetContents( 0 );
- const char *splash = spawnArgs.GetString( "def_splash_damage", "damage_explosion" );
- if ( splash && *splash ) {
- gameLocal.RadiusDamage( GetPhysics()->GetOrigin(), this, attacker, this, this, splash );
- }
- ExplodingEffects( );
-
- //FIXME: need to precache all the debris stuff here and in the projectiles
- const idKeyValue *kv = spawnArgs.MatchPrefix( "def_debris" );
- // bool first = true;
- while ( kv ) {
- const idDict *debris_args = gameLocal.FindEntityDefDict( kv->GetValue(), false );
- if ( debris_args ) {
- idEntity *ent;
- idVec3 dir;
- idDebris *debris;
- //if ( first ) {
- dir = physicsObj.GetAxis()[1];
- // first = false;
- //} else {
- dir.x += gameLocal.random.CRandomFloat() * 4.0f;
- dir.y += gameLocal.random.CRandomFloat() * 4.0f;
- //dir.z = gameLocal.random.RandomFloat() * 8.0f;
- //}
- dir.Normalize();
- gameLocal.SpawnEntityDef( *debris_args, &ent, false );
- if ( !ent || !ent->IsType( idDebris::Type ) ) {
- gameLocal.Error( "'projectile_debris' is not an idDebris" );
- }
- debris = static_cast<idDebris *>(ent);
- 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 );
- }
- physicsObj.PutToRest();
- CancelEvents( &EV_Explode );
- CancelEvents( &EV_Activate );
- f = spawnArgs.GetFloat( "respawn" );
- if ( f > 0.0f ) {
- PostEventSec( &EV_Respawn, f );
- } else {
- PostEventMS( &EV_Remove, 5000 );
- }
- if ( spawnArgs.GetBool( "triggerTargets" ) ) {
- ActivateTargets( this );
- }
- }
- /*
- ================
- idExplodingBarrel::Damage
- ================
- */
- void idExplodingBarrel::Damage( idEntity *inflictor, idEntity *attacker, const idVec3 &dir,
- const char *damageDefName, const float damageScale, const int location ) {
- const idDict *damageDef = gameLocal.FindEntityDefDict( damageDefName );
- if ( !damageDef ) {
- gameLocal.Error( "Unknown damageDef '%s'\n", damageDefName );
- }
- if ( damageDef->FindKey( "radius" ) && GetPhysics()->GetContents() != 0 && GetBindMaster() == NULL ) {
- PostEventMS( &EV_Explode, 400 );
- } else {
- idEntity::Damage( inflictor, attacker, dir, damageDefName, damageScale, location );
- }
- }
- /*
- ================
- idExplodingBarrel::Event_TriggerTargets
- ================
- */
- void idExplodingBarrel::Event_TriggerTargets() {
- ActivateTargets( this );
- }
- /*
- ================
- idExplodingBarrel::Event_Explode
- ================
- */
- void idExplodingBarrel::Event_Explode() {
- if ( state == NORMAL || state == BURNING ) {
- state = BURNEXPIRED;
- Killed( NULL, NULL, 0, vec3_zero, 0 );
- }
- }
- /*
- ================
- idExplodingBarrel::Event_Respawn
- ================
- */
- void idExplodingBarrel::Event_Respawn() {
- int i;
- int minRespawnDist = spawnArgs.GetInt( "respawn_range", "256" );
- if ( minRespawnDist ) {
- float minDist = -1;
- for ( i = 0; i < gameLocal.numClients; i++ ) {
- if ( !gameLocal.entities[ i ] || !gameLocal.entities[ i ]->IsType( idPlayer::Type ) ) {
- continue;
- }
- idVec3 v = gameLocal.entities[ i ]->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
- float dist = v.Length();
- if ( minDist < 0 || dist < minDist ) {
- minDist = dist;
- }
- }
- if ( minDist < minRespawnDist ) {
- PostEventSec( &EV_Respawn, spawnArgs.GetInt( "respawn_again", "10" ) );
- return;
- }
- }
- const char *temp = spawnArgs.GetString( "model" );
- if ( temp && *temp ) {
- 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
- ================
- */
- void idExplodingBarrel::Event_Activate( idEntity *activator ) {
- Killed( activator, activator, 0, vec3_origin, 0 );
- }
- /*
- ================
- idMoveable::WriteToSnapshot
- ================
- */
- void idExplodingBarrel::WriteToSnapshot( idBitMsgDelta &msg ) const {
- idMoveable::WriteToSnapshot( msg );
- msg.WriteBits( IsHidden(), 1 );
- }
- /*
- ================
- idMoveable::ReadFromSnapshot
- ================
- */
- void idExplodingBarrel::ReadFromSnapshot( const idBitMsgDelta &msg ) {
- idMoveable::ReadFromSnapshot( msg );
- if ( msg.ReadBits( 1 ) ) {
- Hide();
- } else {
- Show();
- }
- }
- /*
- ================
- idExplodingBarrel::ClientReceiveEvent
- ================
- */
- 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" ) ) {
- ExplodingEffects( );
- }
- return true;
- }
- default: {
- return idBarrel::ClientReceiveEvent( event, time, msg );
- }
- }
- return false;
- }
|