Skip to content

Instantly share code, notes, and snippets.

@zeddash
Last active April 15, 2020 14:03
Show Gist options
  • Select an option

  • Save zeddash/e081c7ec579943e2c8dcdc0d07681e8a to your computer and use it in GitHub Desktop.

Select an option

Save zeddash/e081c7ec579943e2c8dcdc0d07681e8a to your computer and use it in GitHub Desktop.
staircase generator
{
"scripts": [],
"styles": []
}
//https://developer.valvesoftware.com/wiki/Valve_Map_Format
/*
style
step
top
side
under
stringer
top
side
ramp
side
*/
const stairStyles = {
dev:{
maps:[],
step: {
top:"DEV/GRAYGRID",
sides:"DEV/REFLECTIVITY_30",
positions: {
top:{
u:"world",
v:"world"
},
sides:{
u:"world",
v:"world"
}
}
},
stringer:{
top:"DEV/REFLECTIVITY_10B",
sides:"DEV/REFLECTIVITY_10B",
positions: {
top:{
u:"world",
v:"world"
},
sides:{
u:"world",
v:"world"
}
}
}
},
wooden1:{
maps:["pl_badwater"],
step: {
top:"WOOD/WOOD_BEAM03",
sides:"WOOD/WALL020B",
positions: {
top:{
u:"world",
v:"world"
},
sides:{
u:"world",
v:"world"
}
}
},
stringer:{
top:"WOOD/WOOD_BEAM03",
sides:"WOOD/WOOD_BEAM03",
positions: {
top:{
u:"random",
v:"world"
},
sides:{
u:"world",
v:"world"
}
}
}
},
metal1:{
maps:[],
step: {
top:"METAL/IMETAL005",
sides:"METAL/METALSTAIR001A",
positions: {
top:{
u:"random",
v:"random"
},
sides:{
u:"world",
v:-48 //bottom step is y -48, each step up adds 32 so second step is -16, then 16, etc
}
}
},
stringer:{
top:"METAL/METALTRACK001",
sides:"METAL/METALTRACK001",
positions: {
top:{
u:"random",
v:"world"
},
sides:{
u:"random",
v:"world"
}
}
}
}
}
const settings = {
step:{
depth:12,
height:8,
count:16
},
type:"ramp", //ramp, ramp + stringer, hanging tread, hanging tread + stringer, spiral, spiral + stringer
stringer:null,
spiral:null
}
const data = {
id:0,
uv: {
x: {
u:[0, -1, 0],
v:[0, 0, -1]
},
y: {
u:[1, 0, 0],
v:[0, 0, -1]
},
z: {
u:[-1, 0, 0],
v:[0, -1, 0]
}
},
max: {
x:0,
y:0,
z:0
},
checkMax: (d,v) => data.max[d] = Math.max(data.max[d], v)
}
class VMF {
//Convert JS object into VMF format
constructor(object) {
this.object = object
}
ind = indent => ` `.repeat(indent)
objectToVMF = (obj, i = 0) =>
`${[...Object.keys(obj)].map(x => typeof obj[x] == "object" ? Array.isArray(obj[x]) ?
/*Array*/ obj[x].map(y => `${this.ind(i)}${x}\n${this.ind(i)}{\n${this.objectToVMF(y,i+1)}\n${this.ind(i)}}`).join(`\n`) :
/*Object*/ `${this.ind(i)}${x}\n${this.ind(i)}{\n${this.objectToVMF(obj[x],i+1)}\n${this.ind(i)}}` :
/*Other*/ `${this.ind(i)}"${x}" "${obj[x]}"`).join(`\n`)}`
toString = () => {
this.object.cordon.maxs = `(${data.max.x+64} ${data.max.y+64} ${data.max.z+64})` //Move this
return this.objectToVMF(this.object,0)
}
}
const GetAdjacentVertex = (d, x1, y1, z1, x2, y2, z2) => {
switch (d) {
case "xp":
case "yn":
return [x1, y1, z2]
case "xn":
case "zp":
return [x1, y2, z1]
case "yp":
case "zn":
return [x2, y1, z1]
}
}
const ModifyU = (d, arr) => d[1] == "p" ? arr.map(x => x != 0 ? x *-1 : x) : arr
const SideBuilder = (d, x1, y1, z1, x2, y2, z2, x3, y3, z3) => {
if(x3 == undefined || y3 == undefined || z3 == undefined) { //orthagonal
return SideBuilder(d, x1, y1, z1, x2, y2, z2, ...GetAdjacentVertex(d, x1, y1, z1, x2, y2, z2))
} else { //non-orthagonal
return {
id:data.id++,
plane: `(${x1} ${y1} ${z1}) (${x3} ${y3} ${z3}) (${x2} ${y2} ${z2})`,
material: "DEV/REFLECTIVITY_30",
uaxis:`[${ModifyU(d,data.uv[d[0]].u).join(" ")} 0] 0.25`,
vaxis:`[${data.uv[d[0]].v.join(" ")} 0] 0.25`,
rotation:0,
lightmapscale:16,
smoothing_groups:0
}
}
}
const BrushBuilder = (x,y,z,w,d,h,t="cuboid",o) => {
data.checkMax("x",x+w)
data.checkMax("y",y+d)
data.checkMax("z",z+h)
switch(t) {
case "cuboid":
return {
id:data.id++,
side:[
SideBuilder("xp", x+w, y, z, x+w, y+d, z+h),
SideBuilder("xn", x, y, z, x, y+d, z+h),
SideBuilder("yp", x, y+d, z, x+w, y+d, z+h),
SideBuilder("yn", x, y, z, x+w, y, z+h),
SideBuilder("zp", x, y, z+h, x+w, y+d, z+h),
SideBuilder("zn", x, y, z, x+w, y+d, z)
],
editor: {
color: "255 255 255",
visgroupshown: 1,
visgroupautoshown: 1
//,groupid:0
}
}
case "ramp": //Lower end towards x-axis
return {
id:data.id++,
side:[
SideBuilder("xp", x+w, y, z, x+w, y+d, z+h),
SideBuilder("xn", x y, z, x, y+d, z+h),
SideBuilder("yp", x, y+d, z, x+w, y+d, z+h),
SideBuilder("zp", x, y, z, x+w, y+d, z+h, x, y+d, z+h),
SideBuilder("zn", x, y, z, x+w, y+d, z)
],
editor: {
color: "255 255 255",
visgroupshown: 1,
visgroupautoshown: 1
//,groupid:0
}
}
}
}
const StaircaseMap = {
versioninfo: {
editorversion:420,
editorbuild:1337,
mapversion:1,
formatversion:100,
prefab:0
},
viewsettings: {
bSnapToGrid:1,
bShowGrid:1,
bShowLogicalGrid:0,
nGridSpacing:64,
bShow3DGrid:0
},
world: {
id:data.id++,
mapversion:1,
classname:"worldspawn",
skyname:"sky_tf2_04",
maxpropscreenwidth:-1,
detailvbsp:"detail.vbsp",
detailmaterial:"detail/detailsprites",
solid:[
BrushBuilder(0,0,0,128,384,128),
BrushBuilder(192,0,0,128,128*1.5,128, "ramp")
]
},
cameras: {
activecamera:-1
},
cordon: {
mins:"(-64 -64 -64)",
maxs:"(1024 1024 1024)",
active:1
}
}
console.log(new VMF(StaircaseMap).toString())
body{
background: black;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment