//#CLIENTSIDE
const ZOOM_MIN = 1;
const ZOOM_DEFAULT = 1;
const ZOOM_MAX = 5;
const NAME_ZOOM_IN = "+";
const NAME_ZOOM_OUT = "-";
const NAME_HORIZONTAL = "Horizontal";
const NAME_VERTICAL = "Vertical";
const BLOCK_HORIZONTAL = 8;
const BLOCK_VERTICAL = 11;
const COLOR_WALL = "0,0,50";
const COLOR_FLOOR = "200,200,255";
const EXPORT_FLOOR = ".";
const EXPORT_WALL = "X";
const GUI_PADDING = 5;
function ChatBar.onAction() {
if (ChatBar.text == ":dungeon") {
ChatBar.text = "";
ChatBar.visible = false;
sleep(0.05); // give the chat bar a frame to hide first
this.drawWindow();
}
}
function drawWindow() {
if (DungeonEditor_Window != null) {
DungeonEditor_Window.destroy();
}
new GuiWindowCtrl("DungeonEditor_Window") {
profile = GuiBlueWindowProfile;
clientRelative = canClose = canMinimize = canMaximize = canResize = true;
isExternal = false;
clientWidth = 300;
clientHeight = 300;
minExtent = {280, 200};
x = (GraalControl.width / 2) - (width / 2);
y = (GraalControl.height / 2) - (height / 2);
text = "Dungeon Editor";
temp.currentY = GUI_PADDING;
temp.blockTypes = {
{NAME_HORIZONTAL, BLOCK_HORIZONTAL},
{NAME_VERTICAL, BLOCK_VERTICAL}
};
temp.i = 0;
for (temp.blockType : blockTypes) {
new GuiTextEditCtrl("DungeonEditor_Block_" @ blockType[0] @ "_Count") {
DungeonEditor_Window.blockCounts.add(this);
profile = GuiBlueTextEditProfile;
useOwnProfile = true;
profile.fontSize = 18;
profile.align = "center";
width = 40;
height = 30;
alpha = 0.8;
x = 110 + (GUI_PADDING * 2);
y = currentY;
this.blockTypeID = i;
thiso.catchEvent(this, "onTextChanged", "onBlockSizeChanged");
}
new GuiTextCtrl("DungeonEditor_Block_" @ blockType[0] @ "_Label") {
useOwnProfile = true;
// fix: align doesn't work with GuiBlueTextProfile, why?
profile.fontColor = GuiBlueTextProfile.fontColor;
profile.justify = "right";
profile.modal = false;
x = GUI_PADDING;
y = currentY;
width = 110;
height = profile.getTextHeight();
currentY += height;
text = blockType[0] @ " blocks:";
}
new GuiTextCtrl("DungeonEditor_Block_" @ blockType[0] @ "_Label_Size") {
useOwnProfile = true;
// fix: align doesn't work with GuiBlueTextProfile, why?
profile.fontColor = GuiBlueTextProfile.fontColor;
profile.justify = "right";
profile.modal = false;
profile.fontSize = 12;
x = GUI_PADDING;
y = currentY;
width = 110;
height = profile.getTextHeight();
currentY += height;
text = "(" @ blockType[1] @ " tiles each)";
}
currentY += GUI_PADDING;
i ++;
}
new GuiMLTextCtrl("DungeonEditor_MapSize") {
profile = GuiBlueMLTextProfile;
x = 150 + (GUI_PADDING * 3);
y = GUI_PADDING; //((currentY - GUI_PADDING) / 2) - profile.getTextHeight();
width = DungeonEditor_Window.clientWidth - x - GUI_PADDING;
text = "
Map size:\n4x4 levels";
horizSizing = "width";
}
temp.zoomOptions = {NAME_ZOOM_OUT, NAME_ZOOM_IN};
temp.zoomY = currentY - 24 - GUI_PADDING; //(GUI_PADDING * 2) + ((DungeonEditor_MapSize.profile.getTextHeight() + 1) * 2);
temp.i = 0;
for (temp.zoomOption : zoomOptions) {
new GuiButtonCtrl("DungeonEditor_Zoom_" @ i) {
DungeonEditor_Window.zoomButtons.add(this);
profile = GuiBlueButtonProfile;
width = 24;
height = width;
x = DungeonEditor_Window.clientWidth - (GUI_PADDING * ((1 - i) + 1)) - (((1 - i) + 1) * width);
y = zoomY;
text = zoomOption;
horizSizing = "left";
this.zoomAction = (i == 0 ? (- 1) : 1);
thiso.catchEvent(this, "onAction", "onChangeZoom");
}
i ++;
}
temp.firstZoomButton = DungeonEditor_Window.zoomButtons[0];
new GuiTextCtrl("DungeonEditor_Zoom_Label") {
useOwnProfile = true;
// fix: align doesn't work with GuiBlueTextProfile, why?
profile.fontColor = GuiBlueTextProfile.fontColor;
profile.justify = "right";
profile.modal = false;
profile.fontStyle = "b";
x = GUI_PADDING;
y = zoomY + 4;
width = firstZoomButton.x - x - GUI_PADDING;
height = profile.getTextHeight();
horizSizing = "width";
text = "Zoom:";
}
// currentY += firstZoomButton.y + currentY;
temp.buttonHeight = 28;
new GuiScrollCtrl("DungeonEditor_BlockScroll") {
profile = GuiBlueScrollProfile;
useOwnProfile = true;
profile.border = 1;
x = GUI_PADDING;
y = currentY;
width = DungeonEditor_Window.clientWidth - (x * 2);
height = DungeonEditor_Window.clientHeight - y - (GUI_PADDING * 2) - buttonHeight;
horizSizing = "width";
vertSizing = "height";
vScrollBar = hScrollBar = "dynamic";
}
// button row
new GuiButtonCtrl("DungeonEditor_ExternalToggle") {
profile = GuiBlueButtonProfile;
width = buttonHeight;
height = buttonHeight;
x = GUI_PADDING;
y = DungeonEditor_Window.clientHeight - GUI_PADDING - height;
hint = "Toggle between internal and external display.";
text = "";
vertSizing = "top";
}
new GuiButtonCtrl("DungeonEditor_Load") {
profile = GuiBlueButtonProfile;
width = 120;
height = buttonHeight;
temp.prevButton = DungeonEditor_ExternalToggle;
x = prevButton.x + prevButton.width + GUI_PADDING;
y = DungeonEditor_Window.clientHeight - GUI_PADDING - height;
hint = "Load a map from an existing Dungeon.txt file.";
text = "Load Dungeon";
vertSizing = "top";
}
new GuiButtonCtrl("DungeonEditor_Save") {
profile = GuiBlueButtonProfile;
height = buttonHeight;
temp.prevButton = DungeonEditor_Load;
x = prevButton.x + prevButton.width + GUI_PADDING;
y = DungeonEditor_Window.clientHeight - GUI_PADDING - height;
width = DungeonEditor_Window.clientWidth - x - GUI_PADDING;
hint = "Export the dungeon you've created into Dungeon.txt format.";
text = "Save Dungeon";
horizSizing = "width";
vertSizing = "top";
}
}
this.setZoom(ZOOM_DEFAULT);
this.setBlocks(32, 23);
}
function DungeonEditor_Save.onAction() {
temp.exportedText = "";
for (temp.blockRow : DungeonEditor_BlockScroll.blockRows) {
for (temp.block : blockRow) {
exportedText @= block.isFloor ? EXPORT_FLOOR : EXPORT_WALL;
}
exportedText @= "\n";
}
exportedText = exportedText.substring(0, exportedText.length() - 1);
this.drawSaveWindow(exportedText);
}
function DungeonEditor_Load.onAction() {
this.drawLoadWindow();
}
function setZoom(zoomLevel) {
this.zoomLevel = zoomLevel;
DungeonEditor_Window.zoomButtons[0].active = zoomLevel > ZOOM_MIN;
DungeonEditor_Window.zoomButtons[1].active = zoomLevel < ZOOM_MAX;
temp.by = 0;
for (temp.blockRow : DungeonEditor_BlockScroll.blockRows) {
temp.bx = 0;
for (temp.block : blockRow) {
block.x = this.getBlockX(bx);
block.y = this.getBlockY(by);
block.width = this.getBlockWidth();
block.height = this.getBlockHeight();
bx ++;
}
by ++;
}
}
function onBlockSizeChanged(sizeEdit) {
if (sizeEdit.text == "") {
return;
}
temp.blockTypeID = sizeEdit.blockTypeID;
temp.newDim = min(100, max(1, abs(int(sizeEdit.text))));
if (newDim != sizeEdit.text) {
return sizeEdit.text = newDim;
}
if (this.blockSize[blockTypeID] == newDim) {
return;
}
temp.newSize = this.blockSize;
newSize[blockTypeID] = newDim;
this.setBlocks(newSize[0], newSize[1]);
sizeEdit.makeFirstResponder(true);
}
function ceil(num) {
if (int(num) != num) {
return int(num) + 1;
}
return num;
}
function updateMapSize() {
temp.mapWidth = ceil((this.blockSize[0] * BLOCK_HORIZONTAL) / 64);
temp.mapHeight = ceil((this.blockSize[1] * BLOCK_VERTICAL) / 64);
DungeonEditor_MapSize.text = "Map size:\n" @ mapWidth @ "x" @ mapHeight @ " levels";
}
function setBlocks(horizBlocks, vertBlocks) {
this.blockSize = {horizBlocks, vertBlocks};
temp.horizEdit = DungeonEditor_Window.blockCounts[0];
temp.vertEdit = DungeonEditor_Window.blockCounts[1];
if (horizEdit.text != horizBlocks) {
horizEdit.text = horizBlocks;
}
if (vertEdit.text != vertBlocks) {
vertEdit.text = vertBlocks;
}
this.updateMapSize();
with (DungeonEditor_BlockScroll) {
if (this.blockRows.size() > 0) {
// already has blocks in it, chop some off if needed
// chop from the right
if (this.blockRows[0].size() > horizBlocks) {
temp.rowCount = 0;
for (temp.blockRow : this.blockRows) {
for (temp.i = (blockRow.size() - 1); i > (horizBlocks - 1); i --) {
blockRow[i].destroy();
this.blockRows[rowCount].delete(i);
}
rowCount ++;
}
} else if (this.blockRows[0].size() < horizBlocks) {
// need to add columns
temp.rowCount = 0;
for (temp.blockRow : this.blockRows) {
for (temp.i = blockRow.size(); i < horizBlocks; i ++) {
temp.block = newBlock(i, rowCount);
this.blockRows[rowCount].add(block);
}
rowCount ++;
}
}
// chop from the bottom
if (this.blockRows.size() > vertBlocks) {
for (temp.i = (this.blockRows.size() - 1); i > (vertBlocks - 1); i --) {
temp.blockRow = this.blockRows[i];
for (temp.block : blockRow) {
block.destroy();
}
this.blockRows.delete(i);
}
} else if (this.blockRows.size() < vertBlocks) {
// need to add rows
for (temp.i = this.blockRows.size(); i < vertBlocks; i ++) {
this.blockRows.add(newBlockRow(i, horizBlocks));
}
}
} else {
// doesn't have blocks yet, make some
for (temp.blockRow = 0; blockRow < vertBlocks; blockRow ++) {
this.blockRows.add(newBlockRow(blockRow, horizBlocks));
}
}
thiso.colorBlocks();
}
}
function newBlockRow(blockRow, horizBlocks) {
temp.row = null;
for (temp.blockColumn = 0; blockColumn < horizBlocks; blockColumn ++) {
row.add(newBlock(blockColumn, blockRow));
}
return row;
}
function newBlock(bx, by) {
temp.block = null;
new GuiControl("DungeonEditor_Block_" @ bx @ "_" @ by) {
block = this;
useOwnProfile = true;
profile.opaque = true;
profile.fillColor = {0, 0, 0};
profile.modal = true;
minExtent = {0, 0};
width = thiso.getBlockWidth();
height = thiso.getBlockHeight();
x = thiso.getBlockX(bx);
y = thiso.getBlockY(by);
this.isFloor = false;
cursor = "pointer";
thiso.catchEvent(this, "onMouseDown", "onSwitchBlock");
thiso.catchEvent(this, "onMouseDragged", "onSwitchBlockDrag");
}
return block;
}
function onSwitchBlock(block) {
block.isFloor = ! block.isFloor;
thiso.colorBlock(block);
this.dragSet = block.isFloor;
}
function onSwitchBlockDrag(block) {
block.isFloor = this.dragSet;
thiso.colorBlock(block);
}
function colorBlocks() {
with (DungeonEditor_BlockScroll) {
for (temp.blockRow : this.blockRows) {
for (temp.block : blockRow) {
thiso.colorBlock(block);
}
}
}
}
function colorBlock(block) {
block.profile.fillColor = block.isFloor ? COLOR_FLOOR : COLOR_WALL;
}
function getBlockX(bx) {
return bx * ((BLOCK_HORIZONTAL * thiso.zoomLevel) + 1);
}
function getBlockY(by) {
return by * ((BLOCK_VERTICAL * thiso.zoomLevel) + 1);
}
function getBlockWidth() {
return BLOCK_HORIZONTAL * thiso.zoomLevel;
}
function getBlockHeight() {
return BLOCK_VERTICAL * thiso.zoomLevel;
}
function onChangeZoom(button) {
this.setZoom(this.zoomLevel + button.zoomAction);
}
function DungeonEditor_ExternalToggle.onAction() {
DungeonEditor_Window.isExternal = ! DungeonEditor_Window.isExternal;
}
function drawSaveWindow(exportedText) {
if (DungeonEditorSave_Window != null) {
DungeonEditorSave_Window.destroy();
}
new GuiWindowCtrl("DungeonEditorSave_Window") {
profile = GuiBlueWindowProfile;
clientRelative = canClose = canMinimize = canMaximize = canResize = true;
isExternal = DungeonEditor_Window.isExternal;
clientWidth = 225;
clientHeight = 175;
minExtent = {200, 150};
x = (GraalControl.width / 2) - (width / 2);
y = (GraalControl.height / 2) - (height / 2);
text = "Dungeon Editor Export";
this.showTop();
new GuiMLTextCtrl("DungeonEditorSave_Help") {
profile = GuiBlueMLTextProfile;
x = GUI_PADDING;
y = GUI_PADDING;
width = DungeonEditorSave_Window.clientWidth - (x * 2);
text = "Paste the following code into your Dungeon.txt file:";
horizSizing = "width";
}
new GuiScrollCtrl("DungeonEditorSave_Scroll") {
profile = GuiBlueScrollProfile;
useOwnProfile = true;
profile.border = 1;
x = GUI_PADDING;
y = 50;
width = DungeonEditorSave_Window.clientWidth - (x * 2);
height = DungeonEditorSave_Window.clientHeight - y - GUI_PADDING;
vertSizing = "height";
horizSizing = "width";
hScrollBar = vScrollBar = "alwaysOn";
new GuiMLTextEditCtrl("DungeonEditorSave_Text") {
profile = GuiBlueMLTextProfile;
wordwrap = false;
useOwnProfile = true;
profile.fontType = "Courier New";
x = 2;
y = 2;
width = DungeonEditorSave_Scroll.clientWidth;
text = exportedText;
}
}
}
}
function DungeonEditorSave_Help.onResize(newWidth, newHeight) {
DungeonEditorSave_Scroll.y = newHeight + (GUI_PADDING * 2);
DungeonEditorSave_Scroll.height = DungeonEditorSave_Window.clientHeight - DungeonEditorSave_Scroll.y - GUI_PADDING;
}
function drawLoadWindow() {
if (DungeonEditorLoad_Window != null) {
DungeonEditorLoad_Window.destroy();
}
new GuiWindowCtrl("DungeonEditorLoad_Window") {
profile = GuiBlueWindowProfile;
clientRelative = canClose = canMinimize = canMaximize = canResize = true;
isExternal = DungeonEditor_Window.isExternal;
clientWidth = 225;
clientHeight = 175;
minExtent = {200, 150};
x = (GraalControl.width / 2) - (width / 2);
y = (GraalControl.height / 2) - (height / 2);
text = "Dungeon Editor Load";
this.showTop();
new GuiMLTextCtrl("DungeonEditorLoad_Help") {
profile = GuiBlueMLTextProfile;
x = GUI_PADDING;
y = GUI_PADDING;
width = DungeonEditorLoad_Window.clientWidth - (x * 2);
text = "Enter your Dungeon.txt file here to edit it:";
horizSizing = "width";
}
new GuiScrollCtrl("DungeonEditorLoad_Scroll") {
profile = GuiBlueScrollProfile;
useOwnProfile = true;
profile.border = 1;
x = GUI_PADDING;
y = 50;
width = DungeonEditorLoad_Window.clientWidth - (x * 2);
height = DungeonEditorLoad_Window.clientHeight - y - GUI_PADDING;
vertSizing = "height";
horizSizing = "width";
hScrollBar = vScrollBar = "alwaysOn";
new GuiMLTextEditCtrl("DungeonEditorLoad_Text") {
profile = GuiBlueMLTextProfile;
wordwrap = false;
useOwnProfile = true;
profile.fontType = "Courier New";
x = 2;
y = 2;
width = DungeonEditorLoad_Scroll.clientWidth;
text = "";
}
}
new GuiButtonCtrl("DungeonEditorLoad_Load") {
profile = GuiBlueButtonProfile;
width = DungeonEditorLoad_Window.clientWidth - (GUI_PADDING * 2);
height = 28;
x = GUI_PADDING;
y = DungeonEditorLoad_Window.clientHeight - height - GUI_PADDING;
text = "Load";
vertSizing = "top";
horizSizing = "width";
}
}
}
function DungeonEditorLoad_Help.onResize(newWidth, newHeight) {
DungeonEditorLoad_Scroll.y = newHeight + (GUI_PADDING * 2);
DungeonEditorLoad_Scroll.height = DungeonEditorLoad_Window.clientHeight - DungeonEditorLoad_Scroll.y - (GUI_PADDING * 2) - DungeonEditorLoad_Load.height;
}
function DungeonEditorLoad_Load.onAction() {
temp.lines = DungeonEditorLoad_Text.getLines();
this.setBlocks(lines[0].length(), lines.size());
temp.lineCount = 0;
for (temp.line : lines) {
for (temp.blockCount = 0; blockCount < line.length(); blockCount ++) {
temp.char = line.charat(blockCount);
DungeonEditor_BlockScroll.blockRows[lineCount][blockCount].isFloor = (char == EXPORT_FLOOR);
}
lineCount ++;
}
this.colorBlocks();
}