RestaurantServiceExpansion.Dressing.cs
using Sandbox;
using System;
using System.Threading.Tasks;
namespace PaintballBaddies;
public sealed partial class RestaurantServiceExpansion
{
public const string DumpsterPath="models/trashes/dumpster/dumpster.vmdl";
private GameObject alleyDetails;
private async Task DressServiceAlley()
{
var dumpster=await Cloud.Load<Model>("arcaneprops.dumpster");
var bag=await Cloud.Load<Model>("facepunch.binbag_a3");
var lamp=await Cloud.Load<Model>("facepunch.industrial_wall_light");
var vent=await Cloud.Load<Model>("saandy.vent_01");
var concrete=await Cloud.Load<Material>("facepunch.concrete_aggregate_a_damaged");
if(!IsValid || !root.IsValid())return;
alleyDetails=new GameObject(root,true,"Restaurant service alley details"){NetworkMode=NetworkMode.Never};
// Keep the validated ramp/arrival lane open. Rubbish collection has its
// own corner, away from food deliveries, with enough space for cover.
Place("Restaurant garbage dumpster",dumpster,new Vector3(1258,1510,32.16f),90,1.15f,true,true);
foreach(var spec in new[]{(P:new Vector3(1210,1556,32.16f),Yaw:35f,S:1.2f),(P:new Vector3(1185,1535,32.16f),Yaw:170f,S:1f),(P:new Vector3(1268,1573,32.16f),Yaw:70f,S:.9f)})
Detail(bag,"Tied restaurant bin bag",spec.P,Rotation.FromYaw(spec.Yaw),spec.S,true);
Detail(Model.Load("models/foundry/foundry_pallet/foundry_pallet.vmdl"),"Returned delivery pallet",new Vector3(826,1452,32.16f),Rotation.FromYaw(87),1.35f,true);
Detail(Model.Load("models/citizen_props/crate01.vmdl"),"Dry goods crate",new Vector3(826,1452,38.5f),Rotation.FromYaw(87),.82f,true);
Detail(Model.Load("models/citizen_props/crate01.vmdl"),"Stacked dry goods crate",new Vector3(827,1451,70.8f),Rotation.FromYaw(88),.70f,true);
Detail(lamp,"Caged delivery doorway light",new Vector3(774,1143,195),Rotation.FromYaw(180),1.25f);
Detail(lamp,"Caged waste collection light",new Vector3(774,1505,183),Rotation.FromYaw(180),1.1f);
Detail(vent,"Kitchen extractor wall outlet",new Vector3(774,1365,201),Rotation.FromPitch(90),2.3f);
Detail(Model.Load("models/foundry/wall_service_pipe/pipe.vmdl"),"Restaurant rainwater pipe",new Vector3(778,1618,125),Rotation.FromPitch(90),1.6f);
var warm=new GameObject(alleyDetails,true,"Waste corner warm light"){NetworkMode=NetworkMode.Never,WorldPosition=new Vector3(795,1490,179)};
var light=warm.Components.Create<PointLight>();light.LightColor=new Color(1,.76f,.43f)*.22f;light.Radius=280;light.Shadows=false;
var brick=root.Children.First(g=>g.Name=="delivery_brick_wall").Components.Get<ModelRenderer>();
brick.Tint=new Color(.72f,.67f,.55f);
var yard=root.Children.First(g=>g.Name=="delivery_yard").Components.Get<ModelRenderer>();
yard.MaterialOverride=concrete is {IsError:false} ? concrete : Material.Load("materials/industrial_arena/floor.vmat");yard.Tint=new Color(.7f,.68f,.62f);
// Physical signboards and coping give the broad facade depth. Thin
// render-only dressing cannot change the navigation or trap a player.
Box("Delivery sign backing",new Vector3(770,1143,166),new Vector3(2,156,38),new Color(.08f,.105f,.09f));
Box("Loading canopy",new Vector3(800,1143,210),new Vector3(69,205,3),new Color(.22f,.24f,.22f));
for(int i=0;i<13;i++)Box("Canopy folded seam",new Vector3(800,1047+i*16,212),new Vector3(69,1,2),new Color(.31f,.32f,.29f));
foreach(float y in new[]{1047f,1239f})Box("Canopy support",new Vector3(796,y,199),new Vector3(62,2,3),new Color(.09f,.1f,.09f),Rotation.FromPitch(19));
Box("Brick parapet coping",new Vector3(771,1255,249),new Vector3(13,1200,4),new Color(.23f,.25f,.23f));
Box("Drain grate",new Vector3(802,1510,32.23f),new Vector3(24,45,.12f),new Color(.45f,.4f,.32f),material:"materials/generic/floor_drain_a.vmat");
foreach(float y in new[]{986f,1310f})Box("Faded loading bay line",new Vector3(1010,y,32.23f),new Vector3(332,2,.08f),new Color(.62f,.46f,.15f),material:"materials/industrial_arena/floor.vmat");
// Wayfinding is readable from inside the kitchen, as well as outside.
Box("Interior dock sign backing",new Vector3(733,1143,166),new Vector3(2,132,29),new Color(.06f,.12f,.09f));
Sign("LOADING DOCK",new Vector3(731,1143,171),0,.42f);
Sign("DELIVERIES / WASTE",new Vector3(731,1143,158),0,.21f);
Sign("WASTE COLLECTION",new Vector3(772,1510,151),180,.31f);
Sign("LIDS DOWN. SAUSAGES OUT.",new Vector3(772,1510,140),180,.14f);
foreach(var p in new[]{new Vector3(1170,1420,35),new Vector3(1280,970,35)})
{
var spawn=new GameObject(alleyDetails,true,"PB Alternate dock start"){NetworkMode=NetworkMode.Never,WorldPosition=p,WorldRotation=Rotation.FromYaw(180)};
spawn.Components.Create<SpawnPoint>();
}
foreach(var p in new[]{new Vector3(1250,1520,32.18f),new Vector3(1180,1550,32.18f),new Vector3(1060,1120,32.18f),new Vector3(1080,1240,32.18f),new Vector3(822,1490,32.18f)})
Wear(p,Vector3.Up,new Vector2(100,70),new Color(.12f,.10f,.07f,.58f),p.y%137);
foreach(float y in new[]{910f,1010f,1340f,1440f,1540f,1620f})
Wear(new Vector3(766.68f,y,60),Vector3.Forward,new Vector2(105,54),new Color(.17f,.14f,.09f,.48f),0);
Wear(new Vector3(766.68f,1365,174),Vector3.Forward,new Vector2(64,95),new Color(.08f,.075f,.06f,.47f),180);
DressAlleyBackdrop(vent,lamp);
}
private void DressAlleyBackdrop(Model vent,Model lamp)
{
// This is scenery beyond the closed arena boundary, not another combat
// route. Textured ground and neighbouring facades hide the map edge.
Place("Neighbouring service buildings","models/restaurant/service/alley_backdrop.vmdl",Vector3.Zero,0,1,false,false).Components.Get<ModelRenderer>().Tint=new Color(.59f,.53f,.46f);
Place("Service lane beyond delivery gate","models/restaurant/service/alley_lane.vmdl",Vector3.Zero,0,1,false,false).Components.Get<ModelRenderer>().Tint=new Color(.68f,.68f,.65f);
foreach(float y in new[]{960f,1520f})
{
Box("Neighbour roller shutter",new Vector3(1638,y,103),new Vector3(4,148,142),new Color(.26f,.29f,.29f),material:"models/restaurant/breakfast/steel.vmat");
for(int n=0;n<18;n++)Box("Roller shutter folded slat",new Vector3(1634.8f,y,35+n*8),new Vector3(1.5f,145,1.1f),new Color(.14f,.16f,.16f),material:"models/restaurant/breakfast/steel.vmat");
foreach(float offset in new[]{-77f,77f})Box("Roller shutter guide",new Vector3(1634,y+offset,104),new Vector3(5,4,144),new Color(.12f,.14f,.14f),material:"models/restaurant/breakfast/steel.vmat");
Box("Roller shutter housing",new Vector3(1630,y,180),new Vector3(14,162,14),new Color(.22f,.24f,.24f),material:"models/restaurant/breakfast/steel.vmat");
Detail(vent,"Neighbour kitchen vent",new Vector3(1635,y+170,218),Rotation.FromPitch(90),1.6f);
Detail(lamp,"Neighbour service lamp",new Vector3(1634,y,207),Rotation.Identity,1);
}
foreach(float y in new[]{1123f,1397f})Box("Delivery gate hinge post",new Vector3(1370,y,79),new Vector3(5,5,96),new Color(.25f,.28f,.28f));
Box("Delivery gate latch",new Vector3(1364,1260,77),new Vector3(5,18,3),new Color(.52f,.48f,.37f));
Box("Vehicle gate notice",new Vector3(1362,1220,88),new Vector3(1,83,19),new Color(.08f,.12f,.1f),material:"models/restaurant/breakfast/iron.vmat");
Sign("DELIVERY GATE",new Vector3(1360,1220,90),0,.20f);
Sign("CLOSED DURING SERVICE",new Vector3(1360,1220,82),0,.10f);
}
private void Detail(Model model,string name,Vector3 at,Rotation rotation,float scale,bool floor=false)
{
if(model is null || model.IsError)return;
var center=model.Bounds.Center;if(floor)center=center.WithZ(model.Bounds.Mins.z);
var go=new GameObject(alleyDetails,true,name){NetworkMode=NetworkMode.Never,WorldPosition=at-rotation*(center*scale),WorldRotation=rotation,WorldScale=new Vector3(scale)};
go.Components.Create<ModelRenderer>().Model=model;
}
private void Box(string name,Vector3 center,Vector3 size,Color tint,Rotation? rotation=null,string material="materials/foundry/metalplates006/metalplates006.vmat")
{
var model=Model.Load("models/dev/box.vmdl");var r=rotation??Rotation.Identity;
var go=new GameObject(alleyDetails,true,name){NetworkMode=NetworkMode.Never,WorldScale=size/model.Bounds.Size,WorldRotation=r};
go.WorldPosition=center-r*(model.Bounds.Center*go.WorldScale);
var render=go.Components.Create<ModelRenderer>();render.Model=model;render.Tint=tint;render.MaterialOverride=Material.Load(material);
}
private void Wear(Vector3 at,Vector3 normal,Vector2 size,Color color,float spin)
{
var go=new GameObject(alleyDetails,true,"Service alley grime"){NetworkMode=NetworkMode.Never,WorldPosition=at,WorldRotation=Rotation.LookAt(-normal)};
var d=go.Components.Create<Decal>();d.Decals=[new(){ColorTexture=FoundryPaintWear.GrimeTexture((int)spin),Width=1,Height=1,ColorMix=1}];
d.Size=size;d.Depth=.10f;d.SortLayer=20;d.Parallax=0;d.ColorTint=color;d.Rotation=spin;d.LifeTime=0;d.Transient=false;d.AttenuationAngle=.4f;
}
}