#ifdef WORKBENCH modded class ERR_GameMode { protected ref ERR_ReviewProbe m_ReviewProbe; protected override void StartScenario() {} protected override void EOnInit(IEntity owner) { super.EOnInit(owner); if (SCR_Global.IsEditMode() || !Replication.IsServer()) return; GetGame().GetCallqueue().CallLater(ReviewBegin,2000,false); } protected void ReviewBegin() { m_ReviewProbe=new ERR_ReviewProbe(this);m_ReviewProbe.Begin(); } } class ERR_ReviewTraffic : ERR_CivilianTraffic { protected ref array m_ProbeCars={}; protected float m_Deadline; bool Done; void Begin() { Neutral(); m_Catalog.Find(false); if (m_Catalog.RoadPrefabs.Count()<3 || !m_Catalog.Tractors.IsEmpty()) { Print("ERR SMOKE FAIL: traffic street-only catalog",LogLevel.ERROR);return; } PrintFormat("ERR REVIEW CATALOG: moving=%1 tractors=%2",m_Catalog.RoadPrefabs.Count(),m_Catalog.Tractors.Count()); array choices={}; foreach (ResourceName name:m_Catalog.RoadPrefabs) { string lower=name;lower.ToLower(); if ((choices.IsEmpty() && lower.Contains("/s105/")) || (choices.Count()==1 && lower.Contains("/v2101/"))) choices.Insert(name); } if (choices.Count()!=2) { Print("ERR SMOKE FAIL: traffic family discovery",LogLevel.ERROR);return; } for(int i=0;i seats={};ERR_ConvoyRules.CollectSeats(car.Car,seats); foreach(BaseCompartmentSlot seat:seats) if(seat.GetType()==ECompartmentType.PILOT) {car.Seat=seat;break;} if (!car.Seat) { Print("ERR SMOKE FAIL: traffic seat",LogLevel.ERROR);return; } AIGroup group=car.Group;car.Driver=car.Seat.SpawnCharacterInCompartment(DriverPrefab(),group,ERR_ConvoyResources.GroupPrefab());ERR_Actors.SetFaction(car.Driver,civilian); AICarMovementComponent movement=AICarMovementComponent.Cast(car.Car.FindComponent(AICarMovementComponent)); if (!movement) { Print("ERR SMOKE FAIL: traffic AI movement component",LogLevel.ERROR);return; } movement.SetCruiseSpeed(40); m_ProbeCars.Insert(car); } m_Deadline=GetGame().GetWorld().GetWorldTime()+240000; GetGame().GetCallqueue().CallLater(Check,2000,true); } void Check() { int driven; foreach(ERR_CivilianCar car:m_ProbeCars) { if(!car.Ready) Prepare(car); float distance=vector.DistanceXZ(car.Car.GetOrigin(),car.Route[0]); CarControllerComponent control=CarControllerComponent.Cast(car.Car.FindComponent(CarControllerComponent)); VehicleWheeledSimulation sim=VehicleWheeledSimulation.Cast(car.Car.FindComponent(VehicleWheeledSimulation)); PrintFormat("ERR REVIEW DRIVE STATE: car=%1 engine=%2 brake=%3 throttle=%4 rpm=%5 handbrake=%6 gear=%7 auto=%8",car.Number,control.IsEngineOn(),sim.GetBrake(),sim.GetThrottle(),sim.EngineGetRPM(),control.GetPersistentHandBrake(),control.GetCurrentGear(),control.HasAutomaticGearbox()); PrintFormat("ERR REVIEW TRAFFIC: prefab=%1 ready=%2 travelled=%3 seated=%4",car.Prefab,car.Ready,distance,car.Seat.GetOccupant()==car.Driver); if(car.Ready && distance>=100 && car.Seat.GetOccupant()==car.Driver) car.Finished=true; if(car.Finished) driven++; } if(driven==2) {Done=true;Print("ERR SMOKE PASS: S105 and V2101 street-car families driven over 100m by original native AI drivers");GetGame().GetCallqueue().Remove(Check);} else if(GetGame().GetWorld().GetWorldTime()>m_Deadline) { Print("ERR SMOKE FAIL: traffic driving deadline",LogLevel.ERROR);GetGame().GetCallqueue().Remove(Check); } } } class ERR_ReviewProbe : ERR_GarageVehicles { protected Vehicle m_Tractor; protected IEntity m_Observer; protected IEntity m_Barn; protected ref ERR_ReviewTraffic m_Traffic; protected float m_Deadline; protected bool m_FarmDone; protected bool m_FarmReported; protected int m_UIStep; protected Widget m_UI; protected float m_OriginalDPI; void ERR_ReviewProbe(ERR_GameMode mode) {m_Mode=mode;} protected override bool Running(){return true;} void Begin() { m_Cars.Find(); if(m_Cars.Tractors.Count()!=1 || m_Cars.RoadPrefabs.Count()<3 || m_Cars.Prefabs.Count()!=52) {Fail("catalog");return;} m_Tractor=Vehicle.Cast(ERR_Actors.Spawn(m_Cars.Tractors[0],ERR_Actors.Ground("4788 0 11528")+"0 0.15 0")); m_OriginalDPI=GetGame().GetWorkspace().GetUserDPIScale(); GetGame().GetCallqueue().CallLater(Inspect,2000,false); } void Fail(string reason){Print("ERR SMOKE FAIL: 1.9 review "+reason,LogLevel.ERROR);Stop();GetGame().GetWorkspace().SetUserDPIScale(m_OriginalDPI);} void Inspect() { vector low,high;m_Tractor.GetBounds(low,high); array seats={};ERR_ConvoyRules.CollectSeats(m_Tractor,seats);bool driver; foreach(BaseCompartmentSlot seat:seats) if(seat.GetType()==ECompartmentType.PILOT && seat.IsCompartmentAccessible()) driver=true; PrintFormat("ERR REVIEW TRACTOR: prefab=%1 low=%2 high=%3 driver=%4",m_Cars.Tractors[0],low,high,driver); if(!driver || !ERR_GarageVehicleRules.FarmEnvelope(low,high)){Fail("tractor envelope/seat");return;} ERR_Actors.DeleteSpawned(m_Tractor); m_Barn=ERR_Actors.Spawn("Prefabs/Structures/Agriculture/Barn/Barn_E_01/Barn_E_01.et",ERR_Actors.Ground("4788 0 11528")); m_Observer=ERR_Actors.Spawn(ERR_CivilianTraffic.DriverPrefab(),ERR_Actors.Ground("4888 0 11528")); m_Requested=1;m_GarageChance=100;m_SpawnRadius=1500;m_CleanupRadius=1900;m_SpawnInterval=1000; m_Deadline=Now()+180000; Remember(m_Barn); vector bl,bh;m_Barn.GetBounds(bl,bh);PrintFormat("ERR REVIEW BARN: exists=%1 low=%2 high=%3 alive=%4 sites=%5",m_Barn!=null,bl,bh,ERR_Actors.Alive(m_Barn),m_Sites.Count()); m_Traffic=new ERR_ReviewTraffic(m_Mode);m_Traffic.Begin(); ChimeraAIWorld ai=ChimeraAIWorld.Cast(GetGame().GetAIWorld());PrintFormat("ERR REVIEW AI: partial=%1 dormancy=%2 limit=%3 active=%4",ai.IsPartialFillEnabled(),ai.IsGroupDormancyEnabled(),ai.GetLimitOfActiveAIs(),ai.GetCurrentNumOfActiveAIs()); GetGame().GetCallqueue().CallLater(Step,250,true); GetGame().GetCallqueue().CallLater(UI,500,true); } void UI() { if(m_UI) { m_UI.Update();ERR_AdminMenuView.FitPanel(m_UI);m_UI.Update();Widget panel=m_UI.FindAnyWidget("Panel");float x,y,w,h,rw,rh; panel.GetScreenPos(x,y);panel.GetScreenSize(w,h);m_UI.GetScreenSize(rw,rh); PrintFormat("ERR REVIEW UI: dpi=%1 panel=%2,%3 %4x%5 root=%6x%7 fits=%8",GetGame().GetWorkspace().GetUserDPIScale(),x,y,w,h,rw,rh,x>=0 && y>=0 && x+w<=rw && y+h<=rh); m_UI.RemoveFromHierarchy();m_UI=null; } if(m_UIStep==4){GetGame().GetWorkspace().SetUserDPIScale(m_OriginalDPI);GetGame().GetCallqueue().Remove(UI);return;} GetGame().GetWorkspace().SetUserDPIScale(0.75+m_UIStep*0.25);m_UIStep++; m_UI=GetGame().GetWorkspace().CreateWidgets("UI/layouts/ERR/AdminMenu.layout"); } protected override bool Observers(array positions,array actors) { positions.Clear();actors.Clear();if(!m_Observer)return false;positions.Insert(m_Observer.GetOrigin());actors.Insert(m_Observer);return true; } protected override bool Remember(IEntity entity) { if(entity!=m_Barn)return true; bool result=super.Remember(entity); foreach(ERR_GarageSite site:m_Sites) site.Selected=true; return result; } protected override void Plan(array observers,array actors,float now) { if(!m_FarmReported && !m_Sites.IsEmpty() && !observers.IsEmpty()) { m_FarmReported=true;vector low,high;m_Barn.GetBounds(low,high); for(int side=0;side<4;side++) { vector offset=ERR_GarageVehicleRules.YardOffset(low,high,side,4);vector pos=ERR_Actors.Ground(m_Barn.CoordToParent(offset))+"0 0.08 0"; vector angle=m_Barn.GetYawPitchRoll();angle[1]=0;angle[2]=0;if(side>=2)angle[0]=angle[0]+90; vector mat[4];Math3D.AnglesToMatrix(angle,mat); PrintFormat("ERR REVIEW FARM VETO: side=%1 pos=%2 ground=%3 clear=%4 hidden=%5 distance=%6",side,pos,YardGround(pos,mat,true),Clear(pos,mat,null,true),Hidden(pos,angle,actors,null,true),vector.DistanceXZ(pos,observers[0])); } } super.Plan(observers,actors,now); } protected override void Step() { if(!m_FarmDone) { array views = {m_Observer.GetOrigin()}; array actors = {m_Observer}; if(m_Pending) Pending(views,actors); else Plan(views,actors,Now()); } if(m_Sites.Count()>0 && m_Sites[0].NextTry==Now()) PrintFormat("ERR REVIEW FARM SITES: %1",m_Sites.Count()); if(Now()>m_Deadline){Fail("farm spawn deadline");return;} if(!m_FarmDone && m_Parked.Count()==1) { ERR_ParkedVehicle parked=m_Parked[0];vector matrix[4];parked.Entity.GetWorldTransform(matrix); if(!parked.Site.Farm || !YardGround(parked.Origin,matrix,true) || !Clear(parked.Origin,matrix,parked.Entity,true)){Fail("farm checks");return;} PrintFormat("ERR REVIEW FARM: prefab=%1 position=%2 anchor=%3",parked.Entity.GetPrefabData().GetPrefabName(),parked.Origin,parked.Site.Garage.GetPrefabData().GetPrefabName()); m_FarmDone=true;Print("ERR SMOKE PASS: native farm tractor placement with production ground, visibility and collision checks"); } if(m_FarmDone && m_Traffic.Done){Print("ERR SMOKE COMPLETE: 1.9 review vehicles and UI measurements");Stop();} } } #endif