UDBScript: groups all classes, objects, and methods in a new UDB namespace, usable with the new feature version 4. Updated the documentation accordingly. Resolves #679

This commit is contained in:
biwa 2022-01-06 18:46:37 +01:00
parent 7fbd07e586
commit d59342ed7f
54 changed files with 961 additions and 424 deletions

View file

@ -1,26 +1,33 @@
class Pen
{
constructor(pos = new Vector2D(0, 0))
constructor(pos = [ 0, 0 ])
{
this.angle = Math.PI / 2;
this.snaptogrid = false;
this.vertices = [];
this.curpos = new Vector2D(pos);
this.curpos = this.makevector(pos);
}
makevector(pos)
{
if(typeof UDB == 'undefined')
return new Vector2D(pos);
return new UDB.Vector2D(pos);
}
moveTo(pos)
{
this.curpos = new Vector2D(pos);
this.curpos = this.makevector(pos);
return this;
}
moveForward(distance)
{
this.curpos = new Vector2D(
this.curpos = this.makevector([
this.curpos.x + Math.cos(this.angle) * distance,
this.curpos.y + Math.sin(this.angle) * distance
);
]);
return this;
}
@ -91,7 +98,12 @@ class Pen
if(close)
this.vertices.push(this.vertices[0]);
var result = Map.drawLines(this.vertices);
var result;
if(typeof UDB == 'undefined')
result = Map.drawLines(this.vertices);
else
result = UDB.Map.drawLines(this.vertices);
this.vertices = [];

View file

@ -1,5 +1,7 @@
// Inspired by ribbiks's DBX Lua script: https://github.com/ribbiks/doom_lua/
`#version 4`;
`#name Bevel Linedefs`;
`#description Bevels linedefs at their shared vertices. Only works when the vertices have only two linedefs connected`;
@ -14,7 +16,7 @@ size
}
`;
let lines = Map.getSelectedLinedefs();
let lines = UDB.Map.getSelectedLinedefs();
if(lines.length < 2)
die('You need to select at least 2 connected linedefs');
@ -35,9 +37,9 @@ vertices.forEach(v => {
// Split all lines at the given size from the vertex away
v.getLinedefs().forEach(ld => {
if(ld.start == v)
ld.split(ld.line.getCoordinatesAt(1.0 / ld.length * ScriptOptions.size));
ld.split(ld.line.getCoordinatesAt(1.0 / ld.length * UDB.ScriptOptions.size));
else
ld.split(ld.line.getCoordinatesAt(1.0 - (1.0 / ld.length * ScriptOptions.size)));
ld.split(ld.line.getCoordinatesAt(1.0 - (1.0 / ld.length * UDB.ScriptOptions.size)));
});
// Get one of the connected linedef...

View file

@ -1,3 +1,5 @@
`#version 4`;
`#name Create Line Portal`;
`#description Creates a quick portal (line action 301) between the selected lines. Only works in UDMF. Only works when exactly two lines are selected. Both lines must have exactly the same length. Draws a sector at the back of the selected lines.`;
@ -29,11 +31,11 @@ function drawPortalSector(line, depth)
// the first and last point need to be at the same position
// to get a complete drawing
let points = [
new Vector2D(0, 0),
new Vector2D(0, depth),
new Vector2D(line.getLength(), depth),
new Vector2D(line.getLength(), 0),
new Vector2D(0, 0)
new UDB.Vector2D(0, 0),
new UDB.Vector2D(0, depth),
new UDB.Vector2D(line.getLength(), depth),
new UDB.Vector2D(line.getLength(), 0),
new UDB.Vector2D(0, 0)
];
// The points need to be rotated by the line's angle and moved
@ -45,19 +47,19 @@ function drawPortalSector(line, depth)
}
// Draw the lines
if(!Map.drawLines(points))
if(!UDB.Map.drawLines(points))
throw 'Failed drawing space behind line ' + line;
// Set the front middle texture for the new 1-sided linedefs
Map.getMarkedLinedefs().filter(ld => ld.back == null).forEach(ld => ld.front.middleTexture = ScriptOptions.texture)
UDB.Map.getMarkedLinedefs().filter(ld => ld.back == null).forEach(ld => ld.front.middleTexture = UDB.ScriptOptions.texture)
}
// The line action for portals only works in UDMF (GZDoom and Eternity Engine)
if(!Map.isUDMF)
if(!UDB.Map.isUDMF)
throw 'This script only works in UDMF maps';
// Get selected linedefs
let lines = Map.getSelectedLinedefs();
let lines = UDB.Map.getSelectedLinedefs();
// Make sure exactly two lines are selected
if(lines.length != 2)
@ -69,7 +71,7 @@ if(lines[0].line.getLength() != lines[1].line.getLength())
throw 'Both lines need to have the same length';
// Get a new tag to use for the portal
let newtag = Map.getNewTag();
let newtag = UDB.Map.getNewTag();
// Set the action, arg, and tag of both lines
lines[0].action = lines[1].action = 301; // Line_QuickPortal
@ -77,5 +79,5 @@ lines[0].args[0] = lines[1].args[0] = 0;
lines[0].tag = lines[1].tag = newtag;
// Draw the sectors behind the portal
drawPortalSector(lines[0].line, ScriptOptions.depth);
drawPortalSector(lines[1].line, ScriptOptions.depth);
drawPortalSector(lines[0].line, UDB.ScriptOptions.depth);
drawPortalSector(lines[1].line, UDB.ScriptOptions.depth);

View file

@ -1,3 +1,5 @@
`#version 4`;
`#name Create PolyObject`;
`#description Creates a poliyobject from a selected line. The anchor will be placed at the mouse cursor.`;
@ -18,17 +20,17 @@ startspottype
`;
// Check if the mouse is in the map
if(!Map.mousePosition.isFinite())
die('Mouse cursor is not at a valid map position');
if(!UDB.Map.mousePosition.isFinite())
UDB.die('Mouse cursor is not at a valid map position');
// Get the mouse position in the map, snapped to the grid
var cursorpos = Map.snappedToGrid(Map.mousePosition);
var cursorpos = UDB.Map.snappedToGrid(UDB.Map.mousePosition);
// The polyobject number that will be used
var polyobjectnumber = -1;
// Get selected linedefs
var lines = Map.getSelectedLinedefs();
var lines = UDB.Map.getSelectedLinedefs();
// Make sure exactly one linedef is selected
if(lines.length != 1)
@ -38,7 +40,7 @@ if(lines.length != 1)
var usednumbers = []
// Find all polyobject things and get their polyobject numbers
Map.getThings().filter(o => o.type >= 9300 && o.type <= 9303).forEach(o => {
UDB.Map.getThings().filter(o => o.type >= 9300 && o.type <= 9303).forEach(o => {
usednumbers.push(o.angle);
});
@ -61,9 +63,9 @@ lines[0].args[0] = polyobjectnumber;
var anchorpos = lines[0].line.getCoordinatesAt(0.5); // Center of line
// Create the polyobject start spot thing
var t = Map.createThing(cursorpos, ScriptOptions.startspottype);
var t = UDB.Map.createThing(cursorpos, UDB.ScriptOptions.startspottype);
t.angle = polyobjectnumber;
// Create the polyobject anchor thing
t = Map.createThing(anchorpos, 9300); // 9300 = Polyobject Anchor
t = UDB.Map.createThing(anchorpos, 9300); // 9300 = Polyobject Anchor
t.angle = polyobjectnumber

View file

@ -1,5 +1,7 @@
// Inspired by ribbiks's DBX Lua script: https://github.com/ribbiks/doom_lua/
`#version 4`;
`#name Flank Linedefs`;
`#description Flanks the selected linedefs with newly created linedefs at both ends. Texture changes are only applied to 1-sided lines`;
@ -34,18 +36,18 @@ fixoriginaloffset
}
`;
let lines = Map.getSelectedOrHighlightedLinedefs();
let lines = UDB.Map.getSelectedOrHighlightedLinedefs();
if(lines.length == 0)
die('No linedefs selcted or highlighted');
lines.forEach(ld => {
// The line has to be long enough the flank it
if(ld.length < ScriptOptions.width * 2)
if(ld.length < UDB.ScriptOptions.width * 2)
die(ld + ' is too short to flank');
// Compute how far along the line the flank with is
let length = 1.0 / ld.length * ScriptOptions.width;
let length = 1.0 / ld.length * UDB.ScriptOptions.width;
// Remember the original texture offset
let origoffset = ld.front.offsetX;
@ -67,23 +69,23 @@ lines.forEach(ld => {
ld.split(v2);
// Only do texture stuff to one-sided lines, and if a texture is set
if(ld.back == null && ScriptOptions.texture != '')
if(ld.back == null && UDB.ScriptOptions.texture != '')
{
// Loop through all marked lines (which is the original line and the newly created flanks)
Map.getMarkedLinedefs().forEach(ld => {
UDB.Map.getMarkedLinedefs().forEach(ld => {
// Only apply the flank texture if the current linedef has one of the original vertices
if(vertices.includes(ld.start) || vertices.includes(ld.end))
{
ld.front.middleTexture = ScriptOptions.texture;
ld.front.offsetX = ScriptOptions.offset;
ld.front.middleTexture = UDB.ScriptOptions.texture;
ld.front.offsetX = UDB.ScriptOptions.offset;
}
else if(ScriptOptions.fixoriginaloffset) // Fix original offset, if desired
else if(UDB.ScriptOptions.fixoriginaloffset) // Fix original offset, if desired
{
ld.front.offsetX = origoffset + ScriptOptions.width;
ld.front.offsetX = origoffset + UDB.ScriptOptions.width;
}
});
}
// Clear all marks, since we'll need the correct marks in the next loop iteration
Map.clearAllMarks();
UDB.Map.clearAllMarks();
});

View file

@ -1,3 +1,5 @@
`#version 4`;
`#name Jitter Vertices`;
`#description Jitters the selected vertices. If no vertices are selected all vertices in the map are jittered. Does not make sure that the resulting geometry is still valid.`;
@ -26,16 +28,16 @@ function getRandomValue(min, max)
}
// Get selected vertices
let vertices = Map.getSelectedVertices();
let vertices = UDB.Map.getSelectedVertices();
// No vertices selected? Get all vertices!
if(vertices.length == 0)
vertices = Map.getVertices();
vertices = UDB.Map.getVertices();
// Jitter each vertex
vertices.forEach(v => {
v.position += [
getRandomValue(ScriptOptions.min, ScriptOptions.max),
getRandomValue(ScriptOptions.min, ScriptOptions.max),
getRandomValue(UDB.ScriptOptions.min, UDB.ScriptOptions.max),
getRandomValue(UDB.ScriptOptions.min, UDB.ScriptOptions.max),
];
});

View file

