Add civilian traffic variants, farm tractors and UI scaling; record Workshop 0.0.143
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -69,6 +69,7 @@ class ERR_AdminMenu : ChimeraMenuBase
|
||||
button.m_OnClicked.Insert(OnButton);
|
||||
m_Buttons.Insert(button);
|
||||
}
|
||||
ERR_AdminMenuView.FitPanel(GetRootWidget());
|
||||
m_Ready = false; m_Age = 0; m_Poll = 0;
|
||||
GetGame().GetInputManager().AddActionListener(UIConstants.MENU_ACTION_BACK, EActionTrigger.PRESSED, OnBack);
|
||||
m_Bound = true;
|
||||
@@ -89,6 +90,7 @@ class ERR_AdminMenu : ChimeraMenuBase
|
||||
override void OnMenuUpdate(float tDelta)
|
||||
{
|
||||
super.OnMenuUpdate(tDelta);
|
||||
ERR_AdminMenuView.FitPanel(GetRootWidget());
|
||||
if (!m_Controller || m_Controller != GetGame().GetPlayerController() || !m_Mode || m_Mode != GetGame().GetGameMode() || ERR_MissionRules.Terminal(m_Mode.Phase())) { Close(); return; }
|
||||
m_Age += tDelta; m_Poll += tDelta;
|
||||
m_ClickDelay = Math.Max(0, m_ClickDelay - tDelta);
|
||||
|
||||
@@ -1,6 +1,19 @@
|
||||
// Widget presentation only. No settings writes, authorization or transport here.
|
||||
class ERR_AdminMenuView
|
||||
{
|
||||
// Preserve the requested UI scale until the fixed panel would leave the viewport.
|
||||
static void FitPanel(Widget root)
|
||||
{
|
||||
if (!root || !GetGame() || !GetGame().GetWorkspace()) return;
|
||||
ScaleWidget scale = ScaleWidget.Cast(root.FindAnyWidget("PanelScale"));
|
||||
if (!scale) return;
|
||||
float width, height; root.GetScreenSize(width, height);
|
||||
float panelWidth = GetGame().GetWorkspace().DPIScale(1220);
|
||||
float panelHeight = GetGame().GetWorkspace().DPIScale(760);
|
||||
if (width <= 0 || height <= 0 || panelWidth <= 0 || panelHeight <= 0) return;
|
||||
float fit = Math.Min(1, Math.Min(width * 0.96 / panelWidth, height * 0.96 / panelHeight));
|
||||
if (Math.AbsFloat(scale.GetScale() - fit) > 0.001) scale.SetScale(fit);
|
||||
}
|
||||
static bool ShowPage(Widget root, int page)
|
||||
{
|
||||
int group = ERR_AdminMenuPages.Group(page);
|
||||
|
||||
@@ -205,7 +205,7 @@ class ERR_AdminService
|
||||
if (key == "garageChancePercent") return "Parking-site selection chance (0-100%). Default 70%; applies to suitable garages and residential yards. Next round.";
|
||||
if (key == "garageRadiusMetres") return "Spawn radius (250-1500 metres). Distance around players; default 1000 m. Next round.";
|
||||
if (key == "garageSpawnIntervalSeconds") return "Time between spawns (5-60 seconds). Default 5 s. Increase to spread out spawning. Next round.";
|
||||
if (key == "garageVehicleCount") return "0..24 unclaimed cars in garages and residential yards; default 16. Used vehicles stay. Optional Rally cars and bikes. Applies next round.";
|
||||
if (key == "garageVehicleCount") return "0..24 unclaimed cars in garages and residential yards; default 16. Used vehicles stay. Optional Rally cars, farm tractors and bikes. Next round.";
|
||||
if (key == "civilianTrafficCount") return "Set 0..6 civilian cars (default 3). Zero disables new traffic. Unclaimed cars retire only far from all players and out of sight; player-entered cars are preserved.";
|
||||
if (key == "showAllSites") return "0 disabled (default), 1 enabled. Show prepared sites at their positions as question marks; recovered intel identifies their types. Applies immediately to everyone.";
|
||||
if (key == "selfEpinephrine") return "0 disabled (default), 1 enabled. Unconscious players can press Space to use a carried epinephrine injector. Applies immediately; consumes the item and keeps its normal medical effect.";
|
||||
|
||||
@@ -82,6 +82,7 @@ class ERR_CivilianTraffic
|
||||
{
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected ref array<ref ERR_CivilianCar> m_Cars = {};
|
||||
protected ref ERR_ParkedCarCatalog m_Catalog = new ERR_ParkedCarCatalog();
|
||||
protected float m_Next;
|
||||
protected float m_NextSpawn;
|
||||
protected int m_Serial;
|
||||
@@ -205,7 +206,10 @@ class ERR_CivilianTraffic
|
||||
m_PlayerCursor = m_PlayerCursor % observers.Count();
|
||||
vector centre = observers[m_PlayerCursor++];
|
||||
if (!Plan(centre, observers, actors, route, angles)) return false;
|
||||
ResourceName prefab = CarPrefab(Math.RandomInt(0, 3));
|
||||
m_Catalog.Find(false);
|
||||
// Keep the transport van in traffic; premium Rally cars stay in parked pools.
|
||||
ResourceName prefab = CarPrefab(2);
|
||||
if (Math.RandomInt(0, 5) != 0) prefab = m_Catalog.RoadPrefabs[Math.RandomInt(0, m_Catalog.RoadPrefabs.Count())];
|
||||
array<ResourceName> required = {prefab, DriverPrefab(), ERR_ConvoyResources.GroupPrefab(), ERR_Resources.MoveWaypoint()};
|
||||
foreach (ResourceName name : required) { Resource loaded = Resource.Load(name); if (!loaded || !loaded.IsValid()) return false; }
|
||||
// Loading can take time: check every observer again immediately before spawn.
|
||||
|
||||
@@ -24,14 +24,29 @@ class ERR_GarageVehicleRules
|
||||
|| path.EndsWith("/house_village_e_1i06.et") || path.EndsWith("/house_village_e_1i06_brown.et")
|
||||
|| path.EndsWith("/house_village_e_1i06_white.et");
|
||||
}
|
||||
static vector YardOffset(vector low, vector high, int side)
|
||||
static bool Farm(string path)
|
||||
{
|
||||
path.ToLower();
|
||||
return path.EndsWith("/barn_e_01.et") || path.EndsWith("/barn_e_01_old.et")
|
||||
|| path.EndsWith("/barn_e_01_white.et") || path.EndsWith("/barn_e_02.et")
|
||||
|| path.EndsWith("/barn_e_03_closed.et") || path.EndsWith("/barn_e_03_open.et")
|
||||
|| path.EndsWith("/cowshed_e_01_short.et") || path.EndsWith("/cowshed_e_01_long.et");
|
||||
}
|
||||
static bool FarmEnvelope(vector low, vector high)
|
||||
{
|
||||
return ERR_ForceRules.FiniteVector(low) && ERR_ForceRules.FiniteVector(high)
|
||||
&& low[0] >= -1.45 && high[0] <= 1.45 && low[2] >= -2.95 && high[2] <= 2.95
|
||||
&& low[1] >= -0.3 && high[1] <= 3.1
|
||||
&& high[0] > low[0] && high[1] > low[1] && high[2] > low[2];
|
||||
}
|
||||
static vector YardOffset(vector low, vector high, int side, float clearance = 3)
|
||||
{
|
||||
vector centre = (low + high) * 0.5; centre[1] = 0;
|
||||
// Three metres from the wall leaves almost two metres beside the car.
|
||||
if (side == 0) centre[0] = low[0] - 3;
|
||||
else if (side == 1) centre[0] = high[0] + 3;
|
||||
else if (side == 2) centre[2] = low[2] - 3;
|
||||
else centre[2] = high[2] + 3;
|
||||
// Separate farm clearance leaves room beside a taller, wider tractor.
|
||||
if (side == 0) centre[0] = low[0] - clearance;
|
||||
else if (side == 1) centre[0] = high[0] + clearance;
|
||||
else if (side == 2) centre[2] = low[2] - clearance;
|
||||
else centre[2] = high[2] + clearance;
|
||||
return centre;
|
||||
}
|
||||
}
|
||||
@@ -42,6 +57,7 @@ class ERR_GarageSite
|
||||
bool Selected;
|
||||
float NextTry;
|
||||
bool Yard;
|
||||
bool Farm;
|
||||
int Side;
|
||||
}
|
||||
class ERR_ParkedVehicle
|
||||
@@ -121,8 +137,10 @@ class ERR_GarageVehicles
|
||||
}
|
||||
// Sample both ends/sides and roof, not just the hidden centre of a garage.
|
||||
// Open doors and windows can reveal a bay; no distance alone proves it hidden.
|
||||
protected bool Hidden(vector position, vector angles, array<IEntity> actors, IEntity ignored = null)
|
||||
protected bool Hidden(vector position, vector angles, array<IEntity> actors, IEntity ignored = null, bool farm = false)
|
||||
{
|
||||
float halfWidth = 1.1, halfLength = 2.5, roofStep = 1.3;
|
||||
if (farm) { halfWidth = 1.5; halfLength = 3; roofStep = 2.5; }
|
||||
vector matrix[4]; Math3D.AnglesToMatrix(angles, matrix);
|
||||
foreach (IEntity actor : actors)
|
||||
{
|
||||
@@ -135,7 +153,7 @@ class ERR_GarageVehicles
|
||||
{
|
||||
TraceParam ray = new TraceParam();
|
||||
ray.Start = actor.GetOrigin() + "0 1.7 0";
|
||||
ray.End = position + matrix[0] * (x * 1.1) + matrix[2] * (z * 2.5) + Vector(0, 0.5 + height * 1.3, 0);
|
||||
ray.End = position + matrix[0] * (x * halfWidth) + matrix[2] * (z * halfLength) + Vector(0, 0.5 + height * roofStep, 0);
|
||||
ray.Flags = TraceFlags.WORLD | TraceFlags.ENTS; ray.LayerMask = TRACE_LAYER_CAMERA;
|
||||
ray.ExcludeArray = excluded;
|
||||
float fraction = GetGame().GetWorld().TraceMove(ray, null);
|
||||
@@ -150,12 +168,14 @@ class ERR_GarageVehicles
|
||||
if (m_Sites.Count() >= 2048) return false;
|
||||
if (!entity.GetPrefabData()) return true;
|
||||
string prefab = entity.GetPrefabData().GetPrefabName();
|
||||
bool yard = ERR_GarageVehicleRules.Yard(prefab);
|
||||
bool farm = !m_Cars.Tractors.IsEmpty() && ERR_GarageVehicleRules.Farm(prefab);
|
||||
bool yard = farm || ERR_GarageVehicleRules.Yard(prefab);
|
||||
if (!yard && !ERR_GarageVehicleRules.Garage(prefab)) return true;
|
||||
foreach (ERR_GarageSite site : m_Sites) if (site.Garage == entity) return true;
|
||||
ERR_GarageSite added = new ERR_GarageSite(); added.Garage = entity;
|
||||
added.Yard = yard; added.Side = Math.RandomInt(0, 4);
|
||||
added.Selected = Math.RandomInt(0, 100) < m_GarageChance;
|
||||
added.Yard = yard; added.Farm = farm; added.Side = Math.RandomInt(0, 4);
|
||||
int chance = m_GarageChance; if (farm) chance = Math.Min(chance, 15);
|
||||
added.Selected = Math.RandomInt(0, 100) < chance;
|
||||
m_Sites.Insert(added);
|
||||
return true;
|
||||
}
|
||||
@@ -215,7 +235,7 @@ class ERR_GarageVehicles
|
||||
if (!parked.Entity) { parked.Site.Consumed = true; m_Parked.Remove(index); return; }
|
||||
if (InUse(parked)) { Claim(index); return; }
|
||||
if (!known || !ERR_CivilianTrafficRules.Far(parked.Entity.GetOrigin(), observers, m_CleanupRadius)
|
||||
|| !Hidden(parked.Entity.GetOrigin(), parked.Entity.GetYawPitchRoll(), actors, parked.Entity)) { parked.HiddenSince = -1; return; }
|
||||
|| !Hidden(parked.Entity.GetOrigin(), parked.Entity.GetYawPitchRoll(), actors, parked.Entity, parked.Site.Farm)) { parked.HiddenSince = -1; return; }
|
||||
if (parked.HiddenSince < 0) parked.HiddenSince = now;
|
||||
if (!ERR_CivilianTrafficRules.CleanupDue(now, parked.HiddenSince)) return;
|
||||
// Recheck occupancy immediately before deletion. Claimed cars are no longer
|
||||
@@ -230,18 +250,20 @@ class ERR_GarageVehicles
|
||||
foreach (ERR_ParkedVehicle parked : m_Parked) if (parked.Site == site) return true;
|
||||
return false;
|
||||
}
|
||||
protected bool YardGround(vector position, vector transform[4])
|
||||
protected bool YardGround(vector position, vector transform[4], bool farm = false)
|
||||
{
|
||||
SCR_AIWorld world = SCR_AIWorld.Cast(GetGame().GetAIWorld());
|
||||
if (!world || !world.GetRoadNetworkManager()) return false;
|
||||
BaseRoad road; float distance;
|
||||
world.GetRoadNetworkManager().GetClosestRoad(position, road, distance, skipNavlinks: true);
|
||||
if (road && (!ERR_ForceRules.Finite(distance) || distance < road.GetWidth() * 0.5 + 4)) return false;
|
||||
float halfWidth = 1.1, halfLength = 2.5;
|
||||
if (farm) { halfWidth = 1.5; halfLength = 3; }
|
||||
float ground = SCR_TerrainHelper.GetTerrainY(position);
|
||||
for (int x = -1; x <= 1; x++)
|
||||
for (int z = -1; z <= 1; z++)
|
||||
{
|
||||
vector sample = position + transform[0] * (x * 1.1) + transform[2] * (z * 2.5);
|
||||
vector sample = position + transform[0] * (x * halfWidth) + transform[2] * (z * halfLength);
|
||||
if (!ERR_Actors.DryGround(sample) || Math.AbsFloat(SCR_TerrainHelper.GetTerrainY(sample) - ground) > 0.18) return false;
|
||||
}
|
||||
return true;
|
||||
@@ -262,7 +284,8 @@ class ERR_GarageVehicles
|
||||
vector low, high; site.Garage.GetBounds(low, high);
|
||||
if (!ERR_ForceRules.FiniteVector(low) || !ERR_ForceRules.FiniteVector(high) || (high - low).Length() > 40) continue;
|
||||
int side = site.Side; site.Side = (site.Side + 1) % 4;
|
||||
offset = ERR_GarageVehicleRules.YardOffset(low, high, side);
|
||||
float clearance = 3; if (site.Farm) clearance = 4;
|
||||
offset = ERR_GarageVehicleRules.YardOffset(low, high, side, clearance);
|
||||
angles[1] = 0; angles[2] = 0;
|
||||
if (side >= 2) angles[0] = angles[0] + 90;
|
||||
}
|
||||
@@ -274,7 +297,7 @@ class ERR_GarageVehicles
|
||||
if (site.Yard)
|
||||
{
|
||||
position = ERR_Actors.Ground(position) + "0 0.08 0";
|
||||
if (!YardGround(position, transform)) return;
|
||||
if (!YardGround(position, transform, site.Farm)) return;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -284,10 +307,11 @@ class ERR_GarageVehicles
|
||||
if (!ERR_ForceRules.Finite(fraction) || fraction >= 1 || floor.TraceNorm[1] < 0.98) return;
|
||||
position = vector.Lerp(floor.Start, floor.End, fraction) + "0 0.08 0";
|
||||
}
|
||||
if (ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetGame().GetWorld(), position) || !Clear(position, transform) || !Hidden(position, angles, actors)) return;
|
||||
if (ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetGame().GetWorld(), position) || !Clear(position, transform, null, site.Farm) || !Hidden(position, angles, actors, null, site.Farm)) return;
|
||||
m_Pending = site; m_Position = position; m_Angles = angles;
|
||||
m_Prefab = m_Cars.Prefabs[Math.RandomInt(0, m_Cars.Prefabs.Count())];
|
||||
m_PendingBike = m_Spawned % 4 == 3 && m_BikeCandidate < m_Bikes.Prefabs.Count();
|
||||
if (site.Farm) m_Prefab = m_Cars.Tractors[0];
|
||||
m_PendingBike = !site.Farm && m_Spawned % 4 == 3 && m_BikeCandidate < m_Bikes.Prefabs.Count();
|
||||
if (m_PendingBike) m_Prefab = m_Bikes.Prefabs[m_BikeCandidate];
|
||||
m_Stage = 1; return;
|
||||
}
|
||||
@@ -306,10 +330,10 @@ class ERR_GarageVehicles
|
||||
}
|
||||
ERR_GarageSite site = m_Pending; m_Pending = null;
|
||||
if (!site.Garage || site.Consumed || !ERR_Actors.Alive(site.Garage) || !Nearby(m_Position, observers, m_SpawnRadius)
|
||||
|| !ERR_CivilianTrafficRules.Far(m_Position, observers, 35) || !Hidden(m_Position, m_Angles, actors)) return;
|
||||
|| !ERR_CivilianTrafficRules.Far(m_Position, observers, 35) || !Hidden(m_Position, m_Angles, actors, null, site.Farm)) return;
|
||||
vector transform[4]; Math3D.AnglesToMatrix(m_Angles, transform);
|
||||
if (site.Yard && !YardGround(m_Position, transform)) return;
|
||||
if (!Clear(m_Position, transform)) return;
|
||||
if (site.Yard && !YardGround(m_Position, transform, site.Farm)) return;
|
||||
if (!Clear(m_Position, transform, null, site.Farm)) return;
|
||||
m_NextSpawn = Now() + m_SpawnInterval;
|
||||
IEntity entity = ERR_Actors.Spawn(m_Prefab, m_Position, m_Angles);
|
||||
Vehicle vehicle = Vehicle.Cast(entity);
|
||||
@@ -321,7 +345,9 @@ class ERR_GarageVehicles
|
||||
if (seat.GetType() == ECompartmentType.TURRET) armed = true;
|
||||
if (seat.GetType() == ECompartmentType.PILOT && seat.IsCompartmentAccessible() && !seat.GetOccupant()) driver = true;
|
||||
}
|
||||
if (!driver || armed || !ERR_GarageVehicleRules.Envelope(low, high) || !Clear(m_Position, transform, entity))
|
||||
bool fits = ERR_GarageVehicleRules.Envelope(low, high);
|
||||
if (site.Farm) fits = ERR_GarageVehicleRules.FarmEnvelope(low, high);
|
||||
if (!driver || armed || !fits || !Clear(m_Position, transform, entity, site.Farm))
|
||||
{
|
||||
ERR_Actors.DeleteSpawned(entity); if (m_PendingBike) m_BikeCandidate++; return;
|
||||
}
|
||||
@@ -357,11 +383,12 @@ class ERR_GarageVehicles
|
||||
}
|
||||
// Filled oriented body volume includes furniture, doors, other vehicles and
|
||||
// players. The garage itself is deliberately NOT excluded from collision.
|
||||
protected bool Clear(vector position, vector transform[4], IEntity ignored = null)
|
||||
protected bool Clear(vector position, vector transform[4], IEntity ignored = null, bool farm = false)
|
||||
{
|
||||
TraceOBB body = new TraceOBB();
|
||||
body.Start = position; body.End = position + "0 0.01 0";
|
||||
body.Mins = "-1.1 0.12 -2.5"; body.Maxs = "1.1 2 2.5";
|
||||
if (farm) { body.Mins = "-1.5 0.12 -3"; body.Maxs = "1.5 3.2 3"; }
|
||||
for (int i = 0; i < 3; i++) body.Mat[i] = transform[i];
|
||||
body.Flags = TraceFlags.WORLD | TraceFlags.ENTS | TraceFlags.OCEAN;
|
||||
body.Exclude = ignored;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
class ERR_ParkedCarCatalog
|
||||
{
|
||||
ref array<ResourceName> Prefabs = {};
|
||||
ref array<ResourceName> RoadPrefabs = {};
|
||||
ref array<ResourceName> Tractors = {};
|
||||
protected bool m_Checked;
|
||||
static bool Candidate(string path, bool rally)
|
||||
{
|
||||
@@ -13,27 +15,40 @@ class ERR_ParkedCarCatalog
|
||||
if (rally) return path.Contains("_rally_0");
|
||||
return !path.Contains("_rally");
|
||||
}
|
||||
void Find()
|
||||
static bool MovingCandidate(string path)
|
||||
{
|
||||
path.ToLower();
|
||||
// T601 remains usable as a parked car; native AI did not start it in 1.9.0.37.
|
||||
return Candidate(path, false) && !path.Contains("/t601/");
|
||||
}
|
||||
void Find(bool includeRally = true)
|
||||
{
|
||||
if (m_Checked) return;
|
||||
m_Checked = true;
|
||||
Prefabs.Insert(ERR_CivilianTraffic.CarPrefab(0));
|
||||
Prefabs.Insert(ERR_CivilianTraffic.CarPrefab(1));
|
||||
RoadPrefabs.Copy(Prefabs);
|
||||
SearchResourcesFilter filter = new SearchResourcesFilter();
|
||||
filter.fileExtensions = {"et"}; filter.recursive = true;
|
||||
filter.rootPath = "$" + GameProject.GetAddonID("58D0FB3206B6F859") + ":Prefabs/Vehicles/Wheeled";
|
||||
ResourceDatabase.SearchResources(filter, AddRoad);
|
||||
array<string> loaded = {}; GameProject.GetLoadedAddons(loaded);
|
||||
if (!loaded.Contains("6566A2D70498DA6B")) return;
|
||||
if (!includeRally || !loaded.Contains("6566A2D70498DA6B")) return;
|
||||
filter.rootPath = "$" + GameProject.GetAddonID("6566A2D70498DA6B") + ":Prefabs/Vehicles/Wheeled";
|
||||
ResourceDatabase.SearchResources(filter, AddRally);
|
||||
}
|
||||
protected void AddRoad(ResourceName resource, string path = "")
|
||||
{
|
||||
if (Candidate(resource, false) && Prefabs.Count() < 64 && !Prefabs.Contains(resource)) Prefabs.Insert(resource);
|
||||
if (Candidate(resource, false) && Prefabs.Count() < 64 && !Prefabs.Contains(resource))
|
||||
{
|
||||
Prefabs.Insert(resource);
|
||||
if (MovingCandidate(resource)) RoadPrefabs.Insert(resource);
|
||||
}
|
||||
}
|
||||
protected void AddRally(ResourceName resource, string path = "")
|
||||
{
|
||||
if (Candidate(resource, true) && Prefabs.Count() < 64 && !Prefabs.Contains(resource)) Prefabs.Insert(resource);
|
||||
string lower = resource; lower.ToLower();
|
||||
if (lower.EndsWith("/z7211/z7211_red_civ.et") && Tractors.IsEmpty()) Tractors.Insert(resource);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,17 @@ FrameWidgetClass {
|
||||
Name "ERR_AdminRoot" Slot FrameWidgetSlot { Anchor 0 0 1 1 OffsetLeft 0 OffsetTop 0 OffsetRight 0 OffsetBottom 0 }
|
||||
{
|
||||
ImageWidgetClass { Name "DimBackground" Slot FrameWidgetSlot { Anchor 0 0 1 1 OffsetLeft 0 OffsetTop 0 OffsetRight 0 OffsetBottom 0 } Color 0 0 0 0.65 }
|
||||
FrameWidgetClass {
|
||||
Name "Panel" Slot FrameWidgetSlot { Anchor 0.5 0.5 0.5 0.5 PositionX 0 OffsetLeft 0 PositionY 0 OffsetTop 0 SizeX 1220 OffsetRight -1220 SizeY 760 OffsetBottom -760 Alignment 0.5 0.5 }
|
||||
ScaleWidgetClass {
|
||||
Name "PanelScale" "Scale Mode" "User defined"
|
||||
Slot FrameWidgetSlot { Anchor 0 0 1 1 OffsetLeft 0 OffsetTop 0 OffsetRight 0 OffsetBottom 0 }
|
||||
{
|
||||
SizeLayoutWidgetClass {
|
||||
Name "PanelSize" AllowWidthOverride 1 WidthOverride 1220 AllowHeightOverride 1 HeightOverride 760
|
||||
Slot AlignableSlot { HorizontalAlign 1 VerticalAlign 1 }
|
||||
{
|
||||
FrameWidgetClass {
|
||||
Name "Panel" Slot LayoutSlot { HorizontalAlign 3 VerticalAlign 3 }
|
||||
{
|
||||
ImageWidgetClass { Name "PanelBackground" Slot FrameWidgetSlot { Anchor 0 0 1 1 OffsetLeft 0 OffsetTop 0 OffsetRight 0 OffsetBottom 0 } Color 0.035 0.05 0.065 0.98 }
|
||||
TextWidgetClass { Name "Title" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 20 OffsetTop 20 SizeX 990 OffsetRight -1018 SizeY 44 OffsetBottom -64 } Color 0.9 0.92 0.94 1 Text "Co10 Escape Reintroduced" "Font Size" 32 "Min Font Size" 32 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
|
||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { Name "Close" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 1064 OffsetLeft 1064 PositionY 24 OffsetTop 24 SizeX 128 OffsetRight -1192 SizeY 42 OffsetBottom -66 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Close" } } }
|
||||
@@ -162,7 +170,7 @@ ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { Name
|
||||
ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { Name "Apply_garageSpawnIntervalSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 220 OffsetLeft 220 PositionY 308 OffsetTop 308 SizeX 100 OffsetRight -320 SizeY 32 OffsetBottom -340 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Apply" } } }
|
||||
TextWidgetClass { Name "Saved_garageSpawnIntervalSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 344 OffsetTop 344 SizeX 456 OffsetRight -484 SizeY 28 OffsetBottom -372 } Color 0.9 0.92 0.94 1 Text "Waiting for server" "Font Size" 14 "Min Font Size" 14 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
|
||||
TextWidgetClass { Name "Help_garageSpawnIntervalSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 372 OffsetTop 372 SizeX 456 OffsetRight -484 SizeY 28 OffsetBottom -400 } Color 0.9 0.92 0.94 1 Text "Default 5 s. Increase to spread out spawning. Next round." "Font Size" 14 "Min Font Size" 14 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
|
||||
TextWidgetClass { Name "GarageSettingsNote" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 508 OffsetLeft 508 PositionY 284 OffsetTop 284 SizeX 456 OffsetRight -964 SizeY 110 OffsetBottom -394 } Color 0.9 0.92 0.94 1 Text "Parking settings apply next round. Used vehicles stay. Garages and clear residential yards fill gradually while hidden. Rally cars join when the DLC is loaded." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
|
||||
TextWidgetClass { Name "GarageSettingsNote" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 508 OffsetLeft 508 PositionY 284 OffsetTop 284 SizeX 456 OffsetRight -964 SizeY 110 OffsetBottom -394 } Color 0.9 0.92 0.94 1 Text "Parking settings apply next round. Used vehicles stay. Garages and clear yards fill while hidden. Rally adds cars and occasional farm tractors." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
|
||||
} }
|
||||
FrameWidgetClass { "Is Visible" 0 Name "TelemetryPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 220 OffsetLeft 220 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1220 SizeY 486 OffsetBottom -646 } {
|
||||
TextWidgetClass { Name "TelemetryHeading" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 10 OffsetTop 10 SizeX 936 OffsetRight -964 SizeY 32 OffsetBottom -42 } Color 0.9 0.92 0.94 1 Text "Mission statistics" "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
|
||||
@@ -1263,5 +1271,9 @@ TextWidgetClass { Name "SarkaSettingsHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0
|
||||
TextWidgetClass { Name "Feedback" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 248 OffsetLeft 248 PositionY 670 OffsetTop 670 SizeX 936 OffsetRight -1184 SizeY 70 OffsetBottom -740 } Color 0.9 0.92 0.94 1 Text "" "Font Size" 17 "Min Font Size" 17 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user