node-wad
Version:
A Doom WAD parser and writer.
266 lines (195 loc) • 7.62 kB
text/coffeescript
###
Doom map editing.
Does not support nodebuilding
yet.
###
BufferWriter = require("buffer-utils").BufferWriter
Bitfield = require("bitfield")
isClockwise = (positions) ->
edges = []
for i1 in [0..positions.length - 1]
if i1 is positions.length - 1
i2 = 0
else
i2 = i1 + 1
edges.push( (positions[i2][0] - positions[i1][0]) * (positions[i2][1] + positions[i1][1]) )
return edges.reduce((x, y) -> x + y) > 0
writeChars = (st, bw, cap, maxLen) ->
if not cap? then cap = 0
if not maxLen? then maxLen = st.toString('ascii').length
if cap > 0
padding = "\x00".repeat(cap - st.length)
else
padding = ""
for c in st.slice(0, maxLen).toString() + padding
data = (new Buffer(c, 'ascii'))
bw.writeUInt8(data.readUInt8())
class WSector
constructor: (, , , , , , , ) ->
if not ? then = 0
if not ? then = 128
if not ? then = "FLAT1" else = .toString('ascii')
if not ? then = "FLAT2" else = .toString('ascii')
if not ? then = 192
if not ? then = 0
if not ? then = 0
write: (bw) =>
bw
.writeInt16LE()
.writeInt16LE()
writeChars(, bw, 8)
writeChars(, bw, 8)
bw
.writeInt16LE()
.writeUInt16LE()
.writeUInt16LE()
return @
defaultFlags = new Bitfield(16)
defaultFlags.set(0)
defaultFlags.set(1)
defaultFlags.set(2)
defaultFlags.set(8)
defaultFlags.set(9)
defaultFlags.set(10)
defaultFlags = defaultFlags.buffer.readUInt16LE()
class WThing
constructor: (, , , , ) ->
if not ? then = defaultFlags
if not ? then = 0
write: (bw) =>
bw
.writeInt16LE()
.writeInt16LE()
.writeUInt16LE()
.writeUInt16LE()
.writeUInt16LE()
return @
class WSidedef
constructor: (, , , , , , ) ->
if instanceof WSector then = .index
if not ? then = -1
if not ? then = "STARTAN2" # MWAHAHAHAHAHA
if not ? then = "-"
if not ? then = "-"
if not ? then = 0
if not ? then = 0
write: (bw) =>
bw
.writeInt16LE()
.writeInt16LE()
writeChars(, bw, 8)
writeChars(, bw, 8)
writeChars(, bw, 8)
bw.writeInt16LE()
return @
class WLinedef
constructor: (, , , , , , ) ->
if instanceof WVertex then = .index
if instanceof WVertex then = .index
if instanceof WSidedef then = .index
if instanceof WSidedef then = .index
if not ? then = 0xFFFF
if not ? then = 0xFFFF
if not ? then = (if isnt 0xFFFF then 0b100 else 0b001)
console.log(, )
write: (bw) =>
bw
.writeUInt16LE()
.writeUInt16LE()
.writeUInt16LE()
.writeUInt16LE()
.writeUInt16LE()
.writeUInt16LE()
.writeUInt16LE()
return @
class WVertex
constructor: (, , ) ->
write: (bw) =>
bw
.writeInt16LE()
.writeInt16LE()
return @
distanceTo: (v2) =>
Math.sqrt(Math.abs(Math.pow(v2?.x - , 2) + Math.pow(v2?.y - , 2)))
class MapEdit
constructor: () ->
= []
= []
= []
= []
= []
: (wad, pos) ->
# wip
m = new MapEdit(wad.lumps[pos].name)
return m
toLumps: (wad) =>
wad.addLump()
vb = new BufferWriter()
.forEach((s) -> s.write(vb))
wad.addLump("THINGS", vb.getContents())
.forEach((l) -> l.write(vb))
wad.addLump("LINEDEFS", vb.getContents())
.forEach((s) -> s.write(vb))
wad.addLump("SIDEDEFS", vb.getContents())
.forEach((v) -> v.write(vb))
data = vb.getContents()
wad.addLump("VERTEXES", data)
.forEach((v) -> v.write(vb))
wad.addLump("SECTORS", vb.getContents())
return @ # for chaining
addVertex: (x, y) =>
.push(new WVertex(x, y, .length))
return @ # for chaining
addThing: (x, y, type, angle, flags) =>
.push(new WThing(x, y, angle, type, flags))
return @ # for chaining
buildSector: (positions, sectorData, lineData) =>
if not sectorData? then sectorData = {}
if not lineData? then lineData = {}
newv = []
newlines = []
newpos = .length
for p in positions
if p in .map((v) -> [v.x, v.y])
v = [.map((v2) -> [v2.x, v2.y]).indexOf(p)]
else
v = new WVertex(p[0], p[1], .length)
console.log([v.x, v.y],
.filter((v2) ->
dist = v.distanceTo(v2)
return dist < 16
)
.map((v2) -> [v2.x, v2.y]))
.push(v)
newv.push(v)
vi = 0
sector = new WSector(
sectorData.floorHeight,
sectorData.ceilHeight,
sectorData.floorTex,
sectorData.ceilTex,
sectorData.light,
sectorData.special,
sectorData.tag,
.index
)
.push(sector)
for v1 in newv
v2 = newv[if vi < newv.length - 1 then vi + 1 else 0]
side = new WSidedef(lineData.xOff, lineData.yOff, lineData.upTex, lineData.midTex, lineData.lowTex, sector, .length)
.push(side)
if v1.index >= newpos and v2.index >= newpos
line = new WLinedef(v1, v2, lineData.flags, lineData.lineType, lineData.tag, side, null)
.push(line)
else
for l in
if l.begin == v1.index and l.end == v2.index
line = l
break
if line.backSidedef < 0xFFFF # testing stuff
line.frontSidedef = side
else
line.backSidedef = side
vi++
return @
module.exports = MapEdit