/* ================ rvMonsterConvoyGround::State_Torso_Pain ================ */ stateResult_t rvMonsterConvoyGround::State_Torso_Pain ( const stateParms_t& parms ) { enum { STAGE_START, STAGE_END }; switch ( parms.stage ) { case STAGE_START: // Force the orientation to the direction we got hit from so the animation looks correct OverrideFlag ( AIFLAGOVERRIDE_NOTURN, true ); TurnToward ( physicsObj.GetOrigin() - lastPainDir * 128.0f ); move.current_yaw = move.ideal_yaw; // Just in case the pain anim wasnt set before we got here. if ( !painAnim.Length ( ) ) { painAnim = "pain"; } DisableAnimState ( ANIMCHANNEL_LEGS ); PlayAnim ( ANIMCHANNEL_TORSO, painAnim, parms.blendFrames ); return SRESULT_STAGE ( STAGE_END ); case STAGE_END: if ( AnimDone ( ANIMCHANNEL_TORSO, parms.blendFrames ) ) { return SRESULT_DONE; } return SRESULT_WAIT; } return SRESULT_ERROR; }
void CAIVehicle::Think( void ) { if( !( thinkFlags & TH_THINK ) ) { goto Quit; } if( m_Controller.GetEntity() ) { // Exit the combat state if we somehow got in it. // Later we can fight as directed by player, but right now it's too independent ClearEnemy(); // Update controls and movement dir UpdateSteering(); // Speed controls, for now just AI_MOVE bool bMovementReq = UpdateSpeed(); // Request move at direction if( bMovementReq ) { MoveAlongVector( m_CurAngle ); } else { StopMove( MOVE_STATUS_DONE ); // just turn if no forward/back movement is requested TurnToward( m_CurAngle ); } } idAI::Think(); Quit: return; }
void rvMonsterStroggHover::CircleStrafe ( void ) { if ( !GetEnemy() || strafeTime < gameLocal.GetTime() || !enemy.fl.visible || !enemy.fl.inFov ) { //FIXME: also stop if I bump into something circleStrafing = false; strafeTime = 0; SetState( "State_Combat" ); return; } if ( !strafeTime ) { strafeTime = gameLocal.GetTime() + 8000; //FIXME: try to see which side it clear? strafeRight = (gameLocal.random.RandomFloat()>0.5f); } idVec3 vel = GetPhysics()->GetLinearVelocity(); idVec3 strafeVel = viewAxis[1] * (strafeRight?-circleStrafeSpeed:circleStrafeSpeed); strafeVel.z = 0.0f; vel += strafeVel; vel.Normalize(); vel *= circleStrafeSpeed; physicsObj.UseVelocityMove( true ); GetPhysics()->SetLinearVelocity( vel ); TurnToward( GetEnemy()->GetPhysics()->GetOrigin() ); }
END_CLASS_STATES /* ================ rvMonsterStroggMarine::State_Torso_RollAttack ================ */ stateResult_t rvMonsterStroggMarine::State_Torso_RollAttack ( const stateParms_t& parms ) { enum { TORSO_ROLLATTACK_ROLL, TORSO_ROLLATTACK_FACE, TORSO_ROLLATTACK_FIRE, TORSO_ROLLATTACK_FINISH }; TurnToward(enemy.lastKnownPosition); switch ( parms.stage ) { // Start the roll attack animation case TORSO_ROLLATTACK_ROLL: // Full body animations DisableAnimState ( ANIMCHANNEL_LEGS ); // Play the roll PlayAnim ( ANIMCHANNEL_TORSO, "dive_turn", parms.blendFrames ); move.fl.noTurn = false; //FaceEnemy(); return SRESULT_STAGE ( TORSO_ROLLATTACK_FACE ); // Wait for roll animation to finish case TORSO_ROLLATTACK_FACE: if ( AnimDone ( ANIMCHANNEL_LEGS, 6 ) ) { return SRESULT_STAGE ( TORSO_ROLLATTACK_FIRE ); } return SRESULT_WAIT; // Play fire animation case TORSO_ROLLATTACK_FIRE: if ( !enemy.ent || !enemy.fl.visible ) {//whoops! rolled out of LOS return SRESULT_DONE; } if ( enemy.fl.inFov ) { PlayAnim ( ANIMCHANNEL_TORSO, "shotgun_range_attack", parms.blendFrames ); return SRESULT_STAGE ( TORSO_ROLLATTACK_FINISH ); } return SRESULT_WAIT; // Wait for fire animation to finish case TORSO_ROLLATTACK_FINISH: if ( AnimDone ( ANIMCHANNEL_TORSO, 2 ) ) { return SRESULT_DONE; } return SRESULT_WAIT; } return SRESULT_ERROR; }
void CUnitScript::TickAnims(int deltaTime, AnimType type, std::list< std::list<AnimInfo*>::iterator >& doneAnims) { switch (type) { case AMove: { for (std::list<AnimInfo*>::iterator it = anims[type].begin(); it != anims[type].end(); ++it) { AnimInfo* ai = *it; // NOTE: we should not need to copy-and-set here, because // MoveToward/TurnToward/DoSpin modify pos/rot by reference float3 pos = pieces[ai->piece]->GetPosition(); if (MoveToward(pos[ai->axis], ai->dest, ai->speed / (1000 / deltaTime))) { ai->done = true; doneAnims.push_back(it); } pieces[ai->piece]->SetPosition(pos); unit->localModel->PieceUpdated(ai->piece); } } break; case ATurn: { for (std::list<AnimInfo*>::iterator it = anims[type].begin(); it != anims[type].end(); ++it) { AnimInfo* ai = *it; float3 rot = pieces[ai->piece]->GetRotation(); if (TurnToward(rot[ai->axis], ai->dest, ai->speed / (1000 / deltaTime))) { ai->done = true; doneAnims.push_back(it); } pieces[ai->piece]->SetRotation(rot); unit->localModel->PieceUpdated(ai->piece); } } break; case ASpin: { for (std::list<AnimInfo*>::iterator it = anims[type].begin(); it != anims[type].end(); ++it) { AnimInfo* ai = *it; float3 rot = pieces[ai->piece]->GetRotation(); if (DoSpin(rot[ai->axis], ai->dest, ai->speed, ai->accel, 1000 / deltaTime)) { ai->done = true; doneAnims.push_back(it); } pieces[ai->piece]->SetRotation(rot); unit->localModel->PieceUpdated(ai->piece); } } break; default: { } break; } }
/** * @brief Called by the engine when we are registered as animating. If we return -1 it means that * there is no longer anything animating * @param deltaTime int delta time to update * @return 0 if there are still animations going, -1 else */ int CUnitScript::Tick(int deltaTime) { std::vector<struct AnimInfo *> remove; for (std::list<struct AnimInfo *>::iterator it = anims.begin(); it != anims.end(); ) { struct AnimInfo *ai = *it; bool done = false; switch (ai->type) { case AMove: { float3 pos = pieces[ai->piece]->GetPosition(); done = MoveToward(pos[ai->axis], ai->dest, ai->speed / (1000 / deltaTime)); pieces[ai->piece]->SetPosition(pos); } break; case ATurn: { float3 rot = pieces[ai->piece]->GetRotation(); done = TurnToward(rot[ai->axis], ai->dest, ai->speed / (1000 / deltaTime)); pieces[ai->piece]->SetRotation(rot); } break; case ASpin: { float3 rot = pieces[ai->piece]->GetRotation(); done = DoSpin(rot[ai->axis], ai->dest, ai->speed, ai->accel, 1000 / deltaTime); pieces[ai->piece]->SetRotation(rot); } break; } // Queue for removal (UnblockAll may add new anims) if (done) { remove.push_back(ai); } ++it; } //Tell listeners to unblock? for (std::vector<struct AnimInfo *>::iterator it = remove.begin(); it != remove.end(); ++it) { UnblockAll(*it); //! NOTE: UnblockAll might result in new anims being added } for (std::vector<struct AnimInfo *>::iterator it = remove.begin(); it != remove.end(); ++it) { anims.remove(*it); delete *it; } return anims.empty() ? -1 : 0; }
/** * @brief Called by the engine when we are registered as animating. If we return -1 it means that * there is no longer anything animating * @param deltaTime int delta time to update * @return 0 if there are still animations going, -1 else */ int CUnitScript::Tick(int deltaTime) { std::vector<struct AnimInfo *> remove; for (std::list<struct AnimInfo *>::iterator it = anims.begin(); it != anims.end(); ) { struct AnimInfo *ai = *it; bool done = false; switch (ai->type) { case AMove: done = MoveToward(pieces[ai->piece]->pos[ai->axis], ai->dest, ai->speed / (1000 / deltaTime)); break; case ATurn: done = TurnToward(pieces[ai->piece]->rot[ai->axis], ai->dest, ai->speed / (1000 / deltaTime)); break; case ASpin: done = DoSpin(pieces[ai->piece]->rot[ai->axis], ai->dest, ai->speed, ai->accel, 1000 / deltaTime); break; } // Queue for removal (UnblockAll may add new anims) if (done) { remove.push_back(ai); it = anims.erase(it); } else { ++it; } } //Tell listeners to unblock? for (std::vector<struct AnimInfo *>::iterator it = remove.begin(); it != remove.end(); ++it) { UnblockAll(*it); delete *it; } if (anims.empty()) return -1; else return 0; }
//Called by the engine when we are registered as animating. If we return -1 it means that //there is no longer anything animating int CCobInstance::Tick(int deltaTime) { int done; list<struct AnimInfo *>::iterator it = anims.begin(); list<struct AnimInfo *>::iterator cur; while (it != anims.end()) { //Advance it, so we can erase cur safely cur = it++; done = false; pieces[(*cur)->piece].updated = true; switch ((*cur)->type) { case AMove: done = MoveToward(pieces[(*cur)->piece].coords[(*cur)->axis], (*cur)->dest, (*cur)->speed / (1000 / deltaTime)); break; case ATurn: done = TurnToward(pieces[(*cur)->piece].rot[(*cur)->axis], (*cur)->dest, (*cur)->speed / (1000 / deltaTime)); break; case ASpin: done = DoSpin(pieces[(*cur)->piece].rot[(*cur)->axis], (*cur)->dest, (*cur)->speed, (*cur)->accel, 1000 / deltaTime); break; } //Tell listeners to unblock? if (done) { UnblockAll(*cur); delete *cur; anims.erase(cur); } } if (anims.size() == 0) return -1; else return 0; }
void hhHarvesterSimple::AnimMove( void ) { idVec3 goalPos; idVec3 delta; idVec3 goalDelta; float goalDist; monsterMoveResult_t moveResult; idVec3 newDest; // Turn on physics to prevent flying harvesters BecomeActive(TH_PHYSICS); idVec3 oldorigin = physicsObj.GetOrigin(); #ifdef HUMANHEAD //jsh wallwalk idMat3 oldaxis = GetGravViewAxis(); #else idMat3 oldaxis = viewAxis; #endif AI_BLOCKED = false; if ( move.moveCommand < NUM_NONMOVING_COMMANDS ){ move.lastMoveOrigin.Zero(); move.lastMoveTime = gameLocal.time; } move.obstacle = NULL; if ( ( move.moveCommand == MOVE_FACE_ENEMY ) && enemy.GetEntity() ) { TurnToward( lastVisibleEnemyPos ); goalPos = oldorigin; } else if ( ( move.moveCommand == MOVE_FACE_ENTITY ) && move.goalEntity.GetEntity() ) { TurnToward( move.goalEntity.GetEntity()->GetPhysics()->GetOrigin() ); goalPos = oldorigin; } else if ( GetMovePos( goalPos ) ) { if ( move.moveCommand != MOVE_WANDER ) { CheckObstacleAvoidance( goalPos, newDest ); TurnToward( newDest ); } else { TurnToward( goalPos ); } } Turn(); if ( move.moveCommand == MOVE_SLIDE_TO_POSITION ) { if ( gameLocal.time < move.startTime + move.duration ) { goalPos = move.moveDest - move.moveDir * MS2SEC( move.startTime + move.duration - gameLocal.time ); delta = goalPos - oldorigin; delta.z = 0.0f; } else { delta = move.moveDest - oldorigin; delta.z = 0.0f; StopMove( MOVE_STATUS_DONE ); } } else if ( allowMove ) { #ifdef HUMANHEAD //jsh wallwalk GetMoveDelta( oldaxis, GetGravViewAxis(), delta ); #else GetMoveDelta( oldaxis, viewAxis, delta ); #endif } else { delta.Zero(); } if ( move.moveCommand == MOVE_TO_POSITION ) { goalDelta = move.moveDest - oldorigin; goalDist = goalDelta.LengthFast(); if ( goalDist < delta.LengthFast() ) { delta = goalDelta; } } #ifdef HUMANHEAD //shrink functionality float scale = renderEntity.shaderParms[SHADERPARM_ANY_DEFORM_PARM1]; if ( scale > 0.0f && scale < 2.0f ) { delta *= scale; } #endif physicsObj.SetDelta( delta ); physicsObj.ForceDeltaMove( disableGravity ); RunPhysics(); if ( ai_debugMove.GetBool() ) { // HUMANHEAD JRM - so we can see if grav is on or off if(disableGravity) { gameRenderWorld->DebugLine( colorRed, oldorigin, physicsObj.GetOrigin(), 5000 ); } else { gameRenderWorld->DebugLine( colorCyan, oldorigin, physicsObj.GetOrigin(), 5000 ); } } moveResult = physicsObj.GetMoveResult(); if ( !af_push_moveables && attack.Length() && TestMelee() ) { DirectDamage( attack, enemy.GetEntity() ); } else { idEntity *blockEnt = physicsObj.GetSlideMoveEntity(); if ( blockEnt && blockEnt->IsType( hhHarvesterSimple::Type ) ) { StopMove( MOVE_STATUS_BLOCKED_BY_MONSTER ); return; } if ( blockEnt && blockEnt->IsType( idMoveable::Type ) && blockEnt->GetPhysics()->IsPushable() ) { KickObstacles( viewAxis[ 0 ], kickForce, blockEnt ); } } BlockedFailSafe(); AI_ONGROUND = physicsObj.OnGround(); idVec3 org = physicsObj.GetOrigin(); if ( oldorigin != org ) { TouchTriggers(); } if ( ai_debugMove.GetBool() ) { gameRenderWorld->DebugBounds( colorMagenta, physicsObj.GetBounds(), org, gameLocal.msec ); gameRenderWorld->DebugBounds( colorMagenta, physicsObj.GetBounds(), move.moveDest, gameLocal.msec ); gameRenderWorld->DebugLine( colorYellow, org + EyeOffset(), org + EyeOffset() + viewAxis[ 0 ] * physicsObj.GetGravityAxis() * 16.0f, gameLocal.msec, true ); DrawRoute(); } }