Partial MatchSimulation class for a football sim. Handles the coach-issued directed pass command: validates the requested receiver (possession, distance, offside, kicking state), stores the pending pass with a 5 second timeout, cancels it when conditions break, and executes the actual pass when the passer reaches the ball.
using System;
namespace Socer;
public sealed partial class MatchSimulation
{
public int FieldPasser=-1,FieldPassReceiver=-1,CommandPasses;
public float FieldPassUntil;
public string FieldPassFailure(int receiver)
{
if(!CanFieldCall)return "stoppage";
if(Owner<0 || Players[Owner].Team!=0)return "possession";
if(receiver<0 || receiver>=11 || Players[receiver].SentOff || receiver==Owner)return "receiver";
if(WindupPlayer>=0 || KeeperKickPlayer>=0)return "kicking";
var p=Players[Owner];var q=Players[receiver];float distance=(p.Position-q.Position).Length;
if(distance<2.5f || distance>(p.Keeper?28:48))return "distance";
if(!IsOnside(q,p.Position))return "offside";
return "";
}
public bool CallPass(int receiver)
{
if(FieldPassFailure(receiver)!="")return false;
FieldPasser=Owner;FieldPassReceiver=receiver;FieldPassUntil=Seconds+5;
var p=Players[Owner];p.PlanUntil=0;p.ShotSetupUntil=0;p.KickSetupUntil=0;p.HesitateUntil=0;p.Decision=0;
FieldAttackUntil=FieldShootUntil=0;
AddEvent($"Тренер · #{p.Number}: пас на #{Players[receiver].Number}");return true;
}
public void CancelFieldPass(){FieldPasser=FieldPassReceiver=-1;FieldPassUntil=0;}
void UpdateFieldPass()
{
if(FieldPasser>=0 && (Owner!=FieldPasser || !CanFieldCall || Seconds>FieldPassUntil ||
FieldPassReceiver<0 || Players[FieldPassReceiver].SentOff))CancelFieldPass();
}
bool TryFieldPass(Footballer p)
{
if(p.Id!=FieldPasser || FieldPassReceiver<0)return false;
int receiver=FieldPassReceiver;
if(FieldPassFailure(receiver)!=""){CancelFieldPass();return false;}
if(!p.Keeper && !BallAtFoot(p) || p.Keeper && p.Held<.45f)return true;
p.Action="Пас по команде";p.DecisionReason="Тренер указал адресата передачи";
if(ExecutePlayerPass(p,Players[receiver],false,CarrierPressure(p)))
{CommandPasses++;CancelFieldPass();}
return true;
}
}