Files
EscapistsReintroduced/docs/evidence/review-1.9-2026-11-06/native-probe.c.txt
T
2026-11-06 12:37:08 +01:00

173 lines
9.7 KiB
Plaintext

#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<ref ERR_CivilianCar> 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<ResourceName> 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<choices.Count();i++)
{
vector position,angles,middle,destination,unused;
if (!ERR_SupplyConvoySystem.ApproachDirected(Vector(6900+i*400,0,3600),position,angles,500)
|| !ERR_SupplyConvoySystem.ApproachDirected(position+"250 0 250",middle,unused,500)
|| !ERR_SupplyConvoySystem.ApproachDirected(position+"500 0 500",destination,unused,500)) { Print("ERR SMOKE FAIL: traffic test road",LogLevel.ERROR);return; }
ERR_CivilianCar car=new ERR_CivilianCar();car.Number=i;car.Prefab=choices[i];car.Route={position,middle,destination};car.ProgressPosition=position;
car.Car=Vehicle.Cast(ERR_Actors.Spawn(choices[i],position,angles));
car.Group=SCR_AIGroup.Cast(ERR_Actors.Spawn(ERR_ConvoyResources.GroupPrefab(),position));
Faction civilian=GetGame().GetFactionManager().GetFactionByKey("CIV");car.Group.SetFaction(civilian);car.Group.SetDeleteWhenEmpty(false);ERR_Actors.SetFaction(car.Car,civilian);
array<BaseCompartmentSlot> 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<BaseCompartmentSlot> 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<vector> positions,array<IEntity> 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<vector> observers,array<IEntity> 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<vector> views = {m_Observer.GetOrigin()};
array<IEntity> 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