Пример #1
0
//--------------------------------
// hhProxDoor::SetDoorState
//--------------------------------
void hhProxDoor::SetDoorState( EProxState doorState ) {
	int i;

	//HUMANHEAD PCF mdl 04/27/06 - Don't allow locked doors to become active
	if ( doorLocked && doorState == PROXSTATE_Active ) {
		return;
	}

	switch( doorState ) {
		case PROXSTATE_Active:
			BecomeActive( TH_TICKER );
			CancelEvents( &EV_PollForExit );
			PostEventMS( &EV_PollForExit, 500 );
			OpenPortal();
			break;

		case PROXSTATE_GoingInactive:
			break;

		case PROXSTATE_Inactive:
			// Guarantee the door is closed
			for( i = 0; i < doorPieces.Num(); i++ ) {
				if (doorPieces[i].IsValid()) {
					doorPieces[ i ]->SetProximity( 0.0 );
				}
			}
			ClosePortal();
			CancelEvents( &EV_PollForExit );
			BecomeInactive( TH_TICKER );
			break;
	}

	proxState = doorState;
}
Пример #2
0
/*
================
idDamagingFx::Restart
================
*/
void idDamagingFx::Restart( void ) { 
	//gameLocal.Printf("idDamagingFx::Restart\n");
	CancelEvents( &EV_Activate ); 
	CancelEvents( &EV_Fx_KillFx );

	ResetShaderParms(); 

	//gameLocal.Printf("Restart\n");
	nextTriggerTime = 0; //make sure the event is accepted
	PostEventMS( &EV_Activate, 0, this );
}
Пример #3
0
/*
================
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();
}
Пример #4
0
/*
================
idSound::Event_Off
================
*/
void idSound::Event_Off( void ) {
	if ( timerOn ) {
		timerOn = false;
		CancelEvents( &EV_Speaker_Timer );
	}
	DoSound( false );
}
Пример #5
0
/*
================
idSound::Event_Trigger

this will toggle the idle idSound on and off
================
*/
void idSound::Event_Trigger( idEntity *activator ) {
	if ( wait > 0.0f ) {
		if ( timerOn ) {
			timerOn = false;
			CancelEvents( &EV_Speaker_Timer );
		} else {
			timerOn = true;
			DoSound( true );
			PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
		}
	} else {
		if ( gameLocal.isMultiplayer ) {
			if ( refSound.referenceSound && ( gameLocal.time < playingUntilTime ) ) {
				DoSound( false );
			} else {
				DoSound( true );
			}
		} else {
			if ( refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) {
				DoSound( false );
			} else {
				DoSound( true );
			}
		}
	}
}
Пример #6
0
/*
================
idTrigger_Timer::Disable
================
*/
void idTrigger_Timer::Disable( void ) {
    // if on, turn it off
    if ( on ) {
        on = false;
        CancelEvents( &EV_Timer );
    }
}
/*
=================
hhProjectileCrawlerGrenade::Event_ApplyExpandWound
=================
*/
void hhProjectileCrawlerGrenade::Event_ApplyExpandWound() {
	trace_t trace;

	if( !modelProxy.IsValid() || !modelProxy->GetCombatModel() ) {
		return;
	}

	idBounds clipBounds( modelProxy->GetRenderEntity()->bounds );
	idVec3 traceEnd = GetOrigin();
	idVec3 traceStart = traceEnd + hhUtils::RandomPointInShell( clipBounds.Expand(1.0f).GetRadius(), clipBounds.Expand(2.0f).GetRadius() );
	idVec3 jointOrigin, localOrigin, localNormal;
	idMat3 jointAxis, axisTranspose;
	jointHandle_t jointHandle = INVALID_JOINT;

	CancelEvents( &EV_ApplyExpandWound );
	PostEventSec( &EV_ApplyExpandWound, spawnArgs.GetFloat("expandWoundDelay") );

	if( !gameLocal.clip.TracePoint(trace, traceStart, traceEnd, modelProxy->GetCombatModel()->GetContents(), NULL) ) {
		return;
	}
	
	if( trace.c.entityNum != entityNumber ) {//Make sure we hit ourselves
		return;
	}
			
	modelProxy->AddDamageEffect( trace, vec3_zero, spawnArgs.GetString("def_expandDamage"), (!fl.networkSync || netSyncPhysics) );
}
Пример #8
0
/// Single forward execution step
void spec::Step()
{
  Event *ev;
  POSE_TimeType lastGVT = localPVT->getGVT();
  int iter = 0;

  if (!parent->cancels.IsEmpty()) CancelUnexecutedEvents();
  if (eq->RBevent) Rollback(); 
  if (!parent->cancels.IsEmpty()) CancelEvents();
  parent->Status();

  // Shorten the leash as we near POSE_endtime
  if ((POSE_endtime > POSE_UnsetTS) && (lastGVT + timeLeash > POSE_endtime))
    timeLeash = POSE_endtime - lastGVT + 1;

  // Prepare to execute an event
  ev = eq->currentPtr;
  while ((ev->timestamp > POSE_UnsetTS) && 
	 (ev->timestamp <= lastGVT + timeLeash)) {
    // do all events within the speculative window
    iter++;
    currentEvent = ev;
    ev->done = 2;
    parent->ResolveFn(ev->fnIdx, ev->msg); // execute it
    ev->done = 1; // complete the event execution
    eq->mem_usage++;
    eq->ShiftEvent(); // shift to next event
    ev = eq->currentPtr; // reset ev
  }
#if !CMK_TRACE_DISABLED
  if(pose_config.stats)
    if (iter > 0) localStats->Loop();
#endif  
}
Пример #9
0
//---------------------------------------------------------------------------
void TJS_INTF_METHOD tTJSNI_Timer::Invalidate()
{
	tTVPTimerThread::Remove(this);
	ZeroPendingCount();
	CancelEvents();
	inherited::Invalidate();  // this sets Owner = NULL
}
Пример #10
0
/*
================
idThread::DelayedStart
================
*/
void idThread::DelayedStart( int delay ) {
	CancelEvents( &EV_Thread_Execute );
	if ( gameLocal.time <= 0 ) {
		delay++;
	}
	PostEventMS( &EV_Thread_Execute, delay );
}
Пример #11
0
/*
================
idThread::Start
================
*/
bool idThread::Start( void ) {
	bool result;

	CancelEvents( &EV_Thread_Execute );
	result = Execute();

	return result;
}
Пример #12
0
//--------------------------------
// hhProxDoor::Event_PollForExit
//--------------------------------
void hhProxDoor::Event_PollForExit() {
	if( PollClosestEntity() == -1.f ) {
		SetDoorState( PROXSTATE_GoingInactive );
		return;
	}
	CancelEvents( &EV_PollForExit );
	PostEventMS( &EV_PollForExit, proxDoorRefreshMS );
}
Пример #13
0
/*
================
idSecurityCamera::Event_Alert
================
*/
void idSecurityCamera::Event_Alert( void ) {
	float	wait;
	SetAlertMode( ACTIVATED );
	StopSound( SND_CHANNEL_ANY, false );
	StartSound( "snd_activate", SND_CHANNEL_BODY, 0, false, NULL );
	ActivateTargets( this );
	CancelEvents( &EV_SecurityCam_ContinueSweep );
	wait = spawnArgs.GetFloat( "wait", "20" );
	PostEventSec( &EV_SecurityCam_ContinueSweep, wait );
}
/*
================
idItem::Event_Respawn
================
*/
void idItem::Event_Respawn( void ) {
	BecomeActive( TH_THINK );
	Show();
	inViewTime = -1000;
	lastCycle = -1;
	GetPhysics()->SetContents( CONTENTS_TRIGGER );
	SetOrigin( orgOrigin );
	StartSound( "snd_respawn", SND_CHANNEL_ITEM, 0, false, NULL );
	CancelEvents( &EV_RespawnItem ); // don't double respawn
}
Пример #15
0
/*
================
idEntityFx::FadeOutFx
================
*/
void idEntityFx::FadeOutFx( void ) {
	if( started < 0 || manualFadeIsOn ){ //if not active or already fading
		return;
	}

	manualFadeIsOn = true;
	SetupFade();

	if( endlessSounds ){
		FadeSound( SND_CHANNEL_ANY, -60, 1 ); //fade out sounds
		//gameLocal.Printf("fading sounds!");
	}

	if( manualRemove ){

		CancelEvents( &EV_Activate ); // make sure it's not going to re-activate itself
		CancelEvents( &EV_Fx_KillFx ); // make sure it's not going to kill or re-activate itself too soon

		PostEventMS( &EV_Fx_KillFx, FadeDuration() );
	}
}
void CFrobLock::Event_Lock_OnLockStatusChange(int locked)
{
	// Cancel any pending events
	CancelEvents(&EV_TDM_FrobLock_TriggerLockTargets);
	CancelEvents(&EV_TDM_FrobLock_TriggerUnlockTargets);
	CancelEvents(&EV_TDM_FrobLock_TriggerTargets);

	if (locked == 0)
	{
		// Unlocked
		UnlockTargets();
		FrobLockStartSound("snd_unlock");

		if (spawnArgs.GetBool("trigger_targets_on_unlock", "1"))
		{
			// Get the delay for triggering the event
			int delay = spawnArgs.GetInt("unlock_trigger_delay", "0");
			PostEventMS(&EV_TDM_FrobLock_TriggerUnlockTargets, delay);
		}
	}
	else
	{
		// We're locked now
		CloseAndLockTargets();
		FrobLockStartSound("snd_lock");

		if (spawnArgs.GetBool("trigger_targets_on_lock", "1"))
		{
			int delay = spawnArgs.GetInt("lock_trigger_delay", "0");
			PostEventMS(&EV_TDM_FrobLock_TriggerLockTargets, delay);
		}
	}

	// Fire ordinary targets in any case
	if (spawnArgs.GetBool("trigger_targets", "0"))
	{
		int delay = spawnArgs.GetInt("trigger_delay", "0");
		PostEventMS(&EV_TDM_FrobLock_TriggerTargets, delay);
	}
}
Пример #17
0
/*
================
idItem::Event_Respawn
================
*/
void idItem::Event_Respawn( void ) {
	if ( gameLocal.isServer ) {
		ServerSendEvent( EVENT_RESPAWN, NULL, false, -1 );
	}
	BecomeActive( TH_THINK );
	Show();
	inViewTime = -1000;
	lastCycle = -1;
	GetPhysics()->SetContents( CONTENTS_TRIGGER );
	SetOrigin( orgOrigin );
	StartSound( "snd_respawn", SND_CHANNEL_ITEM, 0, false, NULL );
	CancelEvents( &EV_RespawnItem ); // don't double respawn
}
Пример #18
0
/*
===============
idSound::UpdateChangableSpawnArgs
===============
*/
void idSound::UpdateChangeableSpawnArgs( const idDict *source )
{

	idEntity::UpdateChangeableSpawnArgs( source );
	
	if( source )
	{
		FreeSoundEmitter( true );
		spawnArgs.Copy( *source );
		idSoundEmitter *saveRef = refSound.referenceSound;
		gameEdit->ParseSpawnArgsToRefSound( &spawnArgs, &refSound );
		refSound.referenceSound = saveRef;
		
		idVec3 origin;
		idMat3 axis;
		
		if( GetPhysicsToSoundTransform( origin, axis ) )
		{
			refSound.origin = GetPhysics()->GetOrigin() + origin * axis;
		}
		else
		{
			refSound.origin = GetPhysics()->GetOrigin();
		}
		
		spawnArgs.GetFloat( "random", "0", random );
		spawnArgs.GetFloat( "wait", "0", wait );
		
		if( ( wait > 0.0f ) && ( random >= wait ) )
		{
			random = wait - 0.001;
			gameLocal.DWarning( "speaker '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString( 0 ) );
		}
		
		if( !refSound.waitfortrigger && ( wait > 0.0f ) )
		{
			timerOn = true;
			DoSound( false );
			CancelEvents( &EV_Speaker_Timer );
			PostEventSec( &EV_Speaker_Timer, wait + gameLocal.random.CRandomFloat() * random );
		}
		else  if( !refSound.waitfortrigger && !( refSound.referenceSound && refSound.referenceSound->CurrentlyPlaying() ) )
		{
			// start it if it isn't already playing, and we aren't waitForTrigger
			DoSound( true );
			timerOn = false;
		}
	}
}
END_CLASS

int hhProjectileStickyCrawlerGrenade::ProcessCollision( const trace_t* collision, const idVec3& velocity ) {
	idEntity* entHit = gameLocal.entities[ collision->c.entityNum ];

	//SAFE_REMOVE( fxFly );
	FreeLightDef();
	CancelEvents( &EV_Fizzle );

	//physicsObj.SetContents( 0 );
	physicsObj.PutToRest();

	surfTypes_t matterType = gameLocal.GetMatterType( entHit, collision->c.material, "hhProjectile::ProcessCollision" );
	return PlayImpactSound( gameLocal.FindEntityDefDict(spawnArgs.GetString("def_damage")), collision->endpos, matterType );
}
Пример #20
0
/*
================
idTrigger_Timer::Event_Use
================
*/
void idTrigger_Timer::Event_Use( idEntity *activator ) {
    // if on, turn it off
    if ( on ) {
        if ( offName.Length() && offName.Icmp( activator->GetName() ) ) {
            return;
        }
        on = false;
        CancelEvents( &EV_Timer );
    } else {
        // turn it on
        if ( onName.Length() && onName.Icmp( activator->GetName() ) ) {
            return;
        }
        on = true;
        PostEventSec( &EV_Timer, delay );
    }
}
Пример #21
0
void opt3::Step()
{
  Event *ev;
  POSE_TimeType lastGVT = localPVT->getGVT();
  int iter = 0;

  if (!parent->cancels.IsEmpty()) CancelUnexecutedEvents();
  if (eq->RBevent) Rollback(); 
  if (!parent->cancels.IsEmpty()) CancelEvents();
  parent->Status();

  // Prepare to execute an event
  ev = eq->currentPtr;
  // Shorten the leash as we near POSE_endtime
  if ((POSE_endtime > POSE_UnsetTS) && (lastGVT + timeLeash > POSE_endtime))
    timeLeash = POSE_endtime - lastGVT + 1;
  
  if ((ev->timestamp > POSE_UnsetTS) && (ev->timestamp <= lastGVT + timeLeash)) {
    POSE_TimeType fix_time = ev->timestamp;
    while (ev->timestamp == fix_time) {
      // do all events at the first available timestamp
      iter++;
      currentEvent = ev;
      ev->done = 2;
      parent->ResolveFn(ev->fnIdx, ev->msg); // execute it
      ev->done = 1; // complete the event execution
      eq->mem_usage++;
      eq->ShiftEvent(); // shift to next event
      ev = eq->currentPtr; // reset ev
    }
#ifndef CMK_OPTIMIZE
    if(pose_config.stats)
      if (iter > 0) localStats->Loop();
#endif  
    if (eq->currentPtr->timestamp > POSE_UnsetTS) {
      // execute next event if there is one
      prioMsg *pm = new prioMsg;
      pm->setPriority(eq->currentPtr->timestamp-POSE_TimeMax);
      POSE_Objects[parent->thisIndex].Step(pm);
    }
  }
}
Пример #22
0
void __fastcall TIBEventAlerter::UnRegisterEvents(void)
{
  if( ProcessingEvents )
     throw EIBError( SInvalidRegistration);
  if( ComponentState.Contains( csDesigning  ) )
    FRegistered = false;
  else
   if( ComponentState.Contains( csLoading  ) != true )
   {
    CancelEvents();
    if( FRegistered )
    {
      IscFree( EventBuffer);
      EventBuffer = NULL;
      IscFree( ResultBuffer);
      ResultBuffer = NULL;
    }
    FRegistered = false;
   }
}
Пример #23
0
/// Single forward execution step
void adapt2::Step()
{
  Event *ev;
  POSE_TimeType lastGVT = localPVT->getGVT();
  int iter=0;

  rbFlag = 0;
  if (!parent->cancels.IsEmpty()) CancelUnexecutedEvents();
  if (eq->RBevent) Rollback(); 
  if (!parent->cancels.IsEmpty()) CancelEvents();
  parent->Status();

  if (rbFlag) {
    timeLeash = eq->currentPtr->timestamp - lastGVT;
    if (timeLeash < pose_config.min_leash) timeLeash = pose_config.min_leash;
  }
  else if (timeLeash < pose_config.max_leash) timeLeash += pose_config.leash_flex;
  // Shorten the leash as we near POSE_endtime
  if ((POSE_endtime > POSE_UnsetTS) && (lastGVT + timeLeash > POSE_endtime))
    timeLeash = POSE_endtime - lastGVT;
  // Prepare to execute an event
  ev = eq->currentPtr;
  while ((ev->timestamp > POSE_UnsetTS) && 
	 (ev->timestamp <= lastGVT + timeLeash)) {
    // do all events at under timeLeash
    iter++;
    currentEvent = ev;
    ev->done = 2;
    parent->ResolveFn(ev->fnIdx, ev->msg); // execute it
    ev->done = 1; // complete the event execution
    eq->mem_usage++;
    eq->ShiftEvent(); // shift to next event
    ev = eq->currentPtr;
  }
#if !CMK_TRACE_DISABLED
  if(pose_config.stats)
    if (iter > 0) localStats->Loop();
#endif
}
Пример #24
0
/*
================
hhSound::Event_StartDelayedSoundShader
================
*/
void hhSound::Event_StartDelayedSoundShader( const char *shaderName, const s_channelType channel, int soundShaderFlags, bool broadcast ) {
	int soundLength = 0;
	float volume = 0.0f;

	const idSoundShader *shader = declManager->FindSound( shaderName );
	assert( shader );
	if( !shader ) {
		return;
	}

	if( !GetSoundEmitter() || !GetSoundEmitter()->CurrentlyPlaying() ) {
		soundLength = idSound::StartSoundShader( shader, channel, soundShaderFlags, broadcast );//Not sure if we should broadcast
		
		positionOffset = DeterminePositionOffset();
		if( DetermineVolume(volume) ) {
			HH_SetSoundVolume( volume, channel );
		}
	}

	CancelEvents( &EV_StartDelayedSoundShader );
	PostEventSec( &EV_StartDelayedSoundShader, MS2SEC(soundLength) + RandomRange(spawnArgs.GetFloat("s_minDelay"), spawnArgs.GetFloat("s_maxDelay")), shaderName, (int)channel, (int)soundShaderFlags, (int)broadcast );
}
Пример #25
0
void hhPoker::UpdateView() {
	// UpdateView() is posted as an event because sometimes we're already nested down in the gui handling code when it is called
	// and it in turn re-enters the gui handling code with HandleNamedEvent()
	CancelEvents(&EV_UpdateView);
	PostEventMS(&EV_UpdateView, 0);
}
/*
=================
hhProjectileCrawlerGrenade::EnterDeadState
=================
*/
void hhProjectileCrawlerGrenade::EnterDeadState() {
	state = StateDead;
	CancelEvents( &EV_ApplyExpandWound );
	StopSound( SND_CHANNEL_VOICE, true );
}
Пример #27
0
/*
================
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 );
	}
}
/*
=================
hhProjectileCrawlerGrenade::CancelActivates
=================
*/
void hhProjectileCrawlerGrenade::CancelActivates() {
	CancelEvents( &EV_DyingState );
	CancelEvents( &EV_DeadState );
}
Пример #29
0
/// Single forward execution step
void adapt5::Step()
{
  Event *ev;
  POSE_TimeType lastGVT = localPVT->getGVT();
  POSE_TimeType maxTimeLeash, offset;
  double critStart;

  rbFlag = 0;
  if (!parent->cancels.IsEmpty()) CancelUnexecutedEvents();
  if (eq->RBevent) Rollback();
  if (!parent->cancels.IsEmpty()) CancelEvents();
  parent->Status();

/*
  if (rbFlag) { // adjust leash according to rollback
    timeLeash = avgRBoffset;
  }
  else if (timeLeash < theMaxLeash) { // adjust according to state
    if (eq->currentPtr->timestamp > POSE_UnsetTS) { // adjust to next event
      if (eq->currentPtr->timestamp - lastGVT > timeLeash)
	timeLeash == eq->currentPtr->timestamp - lastGVT;
      // else leave it alone
    }
    // no next event; leave it alone
  }
  // Put leash back into reasonable bounds
  if (timeLeash > theMaxLeash) {
    timeLeash = theMaxLeash;
  }
  else if (timeLeash < 0) timeLeash = 0;
*/


/*
  int i = timeLeash >> 6;
  if (i > 1) {
    if (rbFlag) {
      timeLeash -= i;
    } else {
      timeLeash += i;
    }
  } else {
    if (rbFlag) {
      timeLeash--;
    } else {
      timeLeash++;
    }
  }

  if (timeLeash <= 0) {
    timeLeash = 10;
  }
*/
/*
  if (rbFlag) {
    timeLeash = timeLeash >> 1;
  } else {
    timeLeash++;
  }
*/

// other possibilities:
// -run for a number of events with a fixed timeleash, then analyze
// and adjust
// -simply use recentAvgEventSparsity * avgEventsPerRB
// -add code that looks at the number of RBs this poser is responsible
// for and don't punish it if it doesn't have a lot

  ev = eq->currentPtr;

  if (parent->basicStats[1] > 0) {
    avgEventsPerRB = (int)(parent->basicStats[0] / parent->basicStats[1]);
    if (avgEventsPerRB < 1) {
      avgEventsPerRB = 1;
    }
  }

  // ======== attempt 1 ========
#if ALGORITHM_TO_USE == 1
  if (rbFlag) {
    recentAvgRBLeashCount++;
    recentTotalRBLeash += timeLeash;
    // initial rollback calculation to quickly set recentAvgRBLeash to a reasonable value
    if (initialAvgRBLeashCalc) {
      recentAvgRBLeash = avgRBoffset;
      recentTotalRBLeash = 0;
      recentAvgRBLeashCount = 0;
      initialAvgRBLeashCalc = false;
    }
    // calculate the recent average timeleash when rollbacks occur
    if (recentAvgRBLeashCount >= AVG_LEASH_CALC_PERIOD) {
      recentAvgRBLeash = recentTotalRBLeash / recentAvgRBLeashCount;
      recentTotalRBLeash = 0;
      recentAvgRBLeashCount = 0;
    }
    if (timeLeash > recentAvgRBLeash) {
      timeLeash = recentAvgRBLeash;
    } else {
      timeLeash = recentAvgRBLeash / 2;
    }
  } else {
    timeLeash += recentAvgEventSparsity;
  }

  if (avgRBsPerGVTIter > MAX_RB_PER_GVT_ITER) {
    maxTimeLeash = recentAvgRBLeash / 2;
  } else {
    maxTimeLeash = (POSE_TimeType)MAX_LEASH_MULTIPLIER * (POSE_TimeType)recentAvgEventSparsity * (POSE_TimeType)avgEventsPerRB;
  }

  if (maxTimeLeash > 50000) {
    maxTimeLeash = 50000;
  }
  if (timeLeash > maxTimeLeash) {
    timeLeash = maxTimeLeash;
  }
  if (timeLeash < 1) {
    timeLeash = 1;
  }
#endif

  // ======== attempt 2 ========
#if ALGORITHM_TO_USE == 2
  timeLeash = recentAvgEventSparsity * avgEventsPerRB;

  if (timeLeash > 50000) {
    timeLeash = 50000;
  }

  if (timeLeash < 1) {
    timeLeash = 1;
  }
#endif

  // ======== attempt 3 ========
#if ALGORITHM_TO_USE == 3
  timeLeash += recentAvgEventSparsity;

  if (avgRBsPerGVTIter > MAX_RB_PER_GVT_ITER) {
    maxTimeLeash = ((POSE_TimeType)MAX_LEASH_MULTIPLIER * (POSE_TimeType)recentAvgEventSparsity * (POSE_TimeType)avgEventsPerRB) / (4 * (POSE_TimeType)avgRBsPerGVTIter);
  } else {
    maxTimeLeash = 1000;
  }  

  if (maxTimeLeash > 50000) {
    maxTimeLeash = 50000;
  }
  if (timeLeash > maxTimeLeash) {
    timeLeash = maxTimeLeash;
  }
  if (timeLeash < 1) {
    timeLeash = 1;
  }
#endif

  // ======== attempt 4 ========
#if ALGORITHM_TO_USE == 4
  if (timeLeash > 10000) {
    timeLeash = 10000;
  }
  if (timeLeash < 1) {
    timeLeash = 1;
  }
#endif


/*
  if (rbFlag) {
    GVT *localGVT = (GVT *)CkLocalBranch(TheGVT);
    int numRollbacks = parent->basicStats[1];
    int numGVTIters = localGVT->gvtIterationCount;
    if (userObj->myHandle == 32) {
      CkPrintf("*** ROLLBACK: numRollbacks=%d numGVTIters=%d\n", numRollbacks, numGVTIters);
    }
    if ((numGVTIters > 0) && (((96 * numRollbacks) / numGVTIters) > 2)) {
      timeLeash = avgRBoffset;
    } else {
      timeLeash++;
    }
  } else {
    timeLeash++;
  }

  if (timeLeash > (avgRBoffset << 1)) {
    timeLeash = avgRBoffset << 1;
  }
*/


  // can also just hard-code the time leash
//  timeLeash = 1000;


  //  if (stepCalls == 0) {
  //    timeLeashTotal = 0LL;
  //  }

  //  if (timeLeash < 1000000) {
  //    stepCalls++;
  //    timeLeashTotal += timeLeash;
  //  }

/*
  if (itersAllowed < 1) {
    itersAllowed = 1;
  }
  else {
    itersAllowed = (int)((double)specEventCount * specTol);
    itersAllowed -= specEventCount - eventCount;
    if (itersAllowed < 1) itersAllowed = 1;
  }
*/


  // Prepare to execute an event
  offset = lastGVT + timeLeash;
  // Shorten the leash as we near POSE_endtime
  if ((POSE_endtime > POSE_UnsetTS) && ((offset > POSE_endtime) ||
					(offset <= POSE_UnsetTS)))
    offset = POSE_endtime;

  while ((ev->timestamp > POSE_UnsetTS) && (ev->timestamp <= offset) ){
#ifdef MEM_COARSE
    // Check to see if we should hold off on forward execution to save on 
    // memory.
    // NOTE: to avoid deadlock, make sure we have executed something
    // beyond current GVT before worrying about memory usage
    if (((ev->timestamp > lastGVT) || (userObj->OVT() > lastGVT))
	&& (eq->mem_usage > objUsage)) { // don't deadlock
      break;
    }
#endif

    iter++;
    currentEvent = ev;
    ev->done = 2;
    localPVT->incSpecEventCount();
    localPVT->incEventCount();
    specEventCount++;
    eventCount++;
#ifndef CMK_OPTIMIZE
    if(pose_config.trace)
      critStart = CmiWallTimer();  // trace timing
#endif
    parent->ResolveFn(ev->fnIdx, ev->msg); // execute it
#ifndef CMK_OPTIMIZE
    if(pose_config.trace)
      traceUserBracketEvent(10, critStart, CmiWallTimer());
#endif
    ev->done = 1; // flag the event as executed
    eq->mem_usage++;
    eq->ShiftEvent(); // shift to next event
    ev = eq->currentPtr;
  }
#ifndef CMK_OPTIMIZE
  if(pose_config.stats)
    if (iter > 0) localStats->Loop();
#endif
}
bool CFrobLock::UseBy(EImpulseState impulseState, const CInventoryItemPtr& item)
{
	if (item == NULL) return false;

	// Pass the call on to the master, if we have one
	if (GetFrobMaster() != NULL) 
	{
		return GetFrobMaster()->UseBy(impulseState, item);
	}

	assert(item->Category() != NULL);

	// Retrieve the entity behind that item and reject NULL entities
	idEntity* itemEntity = item->GetItemEntity();
	if (itemEntity == NULL) return false;

	// Get the name of this inventory category
	const idStr& categoryName = item->Category()->GetName();

	if (categoryName == "#str_02392" && impulseState == EPressed ) 			// Keys
	{
		// Keys can be used on button PRESS event, let's see if the key matches
		if (m_UsedByName.FindIndex(itemEntity->name) != -1)
		{
			// just toggle the lock. 
			ToggleLock();
			return true;
		}
		else
		{
			FrobLockStartSound("snd_wrong_key");
			return false;
		}
	}
	else if (categoryName == "#str_02389" ) 					// Lockpicks
	{
		if (!m_Lock->IsPickable())
		{
			// Lock is not pickable
			DM_LOG(LC_LOCKPICK, LT_DEBUG)LOGSTRING("FrobLock %s is not pickable\r", name.c_str());
			return false;
		}

		// First we check if this item is a lockpick. It has to be of correct type
		idStr str = itemEntity->spawnArgs.GetString("lockpick_type", "");

		if (str.Length() == 1)
		{
			// greebo: Check if the item owner is a player, and if yes, 
			// update the immobilization flags.
			idEntity* itemOwner = item->GetOwner();

			if (itemOwner->IsType(idPlayer::Type))
			{
				idPlayer* playerOwner = static_cast<idPlayer*>(itemOwner);
				playerOwner->SetImmobilization("Lockpicking", EIM_ATTACK);

				// Schedule an event 1/3 sec. from now, to enable weapons again after this time
				CancelEvents(&EV_TDM_FrobLock_ClearPlayerImmobilization);
				PostEventMS(&EV_TDM_FrobLock_ClearPlayerImmobilization, 300, playerOwner);
			}

			// Pass the call to the lockpick routine
			return m_Lock->ProcessLockpickImpulse(impulseState, static_cast<int>(str[0]));
		}
		else
		{
			gameLocal.Warning("Wrong 'lockpick_type' spawnarg for lockpicking on item %s, must be a single character.", itemEntity->name.c_str());
			return false;
		}
	}

	return false;
}