AIMotorMoveResult_t CAI_Motor::MoveGroundExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ) { // -------------------------------------------- // turn in the direction of movement // -------------------------------------------- MoveFacing( move ); // -------------------------------------------- float flNewSpeed = GetIdealSpeed(); // -------------------------------------------- // calculate actual travel distance // -------------------------------------------- // assuming linear acceleration, how far will I travel? float flTotal = 0.5 * (GetCurSpeed() + flNewSpeed) * GetMoveInterval(); // can I move farther in this interval than I'm supposed to? if ( flTotal > move.maxDist ) { if ( !(move.flags & AILMG_CONSUME_INTERVAL) ) { // only use a portion of the time interval SetMoveInterval( GetMoveInterval() * (1 - move.maxDist / flTotal) ); } else SetMoveInterval( 0 ); flTotal = move.maxDist; } else { // use all the time SetMoveInterval( 0 ); } SetMoveVel( move.dir * flNewSpeed ); // -------------------------------------------- // walk the distance // -------------------------------------------- AIMotorMoveResult_t result = AIM_SUCCESS; if ( flTotal > 0.0 ) { Vector vecFrom = GetLocalOrigin(); Vector vecTo = vecFrom + move.dir * flTotal; result = MoveGroundStep( vecTo, move.pMoveTarget, -1, true, pTraceResult ); if ( result == AIM_FAILED ) MoveStop(); } else if ( !OnMoveStalled( move ) ) { result = AIM_FAILED; } return result; }
AIMotorMoveResult_t CAI_Motor::MoveFlyExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ) { // turn in the direction of movement MoveFacing( move ); // calc accel/decel rates float flNewSpeed = GetIdealSpeed(); SetMoveVel( move.dir * flNewSpeed ); float flTotal = 0.5 * (GetCurSpeed() + flNewSpeed) * GetMoveInterval(); float distance = move.maxDist; // can I move farther in this interval than I'm supposed to? if (flTotal > distance) { // only use a portion of the time interval SetMoveInterval( GetMoveInterval() * (1 - distance / flTotal) ); flTotal = distance; } else { // use all the time SetMoveInterval( 0 ); } Vector vecStart, vecEnd; vecStart = GetLocalOrigin(); VectorMA( vecStart, flTotal, move.dir, vecEnd ); AIMoveTrace_t moveTrace; GetMoveProbe()->MoveLimit( NAV_FLY, vecStart, vecEnd, MASK_NPCSOLID, NULL, &moveTrace ); if ( pTraceResult ) *pTraceResult = moveTrace; // Check for total blockage if (fabs(moveTrace.flDistObstructed - flTotal) <= 1e-1) { // But if we bumped into our target, then we succeeded! if ( move.pMoveTarget && (moveTrace.pObstruction == move.pMoveTarget) ) return AIM_PARTIAL_HIT_TARGET; return AIM_FAILED; } // The true argument here causes it to touch all triggers // in the volume swept from the previous position to the current position UTIL_SetOrigin(GetOuter(), moveTrace.vEndPosition, true); return (IsMoveBlocked(moveTrace.fStatus)) ? AIM_PARTIAL_HIT_WORLD : AIM_SUCCESS; }
AIMotorMoveResult_t CAI_Motor::MoveGroundExecuteWalk( const AILocalMoveGoal_t &move, float speed, float dist, AIMoveTrace_t *pTraceResult ) { bool bReachingLocalGoal = ( dist > move.maxDist ); // can I move farther in this interval than I'm supposed to? if ( bReachingLocalGoal ) { if ( !(move.flags & AILMG_CONSUME_INTERVAL) ) { // only use a portion of the time interval SetMoveInterval( GetMoveInterval() * (1 - move.maxDist / dist) ); } else SetMoveInterval( 0 ); dist = move.maxDist; } else { // use all the time SetMoveInterval( 0 ); } SetMoveVel( move.dir * speed ); // -------------------------------------------- // walk the distance // -------------------------------------------- AIMotorMoveResult_t result = AIM_SUCCESS; if ( dist > 0.0 ) { Vector vecFrom = GetLocalOrigin(); Vector vecTo = vecFrom + move.dir * dist; if ( move.navType == NAV_CRAWL ) { char *pchHackBoolToInt = (char*)(&bReachingLocalGoal); *pchHackBoolToInt = 2; } result = MoveGroundStep( vecTo, move.pMoveTarget, -1, true, bReachingLocalGoal, pTraceResult ); if ( result == AIM_FAILED ) MoveStop(); } else if ( !OnMoveStalled( move ) ) { result = AIM_FAILED; } return result; }
AIMotorMoveResult_t CAI_BlendedMotor::MoveFlyExecute( const AILocalMoveGoal_t &move, AIMoveTrace_t *pTraceResult ) { if ( move.curExpectedDist < 0.001 ) return BaseClass::MoveFlyExecute( move, pTraceResult ); BuildMoveScript( move, pTraceResult ); float flNewSpeed = GetCurSpeed(); float flTotalDist = GetMoveScriptDist( flNewSpeed ); Assert( move.maxDist < 0.01 || flTotalDist > 0.0 ); // -------------------------------------------- // turn in the direction of movement // -------------------------------------------- float flNewYaw = GetMoveScriptYaw( ); // get facing based on movement yaw AILocalMoveGoal_t move2 = move; move2.facing = UTIL_YawToVector( flNewYaw ); // turn in the direction needed MoveFacing( move2 ); GetOuter()->m_flGroundSpeed = GetSequenceGroundSpeed( GetSequence()); SetMoveScriptAnim( flNewSpeed ); // DevMsg( "%6.2f : Speed %.1f : %.1f\n", gpGlobals->curtime, flNewSpeed, GetIdealSpeed() ); // reset actual "sequence" ground speed based current movement sequence, orientation // FIXME: the above is redundant with MoveGroundExecute, and the below is a mix of MoveGroundExecuteWalk and MoveFlyExecute bool bReachingLocalGoal = ( flTotalDist > move.maxDist ); // can I move farther in this interval than I'm supposed to? if ( bReachingLocalGoal ) { if ( !(move.flags & AILMG_CONSUME_INTERVAL) ) { // only use a portion of the time interval SetMoveInterval( GetMoveInterval() * (1 - move.maxDist / flTotalDist) ); } else SetMoveInterval( 0 ); flTotalDist = move.maxDist; } else { // use all the time SetMoveInterval( 0 ); } SetMoveVel( move.dir * flNewSpeed ); // orig Vector vecStart, vecEnd; vecStart = GetLocalOrigin(); VectorMA( vecStart, flTotalDist, move.dir, vecEnd ); AIMoveTrace_t moveTrace; GetMoveProbe()->MoveLimit( NAV_FLY, vecStart, vecEnd, MASK_NPCSOLID, NULL, &moveTrace ); if ( pTraceResult ) *pTraceResult = moveTrace; // Check for total blockage if (fabs(moveTrace.flDistObstructed - flTotalDist) <= 1e-1) { // But if we bumped into our target, then we succeeded! if ( move.pMoveTarget && (moveTrace.pObstruction == move.pMoveTarget) ) return AIM_PARTIAL_HIT_TARGET; return AIM_FAILED; } // The true argument here causes it to touch all triggers // in the volume swept from the previous position to the current position UTIL_SetOrigin(GetOuter(), moveTrace.vEndPosition, true); return (IsMoveBlocked(moveTrace.fStatus)) ? AIM_PARTIAL_HIT_WORLD : AIM_SUCCESS; }