Vector3 SteeringBehaviors::Calculate() { this->_steeringForce.zero(); Vector3 force; if(On(obstacle_avoidance)) { double weightObstacleAvoidance = 10; force = ObstacleAvoidance(((Agent*)this->_vehicle)->world->obstacles) * weightObstacleAvoidance; if (!AccumulateForce(_steeringForce, force)) return _steeringForce; } if(On(flee)) { force = Flee(_vehicle->target); if (!AccumulateForce(_steeringForce, force)) return _steeringForce; } if(On(seek)) { force = Seek(_vehicle->target); if (!AccumulateForce(_steeringForce, force)) return _steeringForce; } if(On(arrive)) { force = Arrive(_vehicle->target, _deceleration); if (!AccumulateForce(_steeringForce, force)) return _steeringForce; } if(On(pursue)) { force = Pursue(this->evador1); if (!AccumulateForce(_steeringForce, force)) return _steeringForce; } if(On(evade)) { force = Evade(this->pursuer1); if (!AccumulateForce(_steeringForce, force)) return _steeringForce; } if(On(wander)) { force = Wander(); if(!AccumulateForce(_steeringForce, force)) return _steeringForce; } return _steeringForce; };
// alright. this is the "state machine" :( void CtfAiPlayerComp::Update( GActorHandle i_actor ) { GActor* actor = GActor::FromHandle( i_actor ); // make sure the player is valid every frame. if( !m_Player ) { m_Player = g_World::Get().GetActorByName( "PlayerOne" ); if( !m_Player ) return; } g_AudioManager.UpdateChannelPosition( m_walkOnGroundSlow, actor->m_position ); StaminaBrain( i_actor ); if( m_usingStamina ) m_staminaMeter -= g_Clock::Get().SecondsSinceLastFrame() * 5.0f; else m_staminaMeter += g_Clock::Get().SecondsSinceLastFrame() * 1.66667f; GMath::Clamp( &m_staminaMeter, 0.0f, 10.0f ); switch( m_State ) { case SEEK: Seek( i_actor ); break; case CAPTURE: Capture( i_actor ); break; case PURSUE: Pursue( i_actor ); break; } if( m_PathToTarget.m_pathFound ) { GGroundFollowerComp* gFollower = GetComponent<GGroundFollowerComp>( i_actor ); assert( gFollower ); // you f****d up. GVector3 velocity; if( m_PathToTarget.m_PathNodes.size() <= 1 && m_State == PURSUE ) { GActorHandle playerHandle = g_World::Get().GetActorByName( "PlayerOne" ); GActor* player = GActor::FromHandle( playerHandle ); if( !player ) velocity = GVector3( 0.0f, 0.0f, 0.0f ); else velocity = player->m_position - actor->m_position; } else { velocity = m_TargetNodePos - actor->m_position; } velocity.Normalize(); if( m_usingStamina ) velocity *= 1000.0f; else velocity *= 500.0f; m_LastVelocity = velocity; gFollower->m_velocity = velocity; } }
/* ================ rvMonsterStroggHover::Think ================ */ void rvMonsterStroggHover::Think ( void ) { idAI::Think ( ); if ( !aifl.dead ) { // If thinking we should play an effect on the ground under us if ( !fl.hidden && !fl.isDormant && (thinkFlags & TH_THINK ) && !aifl.dead ) { trace_t tr; idVec3 origin; idMat3 axis; // Project the effect 80 units down from the bottom of our bbox GetJointWorldTransform ( jointDust, gameLocal.time, origin, axis ); // RAVEN BEGIN // ddynerman: multiple clip worlds gameLocal.TracePoint ( this, tr, origin, origin + axis[0] * (GetPhysics()->GetBounds()[0][2]+80.0f), CONTENTS_SOLID, this ); // RAVEN END // Start the dust effect if not already started if ( !effectDust ) { effectDust = gameLocal.PlayEffect ( gameLocal.GetEffect ( spawnArgs, "fx_dust" ), tr.endpos, tr.c.normal.ToMat3(), true ); } // If the effect is playing we should update its attenuation as well as its origin and axis if ( effectDust ) { effectDust->Attenuate ( 1.0f - idMath::ClampFloat ( 0.0f, 1.0f, (tr.endpos - origin).LengthFast ( ) / 127.0f ) ); effectDust->SetOrigin ( tr.endpos ); effectDust->SetAxis ( tr.c.normal.ToMat3() ); } // If the hover effect is playing we can set its end origin to the ground /* if ( effectHover ) { effectHover->SetEndOrigin ( tr.endpos ); } */ } else if ( effectDust ) { effectDust->Stop ( ); effectDust = NULL; } //Try to circle strafe or pursue if ( circleStrafing ) { CircleStrafe(); } else if ( !inPursuit ) { if ( !aifl.action && move.fl.done && !aifl.scripted ) { if ( GetEnemy() ) { if ( DistanceTo( GetEnemy() ) > 2000.0f || (GetEnemy()->GetPhysics()->GetLinearVelocity()*(GetEnemy()->GetPhysics()->GetOrigin()-GetPhysics()->GetOrigin())) > 1000.0f ) {//enemy is far away or moving away from us at a pretty decent speed TryStartPursuit(); } } } } else { Pursue(); } //Dodge if ( !circleStrafing ) { if( combat.shotAtTime && gameLocal.GetTime() - combat.shotAtTime < 1000.0f ) { if ( nextBombFireTime < gameLocal.GetTime() - 3000 ) { if ( gameLocal.random.RandomFloat() > evadeChance ) { //40% chance of ignoring it - makes them dodge rockets less often but bullets more often? combat.shotAtTime = 0; } else if ( evadeDebounce < gameLocal.GetTime() ) { //ramps down from 400 to 100 over 1 second float speed = evadeSpeed - ((((float)(gameLocal.GetTime()-combat.shotAtTime))/1000.0f)*(evadeSpeed-(evadeSpeed*0.25f))); idVec3 evadeVel = viewAxis[1] * ((combat.shotAtAngle >= 0)?-1:1) * speed; evadeVel.z *= 0.5f; move.addVelocity += evadeVel; move.addVelocity.Normalize(); move.addVelocity *= speed; /* if ( move.moveCommand < NUM_NONMOVING_COMMANDS ) { //just need to do it once? combat.shotAtTime = 0; } */ if ( evadeDebounceRate > 1 ) { evadeDebounce = gameLocal.GetTime() + gameLocal.random.RandomInt( evadeDebounceRate ) + (ceil(((float)evadeDebounceRate)/2.0f)); } } } } } //If using melee rush to nav to him, stop when we're close enough to attack if ( combat.tacticalCurrent == AITACTICAL_MELEE && move.moveCommand == MOVE_TO_ENEMY && !move.fl.done && nextBombFireTime < gameLocal.GetTime() - 3000 && enemy.fl.visible && DistanceTo( GetEnemy() ) < 2000.0f ) { StopMove( MOVE_STATUS_DONE ); ForceTacticalUpdate(); } else { //whenever we're not in the middle of something, force an update of our tactical if ( !aifl.action ) { if ( !aasFind ) { if ( move.fl.done ) { if ( !inPursuit && !circleStrafing ) { ForceTacticalUpdate(); } } } } } } //update light // if ( lightOn ) { UpdateLightDef ( ); // } }