Tutorial scenario factory for MatchSimulation. Builds and positions players for penalty, free kick, injury, substitution, marking, stamina and skill-link drills on the practice roster.
using System;
using System.Collections.Generic;
namespace Socer;
public sealed partial class MatchSimulation
{
// Only the starting arrangement changes; all 22 players and normal physics remain active.
public static ClubCareer CreateTutorialRoster()=>ClubCareer.Create(738291);
public static MatchSimulation TutorialScenario(string key,ClubCareer practiceRoster=null)
{
if(key is "penalty" or "free-kick")
{
var standard=InteractiveRestartPreview(key=="penalty"?RestartKind.Penalty:RestartKind.FreeKick);
standard.HomeName="COACH ACADEMY";standard.AwayName="PRACTICE XI";
standard.InjuriesEnabled=false;
// Prepare the real manual restart before waiting for the learner.
// No aim, power or successful shot is supplied by the fixture.
for(int i=0;i<120 && !standard.ManualRestartWaiting;i++)standard.Step(1f/60);
return standard;
}
if(key=="freeplay")
{
var practice=Laboratory("match",738291,82,78);
practice.HomeName="COACH ACADEMY";practice.AwayName="PRACTICE XI";
return practice;
}
var m=Laboratory("match",738291,82,72);
if(key is "substitution" or "injury")
{
practiceRoster??=CreateTutorialRoster();practiceRoster.Apply(m);
m.HomeName="COACH ACADEMY";m.AwayName="PRACTICE XI";
m.Seconds=30;m.RestartRemaining=0;m.AutomaticStrategiesEnabled=false;m.InjuriesEnabled=false;
m.GiveLabBall(m.Players[6]);m.Players[9].Stamina=.16f;
if(key=="injury")
{
m.ManualHomeInjurySubstitution=true;
m.Players[9].Position=new Point(64,3);
m.RegisterInjury(m.Players[9],InjurySeverity.Serious,InjuryBodyPart.Ankle);
// Start at the real carry-off phase, keeping the short visible
// finish of treatment and the genuine mandatory choice.
for(int i=0;i<2700 && (m.MedicalStage!=MedicalTreatmentStage.CarryOff || m.MedicalStageProgress<.55f);i++)m.Step(1f/60);
}
return m;
}
m.HomeName="COACH ACADEMY";m.AwayName="PRACTICE XI";
m.Seconds=30;m.RestartRemaining=0;m.Passer=-1;m.AutomaticStrategiesEnabled=false;
foreach(var p in m.Players)
{
p.Profile.SlotRole=PlayerPositions.Slot(Formation.All[0],p.Id%11);p.Profile.RoleFamiliarity=1;
p.Position=m.World(p.Home,p.Team);p.Velocity=new Point();
p.Decision=0;p.Held=2;p.Facing=p.Team==0?0:MathF.PI;
}
m.Players[6].Position=new Point(60,34);m.Players[9].Position=new Point(69,22);
for(int i=12;i<22;i++)m.Players[i].Position=new Point(85+(i%3)*4,7+(i-12)*5.6f);
m.Players[11].Position=new Point(103,34);m.GiveLabBall(m.Players[6]);
if(key is "attack" or "shoot")
{
m.Players[9].Position=new Point(89,34);
foreach(var p in m.Players)if(p.Team==1 && !p.Keeper)p.Position=new Point(68,p.Position.Y);
m.GiveLabBall(m.Players[9]);
}
if(key is "mark" or "press" or "zone" or "clear")
{
m.Players[4].Position=new Point(64,40);m.Players[4].Facing=-.7f;
m.Players[20].Position=new Point(70,34);m.Players[20].Facing=MathF.PI;
m.GiveLabBall(m.Players[20]);
if(key=="clear")m.GiveDirectOrder(4,DirectOrderKind.GuardZone,point:new Point(61,38));
}
if(key=="stamina")
{
m.SetBroadcastPlan(1,1);m.Players[9].Stamina=.78f;
m.GiveDirectOrder(9,DirectOrderKind.AttackRun,point:new Point(86,22));
}
if(key=="links")
{
m.Players[6].Profile.SkillLoadout=new List<SkillInstance>{new(){Skill=UniqueSkill.ThreadNeedle,Grade=2}};
m.Players[9].Profile.SkillLoadout=new List<SkillInstance>{new(){Skill=UniqueSkill.SpaceHunter,Grade=2}};
m.Players[6].Position=new Point(62,34);m.Players[9].Position=new Point(68,26);
m.Players[13].Position=new Point(63,38);
m.Players[2].Profile.SkillLoadout=new List<SkillInstance>{new(){Skill=UniqueSkill.CoverGuard,Grade=2}};
m.Players[3].Profile.SkillLoadout=new List<SkillInstance>{new(){Skill=UniqueSkill.SteelPress,Grade=2}};
m.TeamCohesion[0]=.9f;m.GiveLabBall(m.Players[6]);
}
return m;
}
}