/* ================ idBrittleFracture::Think ================ */ void idBrittleFracture::Think( void ) { int i, startTime, endTime, droppedTime; shard_t *shard; bool atRest = true, fading = false; // remove overdue shards for ( i = 0; i < shards.Num(); i++ ) { droppedTime = shards[i]->droppedTime; if ( droppedTime != -1 ) { if ( gameLocal.time - droppedTime > SHARD_ALIVE_TIME ) { RemoveShard( i ); i--; } fading = true; } } // remove the entity when nothing is visible if ( !shards.Num() ) { PostEventMS( &EV_Remove, 0 ); return; } if ( thinkFlags & TH_PHYSICS ) { startTime = gameLocal.previousTime; endTime = gameLocal.time; // run physics on shards for ( i = 0; i < shards.Num(); i++ ) { shard = shards[i]; if ( shard->droppedTime == -1 ) { continue; } shard->physicsObj.Evaluate( endTime - startTime, endTime ); if ( !shard->physicsObj.IsAtRest() ) { atRest = false; } } if ( atRest ) { BecomeInactive( TH_PHYSICS ); } else { BecomeActive( TH_PHYSICS ); } } if ( !atRest || bounds.IsCleared() ) { bounds.Clear(); for ( i = 0; i < shards.Num(); i++ ) { bounds.AddBounds( shards[i]->clipModel->GetAbsBounds() ); } } if ( fading ) { BecomeActive( TH_UPDATEVISUALS | TH_THINK ); } else { BecomeInactive( TH_THINK ); } RunPhysics(); Present(); }
/* ================ idTrigger_Touch::Disable ================ */ void idTrigger_Touch::Disable() { BecomeInactive( TH_THINK ); }
/* ================ idSecurityCamera::Think ================ */ void idSecurityCamera::Think( void ) { float pct; float travel; if ( thinkFlags & TH_THINK ) { if ( g_showEntityInfo.GetBool() ) { DrawFov(); } if (health <= 0) { BecomeInactive( TH_THINK ); return; } } // run physics RunPhysics(); if ( thinkFlags & TH_THINK ) { if (CanSeePlayer()) { if (alertMode == SCANNING) { float sightTime; SetAlertMode(ALERT); stopSweeping = gameLocal.time; if (sweeping) { CancelEvents( &EV_SecurityCam_Pause ); } else { CancelEvents( &EV_SecurityCam_ReverseSweep ); } sweeping = false; StopSound( SND_CHANNEL_ANY, false ); StartSound( "snd_sight", SND_CHANNEL_BODY, 0, false, NULL ); sightTime = spawnArgs.GetFloat( "sightTime", "5" ); PostEventSec(&EV_SecurityCam_Alert, sightTime); } } else { if (alertMode == ALERT) { float sightResume; SetAlertMode(LOSINGINTEREST); CancelEvents( &EV_SecurityCam_Alert ); sightResume = spawnArgs.GetFloat( "sightResume", "1.5" ); PostEventSec( &EV_SecurityCam_ContinueSweep, sightResume ); } if ( sweeping ) { idAngles a = GetPhysics()->GetAxis().ToAngles(); pct = ( gameLocal.time - sweepStart ) / ( sweepEnd - sweepStart ); travel = pct * sweepAngle; if ( negativeSweep ) { a.yaw = angle + travel; } else { a.yaw = angle - travel; } SetAngles( a ); } } } Present(); }
/* ================ hhSpring::UnLinkSpring HUMANHEAD ================ */ void hhSpring::UnLinkSpring() { BecomeInactive(TH_THINK); }
/* ================ idExplodingBarrel::Think ================ */ void idExplodingBarrel::Think( void ) { idBarrel::BarrelThink(); #ifdef _DENTONMOD if ( thinkFlags & TH_UPDATEWOUNDPARTICLES ) UpdateParticles(); #endif 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; } // This condition fixes the problem where particleRenderEntity is used for explosion effect // and it still tries to track the physics origin even after physics is put to rest. #ifdef _DENTONMOD if ( particleModelDefHandle >= 0 && state == BURNING ){ #else if ( particleModelDefHandle >= 0 ){ #endif particleRenderEntity.origin = physicsObj.GetAbsBounds().GetCenter(); particleRenderEntity.axis = mat3_identity; gameRenderWorld->UpdateEntityDef( particleModelDefHandle, &particleRenderEntity ); } } /* ================ idExplodingBarrel::AddParticles ================ */ void idExplodingBarrel::AddParticles( const char *name, bool burn ) { if ( name && *name ) { 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 ); 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( "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 ); } // put the explosion particle effect to the end -- By Clone JCD temp = spawnArgs.GetString( "model_detonate" ); if ( *temp != '\0' ) { AddParticles( temp, false ); } } //ivan start /* ================ idExplodingBarrel::SpawnDrops ================ */ void idExplodingBarrel::SpawnDrops( void ){ idVec3 offset; idStr offsetKey; const idKeyValue *kv = spawnArgs.MatchPrefix( "def_dropItem", NULL ); while( kv ) { //get the offset offsetKey = kv->GetKey().c_str() + 4; offsetKey += "Offset"; offset = spawnArgs.GetVector( offsetKey.c_str(), "0 0 0" ); idMoveableItem::DropItem( kv->GetValue().c_str(), physicsObj.GetAbsBounds().GetCenter() + offset,physicsObj.GetAxis(), vec3_origin, 0, 0, false ); //don't drop to floor so offset is respected kv = spawnArgs.MatchPrefix( "def_dropItem", kv ); } }
/* ================ idExplodingBarrel::Killed ================ */ void idExplodingBarrel::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) { // This simple condition causes a barrel to explode when shot while burning #ifdef _DENTONMOD if ( IsHidden() || state == EXPLODING ) { #else if ( IsHidden() || state == EXPLODING || state == BURNING ) { #endif return; } float f = spawnArgs.GetFloat( "burn" ); #ifdef _DENTONMOD int explodeHealth = spawnArgs.GetInt( "explode_health" ); if ( f > 0.0f && state == NORMAL && health > explodeHealth ) { #else if ( f > 0.0f && state == NORMAL ) { #endif state = BURNING; PostEventSec( &EV_Explode, f ); StartSound( "snd_burn", SND_CHANNEL_ANY, 0, false, NULL ); AddParticles( spawnArgs.GetString ( "model_burn", "" ), true ); return; } else { #ifdef _DENTONMOD if( state == BURNING && health > explodeHealth ) { return; } #endif 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(); #ifdef _DENTONMOD BecomeInactive(TH_PHYSICS); // This causes the physics not to update after explosion #else physicsObj.SetContents( 0 ); // Set physics content 0 after spawining debris. #endif 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 ); } SpawnDrops(); //ivan #ifdef _DENTONMOD physicsObj.SetContents( 0 ); #endif 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 ); } //ivan start - add score only if player is the killer if ( attacker && attacker->IsType( idPlayer::Type ) ) { static_cast< idPlayer* >( attacker )->AddScore( spawnArgs.GetInt( "score", "100" ) ); } //ivan end } /* ================ 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 ); } #ifdef _DENTONMOD // Following condition means, if inflictor's got a radius damage then explode immediately, // which could cause explosions when barrel's health is greater than 0 so I am disabling it. #else if ( damageDef->FindKey( "radius" ) && GetPhysics()->GetContents() != 0 && GetBindMaster() == NULL ) { PostEventMS( &EV_Explode, 400 ); } else { #endif idEntity::Damage( inflictor, attacker, dir, damageDefName, damageScale, location ); #ifdef _DENTONMOD #else } #endif } /* ================ 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(); }