void PutBallBackInPlay::Execute(GoalKeeper* keeper) { PlayerBase* receiver = NULL; Vector2D BallTarget; //test if there are players further forward on the field we might //be able to pass to. If so, make a pass. if (keeper->Team()->FindPass(keeper, receiver, BallTarget, Prm.MaxPassingForce, Prm.GoalkeeperMinPassDist)) { //make the pass keeper->Ball()->Kick(Vec2DNormalize(BallTarget - keeper->Ball()->Pos()), Prm.MaxPassingForce); //goalkeeper no longer has ball keeper->Pitch()->SetGoalKeeperHasBall(false); //let the receiving player know the ball's comin' at him Dispatcher->DispatchMsg(SEND_MSG_IMMEDIATELY, keeper->ID(), receiver->ID(), Msg_ReceiveBall, &BallTarget); //go back to tending the goal keeper->GetFSM()->ChangeState(TendGoal::Instance()); return; } keeper->SetVelocity(Vector2D()); }
void KickBall::Execute(FieldPlayer* player) { //calculate the dot product of the vector pointing to the ball //and the player's heading Vector2D ToBall = player->Ball()->Pos() - player->Pos(); double dot = player->Heading().Dot(Vec2DNormalize(ToBall)); //cannot kick the ball if the goalkeeper is in possession or if it is //behind the player or if there is already an assigned receiver. So just //continue chasing the ball if (player->Team()->Receiver() != NULL || player->Pitch()->GoalKeeperHasBall() || (dot < 0) ) { #ifdef PLAYER_STATE_INFO_ON debug_con << "Goaly has ball / ball behind player" << ""; #endif player->GetFSM()->ChangeState(ChaseBall::Instance()); return; } /* Attempt a shot at the goal */ //if a shot is possible, this vector will hold the position along the //opponent's goal line the player should aim for. Vector2D BallTarget; //the dot product is used to adjust the shooting force. The more //directly the ball is ahead, the more forceful the kick double power = Prm.MaxShootingForce * dot; //if it is determined that the player could score a goal from this position //OR if he should just kick the ball anyway, the player will attempt //to make the shot if (player->Team()->CanShoot(player->Ball()->Pos(), power, BallTarget) || (RandFloat() < Prm.ChancePlayerAttemptsPotShot)) { #ifdef PLAYER_STATE_INFO_ON debug_con << "Player " << player->ID() << " attempts a shot at " << BallTarget << ""; #endif //add some noise to the kick. We don't want players who are //too accurate! The amount of noise can be adjusted by altering //Prm.PlayerKickingAccuracy BallTarget = AddNoiseToKick(player->Ball()->Pos(), BallTarget); //this is the direction the ball will be kicked in Vector2D KickDirection = BallTarget - player->Ball()->Pos(); player->Ball()->Kick(KickDirection, power); //change state player->GetFSM()->ChangeState(Wait::Instance()); player->FindSupport(); return; } /* Attempt a pass to a player */ //if a receiver is found this will point to it PlayerBase* receiver = NULL; power = Prm.MaxPassingForce * dot; //test if there are any potential candidates available to receive a pass if (player->isThreatened() && player->Team()->FindPass(player, receiver, BallTarget, power, Prm.MinPassDist)) { //add some noise to the kick BallTarget = AddNoiseToKick(player->Ball()->Pos(), BallTarget); Vector2D KickDirection = BallTarget - player->Ball()->Pos(); player->Ball()->Kick(KickDirection, power); #ifdef PLAYER_STATE_INFO_ON debug_con << "Player " << player->ID() << " passes the ball with force " << power << " to player " << receiver->ID() << " Target is " << BallTarget << ""; #endif //let the receiver know a pass is coming Dispatcher->DispatchMsg(SEND_MSG_IMMEDIATELY, player->ID(), receiver->ID(), Msg_ReceiveBall, &BallTarget); //the player should wait at his current position unless instruced //otherwise player->GetFSM()->ChangeState(Wait::Instance()); player->FindSupport(); return; } //cannot shoot or pass, so dribble the ball upfield else { player->FindSupport(); player->GetFSM()->ChangeState(Dribble::Instance()); } }