@ -1,3 +1,5 @@
`#version 4`;
`#name Make Door`;
`#description Creates a door from a selected sector. Functionality is the same as the built-in "make door" action.`;
@ -24,21 +26,21 @@ ceilingtexture {
`;
let sectors = Map.getSelectedSectors();
let sectors = UDB.Map.getSelectedOrHighlightedSectors();
if(sectors.length == 0)
die('You need to select at least one sector!');
UDB.die('You need to select at least one sector!');
sectors.forEach(s => {
s.ceilingHeight = s.floorHeight;
s.ceilingTexture = ScriptOptions.ceilingtexture;
s.ceilingTexture = UDB.ScriptOptions.ceilingtexture;
s.getSidedefs().forEach(sd => {
if(sd.other == null) // 1-sided lines
{
sd.middleTexture = ScriptOptions.doortrack;
sd.middleTexture = UDB.ScriptOptions.doortrack;
if(Map.isUDMF)
if(UDB.Map.isUDMF)
sd.line.flags.dontpegbottom = true;
else
sd.line.flags['16'] = true;
@ -50,10 +52,10 @@ sectors.forEach(s => {
if(sd.isFront)
sd.line.flip();
sd.other.upperTexture = ScriptOptions.doortexture;
sd.other.upperTexture = UDB.ScriptOptions.doortexture;
// Set the action
if(Map.isDoom)
if(UDB.Map.isDoom)
sd.line.action = 1;
else
{
@ -63,7 +65,7 @@ sectors.forEach(s => {
sd.line.args[2] = 150; // Close delay
sd.line.args[3] = 0; // Light tag
if(Map.isHexen)
if(UDB.Map.isHexen)
{
sd.line.activate = 1024; // Player presses use
sd.line.flags['512'] = true; // Can be used repeatedly

View file

@ -1,10 +1,11 @@
`#version 4`;
`#name Triangulate Sectors`;
`#description Triangulates the selected or highlighted sectors into new sectors. Note that the triangulation will not "be beautiful", and that the sectors with islands may cause problems.`;
let sectors = Map.getSelectedOrHighlightedSectors();
let sectors = UDB.Map.getSelectedOrHighlightedSectors();
if(sectors.length == 0)
die('No sectors selected or highlighted');
UDB.die('No sectors selected or highlighted');
// Draw all triangles. Remember to add the first point at the end so that the drawing will be closed
sectors.forEach(s => s.getTriangles().forEach(t => Map.drawLines([...t, t[0]])));
sectors.forEach(s => s.getTriangles().forEach(t => UDB.Map.drawLines([...t, t[0]])));

View file

@ -1,3 +1,5 @@
`#version 4`;
`#name Draw Voodoo Doll Closet`;
`#description Draws a voodoo doll closet from the mouse cursor's position. Requires Boom actions. If linedefs are selected when the script is run, those linedefs will have actions assigned that unblock the voodoo doll: if they have a SW1/SW2 texture a S1 action will be applied, if they are double-sided a W1 action will be applied.`;
@ -40,60 +42,60 @@ looping
`;
// Make sure the has a correct minimum length
if(ScriptOptions.length < 96)
if(UDB.ScriptOptions.length < 96)
throw 'Voodoo doll closet has to be at least 96 map units long!';
// Get the mouse position in the map, snapped to the grid
let basepos = Map.snappedToGrid(Map.mousePosition);
let basepos = UDB.Map.snappedToGrid(UDB.Map.mousePosition);
// Closet width is static
let closetwidth = 64;
// Get the currently selected lines. Those will get actions to release the voodoo doll
let triggerlines = Map.getSelectedLinedefs();
let triggerlines = UDB.Map.getSelectedLinedefs();
// The number of tags we need depend on the selected options
let numnewtags = 1;
let newtagindex = 0;
// We need an additional tag if the player is blocked at the beginning
if(ScriptOptions.inactive)
if(UDB.ScriptOptions.inactive)
numnewtags++;
// We need an additional tag if the closet should be looping
if(ScriptOptions.looping)
if(UDB.ScriptOptions.looping)
numnewtags++;
// Get thew new tags
let tags = Map.getMultipleNewTags(numnewtags);
let tags = UDB.Map.getMultipleNewTags(numnewtags);
// Create a pen for drawing geometry
var p = new Pen();
// Draw the closet
p.setAngle(90 * ScriptOptions.direction).moveTo(basepos).drawVertex()
.moveForward(ScriptOptions.length).drawVertex().turnRight()
p.setAngle(90 * UDB.ScriptOptions.direction).moveTo(basepos).drawVertex()
.moveForward(UDB.ScriptOptions.length).drawVertex().turnRight()
.moveForward(closetwidth).drawVertex().turnRight()
.moveForward(ScriptOptions.length).drawVertex();
.moveForward(UDB.ScriptOptions.length).drawVertex();
if(!p.finishDrawing(true))
throw "Something went wrong while drawing!";
// Get the new sector, assign a tag, and set heights
let sector = Map.getMarkedSectors()[0];
let sector = UDB.Map.getMarkedSectors()[0];
sector.tag = tags[newtagindex];
sector.floorHeight = 0;
sector.ceilingHeight = 56;
// Draw the carrying line
p.setAngle(90 * ScriptOptions.direction).moveTo(basepos).drawVertex()
p.setAngle(90 * UDB.ScriptOptions.direction).moveTo(basepos).drawVertex()
.moveForward(32).drawVertex();
if(!p.finishDrawing())
throw 'Something went wrong while drawing!';
// Assign the action and tag to the line
let carryline = Map.getMarkedLinedefs()[0];
let carryline = UDB.Map.getMarkedLinedefs()[0];
carryline.action = 252;
carryline.tag = tags[newtagindex];
@ -101,10 +103,10 @@ carryline.tag = tags[newtagindex];
newtagindex++;
// Create the player blocking geometry if necessary
if(ScriptOptions.inactive)
if(UDB.ScriptOptions.inactive)
{
// Draw the blocking sector
p.setAngle(90 * ScriptOptions.direction).moveTo(basepos)
p.setAngle(90 * UDB.ScriptOptions.direction).moveTo(basepos)
.moveForward(64).turnRight().moveForward(16).drawVertex()
.turnRight().moveForward(8).drawVertex()
.turnLeft().moveForward(closetwidth - 32).drawVertex();
@ -113,7 +115,7 @@ if(ScriptOptions.inactive)
throw "Something went wrong while drawing!";
// Get the new sectors and assign a tag
sector = Map.getMarkedSectors()[0];
sector = UDB.Map.getMarkedSectors()[0];
sector.tag = tags[newtagindex];
sector.floorHeight = 0;
sector.ceilingHeight = 55;
@ -142,7 +144,7 @@ if(ScriptOptions.inactive)
}
// Create the looping teleporter geometry if necessary
if(ScriptOptions.looping)
if(UDB.ScriptOptions.looping)
{
// Create the teleport destination line
p.setAngle(90 * ScriptOptions.direction).moveTo(basepos)
@ -153,29 +155,29 @@ if(ScriptOptions.looping)
throw 'Something went wrong while drawing!';
// The destination line only needs a tag and no action
let line = Map.getMarkedLinedefs(true)[0];
let line = UDB.Map.getMarkedLinedefs(true)[0];
line.tag = tags[newtagindex];
// Create the teleport line
p.setAngle(90 * ScriptOptions.direction)
p.setAngle(90 * UDB.ScriptOptions.direction)
.moveTo(basepos)
.moveForward(ScriptOptions.length - 32).turnRight().moveForward(8).drawVertex()
.moveForward(UDB.ScriptOptions.length - 32).turnRight().moveForward(8).drawVertex()
.moveForward(closetwidth - 16).drawVertex();
if(!p.finishDrawing())
throw 'Something went wrong while drawing!';
// The teleport line needs a tag and an action
line = Map.getMarkedLinedefs(true)[0];
line = UDB.Map.getMarkedLinedefs(true)[0];
line.action = 263;
line.tag = tags[newtagindex];
}
// Compute the new voodoo doll position
let newpos = new Vector2D(32, 32).getRotated(Angle2D.doomToReal(-90 * ScriptOptions.direction - 90)) + basepos;
let newpos = new UDB.Vector2D(32, 32).getRotated(UDB.Angle2D.doomToReal(-90 * UDB.ScriptOptions.direction - 90)) + basepos;
// Get all player 1 starts
let playerthings = Map.getThings().filter(o => o.type == 1);
let playerthings = UDB.Map.getThings().filter(o => o.type == 1);
// The actual player always spawns on the last player 1 start that was placed, so
// we need to move the last player 1 start to the monster closet and create a new
@ -193,11 +195,11 @@ if(playerthings.length > 0)
pt.snapToAccuracy();
// Create a new player 1 start and move it to the old position
let t = Map.createThing(oldpos, 1);
let t = UDB.Map.createThing(oldpos, 1);
t.angle = oldangle;
}
else
{
let t = Map.createThing(newpos, 1);
let t = UDB.Map.createThing(newpos, 1);
t.snapToAccuracy();
}

View file

@ -1,3 +1,5 @@
`#version 4`;
`#name Logic assertions`;
`#description This script checks if UDBScript's logic (like vector math operations) work correctly.`;
@ -24,139 +26,139 @@ function assert(condition, expectation, comp_result = true)
try
{
// Addition - Vector2D
assert('new Vector2D(2, 3) + new Vector2D(2, 2)', 'new Vector2D(4, 5)');
assert('[ 2, 3 ] + new Vector2D(2, 2)', 'new Vector2D(4, 5)');
assert('{ x: 2, y: 3 } + new Vector2D(2, 2)', 'new Vector2D(4, 5)');
assert('new Vector2D(2, 3) + [ 2, 2 ]', 'new Vector2D(4, 5)');
assert('new Vector2D(2, 3) + { x: 2, y: 2 }', 'new Vector2D(4, 5)');
assert('new Vector2D(2, 3) + 2', 'new Vector2D(4, 5)');
assert('2 + new Vector2D(2, 3)', 'new Vector2D(4, 5)');
assert('new Vector2D(2, 3) + "#"', '"2, 3#"');
assert('"#" + new Vector2D(2, 3)', '"#2, 3"');
assert('"#" + new Vector2D(2, 3) + "#"', '"#2, 3#"');
assert('new UDB.Vector2D(2, 3) + new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(4, 5)');
assert('[ 2, 3 ] + new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(4, 5)');
assert('{ x: 2, y: 3 } + new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(4, 5)');
assert('new UDB.Vector2D(2, 3) + [ 2, 2 ]', 'new UDB.Vector2D(4, 5)');
assert('new UDB.Vector2D(2, 3) + { x: 2, y: 2 }', 'new UDB.Vector2D(4, 5)');
assert('new UDB.Vector2D(2, 3) + 2', 'new UDB.Vector2D(4, 5)');
assert('2 + new UDB.Vector2D(2, 3)', 'new UDB.Vector2D(4, 5)');
assert('new UDB.Vector2D(2, 3) + "#"', '"2, 3#"');
assert('"#" + new UDB.Vector2D(2, 3)', '"#2, 3"');
assert('"#" + new UDB.Vector2D(2, 3) + "#"', '"#2, 3#"');
// Subtraction - Vector2D
assert('new Vector2D(2, 3) - new Vector2D(2, 2)', 'new Vector2D(0, 1)');
assert('[ 2, 3 ] - new Vector2D(2, 2)', 'new Vector2D(0, 1)');
assert('{ x: 2, y: 3 } - new Vector2D(2, 2)', 'new Vector2D(0, 1)');
assert('new Vector2D(2, 3) - [ 2, 2 ]', 'new Vector2D(0, 1)');
assert('new Vector2D(2, 3) - { x: 2, y: 2 }', 'new Vector2D(0, 1)');
assert('new Vector2D(2, 3) - 2', 'new Vector2D(0, 1)');
assert('2 - new Vector2D(2, 3)', 'new Vector2D(0, -1)');
assert('-(new Vector2D(1, 2))', 'new Vector2D(-1, -2)');
assert('new UDB.Vector2D(2, 3) - new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(0, 1)');
assert('[ 2, 3 ] - new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(0, 1)');
assert('{ x: 2, y: 3 } - new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(0, 1)');
assert('new UDB.Vector2D(2, 3) - [ 2, 2 ]', 'new UDB.Vector2D(0, 1)');
assert('new UDB.Vector2D(2, 3) - { x: 2, y: 2 }', 'new UDB.Vector2D(0, 1)');
assert('new UDB.Vector2D(2, 3) - 2', 'new UDB.Vector2D(0, 1)');
assert('2 - new UDB.Vector2D(2, 3)', 'new UDB.Vector2D(0, -1)');
assert('-(new UDB.Vector2D(1, 2))', 'new UDB.Vector2D(-1, -2)');
// Multiplication - Vector2D
assert('new Vector2D(2, 3) * new Vector2D(2, 2)', 'new Vector2D(4, 6)');
assert('[ 2, 3 ] * new Vector2D(2, 2)', 'new Vector2D(4, 6)');
assert('{ x: 2, y: 3 } * new Vector2D(2, 2)', 'new Vector2D(4, 6)');
assert('new Vector2D(2, 2) * [ 2, 3 ]', 'new Vector2D(4, 6)');
assert('new Vector2D(2, 2) * { x: 2, y: 3 }', 'new Vector2D(4, 6)');
assert('new Vector2D(2, 3) * 2', 'new Vector2D(4, 6)');
assert('2 * new Vector2D(2, 3)', 'new Vector2D(4, 6)');
assert('new UDB.Vector2D(2, 3) * new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(4, 6)');
assert('[ 2, 3 ] * new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(4, 6)');
assert('{ x: 2, y: 3 } * new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(4, 6)');
assert('new UDB.Vector2D(2, 2) * [ 2, 3 ]', 'new UDB.Vector2D(4, 6)');
assert('new UDB.Vector2D(2, 2) * { x: 2, y: 3 }', 'new UDB.Vector2D(4, 6)');
assert('new UDB.Vector2D(2, 3) * 2', 'new UDB.Vector2D(4, 6)');
assert('2 * new UDB.Vector2D(2, 3)', 'new UDB.Vector2D(4, 6)');
// Division - Vector2D
assert('new Vector2D(4, 6) / new Vector2D(2, 2)', 'new Vector2D(2, 3)');
assert('[ 4, 6 ] / new Vector2D(2, 2)', 'new Vector2D(2, 3)');
assert('{ x: 4, y: 6 } / new Vector2D(2, 2)', 'new Vector2D(2, 3)');
assert('new Vector2D(4, 6) / [ 2, 2 ]', 'new Vector2D(2, 3)');
assert('new Vector2D(4, 6) / { x: 2, y: 2 }', 'new Vector2D(2, 3)');
assert('new Vector2D(2, 8) / 4', 'new Vector2D(0.5, 2)');
assert('4 / new Vector2D(2, 8)', 'new Vector2D(0.5, 2)');
assert('new UDB.Vector2D(4, 6) / new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(2, 3)');
assert('[ 4, 6 ] / new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(2, 3)');
assert('{ x: 4, y: 6 } / new UDB.Vector2D(2, 2)', 'new UDB.Vector2D(2, 3)');
assert('new UDB.Vector2D(4, 6) / [ 2, 2 ]', 'new UDB.Vector2D(2, 3)');
assert('new UDB.Vector2D(4, 6) / { x: 2, y: 2 }', 'new UDB.Vector2D(2, 3)');
assert('new UDB.Vector2D(2, 8) / 4', 'new UDB.Vector2D(0.5, 2)');
assert('4 / new UDB.Vector2D(2, 8)', 'new UDB.Vector2D(0.5, 2)');
// Equality - Vector2D
assert('new Vector2D(1, 2)', 'new Vector2D(1, 2)');
assert('new Vector2D(1, 2)', '[ 1, 2 ]');
assert('new Vector2D(1, 2)', '{ x: 1, y: 2 }');
assert('[ 1, 2 ]', 'new Vector2D(1, 2)');
assert('{ x: 1, y: 2 }', 'new Vector2D(1, 2)');
assert('[ 2, 1 ]', 'new Vector2D(1, 2)', false);
assert('{ x: 2, y: 1 }', 'new Vector2D(1, 2)', false);
assert('new Vector2D(2, 1)', '[ 1, 2 ]', false);
assert('new Vector2D(2, 1)', '{ x: 1, y: 2 }', false);
assert('new UDB.Vector2D(1, 2)', 'new UDB.Vector2D(1, 2)');
assert('new UDB.Vector2D(1, 2)', '[ 1, 2 ]');
assert('new UDB.Vector2D(1, 2)', '{ x: 1, y: 2 }');
assert('[ 1, 2 ]', 'new UDB.Vector2D(1, 2)');
assert('{ x: 1, y: 2 }', 'new UDB.Vector2D(1, 2)');
assert('[ 2, 1 ]', 'new UDB.Vector2D(1, 2)', false);
assert('{ x: 2, y: 1 }', 'new UDB.Vector2D(1, 2)', false);
assert('new UDB.Vector2D(2, 1)', '[ 1, 2 ]', false);
assert('new UDB.Vector2D(2, 1)', '{ x: 1, y: 2 }', false);
// Addition - Vector3D
assert('new Vector3D(2, 3, 4) + new Vector3D(2, 2, 2)', 'new Vector3D(4, 5, 6)');
assert('[ 2, 3, 4 ] + new Vector3D(2, 2, 2)', 'new Vector3D(4, 5, 6)');
assert('{ x: 2, y: 3, z: 4 } + new Vector3D(2, 2, 2)', 'new Vector3D(4, 5, 6)');
assert('new Vector3D(2, 3, 4) + [ 2, 2, 2 ]', 'new Vector3D(4, 5, 6)');
assert('new Vector3D(2, 3, 4) + { x: 2, y: 2, z: 2 }', 'new Vector3D(4, 5, 6)');
assert('new Vector3D(2, 3, 4) + 2', 'new Vector3D(4, 5, 6)');
assert('2 + new Vector3D(2, 3, 4)', 'new Vector3D(4, 5, 6)');
assert('new Vector2D(2, 3) + new Vector3D(2, 2, 2)', 'new Vector3D(4, 5, 2)');
assert('new Vector3D(2, 3, 4) + new Vector2D(2, 2)', 'new Vector3D(4, 5, 4)');
assert('[ 2, 3 ] + new Vector3D(2, 2, 2)', 'new Vector3D(4, 5, 2)');
assert('new Vector3D(2, 3, 4) + [ 2, 2 ]', 'new Vector3D(4, 5, 4)');
assert('{ x: 2, y: 3 } + new Vector3D(2, 2, 2)', 'new Vector3D(4, 5, 2)');
assert('new Vector3D(2, 3, 4) + { x: 2, y: 2 }', 'new Vector3D(4, 5, 4)');
assert('new Vector3D(2, 3, 4) + "#"', '"2, 3, 4#"');
assert('"#" + new Vector3D(2, 3, 4)', '"#2, 3, 4"');
assert('"#" + new Vector3D(2, 3, 4) + "#"', '"#2, 3, 4#"');
assert('new UDB.Vector3D(2, 3, 4) + new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 5, 6)');
assert('[ 2, 3, 4 ] + new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 5, 6)');
assert('{ x: 2, y: 3, z: 4 } + new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 5, 6)');
assert('new UDB.Vector3D(2, 3, 4) + [ 2, 2, 2 ]', 'new UDB.Vector3D(4, 5, 6)');
assert('new UDB.Vector3D(2, 3, 4) + { x: 2, y: 2, z: 2 }', 'new UDB.Vector3D(4, 5, 6)');
assert('new UDB.Vector3D(2, 3, 4) + 2', 'new UDB.Vector3D(4, 5, 6)');
assert('2 + new UDB.Vector3D(2, 3, 4)', 'new UDB.Vector3D(4, 5, 6)');
assert('new UDB.Vector2D(2, 3) + new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 5, 2)');
assert('new UDB.Vector3D(2, 3, 4) + new UDB.Vector2D(2, 2)', 'new UDB.Vector3D(4, 5, 4)');
assert('[ 2, 3 ] + new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 5, 2)');
assert('new UDB.Vector3D(2, 3, 4) + [ 2, 2 ]', 'new UDB.Vector3D(4, 5, 4)');
assert('{ x: 2, y: 3 } + new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 5, 2)');
assert('new UDB.Vector3D(2, 3, 4) + { x: 2, y: 2 }', 'new UDB.Vector3D(4, 5, 4)');
assert('new UDB.Vector3D(2, 3, 4) + "#"', '"2, 3, 4#"');
assert('"#" + new UDB.Vector3D(2, 3, 4)', '"#2, 3, 4"');
assert('"#" + new UDB.Vector3D(2, 3, 4) + "#"', '"#2, 3, 4#"');
// Subtraction - Vector3D
assert('new Vector3D(2, 3, 4) - new Vector3D(2, 2, 2)', 'new Vector3D(0, 1, 2)');
assert('[ 2, 3, 4 ] - new Vector3D(2, 2, 2)', 'new Vector3D(0, 1, 2)');
assert('{ x: 2, y: 3, z: 4 } - new Vector3D(2, 2, 2)', 'new Vector3D(0, 1, 2)');
assert('new Vector3D(2, 3, 4) - [ 2, 2, 2 ]', 'new Vector3D(0, 1, 2)');
assert('new Vector3D(2, 3, 4) - { x: 2, y: 2, z: 2 }', 'new Vector3D(0, 1, 2)');
assert('new Vector3D(2, 3, 4) - 2', 'new Vector3D(0, 1, 2)');
assert('2 - new Vector3D(2, 3, 4)', 'new Vector3D(0, 1, 2)');
assert('new Vector2D(2, 3) - new Vector3D(2, 2, 2)', 'new Vector3D(0, 1, -2)');
assert('new Vector3D(2, 3, 4) - new Vector2D(2, 2)', 'new Vector3D(0, 1, 4)');
assert('[ 2, 3 ] - new Vector3D(2, 2, 2)', 'new Vector3D(0, 1, -2)');
assert('new Vector3D(2, 3, 4) - [ 2, 2 ]', 'new Vector3D(0, 1, 4)');
assert('{ x: 2, y: 3 } - new Vector3D(2, 2, 2)', 'new Vector3D(0, 1, -2)');
assert('new Vector3D(2, 3, 4) - { x: 2, y: 2 }', 'new Vector3D(0, 1, 4)');
assert('new UDB.Vector3D(2, 3, 4) - new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(0, 1, 2)');
assert('[ 2, 3, 4 ] - new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(0, 1, 2)');
assert('{ x: 2, y: 3, z: 4 } - new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(0, 1, 2)');
assert('new UDB.Vector3D(2, 3, 4) - [ 2, 2, 2 ]', 'new UDB.Vector3D(0, 1, 2)');
assert('new UDB.Vector3D(2, 3, 4) - { x: 2, y: 2, z: 2 }', 'new UDB.Vector3D(0, 1, 2)');
assert('new UDB.Vector3D(2, 3, 4) - 2', 'new UDB.Vector3D(0, 1, 2)');
assert('2 - new UDB.Vector3D(2, 3, 4)', 'new UDB.Vector3D(0, 1, 2)');
assert('new UDB.Vector2D(2, 3) - new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(0, 1, -2)');
assert('new UDB.Vector3D(2, 3, 4) - new UDB.Vector2D(2, 2)', 'new UDB.Vector3D(0, 1, 4)');
assert('[ 2, 3 ] - new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(0, 1, -2)');
assert('new UDB.Vector3D(2, 3, 4) - [ 2, 2 ]', 'new UDB.Vector3D(0, 1, 4)');
assert('{ x: 2, y: 3 } - new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(0, 1, -2)');
assert('new UDB.Vector3D(2, 3, 4) - { x: 2, y: 2 }', 'new UDB.Vector3D(0, 1, 4)');
// Multiplication - Vector3D
assert('new Vector3D(2, 3, 4) * new Vector3D(2, 2, 2)', 'new Vector3D(4, 6, 8)');
assert('[ 2, 3, 4 ] * new Vector3D(2, 2, 2)', 'new Vector3D(4, 6, 8)');
assert('{ x: 2, y: 3, z: 4 } * new Vector3D(2, 2, 2)', 'new Vector3D(4, 6, 8)');
assert('new Vector3D(2, 3, 4) * [ 2, 2, 2 ]', 'new Vector3D(4, 6, 8)');
assert('new Vector3D(2, 3, 4) * { x: 2, y: 2, z: 2 }', 'new Vector3D(4, 6, 8)');
assert('new Vector3D(2, 3, 4) * 2', 'new Vector3D(4, 6, 8)');
assert('2 * new Vector3D(2, 3, 4)', 'new Vector3D(4, 6, 8)');
assert('new Vector2D(2, 3) * new Vector3D(2, 2, 2)', 'new Vector3D(4, 6, 0)');
assert('new Vector3D(2, 3, 4) * new Vector2D(2, 2)', 'new Vector3D(4, 6, 0)');
assert('[ 2, 3 ] * new Vector3D(2, 2, 2)', 'new Vector3D(4, 6, 0)');
assert('new Vector3D(2, 3, 4) * [ 2, 2 ]', 'new Vector3D(4, 6, 0)');
assert('{ x: 2, y: 3 } * new Vector3D(2, 2, 2)', 'new Vector3D(4, 6, 0)');
assert('new Vector3D(2, 3, 4) * { x: 2, y: 2 }', 'new Vector3D(4, 6, 0)');
assert('new UDB.Vector3D(2, 3, 4) * new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 6, 8)');
assert('[ 2, 3, 4 ] * new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 6, 8)');
assert('{ x: 2, y: 3, z: 4 } * new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 6, 8)');
assert('new UDB.Vector3D(2, 3, 4) * [ 2, 2, 2 ]', 'new UDB.Vector3D(4, 6, 8)');
assert('new UDB.Vector3D(2, 3, 4) * { x: 2, y: 2, z: 2 }', 'new UDB.Vector3D(4, 6, 8)');
assert('new UDB.Vector3D(2, 3, 4) * 2', 'new UDB.Vector3D(4, 6, 8)');
assert('2 * new UDB.Vector3D(2, 3, 4)', 'new UDB.Vector3D(4, 6, 8)');
assert('new UDB.Vector2D(2, 3) * new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 6, 0)');
assert('new UDB.Vector3D(2, 3, 4) * new UDB.Vector2D(2, 2)', 'new UDB.Vector3D(4, 6, 0)');
assert('[ 2, 3 ] * new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 6, 0)');
assert('new UDB.Vector3D(2, 3, 4) * [ 2, 2 ]', 'new UDB.Vector3D(4, 6, 0)');
assert('{ x: 2, y: 3 } * new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(4, 6, 0)');
assert('new UDB.Vector3D(2, 3, 4) * { x: 2, y: 2 }', 'new UDB.Vector3D(4, 6, 0)');
// Division - Vector3D
assert('new Vector3D(2, 3, 4) / new Vector3D(2, 2, 2)', 'new Vector3D(1, 1.5, 2)');
assert('[ 2, 3, 4 ] / new Vector3D(2, 2, 2)', 'new Vector3D(1, 1.5, 2)');
assert('{ x: 2, y: 3, z: 4 } / new Vector3D(2, 2, 2)', 'new Vector3D(1, 1.5, 2)');
assert('new Vector3D(2, 3, 4) / [ 2, 2, 2 ]', 'new Vector3D(1, 1.5, 2)');
assert('new Vector3D(2, 3, 4) / { x: 2, y: 2, z: 2 }', 'new Vector3D(1, 1.5, 2)');
assert('new Vector3D(2, 3, 4) / 2', 'new Vector3D(1, 1.5, 2)');
assert('2 / new Vector3D(2, 3, 4)', 'new Vector3D(1, 1.5, 2)');
assert('new Vector2D(2, 3) / new Vector3D(2, 2, 2)', 'new Vector3D(1, 1.5, 0)');
assert('new Vector3D(2, 3, 4) / new Vector2D(2, 2)', 'new Vector3D(1, 1.5, Infinity)');
assert('[ 2, 3 ] / new Vector3D(2, 2, 2)', 'new Vector3D(1, 1.5, 0)');
assert('new Vector3D(2, 3, 4) / [ 2, 2 ]', 'new Vector3D(1, 1.5, Infinity)');
assert('{ x: 2, y: 3 } / new Vector3D(2, 2, 2)', 'new Vector3D(1, 1.5, 0)');
assert('new Vector3D(2, 3, 4) / { x: 2, y: 2 }', 'new Vector3D(1, 1.5, Infinity)');
assert('new UDB.Vector3D(2, 3, 4) / new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(1, 1.5, 2)');
assert('[ 2, 3, 4 ] / new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(1, 1.5, 2)');
assert('{ x: 2, y: 3, z: 4 } / new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(1, 1.5, 2)');
assert('new UDB.Vector3D(2, 3, 4) / [ 2, 2, 2 ]', 'new UDB.Vector3D(1, 1.5, 2)');
assert('new UDB.Vector3D(2, 3, 4) / { x: 2, y: 2, z: 2 }', 'new UDB.Vector3D(1, 1.5, 2)');
assert('new UDB.Vector3D(2, 3, 4) / 2', 'new UDB.Vector3D(1, 1.5, 2)');
assert('2 / new UDB.Vector3D(2, 3, 4)', 'new UDB.Vector3D(1, 1.5, 2)');
assert('new UDB.Vector2D(2, 3) / new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(1, 1.5, 0)');
assert('new UDB.Vector3D(2, 3, 4) / new UDB.Vector2D(2, 2)', 'new UDB.Vector3D(1, 1.5, Infinity)');
assert('[ 2, 3 ] / new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(1, 1.5, 0)');
assert('new UDB.Vector3D(2, 3, 4) / [ 2, 2 ]', 'new UDB.Vector3D(1, 1.5, Infinity)');
assert('{ x: 2, y: 3 } / new UDB.Vector3D(2, 2, 2)', 'new UDB.Vector3D(1, 1.5, 0)');
assert('new UDB.Vector3D(2, 3, 4) / { x: 2, y: 2 }', 'new UDB.Vector3D(1, 1.5, Infinity)');
// Equality - Vector3D
assert('new Vector3D(1, 2, 3)', 'new Vector3D(1, 2, 3)');
assert('new Vector3D(1, 2, 3)', '[ 1, 2, 3 ]');
assert('new Vector3D(1, 2, 3)', '{ x: 1, y: 2, z: 3 }');
assert('[ 1, 2, 3 ]', 'new Vector3D(1, 2, 3)');
assert('{ x: 1, y: 2, z: 3 }', 'new Vector3D(1, 2, 3)');
assert('[ 3, 2, 1 ]', 'new Vector3D(1, 2, 3)', false);
assert('{ x: 3, y: 2, z: 1 }', 'new Vector3D(1, 2, 3)', false);
assert('new Vector3D(3, 2, 1)', '[ 1, 2, 3 ]', false);
assert('new Vector3D(3, 2, 1)', '{ x: 1, y: 2, z: 3 }', false);
assert('new UDB.Vector3D(1, 2, 3)', 'new UDB.Vector3D(1, 2, 3)');
assert('new UDB.Vector3D(1, 2, 3)', '[ 1, 2, 3 ]');
assert('new UDB.Vector3D(1, 2, 3)', '{ x: 1, y: 2, z: 3 }');
assert('[ 1, 2, 3 ]', 'new UDB.Vector3D(1, 2, 3)');
assert('{ x: 1, y: 2, z: 3 }', 'new UDB.Vector3D(1, 2, 3)');
assert('[ 3, 2, 1 ]', 'new UDB.Vector3D(1, 2, 3)', false);
assert('{ x: 3, y: 2, z: 1 }', 'new UDB.Vector3D(1, 2, 3)', false);
assert('new UDB.Vector3D(3, 2, 1)', '[ 1, 2, 3 ]', false);
assert('new UDB.Vector3D(3, 2, 1)', '{ x: 1, y: 2, z: 3 }', false);
let line1 = new Line2D([ 32, 32 ], [ 32, -32 ]);
let line2 = new Line2D([ 0, 16 ], [ 64, 16 ]);
let intersecting = Line2D.areIntersecting(line1, line2);
assert('Line2D.areIntersecting(new Line2D([ 32, 32 ], [ 32, -32 ]), new Line2D([ 0, 16 ], [ 64, 16 ]))', 'true');
let line1 = new UDB.Line2D([ 32, 32 ], [ 32, -32 ]);
let line2 = new UDB.Line2D([ 0, 16 ], [ 64, 16 ]);
let intersecting = UDB.Line2D.areIntersecting(line1, line2);
assert('UDB.Line2D.areIntersecting(new UDB.Line2D([ 32, 32 ], [ 32, -32 ]), new UDB.Line2D([ 0, 16 ], [ 64, 16 ]))', 'true');
showMessage(assertion_log);
UDB.showMessage(assertion_log);
}
catch(e)
{
showMessage(e);
exit();
UDB.showMessage(e);
UDB.exit();
}

View file

@ -1,3 +1,5 @@
`#version 4`;
`#name Show Map Squareness`;
`#description Shows how square a map is. Computes the percentage of orthogonal lines, based on their length.`;
@ -5,7 +7,7 @@
let totalLength = 0;
let orthogonalLength = 0;
Map.getLinedefs().forEach(ld => {
UDB.Map.getLinedefs().forEach(ld => {
totalLength += ld.length;
if(ld.angle % 90 == 0)
@ -14,4 +16,4 @@ Map.getLinedefs().forEach(ld => {
orthogonalPercentage = (orthogonalLength / totalLength * 100).toFixed(2);
showMessage('The map is ' + orthogonalPercentage + '% square.');
UDB.showMessage('The map is ' + orthogonalPercentage + '% square.');

View file

@ -1,11 +1,13 @@
`#version 4`;
`#name Calculate sector area`;
`#description Calculates the area of the selected sectors.`
let sectors = Map.getSelectedSectors();
let sectors = UDB.Map.getSelectedSectors();
if(sectors.length == 0)
die('You need to select at least one sector.');
UDB.die('You need to select at least one sector.');
let area = 0;
@ -15,4 +17,4 @@ sectors.forEach(s => {
});
});
showMessage('The area of the selected sectors is ' + area + ' mu².');
UDB.showMessage('The area of the selected sectors is ' + area + ' mu².');

View file

@ -1,25 +1,25 @@
`#version 4`;
`#name Apply textures to selected surfaces`;
`#description Applies LAVA1 to the selected floors/ceilings, and FIREBLU1 to the selected upper/middle/lower sidedefs. Mostly useful in visual mode`;
`#version 3`;
// Get all selected or highlighted sectors and sidedefs
let elements = Map.getSelectedOrHighlightedSectors().concat(Map.getSidedefsFromSelectedOrHighlightedLinedefs());
let elements = UDB.Map.getSelectedOrHighlightedSectors().concat(UDB.Map.getSidedefsFromSelectedOrHighlightedLinedefs());
// Since the array might contain both selected sectors and highlighted sidedefs (or vice versa)
// we have to filter the array, so that we really only work on the correct map elements, i.e.
// either the single highlighted one, or all selected ones
elements.filter(e => {
if( elements.length == 1 ||
(e instanceof Sector && (e.floorSelected || e.ceilingSelected)) ||
(e instanceof Sidedef && (e.upperSelected || e.middleSelected || e.lowerSelected))
(e instanceof UDB.Sector && (e.floorSelected || e.ceilingSelected)) ||
(e instanceof UDB.Sidedef && (e.upperSelected || e.middleSelected || e.lowerSelected))
) return true;
return false;
}).forEach(e => {
// Check for each sector and sidedef which part is selected/highlighted and
// apply the textures accordingly
if(e instanceof Sector)
if(e instanceof UDB.Sector)
{
if(e.floorSelected || e.floorHighlighted)
e.floorTexture = 'LAVA1';
@ -27,7 +27,7 @@ elements.filter(e => {
if(e.ceilingSelected || e.ceilingHighlighted)
e.ceilingTexture = 'LAVA1';
}
else if(e instanceof Sidedef)
else if(e instanceof UDB.Sidedef)
{
if(e.lowerSelected || e.lowerHighlighted)
e.lowerTexture = 'FIREBLU1';

View file

@ -1,25 +1,27 @@
`#version 4`;
`#name Delete Sector Tag`;
`#description Deletes a tag from the selected sectors (or all sectors if no sectors are selected)`;
// Get the selected sectors
let sectors = Map.getSelectedSectors();
let sectors = UDB.Map.getSelectedSectors();
// If no sectors were selected get all sectors
if(sectors.length == 0)
sectors = Map.getSectors();
sectors = UDB.Map.getSectors();
// Prepare to ask the user for the tag to delete
let qo = new QueryOptions();
let qo = new UDB.QueryOptions();
qo.addOption('tag', 'Tag to delete', 1, 0);
// Ask for the tag to delete, abort script of cancel was pressed
if(!qo.query())
die('Script aborted');
UDB.die('Script aborted');
// Abort when tag was set to 0
if(qo.options.tag == 0)
die("Tag can't be 0");
UDB.die("Tag can't be 0");
// Delete the tag from the sectors
sectors.forEach(s => s.removeTag(qo.options.tag));

View file

@ -1,20 +1,22 @@
`#version 4`;
`#name Flip Triangular Sectors`;
`#description Flips two selected triangular sectors, so that the connecting linedef is between the vertices that previously didn't share a linedef`;
let sectors = Map.getSelectedSectors();
let sectors = UDB.Map.getSelectedSectors();
let vertices = new Set();
let sharedline = null;
if(sectors.length != 2)
die('You have to select exactly 2 sectors');
UDB.die('You have to select exactly 2 sectors');
// Make sure we have triangular sectors selected, and collect all vertices
sectors.forEach(s => {
let sidedefs = s.getSidedefs();
if(sidedefs.length != 3)
die(s + ' does not have exactly 3 sides');
UDB.die(s + ' does not have exactly 3 sides');
sidedefs.forEach(sd => {
// Does this sidedef belong to the linedef that's shared between the sectors?
@ -33,10 +35,10 @@ vertices.delete(sharedline.end);
// There should be exactly 2 vertices
if(vertices.size != 2)
die('Expected to find 2 vertices to draw the new line between, but got ' + vertices.size);
UDB.die('Expected to find 2 vertices to draw the new line between, but got ' + vertices.size);
// Merge the sectors...
Map.mergeSectors(sectors);
UDB.Map.mergeSectors(sectors);
// ... and draw the new line
Map.drawLines(Array.from(vertices, v => v.position));
UDB.Map.drawLines(Array.from(vertices, v => v.position));

View file

@ -1,13 +1,15 @@
`#version 4`;
`#name Imps to Arch-Viles`;
`#description Turns all Imps that appear on UV into Arch-Viles. To make it a bit more fair for the player it also adds a health potion to the monster's position.`;
Map.getThings().filter(t => t.type == 3001 && ((Map.isUDMF && t.flags.skill5) || (!Map.isUDMF && t.flags['4']))).forEach(t => {
UDB.Map.getThings().filter(t => t.type == 3001 && ((UDB.Map.isUDMF && t.flags.skill5) || (!UDB.Map.isUDMF && t.flags['4']))).forEach(t => {
let addav = false;
let skillsum = 0;
// Count the number of skills the Imp appears on
if(Map.isUDMF)
if(UDB.Map.isUDMF)
{
for(let i=1; i <= 5; i++)
if(t.flags['skill' + i])
@ -26,9 +28,9 @@ Map.getThings().filter(t => t.type == 3001 && ((Map.isUDMF && t.flags.skill5) ||
addav = true;
// Create a new health potion at the thing's position
let hp = Map.createThing(t.position, 2014);
let hp = UDB.Map.createThing(t.position, 2014);
if(Map.isUDMF)
if(UDB.Map.isUDMF)
{
hp.flags.skill5 = true;
for(let i=1; i <= 4; i++)
@ -43,13 +45,13 @@ Map.getThings().filter(t => t.type == 3001 && ((Map.isUDMF && t.flags.skill5) ||
if(addav)
{
// Create a new Arch-Vile and copy all the original thing's properties
let av = Map.createThing(t.position);
let av = UDB.Map.createThing(t.position);
t.copyPropertiesTo(av);
av.type = 64;
// Set the skill flags. Since we're addin an Arch-Vile we have to unset the Imp's UV flag,
// and remove the Arch-Viles (and health potion's) other skill flags
if(Map.isUDMF)
if(UDB.Map.isUDMF)
{
t.flags.skill5 = false;
for(let i=1; i <= 4; i++)

View file

@ -1,17 +1,19 @@
`#version 4`;
`#name Randomize Selection Order`;
`#description Randomize the selection order of the selected map elements.`;
// Put all selected map elements into an array
let elements = [
...Map.getSelectedThings(),
...Map.getSelectedVertices(),
...Map.getSelectedLinedefs(),
...Map.getSelectedSectors()
...UDB.Map.getSelectedThings(),
...UDB.Map.getSelectedVertices(),
...UDB.Map.getSelectedLinedefs(),
...UDB.Map.getSelectedSectors()
];
// Clear current selection
Map.clearAllSelected();
UDB.Map.clearAllSelected();
// Keep going as long as there are elements in the array
while(elements.length > 0)

View file

@ -1,3 +1,5 @@
`#version 4`;
`#name Randomize Texture Offsets`;
`#description Randomized texture offsets. Distinct upper, middle, and lower offsets only work if the game configuration supports those local offsets.`;
@ -70,76 +72,76 @@ function getRandomOffset(max)
// Checks if the given name is a proper texture name and if the texture exists
function isValidTexture(texture)
{
return texture != '-' && Data.textureExists(texture);
return texture != '-' && UDB.Data.textureExists(texture);
}
function randomizeSidedefOffsets(sd)
{
// Global X texture offset
if(ScriptOptions.global_x && (isValidTexture(sd.upperTexture) || isValidTexture(sd.middleTexture) || isValidTexture(sd.lowerTexture)))
if(UDB.ScriptOptions.global_x && (isValidTexture(sd.upperTexture) || isValidTexture(sd.middleTexture) || isValidTexture(sd.lowerTexture)))
{
let widths = [];
if(isValidTexture(sd.upperTexture))
widths.push(Data.getTextureInfo(sd.upperTexture).width);
widths.push(UDB.Data.getTextureInfo(sd.upperTexture).width);
if(isValidTexture(sd.middleTexture))
widths.push(Data.getTextureInfo(sd.middleTexture).width);
widths.push(UDB.Data.getTextureInfo(sd.middleTexture).width);
if(isValidTexture(sd.lowerTexture))
widths.push(Data.getTextureInfo(sd.lowerTexture).width);
widths.push(UDB.Data.getTextureInfo(sd.lowerTexture).width);
if(widths.length > 0)
sd.offsetX = getRandomOffset(Math.max(widths));
}
// Global Y texture offset
if(ScriptOptions.global_y && (isValidTexture(sd.upperTexture) || isValidTexture(sd.middleTexture) || isValidTexture(sd.lowerTexture)))
if(UDB.ScriptOptions.global_y && (isValidTexture(sd.upperTexture) || isValidTexture(sd.middleTexture) || isValidTexture(sd.lowerTexture)))
{
let heights = [];
if(isValidTexture(sd.upperTexture))
heights.push(Data.getTextureInfo(sd.upperTexture).height);
heights.push(UDB.Data.getTextureInfo(sd.upperTexture).height);
if(isValidTexture(sd.middleTexture))
heights.push(Data.getTextureInfo(sd.middleTexture).height);
heights.push(UDB.Data.getTextureInfo(sd.middleTexture).height);
if(isValidTexture(sd.lowerTexture))
heights.push(Data.getTextureInfo(sd.lowerTexture).height);
heights.push(UDB.Data.getTextureInfo(sd.lowerTexture).height);
if(heights.length > 0)
sd.offsetY = getRandomOffset(Math.max(heights));
}
// Local X texture offsets
if(GameConfiguration.hasLocalSidedefTextureOffsets)
if(UDB.GameConfiguration.hasLocalSidedefTextureOffsets)
{
if(ScriptOptions.upper_x && isValidTexture(sd.upperTexture))
sd.fields.offsetx_top = getRandomOffset(Data.getTextureInfo(sd.upperTexture).height);
if(UDB.ScriptOptions.upper_x && isValidTexture(sd.upperTexture))
sd.fields.offsetx_top = getRandomOffset(UDB.Data.getTextureInfo(sd.upperTexture).height);
if(ScriptOptions.middle_x && isValidTexture(sd.middleTexture))
sd.fields.offsetx_mid = getRandomOffset(Data.getTextureInfo(sd.middleTexture).height);
if(UDB.ScriptOptions.middle_x && isValidTexture(sd.middleTexture))
sd.fields.offsetx_mid = getRandomOffset(UDB.Data.getTextureInfo(sd.middleTexture).height);
if(ScriptOptions.lower_x && isValidTexture(sd.lowerTexture))
sd.fields.offsetx_bottom = getRandomOffset(Data.getTextureInfo(sd.lowerTexture).height);
if(UDB.ScriptOptions.lower_x && isValidTexture(sd.lowerTexture))
sd.fields.offsetx_bottom = getRandomOffset(UDB.Data.getTextureInfo(sd.lowerTexture).height);
}
// Local Y texture offsets
if(GameConfiguration.hasLocalSidedefTextureOffsets)
if(UDB.GameConfiguration.hasLocalSidedefTextureOffsets)
{
if(ScriptOptions.upper_y && isValidTexture(sd.upperTexture))
sd.fields.offsety_top = getRandomOffset(Data.getTextureInfo(sd.upperTexture).height);
if(UDB.ScriptOptions.upper_y && isValidTexture(sd.upperTexture))
sd.fields.offsety_top = getRandomOffset(UDB.Data.getTextureInfo(sd.upperTexture).height);
if(ScriptOptions.middle_y && isValidTexture(sd.middleTexture))
sd.fields.offsety_mid = getRandomOffset(Data.getTextureInfo(sd.middleTexture).height);
if(UDB.ScriptOptions.middle_y && isValidTexture(sd.middleTexture))
sd.fields.offsety_mid = getRandomOffset(UDB.Data.getTextureInfo(sd.middleTexture).height);
if(ScriptOptions.lower_y && isValidTexture(sd.lowerTexture))
sd.fields.offsety_bottom = getRandomOffset(Data.getTextureInfo(sd.lowerTexture).height);
if(UDB.ScriptOptions.lower_y && isValidTexture(sd.lowerTexture))
sd.fields.offsety_bottom = getRandomOffset(UDB.Data.getTextureInfo(sd.lowerTexture).height);
}
}
// Randomize offset of front and back sidedefs of all selected linedefs
Map.getSelectedLinedefs().forEach(ld => {
UDB.Map.getSelectedLinedefs().forEach(ld => {
if(ld.front != null)
randomizeSidedefOffsets(ld.front);

View file

@ -1,16 +1,18 @@
`#version 4`;
`#name Reorder Things Indices`;
`#description Reorderts the thing inddices of the selected things, so that the thing indices are ascending in the order the things were selected.`;
let things = Map.getSelectedThings();
let things = UDB.Map.getSelectedThings();
if(things.length < 2)
die('You have to select at least 2 things.');
UDB.die('You have to select at least 2 things.');
let sorted = [...things].sort((a, b) => a.index - b.index);
let copies = things.map(t => {
let nt = Map.createThing([ 0, 0 ]);
let nt = UDB.Map.createThing([ 0, 0 ]);
t.copyPropertiesTo(nt);
return nt;
});
@ -18,14 +20,6 @@ let copies = things.map(t => {
for(let i=0; i < sorted.length; i++)
copies[i].copyPropertiesTo(sorted[i]);
// Create new things and copy the properties of the original thing to them
//things.forEach(t => {
// let nt = Map.createThing(t.position);
// t.copyPropertiesTo(nt);
//});
// Delete the old things. Have to do it in an extra loop sice it'd just fill
// up the old thing indexes
//things.reverse().forEach(t => t.delete());
copies.reverse().forEach(t => t.delete());

View file

@ -1,11 +1,13 @@
`#version 4`;
`#name Select Connected Linedefs`;
`#description Recursively selects all linedefs that are connected to the currently selected linedef(s).`;
let lines = Map.getSelectedOrHighlightedLinedefs();
let lines = UDB.Map.getSelectedOrHighlightedLinedefs();
if(lines.length == 0)
die('You have to select at least one linedef!');
UDB.die('You have to select at least one linedef!');
let vertices_to_check = [];
let checked_vertices = [];

View file

@ -27,7 +27,7 @@ using CodeImp.DoomBuilder.Geometry;
#endregion
namespace CodeImp.DoomBuilder.UDBScript.API
namespace CodeImp.DoomBuilder.UDBScript.Wrapper
{
internal struct Angle2DWrapper
{

View file

@ -34,7 +34,7 @@ using CodeImp.DoomBuilder.UDBScript.Wrapper;
#endregion
namespace CodeImp.DoomBuilder.UDBScript.API
namespace CodeImp.DoomBuilder.UDBScript.Wrapper
{
class DataWrapper
{

View file

@ -24,7 +24,7 @@
#region ================== Namespaces
#endregion
namespace CodeImp.DoomBuilder.UDBScript.API
namespace CodeImp.DoomBuilder.UDBScript.Wrapper
{
class GameConfigurationWrapper
{

View file

@ -28,7 +28,7 @@ using CodeImp.DoomBuilder.UDBScript.Wrapper;
#endregion
namespace CodeImp.DoomBuilder.UDBScript.API
namespace CodeImp.DoomBuilder.UDBScript.Wrapper
{
struct ImageInfo
{

View file

@ -56,8 +56,8 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// <summary>
/// Creates a new `Line2D` from two points.
/// ```
/// let line1 = new Line2D(new Vector2D(32, 64), new Vector2D(96, 128));
/// let line2 = new Line2D([ 32, 64 ], [ 96, 128 ]);
/// let line1 = new UDB.Line2D(new Vector2D(32, 64), new Vector2D(96, 128));
/// let line2 = new UDB.Line2D([ 32, 64 ], [ 96, 128 ]);
/// ```
/// </summary>
/// <param name="v1">First point</param>

View file

@ -52,7 +52,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// s.fields.comment = 'This is a comment';
/// s.fields['comment'] = 'This is a comment'; // Also works
/// s.fields.xscalefloor = 2.0;
/// t.score = 100;
/// t.fields.score = 100;
/// ```
/// It is also possible to define new fields:
/// ```
@ -64,7 +64,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// * it does not work for flags. While they are technically also UDMF fields, they are handled in the `flags` field of the respective class (where applicable)
/// * JavaScript does not distinguish between integer and floating point numbers, it only has floating point numbers (of double precision). For fields where UDB knows that they are integers this it not a problem, since it'll automatically convert the floating point numbers to integers (dropping the fractional part). However, if you need to specify an integer value for an unknown or custom field you have to work around this limitation, using the `UniValue` class:
/// ```
/// s.fields.user_myintfield = new UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
/// s.fields.user_myintfield = new UDB.UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
/// ```
/// To remove a field you have to assign `null` to it:
/// ```

View file

@ -369,16 +369,16 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// <summary>
/// Draws lines. Data has to be an `Array` of `Array` of numbers, `Vector2D`s, `Vector3D`s, or objects with x and y properties. Note that the first and last element have to be at the same positions to make a complete drawing.
/// ```
/// Map.drawLines([
/// new Vector2D(64, 0),
/// new Vector2D(128, 0),
/// new Vector2D(128, 64),
/// new Vector2D(64, 64),
/// new Vector2D(64, 0)
/// ```js
/// UDB.Map.drawLines([
/// new UDB.Vector2D(64, 0),
/// new UDB.Vector2D(128, 0),
/// new UDB.Vector2D(128, 64),
/// new UDB.Vector2D(64, 64),
/// new UDB.Vector2D(64, 0)
/// ]);
///
/// Map.drawLines([
/// UDB.Map.drawLines([
/// [ 0, 0 ],
/// [ 64, 0 ],
/// [ 64, 64 ],
@ -976,7 +976,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
}
/// <summary>
/// Gets the `Sidedef`s of the currently selected `Linedef`s *or*, if no `Linede`f`s are selected, the `Sidedef`s of the currently highlighted `Linedef`.
/// Gets the `Sidedef`s of the currently selected `Linedef`s *or*, if no `Linedef`s are selected, the `Sidedef`s of the currently highlighted `Linedef`.
/// In classic modes this will return both sidedefs of 2-sided lines, in visual mode it will only return the actually selected `Sidedef`.
/// </summary>
/// <returns>`Array` of `Sidedef`s</returns>
@ -1040,8 +1040,8 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// <summary>
/// Creates a new `Vertex` at the given position. The position can be a `Vector2D` or an `Array` of two numbers.
/// ```
/// var v1 = Map.createVertex(new Vector2D(32, 64));
/// var v2 = Map.createVertex([ 32, 64 ]);
/// var v1 = UDB.Map.createVertex(new Vector2D(32, 64));
/// var v2 = UDB.Map.createVertex([ 32, 64 ]);
/// ```
/// </summary>
/// <param name="pos">Position where the `Vertex` should be created at</param>
@ -1067,10 +1067,10 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// <summary>
/// Creates a new `Thing` at the given position. The position can be a `Vector2D`, `Vector3D`, or an `Array` of two numbers or three numbers (note that the z position only works for game configurations that support vertical pos. A thing type can be supplied optionally.
/// ```
/// var t1 = Map.createThing(new Vector2D(32, 64));
/// var t2 = Map.createThing([ 32, 64 ]);
/// var t3 = Map.createThing(new Vector2D(32, 64), 3001); // Create an Imp
/// var t4 = Map.createThing([ 32, 64 ], 3001); // Create an Imp
/// var t1 = UDB.Map.createThing(new UDB.Vector2D(32, 64));
/// var t2 = UDB.Map.createThing([ 32, 64 ]);
/// var t3 = UDB.Map.createThing(new UDB.Vector2D(32, 64), 3001); // Create an Imp
/// var t4 = UDB.Map.createThing([ 32, 64 ], 3001); // Create an Imp
/// ```
/// </summary>
/// <param name="pos">Position where the `Thing` should be created at</param>

View file

@ -553,10 +553,10 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// Checks if the given point is in this `Sector` or not. The given point can be a `Vector2D` or an `Array` of two numbers.
/// ```
/// if(s.intersect(new Vector2D(32, 64)))
/// log('Point is in the sector!');
/// UDB.showMessage('Point is in the sector!');
///
/// if(s.intersect([ 32, 64 ]))
/// log('Point is in the sector!');
/// UDB.showMessage('Point is in the sector!');
/// ```
/// </summary>
/// <param name="p">Point to test</param>

View file

@ -297,8 +297,8 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// ```
/// It's also possible to set all fields immediately by assigning either a `Vector2D`, `Vector3D`, or an array of numbers:
/// ```
/// t.position = new Vector2D(32, 64);
/// t.position = new Vector3D(32, 64, 128);
/// t.position = new UDB.Vector2D(32, 64);
/// t.position = new UDB.Vector3D(32, 64, 128);
/// t.position = [ 32, 64 ];
/// t.position = [ 32, 64, 128 ];
/// ```
@ -452,7 +452,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// Gets the squared distance between this `Thing` and the given point.
/// The point can be either a `Vector2D` or an array of numbers.
/// ```
/// t.distanceToSq(new Vector2D(32, 64));
/// t.distanceToSq(new UDB.Vector2D(32, 64));
/// t.distanceToSq([ 32, 64 ]);
/// ```
/// </summary>
@ -477,7 +477,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// <summary>
/// Gets the distance between this `Thing` and the given point. The point can be either a `Vector2D` or an array of numbers.
/// ```
/// t.distanceToSq(new Vector2D(32, 64));
/// t.distanceToSq(new UDB.Vector2D(32, 64));
/// t.distanceToSq([ 32, 64 ]);
/// ```
/// </summary>

View file

@ -0,0 +1,333 @@
#region ================== Copyright (c) 2022 Boris Iwanski
/*
* This program is free software: you can redistribute it and/or modify
*
* it under the terms of the GNU General Public License as published by
*
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
*
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
*
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.If not, see<http://www.gnu.org/licenses/>.
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Jint;
using Jint.Runtime.Interop;
#endregion
namespace CodeImp.DoomBuilder.UDBScript.Wrapper
{
internal class UDBWrapper
{
#region ================== Variables
private GameConfigurationWrapper gameconfiguration;
private TypeReference queryoptions;
private ExpandoObject scriptoptions;
private TypeReference angle2d;
private TypeReference data;
private TypeReference line2d;
private MapWrapper map;
private TypeReference univalue;
private TypeReference vector2d;
private TypeReference vector3d;
private TypeReference linedef;
private TypeReference sector;
private TypeReference sidedef;
private TypeReference thing;
private TypeReference vertex;
private IProgress<int> progress;
private IProgress<string> status;
private IProgress<string> logger;
#endregion
#region ================== Properties
/// <summary>
/// Class containing methods related to the game configuration. See [GameConfiguration](GameConfiguration.md) for more information.
/// </summary>
public GameConfigurationWrapper GameConfiguration
{
get
{
return gameconfiguration;
}
}
/// <summary>
/// Class containing methods and properties related to querying options from the user at runtime. See [QueryOptions](QueryOptions.md) for more information.
/// </summary>
public TypeReference QueryOptions
{
get
{
return queryoptions;
}
}
/// <summary>
/// Object containing the script options. See [Setting script options](gettingstarted.md#setting-script-options).
/// </summary>
public ExpandoObject ScriptOptions
{
get
{
return scriptoptions;
}
}
/// <summary>
/// Class containing methods related to angles. See [Angle2D](Angle2D.md) for more information.
/// ```js
/// let rad = UDB.Angle2D.degToRad(46);
/// ```
/// </summary>
public TypeReference Angle2D
{
get
{
return angle2d;
}
}
/// <summary>
/// Class containing methods related to the game data. See [Data](Data.md) for more information.
/// ```js
/// let hasfireblu = UDB.Data.textureExists('FIREBLU1');
/// ```
/// </summary>
public TypeReference Data
{
get
{
return data;
}
}
/// <summary>
/// Instantiable class that contains methods related to two-dimensional lines. See [Line2D](Line2D.md) for more information.
/// ```js
/// let line = new UDB.Line2D([ 32, 64 ], [ 96, 128 ]);
/// ```
/// </summary>
public TypeReference Line2D
{
get
{
return line2d;
}
}
/// <summary>
/// Object containing methods related to the map. See [Map](Map.md) for more information.
/// ```js
/// let sectors = UDB.Map.getSelectedOrHighlightedSectors();
/// ```
/// </summary>
public MapWrapper Map
{
get
{
return map;
}
}
/// <summary>
/// The `UniValue` class. Is only needed when trying to assign integer values to UDMF fields.
/// ```js
/// s.fields.user_myintfield = new UDB.UniValue(0, 25);
/// ```
/// </summary>
public TypeReference UniValue
{
get
{
return univalue;
}
}
/// <summary>
/// Instantiable class that contains methods related to two-dimensional vectors. See [Vector2D](Vector2D.md) for more information.
/// ```js
/// let v = new UDB.Vector2D(32, 64);
/// ```
/// </summary>
public TypeReference Vector2D
{
get
{
return vector2d;
}
}
/// <summary>
/// Instantiable class that contains methods related to three-dimensional vectors. See [Vector3D](Vector3D.md) for more information.
/// </summary>
/// ```js
/// let v = new UDB.Vector3D(32, 64, 128);
/// ```
public TypeReference Vector3D
{
get
{
return vector3d;
}
}
public TypeReference Linedef { get { return linedef; } }
public TypeReference Sector { get { return sector; } }
public TypeReference Sidedef { get { return sidedef; } }
public TypeReference Thing { get { return thing; } }
public TypeReference Vertex { get { return vertex; } }
#endregion
#region ================== Constructors
internal UDBWrapper(Engine engine, ScriptInfo scriptinfo, IProgress<int> progress, IProgress<string> status, IProgress<string> logger)
{
gameconfiguration = new GameConfigurationWrapper();
queryoptions = TypeReference.CreateTypeReference(engine, typeof(QueryOptions));
scriptoptions = scriptinfo.GetScriptOptionsObject();
angle2d = TypeReference.CreateTypeReference(engine, typeof(Angle2DWrapper));
data = TypeReference.CreateTypeReference(engine, typeof(DataWrapper));
line2d = TypeReference.CreateTypeReference(engine, typeof(Line2DWrapper));
map = new MapWrapper();
univalue = TypeReference.CreateTypeReference(engine, typeof(CodeImp.DoomBuilder.Map.UniValue));
vector2d = TypeReference.CreateTypeReference(engine, typeof(Vector2DWrapper));
vector3d = TypeReference.CreateTypeReference(engine, typeof(Vector3DWrapper));
// These can not be directly instanciated and don't have static method, but it's required to
// for example use "instanceof" in scripts
linedef = TypeReference.CreateTypeReference(engine, typeof(LinedefWrapper));
sector = TypeReference.CreateTypeReference(engine, typeof(SectorWrapper));
sidedef = TypeReference.CreateTypeReference(engine, typeof(SidedefWrapper));
thing = TypeReference.CreateTypeReference(engine, typeof(ThingWrapper));
vertex = TypeReference.CreateTypeReference(engine, typeof(VertexWrapper));
this.progress = progress;
this.status = status;
this.logger = logger;
}
#endregion
#region ================== Methods
/// <summary>
/// Set the progress of the script in percent. Value can be between 0 and 100. Also shows the script running dialog.
/// </summary>
/// <param name="value">Number between 0 and 100</param>
public void setProgress(int value)
{
progress.Report(value);
}
/*
public void setStatus(string text)
{
status.Report(text);
}
*/
/// <summary>
/// Adds a line to the script log. Also shows the script running dialog.
/// </summary>
/// <param name="text">Line to add to the script log</param>
public void log(string text)
{
logger.Report(text);
}
/// <summary>
/// Shows a message box with an "OK" button.
/// </summary>
/// <param name="message">Message to show</param>
public void showMessage(object message)
{
BuilderPlug.Me.ScriptRunnerForm.InvokePaused(new Action(() => {
if (message == null)
message = string.Empty;
MessageForm mf = new MessageForm("OK", null, message.ToString());
DialogResult result = mf.ShowDialog();
if (result == DialogResult.Abort)
throw new UserScriptAbortException();
}));
}
/// <summary>
/// Shows a message box with an "Yes" and "No" button.
/// </summary>
/// <param name="message">Message to show</param>
/// <returns>true if "Yes" was clicked, false if "No" was clicked</returns>
public bool showMessageYesNo(object message)
{
return (bool)BuilderPlug.Me.ScriptRunnerForm.InvokePaused(new Func<bool>(() =>
{
if (message == null)
message = string.Empty;
MessageForm mf = new MessageForm("Yes", "No", message.ToString());
DialogResult result = mf.ShowDialog();
if (result == DialogResult.Abort)
throw new UserScriptAbortException();
return result == DialogResult.OK;
}));
}
/// <summary>
/// Exist the script prematurely without undoing its changes.
/// </summary>
/// <param name="s">Text to show in the status bar (optional)</param>
public void exit(string s=null)
{
if (string.IsNullOrEmpty(s))
throw new ExitScriptException();
throw new ExitScriptException(s);
}
/// <summary>
/// Exist the script prematurely with undoing its changes.
/// </summary>
/// <param name="s">Text to show in the status bar (optional)</param>
public void die(string s=null)
{
if (string.IsNullOrEmpty(s))
throw new DieScriptException();
throw new DieScriptException(s);
}
#endregion
}
}

View file

@ -104,7 +104,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// <summary>
/// Creates a new `Vector2D` from x and y coordinates
/// ```
/// let v = new Vector2D(32, 64);
/// let v = new UDB.Vector2D(32, 64);
/// ```
/// </summary>
/// <param name="x">The x coordinate</param>
@ -119,7 +119,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// <summary>
/// Creates a new `Vector2D` from a point.
/// ```
/// let v = new Vector2D([ 32, 64 ]);
/// let v = new UDB.Vector2D([ 32, 64 ]);
/// ```
/// </summary>
/// <param name="v">The vector to create the `Vector2D` from</param>

View file

@ -119,7 +119,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// <summary>
/// Creates a new `Vector3D` from x and y coordinates
/// ```
/// let v = new Vector3D(32, 64, 128);
/// let v = new UDB.Vector3D(32, 64, 128);
/// ```
/// </summary>
/// <param name="x">The x coordinate</param>
@ -136,7 +136,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// <summary>
/// Creates a new `Vector3D` from a point.
/// ```
/// let v = new Vector3D([ 32, 64, 128 ]);
/// let v = new UDB.Vector3D([ 32, 64, 128 ]);
/// ```
/// </summary>
/// <param name="v">The vector to create the `Vector3D` from</param>

View file

@ -89,7 +89,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// ```
/// It's also possible to set all fields immediately by assigning either a `Vector2D`, or an array of numbers:
/// ```
/// v.position = new Vector2D(32, 64);
/// v.position = new UDB.Vector2D(32, 64);
/// v.position = [ 32, 64 ];
/// ```
/// </summary>
@ -267,7 +267,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// Gets the squared distance between this `Vertex` and the given point.
/// The point can be either a `Vector2D` or an array of numbers.
/// ```
/// v.distanceToSq(new Vector2D(32, 64));
/// v.distanceToSq(new UDB.Vector2D(32, 64));
/// v.distanceToSq([ 32, 64 ]);
/// ```
/// </summary>
@ -293,7 +293,7 @@ namespace CodeImp.DoomBuilder.UDBScript.Wrapper
/// Gets the distance between this `Vertex` and the given point.
/// The point can be either a `Vector2D` or an array of numbers.
/// ```
/// v.distanceTo(new Vector2D(32, 64));
/// v.distanceTo(new UDB.Vector2D(32, 64));
/// v.distanceTo([ 32, 64 ]);
/// ```
/// </summary>

View file

@ -70,7 +70,7 @@ namespace CodeImp.DoomBuilder.UDBScript
#region ================== Constants
private static readonly string SCRIPT_FOLDER = "udbscript";
public static readonly uint UDB_SCRIPT_VERSION = 3;
public static readonly uint UDB_SCRIPT_VERSION = 4;
#endregion

View file

@ -151,15 +151,11 @@ namespace CodeImp.DoomBuilder.UDBScript
/// <returns>True if OK was pressed, otherwise false</returns>
public bool query()
{
// Stop the timer so that the time spent in the dialog is not added to the script runtime constraint
BuilderPlug.Me.ScriptRunner.StopTimer();
DialogResult dr = form.ShowDialog();
// Start the timer again
BuilderPlug.Me.ScriptRunner.ResumeTimer();
return dr == DialogResult.OK;
return (bool)BuilderPlug.Me.ScriptRunnerForm.InvokePaused(new Func<bool>(() =>
{
DialogResult dr = form.ShowDialog();
return dr == DialogResult.OK;
}));
}
#endregion

View file

@ -31,7 +31,6 @@ using System.Windows.Forms;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Windows;
using CodeImp.DoomBuilder.UDBScript.Wrapper;
using CodeImp.DoomBuilder.UDBScript.API;
using Jint;
using Jint.Runtime;
using Jint.Runtime.Interop;
@ -258,7 +257,7 @@ namespace CodeImp.DoomBuilder.UDBScript
/// Sets everything up for running the script. This has to be done on the UI thread.
/// </summary>
/// <param name="cancellationtoken">Cancellation token to cancel the running script</param>
public void PreRun(CancellationToken cancellationtoken)
public void PreRun(CancellationToken cancellationtoken, IProgress<int> progress, IProgress<string> status, IProgress<string> log)
{
string importlibraryerrors;
@ -287,28 +286,38 @@ namespace CodeImp.DoomBuilder.UDBScript
// Create the script engine
engine = new Engine(options);
engine.SetValue("showMessage", new Action<object>(ShowMessage));
engine.SetValue("showMessageYesNo", new Func<object, bool>(ShowMessageYesNo));
engine.SetValue("exit", new Action<string>(ExitScript));
engine.SetValue("die", new Action<string>(DieScript));
engine.SetValue("QueryOptions", TypeReference.CreateTypeReference(engine, typeof(QueryOptions)));
engine.SetValue("ScriptOptions", scriptinfo.GetScriptOptionsObject());
engine.SetValue("Map", new MapWrapper());
engine.SetValue("GameConfiguration", new GameConfigurationWrapper());
engine.SetValue("Angle2D", TypeReference.CreateTypeReference(engine, typeof(Angle2DWrapper)));
engine.SetValue("Vector3D", TypeReference.CreateTypeReference(engine, typeof(Vector3DWrapper)));
engine.SetValue("Vector2D", TypeReference.CreateTypeReference(engine, typeof(Vector2DWrapper)));
engine.SetValue("Line2D", TypeReference.CreateTypeReference(engine, typeof(Line2DWrapper)));
engine.SetValue("UniValue", TypeReference.CreateTypeReference(engine, typeof(UniValue)));
engine.SetValue("Data", TypeReference.CreateTypeReference(engine, typeof(DataWrapper)));
// These can not be directly instanciated and don't have static method, but it's required to
// for example use "instanceof" in scripts
engine.SetValue("Linedef", TypeReference.CreateTypeReference(engine, typeof(LinedefWrapper)));
engine.SetValue("Sector", TypeReference.CreateTypeReference(engine, typeof(SectorWrapper)));
engine.SetValue("Sidedef", TypeReference.CreateTypeReference(engine, typeof(SidedefWrapper)));
engine.SetValue("Thing", TypeReference.CreateTypeReference(engine, typeof(ThingWrapper)));
engine.SetValue("Vertex", TypeReference.CreateTypeReference(engine, typeof(VertexWrapper)));
// Scripts with API version smaller than 4 will use the old global objects, starting from API
// version 4 the new global "UDB" object
if (scriptinfo.Version < 4)
{
engine.SetValue("showMessage", new Action<object>(ShowMessage));
engine.SetValue("showMessageYesNo", new Func<object, bool>(ShowMessageYesNo));
engine.SetValue("exit", new Action<string>(ExitScript));
engine.SetValue("die", new Action<string>(DieScript));
engine.SetValue("QueryOptions", TypeReference.CreateTypeReference(engine, typeof(QueryOptions)));
engine.SetValue("ScriptOptions", scriptinfo.GetScriptOptionsObject());
engine.SetValue("Map", new MapWrapper());
engine.SetValue("GameConfiguration", new GameConfigurationWrapper());
engine.SetValue("Angle2D", TypeReference.CreateTypeReference(engine, typeof(Angle2DWrapper)));
engine.SetValue("Vector3D", TypeReference.CreateTypeReference(engine, typeof(Vector3DWrapper)));
engine.SetValue("Vector2D", TypeReference.CreateTypeReference(engine, typeof(Vector2DWrapper)));
engine.SetValue("Line2D", TypeReference.CreateTypeReference(engine, typeof(Line2DWrapper)));
engine.SetValue("UniValue", TypeReference.CreateTypeReference(engine, typeof(UniValue)));
engine.SetValue("Data", TypeReference.CreateTypeReference(engine, typeof(DataWrapper)));
// These can not be directly instanciated and don't have static method, but it's required to
// for example use "instanceof" in scripts
engine.SetValue("Linedef", TypeReference.CreateTypeReference(engine, typeof(LinedefWrapper)));
engine.SetValue("Sector", TypeReference.CreateTypeReference(engine, typeof(SectorWrapper)));
engine.SetValue("Sidedef", TypeReference.CreateTypeReference(engine, typeof(SidedefWrapper)));
engine.SetValue("Thing", TypeReference.CreateTypeReference(engine, typeof(ThingWrapper)));
engine.SetValue("Vertex", TypeReference.CreateTypeReference(engine, typeof(VertexWrapper)));
}
else
{
engine.SetValue("UDB", new UDBWrapper(engine, scriptinfo, progress, status, log));
}
#if DEBUG
engine.SetValue("log", new Action<object>(Console.WriteLine));
@ -336,9 +345,9 @@ namespace CodeImp.DoomBuilder.UDBScript
/// <summary>
/// Runs the script
/// </summary>
public void Run(IProgress<int> progress, IProgress<string> status, IProgress<string> log)
public void Run()
{
engine.SetValue("ProgressInfo", new ProgressInfo(progress, status, log));
//engine.SetValue("ProgressInfo", new ProgressInfo(progress, status, log));
// Read the current script file
string script = File.ReadAllText(scriptinfo.ScriptFile);

View file

@ -78,6 +78,7 @@
<Compile Include="API\DataWrapper.cs" />
<Compile Include="API\GameConfigurationWrapper.cs" />
<Compile Include="API\ImageInfo.cs" />
<Compile Include="API\UDBWrapper.cs" />
<Compile Include="API\Vector3DWrapper.cs" />
<Compile Include="API\VisualCameraWrapper.cs" />
<Compile Include="BuilderPlug.cs" />

View file

@ -96,7 +96,7 @@ namespace CodeImp.DoomBuilder.UDBScript
{
if (InvokeRequired)
{
return Invoke(new Action(() => InvokePaused(method)));
return Invoke(new Func<object>(() => InvokePaused(method)));
}
else
{
@ -187,11 +187,11 @@ namespace CodeImp.DoomBuilder.UDBScript
running = true;
// Prepare running the script
BuilderPlug.Me.ScriptRunner.PreRun(cancellationtoken);
BuilderPlug.Me.ScriptRunner.PreRun(cancellationtoken, progress, status, log);
try
{
await Task.Run(() => BuilderPlug.Me.ScriptRunner.Run(progress, status, log));
await Task.Run(() => BuilderPlug.Me.ScriptRunner.Run());
stopwatch.Stop();
}
catch (Exception ex)

View file

@ -37,9 +37,11 @@ topics = {
'Sector': [ '../API/SectorWrapper.cs', '../API/MapElementWrapper.cs' ],
'Sidedef': [ '../API/SidedefWrapper.cs', '../API/MapElementWrapper.cs' ],
'Thing': [ '../API/ThingWrapper.cs', '../API/MapElementWrapper.cs' ],
'UDB': [ '../API/UDBWrapper.cs' ],
'Vector2D': [ '../API/Vector2DWrapper.cs' ],
'Vector3D': [ '../API/Vector3DWrapper.cs' ],
'Vertex': [ '../API/VertexWrapper.cs', '../API/MapElementWrapper.cs' ],
'VisualCamera': [ '../API/VisualCameraWrapper.cs' ],
'QueryOptions': [ '../QueryOptions.cs' ],
}

View file

@ -7,8 +7,8 @@
Creates a new `Line2D` from two points.
```js
let line1 = new Line2D(new Vector2D(32, 64), new Vector2D(96, 128));
let line2 = new Line2D([ 32, 64 ], [ 96, 128 ]);
let line1 = new UDB.Line2D(new Vector2D(32, 64), new Vector2D(96, 128));
let line2 = new UDB.Line2D([ 32, 64 ], [ 96, 128 ]);
```
#### Parameters
* v1: First point

View file

@ -38,7 +38,7 @@ UDMF fields. It's an object with the fields as properties.
s.fields.comment = 'This is a comment';
s.fields['comment'] = 'This is a comment'; // Also works
s.fields.xscalefloor = 2.0;
t.score = 100;
t.fields.score = 100;
```
It is also possible to define new fields:
@ -52,7 +52,7 @@ There are some restrictions, though:
* JavaScript does not distinguish between integer and floating point numbers, it only has floating point numbers (of double precision). For fields where UDB knows that they are integers this it not a problem, since it'll automatically convert the floating point numbers to integers (dropping the fractional part). However, if you need to specify an integer value for an unknown or custom field you have to work around this limitation, using the `UniValue` class:
```js
s.fields.user_myintfield = new UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
s.fields.user_myintfield = new UDB.UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
```
To remove a field you have to assign `null` to it:

View file

@ -80,10 +80,10 @@ Clears all selected vertices.
Creates a new `Thing` at the given position. The position can be a `Vector2D`, `Vector3D`, or an `Array` of two numbers or three numbers (note that the z position only works for game configurations that support vertical pos. A thing type can be supplied optionally.
```js
var t1 = Map.createThing(new Vector2D(32, 64));
var t2 = Map.createThing([ 32, 64 ]);
var t3 = Map.createThing(new Vector2D(32, 64), 3001); // Create an Imp
var t4 = Map.createThing([ 32, 64 ], 3001); // Create an Imp
var t1 = UDB.Map.createThing(new UDB.Vector2D(32, 64));
var t2 = UDB.Map.createThing([ 32, 64 ]);
var t3 = UDB.Map.createThing(new UDB.Vector2D(32, 64), 3001); // Create an Imp
var t4 = UDB.Map.createThing([ 32, 64 ], 3001); // Create an Imp
```
#### Parameters
* pos: Position where the `Thing` should be created at
@ -96,8 +96,8 @@ The new `Thing`
Creates a new `Vertex` at the given position. The position can be a `Vector2D` or an `Array` of two numbers.
```js
var v1 = Map.createVertex(new Vector2D(32, 64));
var v2 = Map.createVertex([ 32, 64 ]);
var v1 = UDB.Map.createVertex(new Vector2D(32, 64));
var v2 = UDB.Map.createVertex([ 32, 64 ]);
```
#### Parameters
* pos: Position where the `Vertex` should be created at
@ -109,15 +109,15 @@ The created `Vertex`
Draws lines. Data has to be an `Array` of `Array` of numbers, `Vector2D`s, `Vector3D`s, or objects with x and y properties. Note that the first and last element have to be at the same positions to make a complete drawing.
```js
Map.drawLines([
new Vector2D(64, 0),
new Vector2D(128, 0),
new Vector2D(128, 64),
new Vector2D(64, 64),
new Vector2D(64, 0)
UDB.Map.drawLines([
new UDB.Vector2D(64, 0),
new UDB.Vector2D(128, 0),
new UDB.Vector2D(128, 64),
new UDB.Vector2D(64, 64),
new UDB.Vector2D(64, 0)
]);
Map.drawLines([
UDB.Map.drawLines([
[ 0, 0 ],
[ 64, 0 ],
[ 64, 64 ],
@ -296,7 +296,7 @@ In classic modes this will return both sidedefs of 2-sided lines, in visual mode
---
<span style="float:right;font-weight:normal;font-size:66%">Version: 3</span>
### getSidedefsFromSelectedOrHighlightedLinedefs()
Gets the `Sidedef`s of the currently selected `Linedef`s *or*, if no `Linede`f`s are selected, the `Sidedef`s of the currently highlighted `Linedef`.
Gets the `Sidedef`s of the currently selected `Linedef`s *or*, if no `Linedef`s are selected, the `Sidedef`s of the currently highlighted `Linedef`.
In classic modes this will return both sidedefs of 2-sided lines, in visual mode it will only return the actually selected `Sidedef`.
#### Return value
`Array` of `Sidedef`s

View file

@ -13,12 +13,12 @@ Ceiling height of the `Sector`.
---
<span style="float:right;font-weight:normal;font-size:66%">Version: 3</span>
### ceilingHighlighted
If the `Sector`'s ceiling is highlighted or not. Will always return `true` in classic modes if the `Sector` is highlighted.
If the `Sector`'s ceiling is highlighted or not. Will always return `true` in classic modes if the `Sector` is highlighted. Read-only.
---
<span style="float:right;font-weight:normal;font-size:66%">Version: 3</span>
### ceilingSelected
If the `Sector`'s ceiling is selected or not. Will always return `true` in classic modes if the `Sector` is selected.
If the `Sector`'s ceiling is selected or not. Will always return `true` in classic modes if the `Sector` is selected. Read-only.
---
### ceilingSlopeOffset
@ -36,7 +36,7 @@ UDMF fields. It's an object with the fields as properties.
s.fields.comment = 'This is a comment';
s.fields['comment'] = 'This is a comment'; // Also works
s.fields.xscalefloor = 2.0;
t.score = 100;
t.fields.score = 100;
```
It is also possible to define new fields:
@ -50,7 +50,7 @@ There are some restrictions, though:
* JavaScript does not distinguish between integer and floating point numbers, it only has floating point numbers (of double precision). For fields where UDB knows that they are integers this it not a problem, since it'll automatically convert the floating point numbers to integers (dropping the fractional part). However, if you need to specify an integer value for an unknown or custom field you have to work around this limitation, using the `UniValue` class:
```js
s.fields.user_myintfield = new UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
s.fields.user_myintfield = new UDB.UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
```
To remove a field you have to assign `null` to it:
@ -75,12 +75,12 @@ Floor height of the `Sector`.
---
<span style="float:right;font-weight:normal;font-size:66%">Version: 3</span>
### floorHighlighted
If the `Sector`'s floor is highlighted or not. Will always return `true` in classic modes if the `Sector` is highlighted.
If the `Sector`'s floor is highlighted or not. Will always return `true` in classic modes if the `Sector` is highlighted. Read-only.
---
<span style="float:right;font-weight:normal;font-size:66%">Version: 3</span>
### floorSelected
If the `Sector`'s floor is selected or not. Will always return `true` in classic modes if the `Sector` is selected.
If the `Sector`'s floor is selected or not. Will always return `true` in classic modes if the `Sector` is selected. Read-only.
---
### floorSlopeOffset
@ -169,10 +169,10 @@ Checks if the given point is in this `Sector` or not. The given point can be a `
```js
if(s.intersect(new Vector2D(32, 64)))
log('Point is in the sector!');
UDB.showMessage('Point is in the sector!');
if(s.intersect([ 32, 64 ]))
log('Point is in the sector!');
UDB.showMessage('Point is in the sector!');
```
#### Parameters
* p: Point to test

View file

@ -18,7 +18,7 @@ UDMF fields. It's an object with the fields as properties.
s.fields.comment = 'This is a comment';
s.fields['comment'] = 'This is a comment'; // Also works
s.fields.xscalefloor = 2.0;
t.score = 100;
t.fields.score = 100;
```
It is also possible to define new fields:
@ -32,7 +32,7 @@ There are some restrictions, though:
* JavaScript does not distinguish between integer and floating point numbers, it only has floating point numbers (of double precision). For fields where UDB knows that they are integers this it not a problem, since it'll automatically convert the floating point numbers to integers (dropping the fractional part). However, if you need to specify an integer value for an unknown or custom field you have to work around this limitation, using the `UniValue` class:
```js
s.fields.user_myintfield = new UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
s.fields.user_myintfield = new UDB.UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
```
To remove a field you have to assign `null` to it:

View file

@ -26,7 +26,7 @@ UDMF fields. It's an object with the fields as properties.
s.fields.comment = 'This is a comment';
s.fields['comment'] = 'This is a comment'; // Also works
s.fields.xscalefloor = 2.0;
t.score = 100;
t.fields.score = 100;
```
It is also possible to define new fields:
@ -40,7 +40,7 @@ There are some restrictions, though:
* JavaScript does not distinguish between integer and floating point numbers, it only has floating point numbers (of double precision). For fields where UDB knows that they are integers this it not a problem, since it'll automatically convert the floating point numbers to integers (dropping the fractional part). However, if you need to specify an integer value for an unknown or custom field you have to work around this limitation, using the `UniValue` class:
```js
s.fields.user_myintfield = new UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
s.fields.user_myintfield = new UDB.UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
```
To remove a field you have to assign `null` to it:
@ -87,8 +87,8 @@ t.position.y = 64;
It's also possible to set all fields immediately by assigning either a `Vector2D`, `Vector3D`, or an array of numbers:
```js
t.position = new Vector2D(32, 64);
t.position = new Vector3D(32, 64, 128);
t.position = new UDB.Vector2D(32, 64);
t.position = new UDB.Vector3D(32, 64, 128);
t.position = [ 32, 64 ];
t.position = [ 32, 64, 128 ];
```
@ -129,7 +129,7 @@ Deletes the `Thing`.
Gets the distance between this `Thing` and the given point. The point can be either a `Vector2D` or an array of numbers.
```js
t.distanceToSq(new Vector2D(32, 64));
t.distanceToSq(new UDB.Vector2D(32, 64));
t.distanceToSq([ 32, 64 ]);
```
#### Parameters
@ -143,7 +143,7 @@ Gets the squared distance between this `Thing` and the given point.
The point can be either a `Vector2D` or an array of numbers.
```js
t.distanceToSq(new Vector2D(32, 64));
t.distanceToSq(new UDB.Vector2D(32, 64));
t.distanceToSq([ 32, 64 ]);
```
#### Parameters

View file

@ -0,0 +1,106 @@
# UDB
## Properties
---
### Angle2D
Class containing methods related to angles. See [Angle2D](Angle2D.md) for more information.
```js
let rad = UDB.Angle2D.degToRad(46);
```
---
### Data
Class containing methods related to the game data. See [Data](Data.md) for more information.
```js
let hasfireblu = UDB.Data.textureExists('FIREBLU1');
```
---
### GameConfiguration
Class containing methods related to the game configuration. See [GameConfiguration](GameConfiguration.md) for more information.
---
### Line2D
Instantiable class that contains methods related to two-dimensional lines. See [Line2D](Line2D.md) for more information.
```js
let line = new UDB.Line2D([ 32, 64 ], [ 96, 128 ]);
```
---
### Map
Object containing methods related to the map. See [Map](Map.md) for more information.
```js
let sectors = UDB.Map.getSelectedOrHighlightedSectors();
```
---
### QueryOptions
Class containing methods and properties related to querying options from the user at runtime. See [QueryOptions](QueryOptions.md) for more information.
---
### ScriptOptions
Object containing the script options. See [Setting script options](gettingstarted.md#setting-script-options).
---
### UniValue
The `UniValue` class. Is only needed when trying to assign integer values to UDMF fields.
```js
s.fields.user_myintfield = new UDB.UniValue(0, 25);
```
---
### Vector2D
Instantiable class that contains methods related to two-dimensional vectors. See [Vector2D](Vector2D.md) for more information.
```js
let v = new UDB.Vector2D(32, 64);
```
---
### Vector3D
Instantiable class that contains methods related to three-dimensional vectors. See [Vector3D](Vector3D.md) for more information.
## Methods
---
### die(s=null)
Exist the script prematurely with undoing its changes.
#### Parameters
* s: Text to show in the status bar (optional)
---
### exit(s=null)
Exist the script prematurely without undoing its changes.
#### Parameters
* s: Text to show in the status bar (optional)
---
### log(text)
Adds a line to the script log. Also shows the script running dialog.
#### Parameters
* text: Line to add to the script log
---
### setProgress(value)
Set the progress of the script in percent. Value can be between 0 and 100. Also shows the script running dialog.
#### Parameters
* value: Number between 0 and 100
---
### showMessage(message)
Shows a message box with an "OK" button.
#### Parameters
* message: Message to show
---
### showMessageYesNo(message)
Shows a message box with an "Yes" and "No" button.
#### Parameters
* message: Message to show
#### Return value
true if "Yes" was clicked, false if "No" was clicked

View file

@ -7,7 +7,7 @@
Creates a new `Vector2D` from a point.
```js
let v = new Vector2D([ 32, 64 ]);
let v = new UDB.Vector2D([ 32, 64 ]);
```
#### Parameters
* v: The vector to create the `Vector2D` from
@ -17,7 +17,7 @@ let v = new Vector2D([ 32, 64 ]);
Creates a new `Vector2D` from x and y coordinates
```js
let v = new Vector2D(32, 64);
let v = new UDB.Vector2D(32, 64);
```
#### Parameters
* x: The x coordinate

View file

@ -7,7 +7,7 @@
Creates a new `Vector3D` from a point.
```js
let v = new Vector3D([ 32, 64, 128 ]);
let v = new UDB.Vector3D([ 32, 64, 128 ]);
```
#### Parameters
* v: The vector to create the `Vector3D` from
@ -17,7 +17,7 @@ let v = new Vector3D([ 32, 64, 128 ]);
Creates a new `Vector3D` from x and y coordinates
```js
let v = new Vector3D(32, 64, 128);
let v = new UDB.Vector3D(32, 64, 128);
```
#### Parameters
* x: The x coordinate

View file

@ -14,7 +14,7 @@ UDMF fields. It's an object with the fields as properties.
s.fields.comment = 'This is a comment';
s.fields['comment'] = 'This is a comment'; // Also works
s.fields.xscalefloor = 2.0;
t.score = 100;
t.fields.score = 100;
```
It is also possible to define new fields:
@ -28,7 +28,7 @@ There are some restrictions, though:
* JavaScript does not distinguish between integer and floating point numbers, it only has floating point numbers (of double precision). For fields where UDB knows that they are integers this it not a problem, since it'll automatically convert the floating point numbers to integers (dropping the fractional part). However, if you need to specify an integer value for an unknown or custom field you have to work around this limitation, using the `UniValue` class:
```js
s.fields.user_myintfield = new UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
s.fields.user_myintfield = new UDB.UniValue(0, 25); // Sets the 'user_myintfield' field to an integer value of 25
```
To remove a field you have to assign `null` to it:
@ -60,7 +60,7 @@ v.position.y = 64;
It's also possible to set all fields immediately by assigning either a `Vector2D`, or an array of numbers:
```js
v.position = new Vector2D(32, 64);
v.position = new UDB.Vector2D(32, 64);
v.position = [ 32, 64 ];
```
@ -85,7 +85,7 @@ Gets the distance between this `Vertex` and the given point.
The point can be either a `Vector2D` or an array of numbers.
```js
v.distanceTo(new Vector2D(32, 64));
v.distanceTo(new UDB.Vector2D(32, 64));
v.distanceTo([ 32, 64 ]);
```
#### Parameters
@ -99,7 +99,7 @@ Gets the squared distance between this `Vertex` and the given point.
The point can be either a `Vector2D` or an array of numbers.
```js
v.distanceToSq(new Vector2D(32, 64));
v.distanceToSq(new UDB.Vector2D(32, 64));
v.distanceToSq([ 32, 64 ]);
```
#### Parameters

View file

@ -0,0 +1,15 @@
# VisualCamera
## Properties
---
### angleXY
Angle of the camera on the X/Y axes. Read-only.
---
### angleZ
Angle of the camera on the Z axis. Read-only.
---
### position
Position of the camera as `Vector3D`. Read-only.

View file

@ -1,6 +1,11 @@
# Changes
This site lists all changes between different API version of UDBScript
## Verstion 4
- Moved all classes, object, and methods into the `UDB` namespace (everything has to be prefixed wiht `UDB.`)
- Added methods to report progress for long running scripts and script log output. See [Communicating with the user](gettingstartet.md#communicating-with-the-user) for more information
## Version 3
- Exported the classes `Linedef`, `Sector`, `Sidedef`, `Thing`, and `Vertex`, so that they can be used with `instanceof`

View file

@ -81,6 +81,9 @@ Currently the following metadata commands are available:
- `description`: description of the script. Should include what the script does and what the requirements are (for example if something has to be selected for the script to work)
- `scriptoptions`: the script options. The payload has to be in UDB's configuration file format (see below)
!!! attention
It is highliy recommended to set the feature version through the `version` metadata command. The global `UDB` namespace was added in version 4, and new features will be exclusively added to this namespace!
#### Setting script options
The script options that can be set in the docker prior to running the script can be defined using the `scriptoptions` metadata command. The payload has to be in UDB's configuration file format.
@ -167,7 +170,7 @@ The following types are currently available:
#### Accessing script options in a script
The script option can be accessed through the global object `ScriptOptions`. This object has properties by the name of the blocks of the script option definition, and contains the value set in the docker.
The script option can be accessed through the `ScriptOptions` object in the global `UDB` namespace. This object has properties by the name of the blocks of the script option definition, and contains the value set in the docker.
Example:
@ -182,11 +185,24 @@ length
}
`;
showMessage('The given length is ' + ScriptOptions.length);
UDB.showMessage('The given length is ' + UDB.ScriptOptions.length);
```
!!! tip
You can also query options at runtime. See the `QueryOptions` API documentation.
### The global UDB namespace
Starting with feature version 4 of UDBScript all objects, methods, and classes are combined in the global `UDB` namespace. This is to prevent clashes with existing and future features of Javascript (for example Javascript has a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) class). It is highly recommended to specify the feature version through the `version` metadata command (see above). New UDBScript features will only be added to the global `UDB` namespace.
In practice that means that all methods, objects, and classes have to be prefixed with `UDB.`, for example getting all sectors in a map looked like this in versions prior to 4:
```js
let sectors = Map.getSectors();
```
while in version 4 and later the following code has to be used:
```js
let sectors = UDB.Map.getSectors();
```
### Working with vectors
In UDBScript vectors are commonly used to represent positions, like thing and vertex positions. They come in two flavors, `Vector2D` (representing a two-dimentional vector with `x` and `y` components) and `Vector3D` (representing a three-dimentional vector with `x`, `y`, and `z` components). They feature a range of vector math methods, such as rotating the vector.
@ -194,26 +210,26 @@ In UDBScript vectors are commonly used to represent positions, like thing and ve
There are several ways to create a new vector:
```js
let v1 = new Vector2D(32, 64); // From x and y values
let v2 = new Vector2D([ 32, 64 ]); // From an array with two numbers
let v3 = new Vector2D({ x: 32, y: 64 }); // From an object with x and y properties
let v4 = new Vector2D(v1); // From another Vector2D
let v1 = new UDB.Vector2D(32, 64); // From x and y values
let v2 = new UDB.Vector2D([ 32, 64 ]); // From an array with two numbers
let v3 = new UDB.Vector2D({ x: 32, y: 64 }); // From an object with x and y properties
let v4 = new UDB.Vector2D(v1); // From another Vector2D
let v5 = new Vector3D(32, 64, 16); // From x, y, and z values
let v6 = new Vector3D([ 32, 64, 16 ]); // From an array with three numbers
let v7 = new Vector3D({ x: 32, y: 64, z: 16 }); // From an object with x, y, and z properties
let v8 = new Vector3D(v5); // From another Vector3D
let v5 = new UDB.Vector3D(32, 64, 16); // From x, y, and z values
let v6 = new UDB.Vector3D([ 32, 64, 16 ]); // From an array with three numbers
let v7 = new UDB.Vector3D({ x: 32, y: 64, z: 16 }); // From an object with x, y, and z properties
let v8 = new UDB.Vector3D(v5); // From another Vector3D
```
API methods that accept a `Vector2D` or `Vector3D` as a parameter also accept the array notation. For example the following lines are equivalent:
```js
let t1 = Map.createThing(new Vector2D(32, 64), 3001); // Create an Imp
let t2 = Map.createThing([ 32, 64 ], 3001); // Create an Imp
let t3 = Map.createThing({ x: 32, y: 64 }, 3001); // Create an Imp
let t1 = UDB.Map.createThing(new UDB.Vector2D(32, 64), 3001); // Create an Imp
let t2 = UDB.Map.createThing([ 32, 64 ], 3001); // Create an Imp
let t3 = UDB.Map.createThing({ x: 32, y: 64 }, 3001); // Create an Imp
let v = new Vector2D(32, 64); // Supplying the x and y values
let t4 = Map.createThing(v, 3001); // Create an Imp
let v = new UDB.Vector2D(32, 64); // Supplying the x and y values
let t4 = UDB.Map.createThing(v, 3001); // Create an Imp
```
#### Vector arithmetic
@ -221,24 +237,24 @@ let t4 = Map.createThing(v, 3001); // Create an Imp
It is possible to do elementary arithmetic with vectors, i.e. you can add, substract, multiply, and divide them.
```js
let v1 = new Vector2D(2, 3) + new Vector2D(4, 5); // Results in new Vector(6, 8)
let v2 = new Vector2D(2, 3) - new Vector2D(4, 5); // Results in new Vector(-2, -2)
let v3 = new Vector2D(2, 3) * new Vector2D(4, 5); // Results in new Vector(8, 15)
let v4 = new Vector2D(2, 3) / new Vector2D(4, 5); // Results in new Vector(0.5, 0.6)
let v1 = new UDB.Vector2D(2, 3) + new UDB.Vector2D(4, 5); // Results in new Vector(6, 8)
let v2 = new UDB.Vector2D(2, 3) - new UDB.Vector2D(4, 5); // Results in new Vector(-2, -2)
let v3 = new UDB.Vector2D(2, 3) * new UDB.Vector2D(4, 5); // Results in new Vector(8, 15)
let v4 = new UDB.Vector2D(2, 3) / new UDB.Vector2D(4, 5); // Results in new Vector(0.5, 0.6)
```
This also works with the array and object notation:
```js
let v1 = new Vector2D(2, 3) + [ 4, 5 ]; // Results in new Vector(6, 8)
let v2 = new Vector2D(2, 3) + { x: 4, y: 5 }; // Results in new Vector(6, 8)
let v1 = new UDB.Vector2D(2, 3) + [ 4, 5 ]; // Results in new Vector(6, 8)
let v2 = new UDB.Vector2D(2, 3) + { x: 4, y: 5 }; // Results in new Vector(6, 8)
```
You can also use only a number as one side of the operation, in which case the operation will be applied to each element of the vector:
```js
let v1 = new Vector2D(2, 3) + 3; // Results in new Vector(5, 6)
let v2 = new Vector2D(2, 3) * 3; // Results in new Vector(6, 9)
let v1 = new UDB.Vector2D(2, 3) + 3; // Results in new Vector(5, 6)
let v2 = new UDB.Vector2D(2, 3) * 3; // Results in new Vector(6, 9)
```
!!! attention
@ -247,35 +263,35 @@ let v2 = new Vector2D(2, 3) * 3; // Results in new Vector(6, 9)
### Working with map elements
Map elements (things, sectors, linedefs, sidedefs, vertices) can be accessed through the global `Map` object. This object has methods that return an array of map elements, for example `Map.getSectors()` returns an array of `Sector` objects, which are are all sectors in the map. There are also methods to get all selected (for example `Map.getSelectedSectors()`) and marked (for example `Map.getMarkedSectors()`), or the currently highlighted (for example `Map.getHighlightedSector()`) map elements. There are also methods to get either the currently selected map elements, *or* the currently highlighted map elements (for example `Map.getSelectedOrHighlightedSectors()`). These map elements can then be modified, see the documentation for the particular map element type in the API section.
Map elements (things, sectors, linedefs, sidedefs, vertices) can be accessed through the `UDB.Map` object. This object has methods that return an array of map elements, for example `UDB.Map.getSectors()` returns an array of `Sector` objects, which are are all sectors in the map. There are also methods to get all selected (for example `UDB.Map.getSelectedSectors()`) and marked (for example `UDB.Map.getMarkedSectors()`), or the currently highlighted (for example `UDB.Map.getHighlightedSector()`) map elements. There are also methods to get either the currently selected map elements, *or* the currently highlighted map elements (for example `UDB.Map.getSelectedOrHighlightedSectors()`). These map elements can then be modified, see the documentation for the particular map element type in the API section.
!!! note
"Marking" a map element is a way to denote that something happened to this map element. For example when using the `Map.drawLines()` method all new geometry will be marked.
"Marking" a map element is a way to denote that something happened to this map element. For example when using the `UDB.Map.drawLines()` method all new geometry will be marked.
!!! info
UDB differentiates between "selecting" and "highlighting" map elements. "Selecting" means clicking on the map element, "highlighting" means just hovering the mouse on (or near) a map element. All the `Map.getSelectedOrHighlighted...()` methods behave like UDB usually works, i.e. if at least one map element is selected, the selected map elements will be returned (and the highlighted map element will be ignored), if no map elements are selected the highlighted map element will be returned.
In most circumstances it is recommended to use the `Map.getSelectedOrHighlighted...()` to stay close to UDB's built-in actions.
UDB differentiates between "selecting" and "highlighting" map elements. "Selecting" means clicking on the map element, "highlighting" means just hovering the mouse on (or near) a map element. All the `UDB.Map.getSelectedOrHighlighted...()` methods behave like UDB usually works, i.e. if at least one map element is selected, the selected map elements will be returned (and the highlighted map element will be ignored), if no map elements are selected the highlighted map element will be returned.
In most circumstances it is recommended to use the `UDB.Map.getSelectedOrHighlighted...()` to stay close to UDB's built-in actions.
### Creating new geometry
New map geometry can be created with the `drawLines()` method of the `Map` object. It accepts an array of coordinates in map space. The coordinates can either by instances of `Vector2D`, `Vector3D`, or an array of numbers.
New map geometry can be created with the `drawLines()` method of the `UDB.Map` object. It accepts an array of coordinates in map space. The coordinates can either by instances of `Vector2D`, `Vector3D`, or an array of numbers.
Example 1:
```js
Map.drawLines([
new Vector2D(0, 0),
new Vector2D(64, 0),
new Vector2D(64, 64),
new Vector2D(0, 64),
new Vector2D(0, 0)
UDB.Map.drawLines([
new UDB.Vector2D(0, 0),
new UDB.Vector2D(64, 0),
new UDB.Vector2D(64, 64),
new UDB.Vector2D(0, 64),
new UDB.Vector2D(0, 0)
]);
```
Example 2:
```js
Map.drawLines([
UDB.Map.drawLines([
[ 0, 0 ],
[ 64, 0 ],
[ 64, 64 ],
@ -322,33 +338,46 @@ p.finishDrawing();
Normally a script ends when the last instruction is executed. But there can be situations where you want to end a script early.
- `exit()`: this global function ends the script with success. It can optionally take a string argument that is shown in the status bar upon ending the script
- `die()`: this global function ends the script with a failure. This means that it will undo any changes the script has made. It can optionally take a string argument that is shown in the status bar upon ending the script
- `UDB.exit()`: this global function ends the script with success. It can optionally take a string argument that is shown in the status bar upon ending the script
- `UDB.die()`: this global function ends the script with a failure. This means that it will undo any changes the script has made. It can optionally take a string argument that is shown in the status bar upon ending the script
- `throw`: throws an exception. Only ends the script if it's not caught in a `try`/`catch` block. If not caught it'll end the script with a failure. This means that it will undo any changes the script has made. The string given as a parameter is shown in the status bar upon ending the script
```js
let sectors = Map.getSelectedSectors();
let sectors = UDB.Map.getSelectedSectors();
if(sectors.length == 0)
die('You have to select at least one sector');
UDB.die('You have to select at least one sector');
exit('There were ' + sectors.length + ' sectors selected');
UDB.exit('There were ' + sectors.length + ' sectors selected');
throw 'This part of the script should never be reached!';
```
### Communicating with the user
Sometimes you might want to let the script directly communicate with the user. To do that there are two global functions, `showMessage()` and `showMessageYesNo()`.
Sometimes you might want to let the script directly communicate with the user. To do that there are two functions, `UDB.showMessage()` and `UDB.showMessageYesNo()`.
- `showMessage()`: shows a message box with an "OK" button and the text given as the parameter<br>
- `UDB.showMessage()`: shows a message box with an "OK" button and the text given as the parameter<br>
```js
showMessage('Hello, world!');
UDB.showMessage('Hello, world!');
```
- `showMessageYesNo()`: shows a message box with an "Yes" and "No" button and the text given as the parameter. Returns `true` if the "Yes" button was clicked, and `false` if the "No" button was clicked
- `UDB.showMessageYesNo()`: shows a message box with an "Yes" and "No" button and the text given as the parameter. Returns `true` if the "Yes" button was clicked, and `false` if the "No" button was clicked
```js
if(showMessageYesNo('Are you sure you want to replace all imps with Arch-Viles? That\'s not remotely fair!'))
if(UDB.showMessageYesNo('Are you sure you want to replace all imps with Arch-Viles? That\'s not remotely fair!'))
{
Map.getThings().filter(t => t.type == 3001).forEach(t => t.type=64);
UDB.Map.getThings().filter(t => t.type == 3001).forEach(t => t.type=64);
}
```
```
For long-running scripts it's also possible to report the progress to the user using the `UDB.setProgress()` method, which accepts values from 0 to 100. For example the following code will set the progress bar to 25%:
```js
UDB.setProgress(25);
```
Additional output can be shown using the `UDB.log()` method, which will add a line of text to the log in the running script dialog:
```js
UDB.log('Hello, world!');
```
![Running Script Dialog](runningscriptdialog.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -20,8 +20,10 @@ nav:
- Sector: 'Sector.md'
- Sidedef: 'Sidedef.md'
- Thing: 'Thing.md'
- UDB: 'UDB.md'
- Vector2D: 'Vector2D.md'
- Vector3D: 'Vector3D.md'
- Vertex: 'Vertex.md'
- VisualCamera: 'VisualCamera.md'
- 'Built-in libraries':
- Pen: 'Pen.md'