예제 #1
0
/*
================
sdWalker::UpdateModelTransform
================
*/
void sdWalker::UpdateModelTransform( void ) {
	sdTeleporter* teleportEnt = teleportEntity;
	if ( teleportEnt != NULL ) {
		idPlayer* player = gameLocal.GetLocalPlayer();
		if ( player != NULL && player->GetProxyEntity() == this ) {
			idEntity* viewer = teleportEnt->GetViewEntity();
			if ( viewer ) {
				renderEntity.axis	= viewer->GetPhysics()->GetAxis();
				renderEntity.origin	= viewer->GetPhysics()->GetOrigin();
				return;
			}
		}
	}

	renderEntity.axis	= viewAxis;
	renderEntity.origin	= GetPhysics()->GetOrigin();

	idPlayer* player = gameLocal.GetLocalViewPlayer();
	if ( !player || player->GetProxyEntity() != this ) {
		DoPredictionErrorDecay();
	}
}
예제 #2
0
bool idActor::CheckFOV( const noVec3 &pos ) const
{
	if ( fovDot == 1.0f ) {
		return true;
	}

	float	dot;
	noVec3	delta;

	delta = pos - GetEyePosition();

	// get our gravity normal
	const noVec3 &gravityDir = GetPhysics()->GetGravityNormal();

	// infinite vertical vision, so project it onto our orientation plane
	delta -= gravityDir * ( gravityDir * delta );

	delta.Normalize();
	dot = viewAxis[ 0 ] * delta;

	return ( dot >= fovDot );
}
예제 #3
0
/*
================
idAF::SetConstraintPosition

  Only moves constraints that bind the entity to another entity.
================
*/
void idAF::SetConstraintPosition(const char *name, const idVec3 &pos)
{
	idAFConstraint *constraint;

	constraint = GetPhysics()->GetConstraint(name);

	if (!constraint) {
		gameLocal.Warning("can't find a constraint with the name '%s'", name);
		return;
	}

	if (constraint->GetBody2() != NULL) {
		gameLocal.Warning("constraint '%s' does not bind to another entity", name);
		return;
	}

	switch (constraint->GetType()) {
		case CONSTRAINT_BALLANDSOCKETJOINT: {
			idAFConstraint_BallAndSocketJoint *bs = static_cast<idAFConstraint_BallAndSocketJoint *>(constraint);
			bs->Translate(pos - bs->GetAnchor());
			break;
		}
		case CONSTRAINT_UNIVERSALJOINT: {
			idAFConstraint_UniversalJoint *uj = static_cast<idAFConstraint_UniversalJoint *>(constraint);
			uj->Translate(pos - uj->GetAnchor());
			break;
		}
		case CONSTRAINT_HINGE: {
			idAFConstraint_Hinge *hinge = static_cast<idAFConstraint_Hinge *>(constraint);
			hinge->Translate(pos - hinge->GetAnchor());
			break;
		}
		default: {
			gameLocal.Warning("cannot set the constraint position for '%s'", name);
			break;
		}
	}
}
예제 #4
0
bool rvMonsterStroggHover::MarkerPosValid ( void )
{
	//debouncer ftw
	if( markerCheckTime > gameLocal.GetTime() )	{
		return true;
	}

	markerCheckTime = gameLocal.GetTime() + 500 + (gameLocal.random.RandomFloat() * 500);

	trace_t trace;
	gameLocal.TracePoint( this, trace, marker.GetEntity()->GetPhysics()->GetOrigin(), marker.GetEntity()->GetPhysics()->GetOrigin(), GetPhysics()->GetClipMask(), NULL );
	if ( !(trace.c.contents&GetPhysics()->GetClipMask()) )
	{//not in solid
		gameLocal.TracePoint( this, trace, marker.GetEntity()->GetPhysics()->GetOrigin(), GetEnemy()->GetEyePosition(), MASK_SHOT_BOUNDINGBOX, GetEnemy() );
		idActor* enemyAct = NULL;
		rvVehicle* enemyVeh = NULL;
		if ( GetEnemy()->IsType( rvVehicle::GetClassType() ) ) {
			enemyVeh = static_cast<rvVehicle*>(GetEnemy());
		} else if ( GetEnemy()->IsType( idActor::GetClassType() ) ) {
			enemyAct = static_cast<idActor*>(GetEnemy());
		}
		idEntity* hitEnt = gameLocal.entities[trace.c.entityNum];
		idActor* hitAct = NULL;
		if ( hitEnt && hitEnt->IsType( idActor::GetClassType() ) ) {
			hitAct = static_cast<idActor*>(hitEnt);
		}
		if ( trace.fraction >= 1.0f 
			|| (enemyAct && enemyAct->IsInVehicle() && enemyAct->GetVehicleController().GetVehicle() == gameLocal.entities[trace.c.entityNum])
			|| (enemyVeh && hitAct && hitAct->IsInVehicle() && hitAct->GetVehicleController().GetVehicle() == enemyVeh) )
		{//have a clear LOS to enemy
			if ( PointReachableAreaNum( marker.GetEntity()->GetPhysics()->GetOrigin() ) )
			{//valid AAS there...
				return true;
			}
		}
	}
	return false;
}
/*
================
rvMonsterConvoyGround::OnDeath
================
*/
void rvMonsterConvoyGround::OnDeath	( void ) {
	idVec3 fxOrg;
	idVec3 up;
	idMat3 fxAxis;

	//center it
	fxOrg = GetPhysics()->GetCenterMass();

	//point it up
	up.Set( 0, 0, 1 );
	fxAxis = up.ToMat3();

	//if we can play it at the joint, do that
	jointHandle_t axisJoint = animator.GetJointHandle ( "axis" );
	if ( axisJoint != INVALID_JOINT ) {
		idMat3 junk;
		animator.GetJointLocalTransform( axisJoint, gameLocal.GetTime(), fxOrg, junk );
		fxOrg = renderEntity.origin + (fxOrg*renderEntity.axis);
	}

	gameLocal.PlayEffect ( spawnArgs, "fx_death", fxOrg, fxAxis );
	idAI::OnDeath ( );
}
예제 #6
0
int CVehicleMovementAerodynamic::AddBox(Vec3 *_pvPos,Vec3 *_pvSize,float _fMass,int _iID/*=-1*/)
{
  IPhysicalEntity* pPhysics = GetPhysics();
	IGeomManager *pGeomManager = gEnv->pPhysicalWorld->GetGeomManager();

	primitives::box Box;
	Box.Basis.SetIdentity();
	Box.center.Set(0.0f,0.0f,0.0f);
	Box.size = (*_pvSize) / 2.0f;
	Box.bOriented = 0;
	IGeometry *pGeometry = pGeomManager->CreatePrimitive(primitives::box::type,&Box);
	phys_geometry *pPhysGeometry = pGeomManager->RegisterGeometry(pGeometry);
	pGeometry->Release();

	pe_geomparams partpos;
	partpos.pos = *_pvPos;
	partpos.mass = _fMass;
	int id = pPhysics->AddGeometry(pPhysGeometry,&partpos,_iID);

	pGeomManager->UnregisterGeometry(pPhysGeometry);

  return id;
}
예제 #7
0
/*
================
idTrigger_EntityName::Spawn
================
*/
void idTrigger_EntityName::Spawn( void ) {
	spawnArgs.GetFloat( "wait", "0.5", wait );
	spawnArgs.GetFloat( "random", "0", random );
	spawnArgs.GetFloat( "delay", "0", delay );
	spawnArgs.GetFloat( "random_delay", "0", random_delay );
	if( random && ( random >= wait ) && ( wait >= 0 ) ) {
		random = wait - 1;
		gameLocal.Warning( "idTrigger_EntityName '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString( 0 ) );
	}
	if( random_delay && ( random_delay >= delay ) && ( delay >= 0 ) ) {
		random_delay = delay - 1;
		gameLocal.Warning( "idTrigger_EntityName '%s' at (%s) has random_delay >= delay", name.c_str(), GetPhysics()->GetOrigin().ToString( 0 ) );
	}
	spawnArgs.GetBool( "triggerFirst", "0", triggerFirst );
	entityName = spawnArgs.GetString( "entityname" );
	if( !entityName.Length() ) {
		gameLocal.Error( "idTrigger_EntityName '%s' at (%s) doesn't have 'entityname' key specified", name.c_str(), GetPhysics()->GetOrigin().ToString( 0 ) );
	}
	nextTriggerTime = 0;
	if( !spawnArgs.GetBool( "noTouch" ) ) {
		GetPhysics()->SetContents( CONTENTS_TRIGGER );
	}
}
예제 #8
0
void hhProxDoor::ReadFromSnapshot( const idBitMsgDelta &msg ) {
	ReadBindFromSnapshot(msg);
	GetPhysics()->ReadFromSnapshot(msg);

	int num = msg.ReadBits(8);
	doorPieces.SetNum(num);
	for (int i = 0; i < num; i++) {
		int spawnId = msg.ReadBits(32);
		if (!spawnId) {
			doorPieces[i] = NULL;
		}
		else {
			doorPieces[i].SetSpawnId(spawnId);
		}
	}

	EProxState newProxState = (EProxState)msg.ReadBits(8);
	if (proxState != newProxState) {
		SetDoorState(newProxState);
	}

	lastAmount = msg.ReadFloat();

	bool closed = !!msg.ReadBits(1);
	if (aas_area_closed != closed) {
		SetAASAreaState(closed);
	}

	/*
	EPDoorSound newSndState = (EPDoorSound)msg.ReadBits(8);
	if (newSndState != doorSndState) {
		UpdateSoundState(newSndState);
	}
	*/

	hasNetData = true;
}
예제 #9
0
/*
=================
idMoveable::Collide
=================
*/
bool idMoveable::Collide( const trace_t &collision, const idVec3 &velocity ) {
	float v, f;
	idVec3 dir;
	idEntity *ent;

	//gameLocal.Printf("collision\n");

	v = -( velocity * collision.c.normal );
	if ( v > BOUNCE_SOUND_MIN_VELOCITY && gameLocal.time > nextSoundTime ) {
		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 ( StartSound( "snd_bounce", SND_CHANNEL_BODY, 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 );
		}
		nextSoundTime = gameLocal.time + 500;
	}
	

	if ( canDamage && damage.Length() && gameLocal.time > nextDamageTime ) {
		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();
			ent->Damage( this, GetPhysics()->GetClipModel()->GetOwner(), dir, damage, f, INVALID_JOINT );
			nextDamageTime = gameLocal.time + 1000;
		}
	}

	if ( fxCollide.Length() && gameLocal.time > nextCollideFxTime ) {
		idEntityFx::StartFx( fxCollide, &collision.c.point, NULL, this, false );
		nextCollideFxTime = gameLocal.time + 3500;
	}

	return false;
}
예제 #10
0
/*
=================
idEntityFx::ReadFromSnapshot
=================
*/
void idEntityFx::ReadFromSnapshot( const idBitMsgDelta &msg ) {
	int fx_index, start_time, max_lapse;

	GetPhysics()->ReadFromSnapshot( msg );
	ReadBindFromSnapshot( msg );
	fx_index = gameLocal.ClientRemapDecl( DECL_FX, msg.ReadLong() );
	start_time = msg.ReadLong();

	if ( fx_index != -1 && start_time > 0 && !fxEffect && started < 0 ) {
		spawnArgs.GetInt( "effect_lapse", "1000", max_lapse );
		if ( gameLocal.time - start_time > max_lapse ) {
			// too late, skip the effect completely
			started = 0;
			return;
		}
		const idDeclFX *fx = static_cast<const idDeclFX *>( declManager->DeclByIndex( DECL_FX, fx_index ) );
		if ( !fx ) {
			gameLocal.Error( "FX at index %d not found", fx_index );
		}
		fxEffect = fx;
		Setup( fx->GetName() );
		Start( start_time );
	}
}
예제 #11
0
/*
================
idTrigger_Hurt::Event_Touch
================
*/
void idTrigger_Hurt::Event_Touch( idEntity *other, trace_t *trace )
{
	const char *damage;
	
	if( on && other && gameLocal.time >= nextTime )
	{
#ifdef _D3XP
		bool playerOnly = spawnArgs.GetBool( "playerOnly" );
		if( playerOnly )
		{
			if( !other->IsType( idPlayer::Type ) )
			{
				return;
			}
		}
#endif
		damage = spawnArgs.GetString( "def_damage", "damage_painTrigger" );
		
#ifdef _D3XP
		idVec3 dir = vec3_origin;
		if( spawnArgs.GetBool( "kick_from_center", "0" ) )
		{
			dir = other->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
			dir.Normalize();
		}
		other->Damage( NULL, NULL, dir, damage, 1.0f, INVALID_JOINT );
#else
		other->Damage( NULL, NULL, vec3_origin, damage, 1.0f, INVALID_JOINT );
#endif
		
		ActivateTargets( other );
		CallScript();
		
		nextTime = gameLocal.time + SEC2MS( delay );
	}
}
예제 #12
0
파일: Effect.cpp 프로젝트: ET-NiK/amxxgroup
/*
================
rvEffect::Event_LookAtTarget

Reorients the effect entity towards its target and sets the end origin as well
================
*/
void rvEffect::Event_LookAtTarget ( void ) {
    const idKeyValue	*kv;
    idVec3				dir;

    if ( !effect || !clientEffect ) {
        return;
    }

    kv = spawnArgs.MatchPrefix( "target", NULL );
    while( kv ) {
        idEntity *ent = gameLocal.FindEntity( kv->GetValue() );
        if( ent ) {
            if( !idStr::Icmp( ent->GetEntityDefName(), "target_null" ) ) {
                dir = ent->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
                dir.Normalize();

                clientEffect->SetEndOrigin ( ent->GetPhysics()->GetOrigin() );
                clientEffect->SetAxis ( dir.ToMat3( ) );
                return;
            }
        }
        kv = spawnArgs.MatchPrefix( "target", kv );
    }
}
예제 #13
0
/*
================
idTrigger_Multi::CheckFacing
================
*/
bool idTrigger_Multi::CheckFacing( idEntity *activator ) {
    if ( spawnArgs.GetBool( "facing" ) ) {
        if ( !activator->IsType( idPlayer::GetClassType() ) ) {
            return true;
        }
        idPlayer *player = static_cast< idPlayer* >( activator );

        // Unfortunately, the angle key rotates the trigger entity also.  So I've added
        //	an angleFacing key which is used instead when present, otherwise the code defaults
        //	to the behaviour present prior to this change
        idVec3 tFacing = GetPhysics()->GetAxis()[0];
        if ( spawnArgs.FindKey( "angleFacing" )) {
            idAngles angs(0,spawnArgs.GetFloat( "angleFacing", "0" ),0);
            tFacing = angs.ToForward();
        }
        float dot = player->viewAngles.ToForward() * tFacing;

        float angle = RAD2DEG( idMath::ACos( dot ) );
        if ( angle  > spawnArgs.GetFloat( "angleLimit", "30" ) ) {
            return false;
        }
    }
    return true;
}
예제 #14
0
// RAVEN BEGIN
// kfuller:
void idTrigger_Multi::Event_EarthQuake(float requiresLOS)
{
    // does this entity even care about earthquakes?
    float	quakeChance = 0;

    if (!spawnArgs.GetFloat("quakeChance", "0", quakeChance))
    {
        return;
    }
    if (rvRandom::flrand(0, 1.0f) > quakeChance)
    {
        // failed its activation roll
        return;
    }
    if (requiresLOS)
    {
        // if the player doesn't have line of sight to this fx, don't do anything
        trace_t		trace;
        idPlayer	*player = gameLocal.GetLocalPlayer();
        idVec3		viewOrigin;
        idMat3		viewAxis;

        player->GetViewPos(viewOrigin, viewAxis);
// RAVEN BEGIN
// ddynerman: multiple clip worlds
        gameLocal.TracePoint( this, trace, viewOrigin, GetPhysics()->GetOrigin(), MASK_OPAQUE, player );
// RAVEN END
        if (trace.fraction < 1.0f)
        {
            // something blocked LOS
            return;
        }
    }
    // activate this effect now
    TriggerAction(gameLocal.entities[ENTITYNUM_WORLD]);
}
예제 #15
0
파일: Effect.cpp 프로젝트: ET-NiK/amxxgroup
/*
================
rvEffect::Spawn
================
*/
void rvEffect::Spawn( void ) {
    const char* fx;
    if ( !spawnArgs.GetString ( "fx", "", &fx ) || !*fx ) {
        if ( !( gameLocal.editors & EDITOR_FX ) ) {
            gameLocal.Warning ( "no effect file specified on effect entity '%s'", name.c_str() );
            PostEventMS ( &EV_Remove, 0 );
            return;
        }
    } else {
        effect = ( const idDecl * )declManager->FindEffect( spawnArgs.GetString ( "fx" ) );
        if( effect->IsImplicit() ) {
            common->Warning( "Unknown effect \'%s\' on entity \'%s\'", spawnArgs.GetString ( "fx" ), GetName() );
        }
    }

    spawnArgs.GetVector ( "endOrigin", "0 0 0", endOrigin );

    spawnArgs.GetBool ( "loop", "0", loop );

    // If look at target is set the effect will continually update itself to look at its target
    spawnArgs.GetBool( "lookAtTarget", "0", lookAtTarget );

    renderEntity.shaderParms[SHADERPARM_ALPHA] = spawnArgs.GetFloat ( "_alpha", "1" );
    renderEntity.shaderParms[SHADERPARM_BRIGHTNESS] = spawnArgs.GetFloat ( "_brightness", "1" );

    if( spawnArgs.GetBool( "start_on", loop ? "1" : "0" ) ) {
        ProcessEvent( &EV_Activate, this );
    }
#if 0
    // If anyone ever gets around to a flood fill from the origin rather than the over generous PushVolumeIntoTree bounds,
    // this warning will become useful. Until then, it's a bogus warning.
    if( gameRenderWorld->PointInArea( GetPhysics()->GetOrigin() ) < 0 ) {
        common->Warning( "Effect \'%s\' out of world", name.c_str() );
    }
#endif
}
예제 #16
0
/*
================
idSecurityCamera::DrawFov
================
*/
void idSecurityCamera::DrawFov()
{
	int i;
	float radius, a, s, c, halfRadius;
	idVec3 right, up;
	idVec4 color( 1, 0, 0, 1 ), color2( 0, 0, 1, 1 );
	idVec3 lastPoint, point, lastHalfPoint, halfPoint, center;
	
	idVec3 dir = GetAxis();
	dir.NormalVectors( right, up );
	
	radius = tan( scanFov * idMath::PI / 360.0f );
	halfRadius = radius * 0.5f;
	lastPoint = dir + up * radius;
	lastPoint.Normalize();
	lastPoint = GetPhysics()->GetOrigin() + lastPoint * scanDist;
	lastHalfPoint = dir + up * halfRadius;
	lastHalfPoint.Normalize();
	lastHalfPoint = GetPhysics()->GetOrigin() + lastHalfPoint * scanDist;
	center = GetPhysics()->GetOrigin() + dir * scanDist;
	for( i = 1; i < 12; i++ )
	{
		a = idMath::TWO_PI * i / 12.0f;
		idMath::SinCos( a, s, c );
		point = dir + right * s * radius + up * c * radius;
		point.Normalize();
		point = GetPhysics()->GetOrigin() + point * scanDist;
		gameRenderWorld->DebugLine( color, lastPoint, point );
		gameRenderWorld->DebugLine( color, GetPhysics()->GetOrigin(), point );
		lastPoint = point;
		
		halfPoint = dir + right * s * halfRadius + up * c * halfRadius;
		halfPoint.Normalize();
		halfPoint = GetPhysics()->GetOrigin() + halfPoint * scanDist;
		gameRenderWorld->DebugLine( color2, point, halfPoint );
		gameRenderWorld->DebugLine( color2, lastHalfPoint, halfPoint );
		lastHalfPoint = halfPoint;
		
		gameRenderWorld->DebugLine( color2, halfPoint, center );
	}
}
예제 #17
0
파일: Light.cpp 프로젝트: alepulver/dhewm3
/*
================
idLight::GetPhysicsToSoundTransform
================
*/
bool idLight::GetPhysicsToSoundTransform( idVec3 &origin, idMat3 &axis ) {
	origin = localLightOrigin + renderLight.lightCenter;
	axis = localLightAxis * GetPhysics()->GetAxis();
	return true;
}
예제 #18
0
파일: Light.cpp 프로젝트: alepulver/dhewm3
/*
================
idLight::Spawn
================
*/
void idLight::Spawn( void ) {
	bool start_off;
	bool needBroken;
	const char *demonic_shader;

	// do the parsing the same way dmap and the editor do
	gameEdit->ParseSpawnArgsToRenderLight( &spawnArgs, &renderLight );

	// we need the origin and axis relative to the physics origin/axis
	localLightOrigin = ( renderLight.origin - GetPhysics()->GetOrigin() ) * GetPhysics()->GetAxis().Transpose();
	localLightAxis = renderLight.axis * GetPhysics()->GetAxis().Transpose();

	// set the base color from the shader parms
	baseColor.Set( renderLight.shaderParms[ SHADERPARM_RED ], renderLight.shaderParms[ SHADERPARM_GREEN ], renderLight.shaderParms[ SHADERPARM_BLUE ] );

	// set the number of light levels
	spawnArgs.GetInt( "levels", "1", levels );
	currentLevel = levels;
	if ( levels <= 0 ) {
		gameLocal.Error( "Invalid light level set on entity #%d(%s)", entityNumber, name.c_str() );
	}

	// make sure the demonic shader is cached
	if ( spawnArgs.GetString( "mat_demonic", NULL, &demonic_shader ) ) {
		declManager->FindType( DECL_MATERIAL, demonic_shader );
	}

	// game specific functionality, not mirrored in
	// editor or dmap light parsing

	// also put the light texture on the model, so light flares
	// can get the current intensity of the light
	renderEntity.referenceShader = renderLight.shader;

	lightDefHandle = -1;		// no static version yet

	// see if an optimized shadow volume exists
	// the renderer will ignore this value after a light has been moved,
	// but there may still be a chance to get it wrong if the game moves
	// a light before the first present, and doesn't clear the prelight
	renderLight.prelightModel = 0;
	if ( name[ 0 ] ) {
		// this will return 0 if not found
		renderLight.prelightModel = renderModelManager->CheckModel( va( "_prelight_%s", name.c_str() ) );
	}

	spawnArgs.GetBool( "start_off", "0", start_off );
	if ( start_off ) {
		Off();
	}

	health = spawnArgs.GetInt( "health", "0" );
	spawnArgs.GetString( "broken", "", brokenModel );
	spawnArgs.GetBool( "break", "0", breakOnTrigger );
	spawnArgs.GetInt( "count", "1", count );

	triggercount = 0;

	fadeFrom.Set( 1, 1, 1, 1 );
	fadeTo.Set( 1, 1, 1, 1 );
	fadeStart			= 0;
	fadeEnd				= 0;

	// if we have a health make light breakable
	if ( health ) {
		idStr model = spawnArgs.GetString( "model" );		// get the visual model
		if ( !model.Length() ) {
			gameLocal.Error( "Breakable light without a model set on entity #%d(%s)", entityNumber, name.c_str() );
		}

		fl.takedamage	= true;

		// see if we need to create a broken model name
		needBroken = true;
		if ( model.Length() && !brokenModel.Length() ) {
			int	pos;

			needBroken = false;

			pos = model.Find( "." );
			if ( pos < 0 ) {
				pos = model.Length();
			}
			if ( pos > 0 ) {
				model.Left( pos, brokenModel );
			}
			brokenModel += "_broken";
			if ( pos > 0 ) {
				brokenModel += &model[ pos ];
			}
		}

		// make sure the model gets cached
		if ( !renderModelManager->CheckModel( brokenModel ) ) {
			if ( needBroken ) {
				gameLocal.Error( "Model '%s' not found for entity %d(%s)", brokenModel.c_str(), entityNumber, name.c_str() );
			} else {
				brokenModel = "";
			}
		}

		GetPhysics()->SetContents( spawnArgs.GetBool( "nonsolid" ) ? 0 : CONTENTS_SOLID );

		// make sure the collision model gets cached
		idClipModel::CheckModel( brokenModel );
	}

	PostEventMS( &EV_PostSpawn, 0 );

// sikk---> Soft Shadows PostProcess
	// only put lights that cast shadows into the list
	if ( spawnArgs.GetInt( "noshadows" ) == 0  ) {
		gameLocal.currentLights.Append( entityNumber );
	}
// <---sikk

	UpdateVisuals();
}
예제 #19
0
/*
================
idTrigger::Enable
================
*/
void idTrigger::Enable( void ) {
    GetPhysics()->SetContents( CONTENTS_TRIGGER );
    GetPhysics()->EnableClip();
}
예제 #20
0
/*
================
idTrigger_Touch::TouchEntities
================
*/
void idTrigger_Touch::TouchEntities( void ) {
    int numClipModels, i;
    idBounds bounds;
    idClipModel *cm, *clipModelList[ MAX_GENTITIES ];

// RAVEN BEGIN
// abahr: now scriptFunction list
    if ( clipModel == NULL || !scriptFunctions.Num() ) {
// RAVEN END
        return;
    }

    bounds.FromTransformedBounds( clipModel->GetBounds(), GetBindMaster()!=NULL?GetPhysics()->GetOrigin():clipModel->GetOrigin(), GetBindMaster()!=NULL?GetPhysics()->GetAxis():clipModel->GetAxis() );
// RAVEN BEGIN
// MCG: filterTeam
    if ( filterTeam != -1 )
    {
        idActor* actor;
        // Iterate through the filter team
        for( actor = aiManager.GetAllyTeam ( (aiTeam_t)filterTeam ); actor; actor = actor->teamNode.Next() ) {
            // Skip hidden actors and actors that can't be targeted
            if( actor->fl.notarget || actor->fl.isDormant || ( actor->IsHidden ( ) && !actor->IsInVehicle() ) ) {
                continue;
            }
            if ( !bounds.IntersectsBounds ( actor->GetPhysics()->GetAbsBounds ( ) ) ) {
                continue;
            }
            cm = actor->GetPhysics()->GetClipModel();
            if ( !cm || !cm->IsTraceModel() ) {
                continue;
            }
            if ( !gameLocal.ContentsModel( this, cm->GetOrigin(), cm, cm->GetAxis(), -1,
                                           clipModel->GetCollisionModel(), GetBindMaster()!=NULL?GetPhysics()->GetOrigin():clipModel->GetOrigin(), GetBindMaster()!=NULL?GetPhysics()->GetAxis():clipModel->GetAxis() ) ) {
                continue;
            }
            ActivateTargets( (idEntity*)actor );

            CallScript( (idEntity*)actor );
        }
        return;
    }
// ddynerman: multiple clip worlds
    numClipModels = gameLocal.ClipModelsTouchingBounds( this, bounds, -1, clipModelList, MAX_GENTITIES );
// RAVEN END

    for ( i = 0; i < numClipModels; i++ ) {
        cm = clipModelList[ i ];

        if ( !cm->IsTraceModel() ) {
            continue;
        }

        idEntity *entity = cm->GetEntity();

        if ( !entity ) {
            continue;
        }

// RAVEN BEGIN
// ddynerman: multiple clip worlds
        if ( !gameLocal.ContentsModel( this, cm->GetOrigin(), cm, cm->GetAxis(), -1,
                                       clipModel->GetCollisionModel(), clipModel->GetOrigin(), clipModel->GetAxis() ) ) {
// RAVEN END
            continue;
        }

        ActivateTargets( entity );

// RAVEN BEGIN
// abahr: changed to be compatible with new script function utility
        CallScript( entity );
// RAVEN END
    }
}
예제 #21
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 );
	}
}
예제 #22
0
/*
================
idTrigger_Timer::Spawn

Repeatedly fires its targets.
Can be turned on or off by using.
================
*/
void idTrigger_Timer::Spawn( void ) {
    spawnArgs.GetFloat( "random", "1", random );
    spawnArgs.GetFloat( "wait", "1", wait );
    spawnArgs.GetBool( "start_on", "0", on );
    spawnArgs.GetFloat( "delay", "0", delay );
    onName = spawnArgs.GetString( "onName" );
    offName = spawnArgs.GetString( "offName" );

    if ( random >= wait && wait >= 0 ) {
        random = wait - 0.001;
        gameLocal.Warning( "idTrigger_Timer '%s' at (%s) has random >= wait", name.c_str(), GetPhysics()->GetOrigin().ToString(0) );
    }

    if ( on ) {
        PostEventSec( &EV_Timer, delay );
    }
}
//////////////////////////////////////////////////////////////////////////
// NOTE: This function must be thread-safe. Before adding stuff contact MarcoC.
void CVehicleMovementHelicopter::ProcessMovement(const float deltaTime)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );

	IPhysicalEntity* pPhysics = GetPhysics();
	assert(pPhysics);
	
	if (m_arcade.m_handling.maxSpeedForward>0.f) // Use the new handling code
	{
		CryAutoCriticalSection lk(m_lock);

		if (!m_isEnginePowered)
			return;

		CVehicleMovementBase::ProcessMovement(deltaTime);
		SVehiclePhysicsStatus* physStatus = &m_physStatus[k_physicsThread];

		if(m_bApplyNoiseAsVelocity)
		{
			physStatus->v -= m_pNoise->m_posDifference;
			physStatus->w -= m_pNoise->m_angDifference;

			m_pNoise->Update(deltaTime);
		}

	
		///////////////////////////////////////////////////////////////
		// Pass on the movement request to the active physics handler
		// NB: m_physStatus is update by this call
		SVehiclePhysicsHelicopterProcessParams params;
		params.pPhysics = pPhysics;
		params.pPhysStatus = physStatus;
		params.pInputAction = &m_inputAction;
		params.dt = deltaTime;
		params.haveDriver = (m_actorId!=0)||m_remotePilot;
		params.isAI = m_movementAction.isAI;
		params.aiRequiredVel = m_CurrentVel;
		
		m_arcade.ProcessMovement(params);
		
		// Network error adjustment
		m_netPosAdjust *= max(0.f, 1.f-deltaTime*k_netErrorPosScale);
		physStatus->v += m_netPosAdjust * k_netErrorPosScale;

		if(m_bApplyNoiseAsVelocity)
		{
			physStatus->v += m_pNoise->m_posDifference;
			physStatus->w += m_pNoise->m_angDifference;
		}

		//===============================================
		// Commit the velocity back to the physics engine
		//===============================================
		// if (fabsf(m_movementAction.rotateYaw)>0.05f || vel.GetLengthSquared()>0.001f || m_chassis.vel.GetLengthSquared()>0.001f || angVel.GetLengthSquared()>0.001f || angVel.GetLengthSquared()>0.001f) 
		{
			pe_action_set_velocity setVelocity;
			setVelocity.v = physStatus->v;
			setVelocity.w = physStatus->w;
			pPhysics->Action(&setVelocity, 1);
		}
		///////////////////////////////////////////////////////////////
	}
	else
	{
		if (m_isEnginePowered && pPhysics)
		{
			m_movementAction.isAI = true;
	
			pe_status_pos psp;
			pe_status_dynamics psd;
			if (!pPhysics->GetStatus(&psp) || !pPhysics->GetStatus(&psd))
				return;
			UpdatePhysicsStatus(&m_physStatus[k_physicsThread], &psp, &psd);

			ProcessAI(deltaTime);
		}
	}
}
void CVehicleMovementHelicopter::ProcessAI(const float deltaTime)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );

	CryAutoCriticalSection lk(m_lock);
	SVehiclePhysicsStatus* physStatus = &m_physStatus[k_physicsThread];
		
	if (m_arcade.m_handling.maxSpeedForward>0.f) // Use the new handling code
	{
		//ResetActions();
		m_movementAction.Clear();
		m_movementAction.isAI = true;

		SVehiclePhysicsHelicopterProcessAIParams params;
		params.pPhysStatus = physStatus;
		params.pInputAction = &m_inputAction;
		params.pAiRequest = &m_aiRequest;
		params.dt = deltaTime;
		params.aiRequiredVel = m_CurrentVel;
		params.aiCurrentSpeed = m_CurrentSpeed;
		params.aiYawResponseScalar = m_yawResponseScalar;
		m_yawResponseScalar = 1.f;
	
		// Use helper class to process the AI input
		// It will return a requested velocity, and change the input
		m_arcade.ProcessAI(params);

		// Get the output velocity
		m_CurrentVel = params.aiRequiredVel;
		m_CurrentSpeed = params.aiCurrentSpeed;
		return;
	}
	////////////////////// OLD DEPRECATED CODE :( //////////////////////////////////

	m_movementAction.Clear();
	ResetActions();

	// Our current state
	const Vec3 worldPos =  physStatus->pos;
	const Matrix33 worldMat( physStatus->q);
	const Matrix33 localMat( physStatus->q.GetInverted());
	const Ang3 worldAngles = Ang3::GetAnglesXYZ(worldMat);
	const Ang3 localAngles = Ang3::GetAnglesXYZ(localMat);

	const Vec3 currentVel = physStatus->v;
	const Vec3 currentVel2D(currentVel.x, currentVel.y, 0.0f);
	m_CurrentSpeed = m_CurrentVel.len(); //currentVel.len();
  float currentSpeed2d = currentVel2D.len();

	// +ve direction mean rotation anti-clocwise about the z axis - 0 means along y
	float currentDir = worldAngles.z;

	// to avoid singularity
	const Vec3 vWorldDir = worldMat.GetRow(1);
	const Vec3 vSideWays = worldMat.GetRow(0);
	const Vec3 vWorldDir2D =  Vec3( vWorldDir.x,  vWorldDir.y, 0.0f ).GetNormalizedSafe();

	// Our inputs
	float desiredSpeed = m_aiRequest.HasDesiredSpeed() ? m_aiRequest.GetDesiredSpeed() : 0.0f;
	Limit(desiredSpeed, -m_maxSpeed, m_maxSpeed);

	const Vec3 desiredMoveDir = m_aiRequest.HasMoveTarget() ? (m_aiRequest.GetMoveTarget() - worldPos).GetNormalizedSafe() : vWorldDir;
	Vec3 desiredMoveDir2D = Vec3(desiredMoveDir.x, desiredMoveDir.y, 0.0f);
	desiredMoveDir2D = desiredMoveDir2D.GetNormalizedSafe(desiredMoveDir2D);

	const Vec3 desiredVel = desiredMoveDir * desiredSpeed; 
	const Vec3 desiredVel2D(desiredVel.x, desiredVel.y, 0.0f);

  Vec3 desiredLookDir(desiredMoveDir);

  if (m_aiRequest.HasDesiredBodyDirectionAtTarget())
  {
	    desiredLookDir = m_aiRequest.GetDesiredBodyDirectionAtTarget().GetNormalizedSafe(desiredMoveDir);
  }
  else if (m_aiRequest.HasLookTarget())
  {
    desiredLookDir = (m_aiRequest.GetLookTarget() - worldPos).GetNormalizedSafe(desiredMoveDir);  
  }


	//const Vec3 desiredLookDir = m_aiRequest.HasLookTarget() ? (m_aiRequest.GetLookTarget() - worldPos).GetNormalizedSafe() : desiredMoveDir;
	const Vec3 desiredLookDir2D = Vec3(desiredLookDir.x, desiredLookDir.y, 0.0f).GetNormalizedSafe(vWorldDir2D);

  Vec3 prediction = m_aiRequest.HasBodyTarget() ? m_aiRequest.GetBodyTarget() : ZERO;

  prediction = (prediction.IsEquivalent(ZERO)) ? desiredMoveDir2D : prediction - worldPos;
  prediction.z = 0.0f;

  float speedLimit = prediction.GetLength2D();

	if(speedLimit > 0.0f)
	{
		prediction *= 1.0f / speedLimit;
	}

  Vec3 tempDir = currentVel2D.IsEquivalent(ZERO) ? localMat.GetRow(1) : currentVel2D;
  tempDir.z = 0.0f;
  tempDir.NormalizeFast();

	float dotProd = tempDir.dot(prediction);
	Limit(dotProd, FLT_EPSILON, 1.0f);

	float accel = m_enginePowerMax * min(2.0f,  1.0f / dotProd); // * dotProd;

	if (!m_aiRequest.HasDesiredBodyDirectionAtTarget())
	{
		dotProd *= dotProd;
		dotProd *= dotProd;
		float tempf = min(max(speedLimit * speedLimit, 2.0f), m_maxSpeed * dotProd);
		Limit(desiredSpeed, -tempf, tempf);
	}
	else if (dotProd < 0.0125f)
	{
		Limit(desiredSpeed, -m_maxSpeed * 0.25f, m_maxSpeed * 0.25f);
	}
  
  float posNeg = (float)__fsel(desiredSpeed - m_CurrentSpeed, 1.0f, -5.0f);

  if (desiredVel2D.GetLengthSquared() > FLT_EPSILON)
  {
	  m_CurrentSpeed = m_CurrentSpeed + posNeg * accel * deltaTime;
  }
  else
  {
    m_CurrentSpeed = m_CurrentSpeed + posNeg * accel * deltaTime;
  }

	if (posNeg > 0.0f && m_CurrentSpeed > desiredSpeed)
	{
		m_CurrentSpeed = desiredSpeed;
	}
	else if (posNeg < 0.0f && m_CurrentSpeed < desiredSpeed)
	{
		m_CurrentSpeed = desiredSpeed;
	}

	
	// ---------------------------- Rotation ----------------------------
	
	float desiredDir = (desiredLookDir2D.GetLengthSquared() > 0.0f) ? atan2f(-desiredLookDir2D.x, desiredLookDir2D.y) : atan2f(-vWorldDir2D.x, vWorldDir2D.y);
	while (currentDir < desiredDir - gf_PI)
		currentDir += 2.0f * gf_PI;
	while (currentDir > desiredDir + gf_PI)
		currentDir -= 2.0f * gf_PI;

	// ---------------------------- Yaw ----------------------------

	Ang3 dirDiff(0.0f, 0.0f, desiredDir - currentDir);
	dirDiff.RangePI();
	float absDiff   = fabsf(dirDiff.z);

	float rotSpeed		= (float)__fsel(dirDiff.z, m_yawPerRoll, -m_yawPerRoll);
	m_actionYaw		= m_actionYaw + deltaTime * (rotSpeed - m_actionYaw);

	float temp = fabsf(m_actionYaw);

	float multiplier = ((absDiff / (temp + 0.001f)) + 1.0f) * 0.5f;
	
	m_actionYaw	*= (float)__fsel(absDiff - temp, 1.0f, multiplier);

	// ---------------------------- Yaw ------------------------------

	m_CurrentVel = desiredMoveDir * m_CurrentSpeed;

  // ---------------------------- Pitch ----------------------------

  if (m_CurrentVel.GetLengthSquared2D() > 0.1f)
  {
    CalculatePitch(worldAngles, desiredMoveDir, currentSpeed2d, desiredSpeed, deltaTime);
  }
  else
  {
    Quat rot;
    rot.SetRotationVDir(desiredLookDir, 0.0f);
    float desiredXRot = Ang3::GetAnglesXYZ(rot).x + m_steeringDamage.x;

    m_actionPitch = worldAngles.x + (desiredXRot - worldAngles.x) * deltaTime/* * 10.0f*/;
    Limit(m_actionPitch, -m_maxPitchAngle * 2.0f, m_maxPitchAngle * 2.0f);
  }


	// ---------------------------- Roll ----------------------------
	float rollSpeed = GetRollSpeed();

	rollSpeed *= deltaTime;
	rollSpeed		= (float)__fsel(absDiff - rollSpeed, rollSpeed, absDiff);
	float roll		=(float) __fsel(dirDiff.z, -rollSpeed, rollSpeed);

	float speedPerUnit	   = 1.5f;
	float desiredRollSpeed = absDiff * speedPerUnit * (float)__fsel(dirDiff.z, 1.0f, -1.0f);
  
	desiredRollSpeed = -m_actionYaw * 2.5f;
  desiredRollSpeed += m_steeringDamage.y;

	m_actionRoll = m_actionRoll + deltaTime * (desiredRollSpeed - m_actionRoll);
	Limit(m_actionRoll, -m_maxRollAngle + m_steeringDamage.y, m_maxRollAngle - m_steeringDamage.y);
	m_actionRoll *= m_rollDamping;
	// ---------------------------- Roll ----------------------------


	// ---------------------------- Convert and apply ----------------------------
	Ang3 angles(m_actionPitch, m_actionRoll, worldAngles.z + deltaTime * m_actionYaw);
	
	pe_params_pos paramPos;
	paramPos.q.SetRotationXYZ(angles);
	paramPos.q.Normalize();

	IPhysicalEntity * pPhysicalEntity = GetPhysics();
	pPhysicalEntity->SetParams(&paramPos, 1);

	pe_action_set_velocity vel;
	vel.v = m_CurrentVel + m_netPosAdjust;
	pPhysicalEntity->Action(&vel, 1);

	// ---------------------------- Convert and apply ----------------------------

  m_rpmScale = max(0.2f, cry_fabsf(m_CurrentSpeed / m_maxSpeed));
}
//------------------------------------------------------------------------
void CVehicleMovementHelicopter::OnEvent(EVehicleMovementEvent event, const SVehicleMovementEventParams& params)
{
	switch (event)
	{
	case eVME_Repair:
		{
			if(params.fValue < 0.25)
			{
				m_damageActual = 0.0f;
				m_damage = 0.0f;
			}
		}
		break;

  case eVME_Collision:
    {
      if (0)
      {
        m_isEnginePowered = false;

        pe_simulation_params simParams;
        simParams.dampingFreefall = 0.01f;
        simParams.gravity = Vec3(0.0f, 0.0f, -9.8f);
        GetPhysics()->SetParams(&simParams);
      }
    }
    break;

	case eVME_GroundCollision:
		{
			const float stopOver = 1.0f;
		}
		break;

	case eVME_Damage:
		{
      if (!m_pVehicle->IsIndestructable())
      {
			  const float stopOver = 1.0f;

			  m_damage = params.fValue;

        if (m_damage > 0.95f)
        {
          m_isEngineDisabled	= true;
          m_isEnginePowered	= false;

          StopExhaust();
          StopSounds();

					IPhysicalEntity * pPhysicalEntity = GetPhysics();

          pe_action_impulse impulse;
          impulse.angImpulse = Vec3(0.1f, 100.f, 0.0f);
          pPhysicalEntity->Action(&impulse);

          pe_simulation_params simParams;
          simParams.dampingFreefall = 0.01f;
          simParams.gravity = Vec3(0.0f, 0.0f, -9.8f);
          pPhysicalEntity->SetParams(&simParams);

          SVehicleEventParams eventParams;
          eventParams.entityId = 0;
          m_pVehicle->BroadcastVehicleEvent(eVE_Destroyed, eventParams);

          if (m_pVehicle)
          {
            if (IEntity *entity = m_pVehicle->GetEntity())
            {
              if (IAIObject *aiobject = entity->GetAI())
              {
                aiobject->Event(AIEVENT_DISABLE, NULL);
              }
            }
          }
        }
      }
		}
		break;

	case eVME_WarmUpEngine:
		m_enginePower = m_enginePowerMax;
		break;

	//case eVME_Turbulence:
	//	m_turbulence = max(m_turbulence, params.fValue);
	//	break;

	default:
		CVehicleMovementBase::OnEvent(event, params);
		break; 
	}
}
예제 #26
0
파일: Effect.cpp 프로젝트: ET-NiK/amxxgroup
/*
=================
rvEffect::WriteToSnapshot
=================
*/
void rvEffect::WriteToSnapshot( idBitMsgDelta &msg ) const {
    GetPhysics()->WriteToSnapshot( msg );
    WriteBindToSnapshot( msg );
    idGameLocal::WriteDecl( msg, effect );
    msg.WriteBits( loop, 1 );
}
예제 #27
0
/*
================
sdDeliveryVehicle::Jotun_DoMove
================
*/
void sdDeliveryVehicle::Jotun_DoMove( const idVec3& aheadPointIdeal, const idVec3& aheadPointDirIdeal, const idVec3& endPoint, bool levelOut, bool leaving, float pathSpeed ) {
	float frameTime = MS2SEC( gameLocal.msec );

	idVec3 aheadPoint = aheadPointIdeal;
	idVec3 aheadPointDir = aheadPointDirIdeal;

	const idVec3& origin = GetPhysics()->GetOrigin();
	const idVec3& velocity = GetPhysics()->GetLinearVelocity();
	const idMat3& axis = GetPhysics()->GetAxis();
	const idAngles angles = axis.ToAngles();
	const idVec3& angVel = GetPhysics()->GetAngularVelocity();
	
	const idVec3& currentFwd = axis[ 0 ];
	const idVec3& currentRight = axis[ 1 ];
	const idVec3& currentUp = axis[ 2 ];
	
	float rollVel = angVel * currentFwd;
	float pitchVel = angVel * currentRight;
	float yawVel = angVel * currentUp;

	float aheadToEnd = ( aheadPoint - endPoint ).Length();
	if ( aheadToEnd < 4096.0f && !leaving ) {
		aheadPoint.z += 4096.0f;
	}

	float currentHeight = JOTUN_FLY_HEIGHT_RESCUE;
	
	// check out ahead and see that we're not going to collide with something
	if ( velocity != vec3_origin ) {
		idVec3 futureSpot = velocity * 1.0f;
		futureSpot.z -= 4096.0f;
		futureSpot.Normalize();;
		futureSpot *= 3500.0f;
		futureSpot += origin;

		trace_t trace;
		gameLocal.clip.TraceBounds( CLIP_DEBUG_PARMS trace, origin, futureSpot, GetPhysics()->GetBounds(), axis, MASK_SOLID | MASK_OPAQUE, this );
		futureSpot = trace.endpos;
		float futureFrac = trace.fraction;
				
		float futureDist = futureFrac * 3500.0f;
		if ( futureDist < 3500.0f ) {
			int surfaceFlags = trace.c.material != NULL ? trace.c.material->GetSurfaceFlags() : 0;
			if ( !( surfaceFlags & SURF_NOIMPACT ) ) {
				float moveUp = ( 3500.0f - futureDist ) / 3500.0f;
				moveUp = idMath::Sqrt( moveUp );

				if ( aheadToEnd < 32.0f || leaving ) {
					aheadPoint = origin + currentFwd * 3500.0f;
					aheadPoint.z += moveUp * 4096.0f;
					aheadPointDir.z += moveUp * 10.0f;
				}
				
				aheadPoint.z += moveUp * 4096.0f;
				aheadPointDir.z += moveUp * 2.0f;
				aheadPointDir.Normalize();
			} else {
				futureDist = 3500.0f;
			}
		}
		
		currentHeight = futureDist;
		
//		gameRenderWorld->DebugCircle( colorRed, origin, idVec3( 0.0f, 0.0f, 1.0f ), 16, 8 );
//		gameRenderWorld->DebugArrow( colorRed, origin, futureSpot, 256 );
//		gameRenderWorld->DebugCircle( colorRed, futureSpot, idVec3( 0.0f, 0.0f, 1.0f ), 16, 8 );
	}
//	gameRenderWorld->DebugCircle( colorGreen, aheadPoint, idVec3( 0.0f, 0.0f, 1.0f ), 256, 16 );
	
	
	// generate a cubic spline between the two points
	idVec3 point = vec3_origin;

	{
		idVec3 x0 = origin;
		idVec3 x1 = aheadPoint;
		idVec3 dx0 = velocity * 3.0f;					// maintaining our current velocity is more important
		idVec3 dx1 = aheadPointDir * pathSpeed * 1.0f;	// than matching the destination vector
		
		// calculate coefficients
		idVec3 D = x0;
		idVec3 C = dx0;
		idVec3 B = 3*x1 - dx1 - 2*C - 3*D;
		idVec3 A = x1 - B - C - D;
		
		float distanceLeft = ( endPoint - origin ).Length();
		float lookaheadFactor = ( distanceLeft / 4096.0f ) * 0.5f;
		lookaheadFactor = idMath::ClampFloat( 0.2f, 0.5f, lookaheadFactor );
		
		point = ( A * lookaheadFactor + B )*lookaheadFactor*lookaheadFactor + C*lookaheadFactor + D;
	}

	idVec3 idealNewForward = point - origin;
	idealNewForward.Normalize();
	
	idVec3 delta = point - origin;
	idVec3 endDelta = endPoint - origin;
	endDelta.Normalize();
	endDelta.z = 0.0f;
	
	idAngles endAngles = endDelta.ToAngles().Normalize180();
	
	// treat the local delta as if the thing is on a flat plane - simplifies everything
	idVec3 localDelta = axis.TransposeMultiply( delta );

	idVec3 newVelocity = vec3_origin;
	idVec3 newAngVel = angVel;
	
	//
	// A flying vehicle needs to roll and then pull up to turn (to look cool)
	//
	
	//
	// Roll!
	float targetRoll = endAngles.roll;
	if ( !levelOut ) {
		targetRoll = -( localDelta.y / 1024.0f ) * 45.0f;
		targetRoll = idMath::ClampFloat( -30.0f, 30.0f, targetRoll );
	}

	float rollAmount = idMath::AngleNormalize180( targetRoll - angles.roll );
	
	// so we know how much we need to roll to get to our new angle
	// how fast do we want to go to get there?
	float targetRollVel = ( rollAmount / 15 ) * 30;
	targetRollVel = idMath::ClampFloat( -30.0f, 30.0f, targetRollVel );

	float maxRollAccel = 15.0f;
	if ( levelOut ) {
		maxRollAccel = 35.0f;
	}
	
	// now figure out what roll acceleration that needs, clamp it
	float rollAccel = idMath::AngleNormalize180( targetRollVel - rollVel ) / frameTime;
	rollAccel = idMath::ClampFloat( -maxRollAccel, maxRollAccel, rollAccel );
	
	// dampen out the rolling inputs, like its a guy on a stick controlling it
	rollAccel = rollAccel * 0.2f + lastRollAccel * 0.8f;
	if ( idMath::Fabs( rollAccel ) < idMath::FLT_EPSILON ) {
		rollAccel = 0.f;
	}
	newAngVel += rollAccel * frameTime * currentFwd;
	 
	lastRollAccel = rollAccel;
	
	//
	// Pull up!
	float targetPitch = -( localDelta.z / 256.0f ) * 15.0f;
	if ( !leaving ) {
		targetPitch = idMath::ClampFloat( -25.0f, 15.0f, targetPitch );
	} else {
		targetPitch = idMath::ClampFloat( -25.0f, 15.0f, targetPitch );
	}
		
	if ( leaving && targetPitch > -15.0f ) {
		targetPitch = -15.0f;
	}

	float pitchAmount = idMath::AngleNormalize180( targetPitch - angles.pitch );
	
	// so we know how much we need to pitch to get to our new angle
	// how fast do we want to go to get there?
	float targetPitchVel = ( pitchAmount / 8 ) * 15;
	if ( !leaving ) {
		targetPitchVel = idMath::ClampFloat( -25.0f, 15.0f, targetPitchVel );
	} else {
		targetPitchVel = idMath::ClampFloat( -35.0f, 15.0f, targetPitchVel );	
	}
	
	// now figure out what roll acceleration that needs, clamp it
	float pitchAccel = idMath::AngleNormalize180( targetPitchVel - pitchVel ) / frameTime;
	if ( !leaving ) {
		pitchAccel = idMath::ClampFloat( -12.0f, 12.0f, pitchAccel );
	} else { 
		pitchAccel = idMath::ClampFloat( -36.0f, 12.0f, pitchAccel );
	}
	
	newAngVel += pitchAccel * frameTime * currentRight;
		
	//
	// Yaw
	float targetYaw = angles.yaw;
	if ( !levelOut ) {
		targetRoll = -( localDelta.y / 1024.0f ) * 5.0f;
		targetRoll = idMath::ClampFloat( -8.0f, 8.0f, targetRoll );
	} else {
		targetYaw = endAngles.yaw;
	}
	
	float yawAmount = idMath::AngleNormalize180( targetYaw - angles.yaw );

	// so we know how much we need to yaw to get to our new angle
	// how fast do we want to go to get there?
	float targetYawVel = ( yawAmount / 8 ) * 15;
	targetYawVel = idMath::ClampFloat( -15.0f, 15.0f, targetYawVel );
	
	// now figure out what yaw acceleration that needs, clamp it
	float yawAccel = idMath::AngleNormalize180( targetYawVel - yawVel ) / frameTime;
	yawAccel = idMath::ClampFloat( -10.0f, 10.0f, yawAccel );
	
	newAngVel += yawAccel * frameTime * currentUp;		

	newVelocity = currentFwd * pathSpeed;
	if ( levelOut ) {
		// HACK: Drift back towards the target, to try to ensure it gets there ok
		newVelocity = newVelocity * 0.7f + endDelta * pathSpeed * 0.3f;
	}
	
	
	// HACK: ensure it never gets below the minimum height
	if ( currentHeight < JOTUN_FLY_HEIGHT_MIN ) {
		idVec3 newOrigin = origin;
		newOrigin.z = newOrigin.z - currentHeight + JOTUN_FLY_HEIGHT_MIN;
		GetPhysics()->SetOrigin( newOrigin );			
	} else if ( currentHeight < JOTUN_FLY_HEIGHT_RESCUE ) {
		float oldNewVelLength = newVelocity.Length();
	
		float scale = ( JOTUN_FLY_HEIGHT_RESCUE - currentHeight ) / ( JOTUN_FLY_HEIGHT_RESCUE - JOTUN_FLY_HEIGHT_MIN );
		scale = idMath::Sqrt( scale );
		float rescueVelocity = scale * ( JOTUN_FLY_HEIGHT_RESCUE - JOTUN_FLY_HEIGHT_MIN ) / 0.5f;
		float rescueAcceleration = ( rescueVelocity - velocity.z ) / frameTime;
		rescueAcceleration = idMath::ClampFloat( 0.0f, 1800.0f, rescueAcceleration );
		rescueVelocity = velocity.z + rescueAcceleration * frameTime;
		if ( rescueVelocity > newVelocity.z ) {
			newVelocity.z = rescueVelocity;
		}
		
		newVelocity.Normalize();
		newVelocity *= oldNewVelLength;
	}
	
	//
	// set the new stuff
	//
	GetPhysics()->SetLinearVelocity( newVelocity );
	GetPhysics()->SetAngularVelocity( newAngVel );
}
예제 #28
0
/*
================
idTrigger::Disable
================
*/
void idTrigger::Disable( void ) {
    // we may be relinked if we're bound to another object, so clear the contents as well
    GetPhysics()->SetContents( 0 );
    GetPhysics()->DisableClip();
}
예제 #29
0
/*
================
sdDeliveryVehicle::Magog_DoMove
================
*/
void sdDeliveryVehicle::Magog_DoMove( const idVec3& aheadPointIdeal, const idVec3& aheadPointDir, const idVec3& endPoint, float itemRotation, float maxYawScale, bool orientToEnd, bool clampRoll, bool slowNearEnd, float pathSpeed ) {
	float frameTime = MS2SEC( gameLocal.msec );

	idVec3 aheadPoint = aheadPointIdeal;
	const idVec3& origin = GetPhysics()->GetOrigin();
	const idVec3& velocity = GetPhysics()->GetLinearVelocity();
	const idMat3& axis = GetPhysics()->GetAxis();
	const idAngles angles = axis.ToAngles();
	const idVec3& angVel = GetPhysics()->GetAngularVelocity();
	
	const idVec3& currentFwd = axis[ 0 ];
	const idVec3& currentRight = axis[ 1 ];
	const idVec3& currentUp = axis[ 2 ];
	
	float rollVel = angVel * currentFwd;
	float pitchVel = angVel * currentRight;
	float yawVel = angVel * currentUp;

	// find the current height of the vehicle
	idVec3 futureContribution = velocity * 1.0f;
	futureContribution.z = 0.0f;
	float futureContributionLength = futureContribution.Length();
	if ( futureContributionLength > 2000.0f ) {
		futureContribution = futureContribution * ( 2000.0f / futureContributionLength );
	}

	idVec3 futureSpot = origin + futureContribution;
	futureSpot.z -= HOVER_DOWNCAST_LENGTH;

	trace_t trace;
	gameLocal.clip.TraceBounds( CLIP_DEBUG_PARMS trace, origin, futureSpot, GetPhysics()->GetBounds(), axis, MASK_SOLID | MASK_OPAQUE, this );
	futureSpot = trace.endpos;

	// shift the ahead point based on the trace
	float currentHeight = origin.z - futureSpot.z;
	if ( currentHeight < HOVER_DOWNCAST_LENGTH ) { 
		aheadPoint.z = origin.z - currentHeight + HOVER_HEIGHT_AIM;
	} else {
		aheadPoint.z = origin.z - HOVER_DOWNCAST_LENGTH + HOVER_HEIGHT_AIM;
	}

//	sys.debugCircle( g_colorRed, origin, '0 0 1', 16, 8, 0 );
//	sys.debugArrow( g_colorRed, origin, futureSpot, 256, 0 );
//	sys.debugCircle( g_colorRed, futureSpot, '0 0 1', 16, 8, 0 );
//	sys.debugCircle( '0 1 0', aheadPoint, '0 0 1', 256.0f, 16, 0 );


	idVec3 point;
	float lookaheadFactor;

	{
		// generate a cubic spline between the two points
		idVec3 x0 = origin;
		idVec3 x1 = aheadPoint;
		idVec3 dx0 = velocity * 3.0f;					// maintaining our current velocity is more important
		idVec3 dx1 = aheadPointDir * pathSpeed * 1.0f;	// than matching the destination vector
		
		// calculate coefficients
		idVec3 D = x0;
		idVec3 C = dx0;
		idVec3 B = 3*x1 - dx1 - 2*C - 3*D;
		idVec3 A = x1 - B - C - D;
		
		float distanceLeft = ( endPoint - origin ).Length();
		lookaheadFactor = ( distanceLeft / 6096.0f ) * 0.5f;
		lookaheadFactor = idMath::ClampFloat( 0.2f, 0.5f, lookaheadFactor );
		if ( !slowNearEnd ) {
			lookaheadFactor = 0.5f;
		}
		
		point = ( A * lookaheadFactor + B )*lookaheadFactor*lookaheadFactor + C*lookaheadFactor + D;
	}


	//
	// Follower logic
	//
	idVec3 delta = point - origin;
	idVec3 aheadDelta = aheadPoint - origin;

	idVec3 newVelocity = vec3_origin;

	//
	// Z axis
	//

	// figure out what Z velocity is needed to get where we want to go within a frame
	float Zvel = aheadDelta.z / frameTime;
	Zvel = idMath::ClampFloat( -maxZVel, maxZVel, Zvel );
	
	// figure out what Z acceleration is neccessary
	float ZAccel = ( Zvel - velocity.z ) / frameTime;
	ZAccel = idMath::ClampFloat( -maxZAccel, maxZAccel, ZAccel );
	
	// chop the Z acceleration when its nearing the end - helps to avoid settling issues
	if ( lookaheadFactor < 0.5f ) {
		ZAccel *= idMath::Sqrt( lookaheadFactor * 2.0f );
	}
	
	Zvel = velocity.z + ZAccel * frameTime;
	
	// rapidly prevent acceleration downwards when its below the target
	if ( aheadDelta.z > 0.0f && Zvel < 0.0f ) {
		Zvel *= 0.9f;
	}
			
	//
	// X & Y
	//
	
	// ignore Z
	delta.z = 0.0f;
	aheadDelta.z = 0.0f;
	idVec3 flatVelocity = velocity;
	flatVelocity.z = 0.0f;

	float distance = delta.Length();
	idVec3 direction;
	if ( distance > idMath::FLT_EPSILON ) {
		direction = delta / distance;
	} else {
		direction = vec3_origin;
	}
	
	// figure out how fast it needs to go to get there in time
	float vel = distance / 0.5f;
	vel = idMath::ClampFloat( -pathSpeed, pathSpeed, vel );
	
	idVec3 vecVel = vel * direction;
	
	// figure out what acceleration is neccessary
	idVec3 velDelta = vecVel - flatVelocity;
	idVec3 velDeltaDir = velDelta;
	float velDeltaLength = velDeltaDir.Normalize();

	float accel = velDeltaLength / frameTime;
	accel = idMath::ClampFloat( -600.0f, 600.0f, accel );
	
	idVec3 vecAccel = accel * frameTime * velDeltaDir;
	newVelocity = flatVelocity + vecAccel;
	
	
	newVelocity.z = Zvel;
	
	//
	// Angles
	//
	idVec3 velDir = velocity;
	float velLength = velDir.Normalize();
	
	// calculate what acceleration we are undergoing
	idVec3 velAccel = ( newVelocity - velocity ) / frameTime;
	
	// calculate a component due to air resistance
	float speed = InchesToMetres( velLength );
	float rho = 1.2f;
	float sideArea = InchesToMetres( 650.0f ) * InchesToMetres( 650.0f );
	float Cd = 0.6f;
	float dragForceMagnitude = MetresToInches( 0.5 *  Cd * sideArea * rho * speed * speed );
	// assume mass is 10,000 -> I know this works nicely
	idVec3 dragAccel = ( dragForceMagnitude / 10000.f ) * velDir;
	
	idVec3 desiredAccel = velAccel + dragAccel;
	desiredAccel *= 0.4f;
	desiredAccel.z += MetresToInches( 9.8f );
	
	// ok, so we desire to be looking at the target
	idVec3 forwards = endPoint - origin;
	forwards.z = 0.0f;
	forwards.Normalize();
			
	if ( orientToEnd ) {
		idAngles targetAngles = ang_zero;
		targetAngles.yaw = idMath::AngleNormalize180( itemRotation );
		forwards = targetAngles.ToForward();
	}
	
	// figure out the axes corresponding to this orientation
	idVec3 up = desiredAccel;
	up.Normalize();
	idVec3 right = up.Cross( forwards );
	right.Normalize();
	forwards = right.Cross( up );
	forwards.Normalize();
	
	// convert that to an angles
	idAngles desiredAngles = ( idMat3( forwards, right, up ) ).ToAngles();
	if ( clampRoll ) {
		desiredAngles.roll = idMath::ClampFloat( -9.0f, 9.0f, desiredAngles.roll );
	} else {
		desiredAngles.roll = idMath::ClampFloat( -30.0f, 30.0f, desiredAngles.roll );
	}
	desiredAngles.pitch = idMath::ClampFloat( -30.0f, 30.0f, desiredAngles.pitch );

	// find the diff between that and what we currently have
	idAngles diffAngles = ( desiredAngles - angles ).Normalize180();
	diffAngles = diffAngles * 0.1f;
	diffAngles = diffAngles / frameTime;
	diffAngles *= 0.1f;

	
	// translate the old angular velocity back to an angle diff style value
	idAngles oldDiffAngles;
	oldDiffAngles.pitch = angVel * currentRight;
	oldDiffAngles.yaw = angVel * currentUp;
	oldDiffAngles.roll = angVel * currentFwd;
	
	// blend the old and the new to soften the quick changes
	diffAngles = oldDiffAngles * 0.9f + diffAngles * 0.1f;
	
	// figure out how much we're trying to change by in a single frame
	idAngles angleAccel = diffAngles - oldDiffAngles;
	float maxAngleAccel = 45.0f * frameTime;
	float maxYawAccel = maxAngleAccel * maxYawScale;
	
	angleAccel.pitch = idMath::ClampFloat( -maxAngleAccel, maxAngleAccel, angleAccel.pitch );
	angleAccel.yaw = idMath::ClampFloat( -maxYawAccel, maxYawAccel, angleAccel.yaw );
	angleAccel.roll = idMath::ClampFloat( -maxAngleAccel, maxAngleAccel, angleAccel.roll );

	diffAngles = oldDiffAngles + angleAccel;	
	idVec3 newAngVel = diffAngles.pitch * currentRight + 
						diffAngles.yaw * currentUp + 
						diffAngles.roll * currentFwd;

	// HACK: ensure it never gets below the minimum height
	if ( currentHeight < HOVER_HEIGHT_MIN ) {
		idVec3 newOrigin = origin;
		newOrigin.z = origin.z - currentHeight + HOVER_HEIGHT_MIN;
		GetPhysics()->SetOrigin( newOrigin );			
	} else if ( currentHeight < HOVER_HEIGHT_RESCUE ) {
		float oldNewVelLength = newVelocity.Length();
	
		float scale = ( HOVER_HEIGHT_RESCUE - currentHeight ) / ( HOVER_HEIGHT_RESCUE - HOVER_HEIGHT_MIN );
		scale = idMath::Sqrt( scale );
		float rescueVelocity = scale * ( HOVER_HEIGHT_RESCUE - HOVER_HEIGHT_MIN ) / 0.5f;
		float rescueAcceleration = ( rescueVelocity - velocity.z ) / frameTime;
		rescueAcceleration = idMath::ClampFloat( 0.0f, 1800.0f, rescueAcceleration );
		rescueVelocity = velocity.z + rescueAcceleration * frameTime;
		if ( rescueVelocity > newVelocity.z ) {
			newVelocity.z = rescueVelocity;
		}
		
		newVelocity.Normalize();
		newVelocity *= oldNewVelLength;
	}
			
	GetPhysics()->SetLinearVelocity( newVelocity );
	GetPhysics()->SetAxis( angles.ToMat3() );
	GetPhysics()->SetAngularVelocity( newAngVel );
}
예제 #30
0
/*
================
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", "" );
	canDamage = spawnArgs.GetBool( "damageWhenActive" ) ? false : true;
	minDamageVelocity = spawnArgs.GetFloat( "minDamageVelocity", "100" );
	maxDamageVelocity = spawnArgs.GetFloat( "maxDamageVelocity", "200" );
	nextDamageTime = 0;
	nextSoundTime = 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", "10", 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" );

	PostEventMS( &EV_SetOwnerFromSpawnArgs, 0 );
}