Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**************************************************************\
- #Title
- Pixel Perfect Tile Editor
- ScriptExtension for Links by MysticalDragon
- #Version
- 1.4
- #Features
- - Relatively easy setup with simple configuration
- - Works with graal file browser rights system
- - Scrolls automatically when selecting large portions of the gui
- - Open, save, and delete tile clipboard files
- - Undo & redo (Note: history is cleared when the editor closes)
- - [Toggle] Fade inactive tilelayers
- - [Toggle] Level grid to separate tiles
- - [Toggle] Extra cursor info
- - [Toggle] External window
- - Create new levels
- - Flood fill
- - Can check for updates
- - add and remove tilelayers
- - More
- #Installation
- 1. Create a new weapon script named -Development/TileEditor or
- whatever whatever is pleasing to you
- 2. Copy the entire text of this document into the script
- 3. Modify the configuration portion of the script to suit your
- server best
- 4. Give (npcserver) the required rights
- By default, this includes:
- rw access to TileEditor/Clipboard/ and subfolders,
- rw access to levels folders,
- rw access to levels/images/tileeditor_icon_1-1.png ,
- rw access to levels/images/tileeditor_bucket_1-1.png ,
- rw access to levels/images/tileeditor_pencil_1-1.png
- 5. Give level designers necessary rights
- r and/or w access to TileEditor/Clipboard/ and/or
- subfolders,
- rw access to level files to use this program on
- 6. Add the weapon script to the level designers
- #Script Interface
- - The following clientside public functions are available:
- open() - triggers the request to open the editor
- close() - triggers the program to close
- isOpen() - returns true if the program is open
- #Directions
- Type /te into the chat bar to open the program
- Left click to select tiles, right click to paste the selection
- #Credits
- Scripted by Pixel
- \**************************************************************/
- public function onPlayerLogin(pl){
- if(ServerOptions.contains("staff_leveleditor",pl.account) || ServerOptions.contains("staff_admin_house",pl.account) || temp.pl.clientr.staff == 4
- //Graal772951 = BrentWood
- || temp.pl.account in {""}){ //Add non-staff accounts here. I've removed Death_Striker, he no longer needs this. - Exolia
- temp.pl.addWeapon(this.name);
- }
- }
- /*********************** Configuration ************************/
- // Check for updates when the weapon script is initialized?
- // (recommended to know when future updates are released)
- const TE_CHECK_UPDATE = false;
- // Must the user be in the serveroptions staff list?
- // Set the value to true if you want to restrict the use of the
- // program to only staff. Otherwise set the value to false.
- const TE_ONLYSTAFF = false;
- // Must the user have rights to levels and files?
- // Set the value to true if you want to secure levels and files
- // using the default graal rights system (Strongly recommended).
- // Otherwise set the value to false
- const TE_NEEDRIGHTS = false;
- // Where should the clipboard files be stored?
- // (recommended to keep this as "TileEditor/Clipboard/")
- const TE_DIR_CLIPBOARD = "TileEditor/Clipboard/";
- // Should the program save images and icons to the server?
- // (recommended to keep this as true usually)
- const TE_WRITE_IMAGES = true;
- // Where should the program save it's images and icons?
- // This can vary depending on your server's folder options
- const TE_DIR_IMAGES = "levels/images/";
- /**************************************************************/
- /******************* Don't Touch Below Here *******************/
- const TE_VERSION = "1.4.1";
- // images are stored here as base 64 encoded strings. the images
- // are saved to the server onCreated
- const TE_ICON_DATA = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAB3RJTUUH3AYDFREoSFzGywAAABd0RVh0U29mdHdhcmUAR0xEUE5HIHZlciAzLjRxhaThAAAACHRwTkdHTEQzAAAAAEqAKR8AAAAEZ0FNQQAAsY8L/GEFAAADAFBMVEUAAACAAAAAgACAgADAwMCAAIAAgIAAAIDA3MCmyvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+/CgoKSAgID/AAAA/wD//wAAAP//AP8A//////+6YMT6AAAAAWJLR0T/pQfyxQAAAHBJREFUeJxljjEOgDAMA93AENGJ/z8SMQVaJMghsdCTslh2bE29T0fEYa1ZuId6EklLPBmFf8TmUuZ7Xe+SLPu+6EqwEj2TQbAq1U3aXHJO76N8yGMKhJ1KqomNwj9idLOBLWwSVViJMmEQ7OtnC5sexROSefnyghYAAAAASUVORK5CYII=";
- const TE_BUCKET_DATA = "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAALISURBVDiNjZNLTFRnFMd/3537fXfuTUZa7IiBMDFprInxURIJ7Uqxm8b4SMowjPiANrG8FHXZaGVRVColJiAkoqs2jQbpgoUFN+7wEcXuuqNJIeMAGkoodx7eufdzYcYQY7UnOavzO/9z8j85QmvNuyKRjFcAvUAtkAXuAOdGbo4+AzDe2f0qLgEZYCewF/gA6C4Wzf8h0AhUSSmv+r4/HgRBG/AcaHnvBolkfA1AyZqS+x3tJ3batt0F2ECoyLxVIJGMGw0H648ppWYArgwMhbdu2SpajrWGpVRDq1nzYMe1DVKZwwXP3wUEgfePDjsfqprqKvF1U7No/uYoqVSK5eVltm3bbsRilV9OT0+/FjCUkn2bNm344vPaHdI2/rIqSubDvRe7jfbWNjEz8zdCGPT8eIH0XJpUKkXn8ZNhwEsk4yaA8eKFd6C6Zotxb2xI7/5ss+45fxHbtvF9n77LP7Hx441UVsYYn7iN67qEwzb79u4PQqFQZ9GDkGUptP2JfvLHVE5rzeLiIq7rYlkWpjSJRCKEQiZSSmZnZ6n7Km45jvNDIhkve22iMEtEOj039vjxIz8SieC6Lp0nTrHirjC/ME/TkSaUUhQHtHzbFlZKDa6+gij4nB6+fjXnOA6e5xH9KMqlnl7OfHeW8vIKlFJIKcnn81R9WmUEQbDHEEIUVv7NAPgjN27M5XK5c6O/3cqXlpbiui75fB6lFEopLMsiFotRVraOwaGBnBBizJDSHPn1l9u+Kc1RgCAI+icmxucy2QxCCDKZDFJKHMchGo0y9WTKb+toXXnw8MFpz/MOobUm2T5crrWmmPUNdbu/7zqTyWazemFhQfu+r5+mn+rOU8ezR5oO/VzfULe2yLK6cXU2Hk7+PnlvMlhaWtJXBvtzR5sP/1nfUFf9Jif+650Tyfh6acq7CEoLhUKX1vrayM3R4E3uJf0eQEfPmPQuAAAAAElFTkSuQmCC";
- const TE_PENCIL_DATA = "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";
- // enumeration of network replies
- // this list must match the clientside list exactly. otherwise
- // bugs will occur
- enum RPL {
- NONE,
- ERROR,
- REQUESTUSE,
- PLACETILES,
- LISTCLIPBOARDFOLDER,
- LOADCLIPBOARDFILE,
- SAVECLIPBOARDFILE,
- DELETECLIPBOARDFILE,
- CREATENEWLEVEL,
- UPDATELEVEL,
- ADDTILELAYER,
- REMOVETILELAYER
- }
- /**
- * events
- */
- function onCreated() {
- // if configured to check for updates at initialization
- // do that
- /*if (TE_CHECK_UPDATE) {
- temp.req = requesturl("http://forums.graalonline.com/forums/showthread.php?t=134267103");
- temp.time = timevar2;
- waitfor(temp.req, "onReceiveData", 10);
- if (timevar2 - temp.time < 10) {
- temp.position = temp.req.fulldata.pos("[VERSION]") + 9;
- temp.currentVersionString = temp.req.fulldata.substring(temp.position, temp.req.fulldata.pos("[/VERSION]") - position).trim();
- if (TE_VERSION != temp.currentVersionString && temp.currentVersionString != "") {
- temp.a = int(TE_VERSION.substring(0, 1) @ TE_VERSION.substring(2, 1) @ TE_VERSION.substring(4, 1));
- temp.b = int(temp.currentVersionString.substring(0, 1) @ temp.currentVersionString.substring(2, 1) @ temp.currentVersionString.substring(4, 1));
- if (temp.a < temp.b)
- TE_echo("A new version is available: " @ temp.currentVersionString);
- }
- }
- }*/
- // if the image saving is disabled in the config
- // there's no need to continue
- if (!TE_WRITE_IMAGES)
- return;
- // check if the icon image is on the server
- // if it is not, attempt to write it
- temp.filePath = TE_DIR_IMAGES @ "tileeditor_icon_1-1.png";
- temp.files.loadfolder(temp.filePath, 0);
- if (temp.files.size() == 0) {
- temp.data = base64decode(TE_ICON_DATA);
- temp.data.savestring(temp.filePath, 0);
- temp.files = NULL;
- temp.files.loadfolder(temp.filePath, 0);
- if (temp.files.size() == 0) {
- TE_echo("prob: (npcserver) cannot write the icon image file as" SPC temp.filePath @ ". Ensure that both the configuration and the (npcserver)'s rights are correct");
- } else {
- TE_echo("icon image saved to" SPC temp.filePath);
- }
- }
- // check if the bucket image is on the server
- // if it is not, attempt to write it
- temp.filePath = TE_DIR_IMAGES @ "tileeditor_bucket_1-1.png";
- temp.files.loadfolder(temp.filePath, 0);
- if (temp.files.size() == 0) {
- temp.data = base64decode(TE_BUCKET_DATA);
- temp.data.savestring(temp.filePath, 0);
- temp.files = NULL;
- temp.files.loadfolder(temp.filePath, 0);
- if (temp.files.size() == 0) {
- TE_echo("prob: (npcserver) cannot write the bucket image file as" SPC temp.filePath @ ". Ensure that both the configuration and the (npcserver)'s rights are correct");
- } else {
- TE_echo("bucket image saved to" SPC temp.filePath);
- }
- }
- // check if the pencil image is on the server
- // if it is not, attempt to write it
- temp.filePath = TE_DIR_IMAGES @ "tileeditor_pencil_1-1.png";
- temp.files.loadfolder(temp.filePath, 0);
- if (temp.files.size() == 0) {
- temp.data = base64decode(TE_PENCIL_DATA);
- temp.data.savestring(temp.filePath, 0);
- temp.files = NULL;
- temp.files.loadfolder(temp.filePath, 0);
- if (temp.files.size() == 0) {
- TE_echo("prob: (npcserver) cannot write the pencil image file as" SPC temp.filePath @ ". Ensure that both the configuration and the (npcserver)'s rights are correct");
- } else {
- TE_echo("pencil image saved to" SPC temp.filePath);
- }
- }
- }
- function onActionServerSide() {
- //gville = Graal756346
- if(player.account in {"Mesh_P2P", "Tim_Rocks"}){
- if(!player.level.name.starts("era_gang") && !player.level.name.starts("era_metro") && !player.level.name.starts("era_ghost") && !player.level.name.starts("era_halloween") && !player.level.name.starts("era_metro_headsup")) return;
- }
- if(player.account in {"bloodwork"}){
- if(!player.level.name.starts("era_event"))return;
- }
- if(player.account in {"Knux"}){
- if(!player.level.name.starts("era_event_savesanta") && !player.level.name.starts("era_metro") && !player.level.name.starts("era_house"))return;
- }
- if(player.account == "FRIEDRICE" && !player.level.name.starts("era_event") && !player.level.name.starts("era_et")&& !player.level.name.starts("era_friedrice-")){ // fried rice
- return;
- }
- /*
- if (player.level.name.starts("era_present") && player.clientr.staff < 2 && !player.account in {""}) {
- return;
- }*/
- // if the script is configured to be staff only
- // detect non-staff usage attempts here
- if (TE_ONLYSTAFF) {
- temp.staffList = serveroptions.staff.lower().tokenize(",");
- if (!(player.account.lower() in temp.staffList)
- && (player.communityname == ""
- || !(player.communityname.lower() in temp.staffList))) {
- TE_echo(format("%s tried to use the tile editor, but is not staff", player.account));
- return;
- }
- }
- replySwitch:
- switch (params[0]) {
- // when the program is triggered to open
- // it triggers the server with the REQUESTUSE reply
- // the server returns a "1" or "0"
- case RPL.REQUESTUSE: {
- if (TE_NEEDRIGHTS) {
- if (player.level.name.ends(".gmap")) {
- temp.mapPartLevelName = player.level.getmappartfile(player.x, player.y);
- temp.allowUse = player.hasright("r", temp.mapPartLevelName);
- } else {
- temp.allowUse = player.hasright("r", player.level.name);
- }
- } else {
- temp.allowUse = true;
- }
- player.triggerclient("gui", this.name, RPL.REQUESTUSE, temp.allowUse, TE_VERSION, tilelayercount);
- break;
- }
- // determine if the player is allowed to edit the level
- // if so, paste the data to the levels tile board
- // otherwise, send an ERROR reply
- case RPL.PLACETILES: {
- if (params[1].size() == 0)
- break;
- temp.data = params;
- temp.dataSize0 = temp.data[1].size();
- temp.dataSize1 = temp.data[1][0].size();
- maxlooplimit = 1000000;
- if (TE_NEEDRIGHTS) {
- if (player.level.name.ends(".gmap")) {
- temp.yMin = int((temp.data[3]) / 64) * 64;
- temp.xMin = int((temp.data[2]) / 64) * 64;
- temp.yMax = int((temp.data[3] - 1 + temp.dataSize0) / 64) * 64;
- temp.xMax = int((temp.data[2] - 1 + temp.dataSize1) / 64) * 64;
- player.chat = {temp.xMin, temp.yMin, temp.xMax, temp.yMax};
- for (temp.i = temp.yMin; temp.i <= temp.yMax; temp.i += 64) {
- for (temp.j = temp.xMin; temp.j <= temp.xMax; temp.j += 64) {
- temp.mapPartLevelName = player.level.getmappartfile(temp.j, temp.i);
- if (temp.mapPartLevelName != ""
- && !player.hasright("w", temp.mapPartLevelName)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "You do not have rights to edit" SPC temp.mapPartLevelName);
- break replySwitch;
- }
- }
- }
- } else {
- if (!player.hasright("w", player.level.name)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "You do not have rights to edit" SPC player.level.name);
- break;
- }
- }
- }
- for (temp.y = 0; temp.y < temp.dataSize0; temp.y++) {
- if (temp.data[4] == 0 && temp.data[1][temp.y].index(-1) != -1) {
- do {
- temp.ind = temp.data[1][temp.y].index(-1);
- temp.data[1][temp.y][temp.ind] = 0;
- } while (temp.data[1][temp.y].index(-1) != -1);
- }
- for (temp.x = 0; temp.x < temp.dataSize1; temp.x++) {
- temp.tile = temp.data[1][temp.y][temp.x];
- if (temp.tile == -2)
- continue;
- tilelayers[temp.data[4]].tiles[temp.x + temp.data[2], temp.y + temp.data[3]] = temp.tile;
- }
- }
- tilelayers[temp.data[4]].updateboard2(temp.data[2], temp.data[3], temp.data[1][0].size(), temp.data[1].size());
- break;
- }
- // provided the player is allowed to READ the file
- // this loads the file data and sends it to the client
- case RPL.LOADCLIPBOARDFILE: {
- if (!fileExists2(TE_DIR_CLIPBOARD @ params[1]))
- break;
- temp.obj = {};
- temp.obj.loadlines(TE_DIR_CLIPBOARD @ params[1]);
- if (temp.obj.size() == 0) {
- player.triggerclient("gui", this.name, RPL.ERROR, "The (npcserver) lacks the rights to read the file");
- return;
- }
- player.triggerclient("gui", this.name, RPL.LOADCLIPBOARDFILE, temp.obj, params[1], getfilemodtime(TE_DIR_CLIPBOARD @ params[1]));
- break;
- }
- // provided the player is allowed to WRITE the file
- // this saves the file data
- case RPL.SAVECLIPBOARDFILE: {
- temp.fileBase = extractfilebase(params[2]);
- if (temp.fileBase == "")
- break;
- temp.filePath = TE_DIR_CLIPBOARD @ extractfilepath(params[2]);
- temp.filePath = temp.filePath @ temp.fileBase @ ".txt";
- if (TE_NEEDRIGHTS && !player.hasright("w", temp.filePath)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "You do not have rights for" SPC temp.filePath);
- return;
- }
- params[1].savelines(temp.filePath, 0);
- temp.files.loadfolder(temp.filePath, 0);
- if (temp.files.size() == 0) {
- player.triggerclient("gui", this.name, RPL.ERROR, "The (npcserver) lacks the rights to create the file");
- return;
- }
- player.triggerclient("gui", this.name, RPL.SAVECLIPBOARDFILE, temp.filePath);
- break;
- }
- // provided the player is allowed to WRITE the file
- // this deletes the file
- case RPL.DELETECLIPBOARDFILE: {
- temp.filePath = TE_DIR_CLIPBOARD @ params[1];
- if (TE_NEEDRIGHTS && !player.hasright("w", temp.filePath)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "You do not have rights for" SPC temp.filePath);
- return;
- }
- if (!fileExists2(temp.filePath)) {
- player.triggerclient("gui", this.name, RPL.ERROR, temp.filePath SPC "does not exist");
- return;
- }
- deletefile(temp.filePath);
- temp.files.loadfolder(temp.filePath, 0);
- if (temp.files.size() == 1)
- player.triggerclient("gui", this.name, RPL.ERROR, "The (npcserver) lacks the rights to delete the file");
- }
- // will read all clipboard files which the player
- // is allowed to read, and return the list to the client
- case RPL.LISTCLIPBOARDFOLDER: {
- temp.obj = {};
- temp.obj.loadfolder(TE_DIR_CLIPBOARD @ "*", 1);
- if (TE_NEEDRIGHTS) {
- temp.list = {};
- for (temp.o: temp.obj) {
- temp.filePath = TE_DIR_CLIPBOARD @ temp.o;
- if (player.hasright("r", temp.filePath))
- temp.list.add(temp.o);
- }
- } else {
- temp.list = temp.obj;
- }
- player.triggerclient("gui", this.name, RPL.LISTCLIPBOARDFOLDER, temp.list);
- break;
- }
- // checks for an invalid filename
- // if not, reply with ERROR
- // checks if the player is allowed to WRITE the file
- // if not, reply with ERROR
- // checks if the file already exists
- // if not, write
- // if so, checks if the override parameter is set
- // if not, reply with ERROR
- // if so, write
- case RPL.CREATENEWLEVEL: {
- temp.fileBase = extractfileBase(params[1]).lower();
- temp.fileExt = extractfileext(params[1]).lower();
- if (temp.fileBase == ""
- || temp.fileExt != ".nw") {
- player.triggerclient("gui", this.name, RPL.ERROR, "Invalid file name");
- return;
- }
- temp.filePath = extractfilepath(params[1]).lower() @ temp.fileBase @ temp.fileExt;
- if (TE_NEEDRIGHTS && !player.hasright("w", temp.filePath)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "You do not have rights for" SPC temp.filePath);
- return;
- }
- if (fileExists2(temp.filePath) && !params[2]) {
- player.triggerclient("gui", this.name, RPL.ERROR, "That file already exists! Type the same thing in again to overwrite");
- return;
- }
- temp.lines = {
- "GLEVNW01"
- };
- temp.lines.savelines(temp.filePath, 0);
- SourceControl.handleUpdate(player.account, {{"file", temp.filePath}});
- if (!fileExists2(temp.filePath)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "The (npcserver) lacks the rights to create the file");
- return;
- }
- player.triggerclient("gui", this.name, RPL.CREATENEWLEVEL, temp.filePath);
- break;
- }
- case RPL.UPDATELEVEL: {
- if (TE_NEEDRIGHTS && !player.hasrightflag("updatelevel")) {
- player.triggerclient("gui", this.name, RPL.ERROR, "You do not have the rights to use Update Level");
- break;
- }
- temp.levelName = player.level.name.ends(".gmap") ? player.level.getmappartfile(player.x + 1.5, player.y + 1.5) : player.level.name;
- //echo(temp.levelName);
- temp.levelFilePath = getLevelFilePath(temp.levelName);
- temp.filePath = temp.levelFilePath;
- //echo(temp.filePath);
- temp.hasReadRights = fileexists(temp.filePath);
- if (!temp.hasReadRights) {
- player.triggerclient("gui", this.name, RPL.ERROR, "The (npcserver) lacks the rights to read" SPC temp.filePath);
- break;
- }
- temp.fileLines = {};
- temp.fileLines.loadlines(temp.filePath);
- temp.boardLines = getBoardLines(temp.levelName);
- temp.fileLines = replaceLinesStartingWith(temp.fileLines, temp.boardLines, "BOARD");
- deletefile(temp.filePath);
- if (fileExists2(temp.filePath)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "The (npcserver) lacks the rights to write" SPC temp.filePath);
- break;
- }
- temp.fileLines.savelines(temp.filePath, 0);
- SourceControl.handleUpdate(player.account, {{"file", temp.filePath}});
- player.triggerclient("gui", this.name, RPL.UPDATELEVEL);
- break;
- }
- case RPL.ADDTILELAYER: {
- temp.levelName = player.level.name.ends(".gmap") ? player.level.getmappartfile(player.x + 1.5, player.y + 1.5) : player.level.name;
- if (TE_NEEDRIGHTS && !player.hasright("w", temp.levelName)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "You do not have the rights to edit " @ temp.levelName);
- break;
- }
- temp.levelFilePath = getLevelFilePath(temp.levelName);
- temp.filePath = temp.levelFilePath;
- temp.hasReadRights = fileexists(temp.filePath);
- if (!temp.hasReadRights) {
- player.triggerclient("gui", this.name, RPL.ERROR, "The (npcserver) lacks the rights to read" SPC temp.filePath);
- break;
- }
- temp.fileLines = {};
- temp.fileLines.loadlines(temp.filePath);
- temp.boardLines = getBoardLines(temp.levelName, 1);
- temp.fileLines = replaceLinesStartingWith(temp.fileLines, temp.boardLines, "BOARD");
- deletefile(temp.filePath);
- if (fileExists2(temp.filePath)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "The (npcserver) lacks the rights to write" SPC temp.filePath);
- break;
- }
- player.level.tilelayercount++;
- temp.fileLines.savelines(temp.filePath, 0);
- SourceControl.handleUpdate(player.account, {{"file", temp.filePath}});
- for (temp.pl: player.level.players)
- temp.pl.triggerclient("gui", this.name, RPL.ADDTILELAYER);
- break;
- }
- case RPL.REMOVETILELAYER: {
- temp.levelName = player.level.name.ends(".gmap") ? player.level.getmappartfile(player.x + 1.5, player.y + 1.5) : player.level.name;
- if (TE_NEEDRIGHTS && !player.hasright("w", temp.levelName)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "You do not have the rights to edit " @ temp.levelName);
- break;
- }
- temp.levelFilePath = getLevelFilePath(temp.levelName);
- temp.filePath = temp.levelFilePath;
- temp.hasReadRights = fileexists(temp.filePath);
- if (!temp.hasReadRights) {
- player.triggerclient("gui", this.name, RPL.ERROR, "The (npcserver) lacks the rights to read" SPC temp.filePath);
- break;
- }
- temp.fileLines = {};
- temp.fileLines.loadlines(temp.filePath);
- temp.boardLines = getBoardLines(temp.levelName, -1);
- temp.fileLines = replaceLinesStartingWith(temp.fileLines, temp.boardLines, "BOARD");
- deletefile(temp.filePath);
- if (fileExists2(temp.filePath)) {
- player.triggerclient("gui", this.name, RPL.ERROR, "The (npcserver) lacks the rights to write" SPC temp.filePath);
- break;
- }
- player.level.tilelayercount--;
- temp.fileLines.savelines(temp.filePath, 0);
- SourceControl.handleUpdate(player.account, {{"file", temp.filePath}});
- for (temp.pl: player.level.players)
- temp.pl.triggerclient("gui", this.name, RPL.REMOVETILELAYER);
- break;
- }
- }
- }
- /**
- * functions
- */
- // just a simple, customized output function
- function TE_echo(temp.text) {
- echo(this.name @ ":" SPC temp.text);
- }
- // altered version of Tigairius' Base10 Converter
- // http://forums.graalonline.com/forums/showthread.php?t=134261707
- //
- // this version encodes the given numeric as a .nw tile string
- function nw_encode(temp.i) {
- if (temp.i < 0)
- return "//";
- while (temp.i > 0) {
- temp.s0 @= ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/").substring(temp.i % 64, 1);
- temp.i = int(temp.i / 64);
- temp.j++;
- }
- switch (temp.j) {
- case 0: { return "AA"; }
- case 1: { temp.s1 = "A"; break; }
- case 2: { temp.s1 = ""; break; }
- }
- while (--temp.j >= 0)
- temp.s1 @= temp.s0.substring(temp.j, 1);
- return temp.s1;
- }
- // will find the level filepath
- // might be slow; especially on larger servers
- // need to find an optimisation
- //
- // found an optimisation using findfiles("file",1) (1 for recursive)
- // - BlueMelon 9/17/2013
- function getLevelFilePath(temp.levelName) {
- temp.fileList = findfiles(temp.levelName,1);
- if(temp.fileList.size() > 0){
- return temp.fileList[0];
- }else{
- return NULL;
- }
- /* // OLD
- temp.fileList = {};
- temp.fileList.loadfolder("levels/*", 1);
- for (temp.filePath: temp.fileList) {
- temp.fileName = extractfilename(temp.filePath);
- if (temp.fileName == temp.levelName) {
- return "levels/"@temp.filePath;
- }
- }
- return NULL;
- */
- }
- function getBoardLines(temp.levelName, temp.modifyLayerCount) {
- if (player.level.name.ends(".gmap")) {
- temp.level = player.level;
- temp.xOffset = int((player.x + 1.5) / 64) * 64;
- temp.yOffset = int((player.y + 1.5) / 64) * 64;
- } else {
- temp.level = findlevel(temp.levelName);
- }
- if (temp.layerCount <= 0)
- temp.layerCount = temp.level.tilelayercount;
- // generate level file board lines
- temp.lines = {};
- // loop through layers
- temp.layerCount = (temp.modifyLayerCount == -1 && temp.level.tilelayercount > 1)
- ? temp.level.tilelayercount - 1 : temp.level.tilelayercount;
- for (temp.i = 0; temp.i < temp.layerCount; temp.i++) {
- temp.tileLayer = temp.level.tilelayers[temp.i];
- // loop through rows
- for (temp.j = temp.yOffset; temp.j < temp.yOffset + 64; temp.j++) {
- temp.line = "BOARD 0 " @ (temp.j % 64) @ " 64 " @ temp.i @ " ";
- // convert tile numerics to nw64 and concat to end of line
- for (temp.k = temp.xOffset; temp.k < temp.xOffset + 64; temp.k++) {
- temp.line @= nw_encode(temp.tileLayer.tiles[temp.k, temp.j]);
- }
- if (temp.line.ends("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"))
- continue;
- temp.lines.add(temp.line);
- }
- }
- if (temp.modifyLayerCount == 1) {
- temp.line = "BOARD 0 0 64 " @ temp.level.tilelayercount SPC "////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////";
- temp.lines.add(temp.line);
- }
- return temp.lines;
- }
- function replaceLinesStartingWith(temp.oLines, temp.nLines, temp.start) {
- // find first index of temp.start in temp.oLines
- temp.i = 0;
- temp.sz = temp.oLines.size();
- while (temp.i < temp.sz) {
- if (temp.oLines[temp.i].starts(temp.start))
- break;
- temp.i++;
- }
- // delete old lines
- while (temp.oLines[temp.i].starts(temp.start))
- temp.oLines.delete(temp.i);
- // insert new lines
- temp.oLines.insertarray(temp.i, temp.nLines);
- return temp.oLines;
- }
- // unlike the built in fileexists(str) function
- // this one will work regardless of whether the
- // (npcserver) has rights or not
- function fileExists2(temp.filePath) {
- temp.fileList.loadfolder(temp.filePath, 0);
- return (temp.fileList.size() != 0);
- }
- //#CLIENTSIDE
- //Script Extensions
- const scriptextension = "-OLELink";
- // numeric network replies
- // these MUST match the serverside
- enum RPL {
- NONE,
- ERROR,
- REQUESTUSE,
- PLACETILES,
- LISTCLIPBOARDFOLDER,
- LOADCLIPBOARDFILE,
- SAVECLIPBOARDFILE,
- DELETECLIPBOARDFILE,
- CREATENEWLEVEL,
- UPDATELEVEL,
- ADDTILELAYER,
- REMOVETILELAYER
- }
- // numeric paste modes
- enum PASTEMODE {
- NONE,
- NORMAL,
- FILL
- }
- /**
- * events
- */
- function onCreated() {
- // if the script is updated while someone
- // is using the editor, and they are using the grid
- // the grid disappears because all the images
- // of the script become reset.
- // so, if the grid is enabled, we re-draw it here
- if (GuiWindow_TileEditor.grid)
- updateGridEffect();
- }
- function onPlayerEnters() {
- if (player.account in {"Tim_Rocks", "swift", "SharkeySprinkles", "CynicalFree1"}) {
- return;
- }
- // if the program is open, and the player enters a new level
- // exit the program, to prevent problems such as
- // undo and redo affecting the wrong level
- if (GuiWindow_TileEditor != NULL
- && GuiWindow_TileEditor.editingLevel != (isonmap ? player.gmap.name : player.level.name)) {
- onCloseEditor();
- }
- }
- function onActionClientSide() {
- if (GuiWindow_TileEditor == NULL)
- return;
- switch (params[0]) {
- // depending which gui is open (Open or Save)
- // loads the tree view of the gui with
- // the clipboard file list supplied by server
- case RPL.LISTCLIPBOARDFOLDER: {
- if (GuiWindow_TileEditor_FileOpen != NULL) {
- GuiTreeView_TileEditor_FileOpen.clearnodes();
- for (temp.fileName: params[1]) {
- temp.fileExt = extractfileext(temp.fileName);
- if (temp.fileExt != ".txt" && temp.fileExt != "")
- continue;
- with (GuiTreeView_TileEditor_FileOpen.addnodebypath(temp.fileName, "/")) {
- image = selectedimage = temp.fileExt == "" ? 1 : 2;
- }
- }
- }
- if (GuiWindow_TileEditor_FileSave != NULL) {
- GuiTreeView_TileEditor_FileSave.clearnodes();
- for (temp.fileName: params[1]) {
- temp.fileExt = extractfileext(temp.fileName);
- if (temp.fileExt != ".txt" && temp.fileExt != "")
- continue;
- with (GuiTreeView_TileEditor_FileSave.addnodebypath(temp.fileName, "/")) {
- image = selectedimage = temp.fileExt == "" ? 1 : 2;
- }
- }
- }
- break;
- }
- // sets clipboard from server data
- case RPL.LOADCLIPBOARDFILE: {
- temp.lines = {};
- for (temp.line: params[1])
- temp.lines.add(temp.line.tokenize());
- temp.extent = {
- temp.lines[0].size(),
- temp.lines.size()
- };
- if (GuiWindow_TileEditor_FileOpen != NULL) {
- GuiText_TileEditor_FileOpen_Title_Value.text = params[2];
- GuiText_TileEditor_FileOpen_Extent_Value.text = temp.extent[0] @ "," SPC temp.extent[1];
- GuiText_TileEditor_FileOpen_Created_Value.text = converttimetostring(params[3]);
- GuiStretch_TileEditor_FileOpen.clientwidth =
- GuiDrawingPanel_TileEditor_FileOpen_Preview.width = temp.extent[0] * 16;
- GuiStretch_TileEditor_FileOpen.clientheight =
- GuiDrawingPanel_TileEditor_FileOpen_Preview.height = temp.extent[1] * 16;
- GuiDrawingPanel_TileEditor_FileOpen_Preview.clearall();
- for (temp.i = 0; temp.i < temp.extent[0]; temp.i++) {
- for (temp.j = 0; temp.j < temp.extent[1]; temp.j++) {
- temp.tileXY = getTileXY(temp.lines[temp.j][temp.i]);
- GuiDrawingPanel_TileEditor_FileOpen_Preview.drawimagerectangle(
- temp.i * 16,
- temp.j * 16,
- GuiWindow_TileEditor.tilesetImage,
- temp.tileXY[0],
- temp.tileXY[1],
- 16,
- 16
- );
- }
- GuiWindow_TileEditor_FileOpen.clipboard = temp.lines;
- }
- }
- if (GuiWindow_TileEditor_FileSave != NULL) {
- GuiText_TileEditor_FileSave_Title_Value.text = params[2];
- GuiText_TileEditor_FileSave_Extent_Value.text = temp.extent[0] @ "," SPC temp.extent[1];
- GuiText_TileEditor_FileSave_Created_Value.text = converttimetostring(params[3]);
- GuiStretch_TileEditor_FileSave.clientwidth =
- GuiDrawingPanel_TileEditor_FileSave_Preview.width = temp.extent[0] * 16;
- GuiStretch_TileEditor_FileSave.clientheight =
- GuiDrawingPanel_TileEditor_FileSave_Preview.height = temp.extent[1] * 16;
- GuiDrawingPanel_TileEditor_FileSave_Preview.clearall();
- for (temp.i = 0; temp.i < temp.extent[0]; temp.i++) {
- for (temp.j = 0; temp.j < temp.extent[1]; temp.j++) {
- temp.tileXY = getTileXY(temp.lines[temp.j][temp.i]);
- GuiDrawingPanel_TileEditor_FileSave_Preview.drawimagerectangle(
- temp.i * 16,
- temp.j * 16,
- GuiWindow_TileEditor.tilesetImage,
- temp.tileXY[0],
- temp.tileXY[1],
- 16,
- 16
- );
- }
- }
- }
- break;
- }
- // just a reply from the server indicating that
- // the clipboard file successfully saved
- case RPL.SAVECLIPBOARDFILE: {
- shared.adminmessage(params[1] SPC "is saved");
- break;
- }
- // generic error reply from the server
- // if an error message is supplied, display it
- // otherwises display the default error message
- case RPL.ERROR: {
- if (params[1] != NULL)
- shared.adminmessage(params[1]);
- else
- shared.adminmessage("An unexpected error occurred");
- break;
- }
- // just a reply from the server indicating that
- // the new level has been created
- case RPL.CREATENEWLEVEL: {
- shared.adminmessage(params[1] SPC "is saved");
- GuiWindow_TileEditor.newLevelOverwrite = NULL;
- break;
- }
- case RPL.UPDATELEVEL: {
- shared.adminmessage("Level saved!");
- break;
- }
- case RPL.ADDTILELAYER: {
- shared.adminmessage("Level saved with an additional tilelayer!");
- GuiMenu_TileEditor.findmenu("Layer").addrow(tilelayercount + 1, tilelayercount).hint = "Change the current editing layer to " @ tilelayercount;
- break;
- }
- case RPL.REMOVETILELAYER: {
- if (tilelayercount > 1) {
- tilelayercount--;
- if (GuiWindow_TileEditor.editingLayer > tilelayercount - 1) {
- GuiWindow_TileEditor.editingLayer = tilelayercount - 1;
- GuiWindow_TileEditor.text = "Tile Editor v" @ GuiWindow_TileEditor.version SPC "(Layer " @ tilelayercount @ ")";
- GuiMenu_TileEditor.findmenu("Layer").setrowbyid(tilelayercount + 1, "*" @ tilelayercount);
- }
- GuiMenu_TileEditor.findmenu("Layer").removerow(tilelayercount + 2);
- shared.adminmessage("Level saved with a tilelayer taken off!");
- }
- break;
- }
- }
- }
- function ChatBar.onAction() {
- if (ChatBar.text.lower().trim() == ":te" || ChatBar.text.lower().trim() == "/te") {
- this.onRequestUse();
- }
- }
- function GuiWindow_TileEditor.onResize(temp.newWidth, temp.newHeight) {
- // there is a bit of weird code here because
- // the behavior of the window gui changes
- // after it becomes external
- if (GuiWindow_TileEditor.isexternal) {
- GuiMenu_TileEditor.x = 0;
- GuiMenu_TileEditor.y = 0;
- GuiMenu_TileEditor.width = temp.newWidth;
- GuiScroll_TileEditor.x = 0;
- GuiScroll_TileEditor.y = 20;
- GuiScroll_TileEditor.width = temp.newWidth;
- GuiScroll_TileEditor.height = temp.newHeight - 20;
- } else {
- GuiMenu_TileEditor.width = temp.newWidth - 12;
- GuiScroll_TileEditor.width = temp.newWidth - 12;
- GuiScroll_TileEditor.height = temp.newHeight - 50;
- }
- }
- function GuiWindow_TileEditor.onCloseQuery() {
- onCloseEditor();
- }
- function GuiMenu_TileEditor.onSelect(temp.menuName, temp.entryId, temp.entryText, temp.entryIndex) {
- temp.menu = GuiMenu_TileEditor.findmenu(temp.menuName);
- switch (temp.menuName) {
- case "File": {
- switch (temp.entryId) {
- case 0: {
- // display a text edit gui for the player to type in
- // the file path they would like to save the new
- // level as
- with (GuiWindow_TileEditor) {
- new GuiTextEditCtrl("GuiTextEdit_TileEditor_NewLevel") {
- profile = GuiBlueTextEditProfile;
- x = GuiWindow_TileEditor.wasExternal ? 0 : 6;
- y = GuiWindow_TileEditor.wasExternal ? 20 : 44;
- width = GuiWindow_TileEditor.width - x * 2;
- height = 20;
- text = "levels/new.nw";
- makefirstresponder(true);
- setselection(0, text.length());
- }
- }
- break;
- }
- case 1: {
- triggerserver("gui", this.name, RPL.UPDATELEVEL);
- break;
- }
- case 2: {
- (@scriptextension).onLoadLinkEditor();
- break;
- }
- case 3: {
- showFileOpenGui();
- break;
- }
- case 4: {
- showFileSaveGui();
- break;
- }
- case 5: {
- onCloseEditor();
- break;
- }
- }
- break;
- }
- case "Edit": {
- switch (temp.entryId) {
- case 0: {
- editorUndo();
- break;
- }
- case 1: {
- editorRedo();
- break;
- }
- }
- break;
- }
- case "View": {
- switch (temp.entryId) {
- case 0: {
- GuiWindow_TileEditor.fadeLayers = !GuiWindow_TileEditor.fadeLayers;
- if (GuiWindow_TileEditor.fadeLayers)
- temp.menu.setrowbyid(0, "*Fade inactive layers");
- else
- temp.menu.setrowbyid(0, "Fade inactive layers");
- updateFadeEffect();
- break;
- }
- case 1: {
- GuiWindow_TileEditor.grid = !GuiWindow_TileEditor.grid;
- if (GuiWindow_TileEditor.grid)
- temp.menu.setrowbyid(1, "*Grid");
- else
- temp.menu.setrowbyid(1, "Grid");
- updateGridEffect();
- break;
- }
- case 2: {
- GuiWindow_TileEditor.extraCursorInfo = !GuiWindow_TileEditor.extraCursorInfo;
- if (GuiWindow_TileEditor.extraCursorInfo) {
- temp.menu.setrowbyid(2, "*Extra cursor info");
- } else {
- hideimgs(200, 204);
- temp.menu.setrowbyid(2, "Extra cursor info");
- }
- break;
- }
- }
- break;
- }
- case "Tileset": {
- switch (temp.entryId) {
- // displays a text edit gui for the player
- // to type in what image to use as the tileset
- // in the gui
- case 0: {
- with (GuiWindow_TileEditor) {
- new GuiTextEditCtrl("GuiTextEdit_TileEditor_Tileset") {
- profile = GuiBlueTextEditProfile;
- x = GuiWindow_TileEditor.wasExternal ? 0 : 6;
- y = GuiWindow_TileEditor.wasExternal ? 20 : 44;
- width = GuiWindow_TileEditor.width - x * 2;
- height = 20;
- text = "pics1.png";
- makefirstresponder(true);
- setselection(0, text.length());
- }
- }
- break;
- }
- // resets the gui tileset image to the current tiledefs
- case 1: {
- with (GuiDrawingPanel_TileEditor) {
- clearall();
- GuiWindow_TileEditor.tilesetImage = "TILES";
- drawimage(0, 0, GuiWindow_TileEditor.tilesetImage);
- }
- break;
- }
- }
- break;
- }
- case "Layer": {
- switch (temp.entryId) {
- case 0: {
- triggerserver("gui", this.name, RPL.ADDTILELAYER);
- break;
- }
- case 1: {
- if (timevar2 - GuiWindow_TileEditor.layerRemoveTimeout > 5) {
- shared.adminmessage("If you are certain you want to remove the top tilelayer, press remove again within 5 seconds");
- GuiWindow_TileEditor.layerRemoveTimeout = timevar2;
- break;
- }
- GuiWindow_TileEditor.layerRemoveTimeout = 0;
- triggerserver("gui", this.name, RPL.REMOVETILELAYER);
- break;
- }
- default: {
- // change current editing layer based on which
- // entryId was selected
- temp.menu.setrowbyid(GuiWindow_TileEditor.editingLayer + 2, GuiWindow_TileEditor.editingLayer + 1);
- temp.menu.setrowbyid(temp.entryId, "*" @ (temp.entryId - 1));
- GuiWindow_TileEditor.editingLayer = temp.entryId - 2;
- GuiWindow_TileEditor.text = " Tile Editor v" @ GuiWindow_TileEditor.version SPC "(Layer" SPC GuiWindow_TileEditor.editingLayer + 1 @ ")";
- updateFadeEffect();
- break;
- }
- }
- break;
- }
- case "Options": {
- switch (temp.entryId) {
- case 0: {
- GuiWindow_TileEditor.isexternal = !GuiWindow_TileEditor.isexternal;
- GuiWindow_TileEditor.wasExternal = true;
- if (GuiWindow_TileEditor.isexternal)
- temp.menu.setrowbyid(0, "*External");
- else
- temp.menu.setrowbyid(0, "External");
- GuiWindow_TileEditor.trigger("onResize", GuiWindow_TileEditor.width, GuiWindow_TileEditor.height);
- break;
- }
- case 1: {
- openurl("http://forums.graalonline.com/forums/showthread.php?t=134267103");
- break;
- }
- case 2: {
- temp.req = requesturl("http://forums.graalonline.com/forums/showthread.php?t=134267103");
- temp.time = timevar2;
- waitfor(temp.req, "onReceiveData", 10);
- if (timevar2 - temp.time < 10) {
- temp.position = temp.req.fulldata.pos("[VERSION]") + 9;
- temp.currentVersionString = temp.req.fulldata.substring(temp.position, temp.req.fulldata.pos("[/VERSION]") - position).trim();
- temp.a = int(GuiWindow_TileEditor.version.substring(0, 1) @ GuiWindow_TileEditor.version.substring(2, 1) @ GuiWindow_TileEditor.version.substring(4, 1));
- temp.b = int(temp.currentVersionString.substring(0, 1) @ temp.currentVersionString.substring(2, 1) @ temp.currentVersionString.substring(4, 1));
- if (temp.a >= temp.b)
- shared.adminmessage("You are using the newest version already");
- else
- shared.adminmessage("A new version is available:\n" @ temp.currentVersionString);
- } else {
- shared.adminmessage("Version check timed out");
- }
- break;
- }
- }
- break;
- }
- }
- }
- function GuiButton_TileEditor_PasteMode.onAction() {
- // toggles between the fill pastemode and the normal pastemode
- if (GuiWindow_TileEditor.pasteMode == PASTEMODE.NORMAL) {
- GuiWindow_TileEditor.pasteMode = PASTEMODE.FILL;
- GuiShowImg_TileEditor_PasteMode.image = "tileeditor_pencil_1-1.png";
- } elseif (GuiWindow_TileEditor.pasteMode == PASTEMODE.FILL) {
- GuiWindow_TileEditor.pasteMode = PASTEMODE.NORMAL;
- GuiShowImg_TileEditor_PasteMode.image = "tileeditor_bucket_1-1.png";
- }
- }
- function GuiWindow_TileEditor.onHide() {
- // detect when the editor is closed from external window
- // it looks weird because external stuff is weird
- if (GuiWindow_TileEditor.isexternal && !GuiWindow_TileEditor.visible)
- onCloseEditor();
- }
- function GuiTextEdit_TileEditor_NewLevel.onAction() {
- // triggers the server requesting to create a new level
- // at the specified filepath
- temp.text = GuiTextEdit_TileEditor_NewLevel.text;
- triggerserver("gui", this.name, RPL.CREATENEWLEVEL, temp.text, (temp.text.lower() == GuiWindow_TileEditor.newLevelOverwrite));
- GuiWindow_TileEditor.newLevelOverwrite = temp.text.lower();
- GuiTextEdit_TileEditor_NewLevel.destroy();
- }
- function GuiTextEdit_TileEditor_Tileset.onAction() {
- // draw the gui tileset as the image specified
- with (GuiDrawingPanel_TileEditor) {
- clearall();
- drawimage(0, 0, GuiTextEdit_TileEditor_Tileset.text);
- }
- GuiWindow_TileEditor.tilesetImage = GuiTextEdit_TileEditor_Tileset.text;
- GuiTextEdit_TileEditor_Tileset.destroy();
- }
- function GuiDrawingPanel_TileEditor.onMouseDown(temp.keyMod, temp.xMouse, temp.yMouse, temp.clickCount) {
- // beginning of gui tile selection
- GuiDrawingPanel_TileEditor.mouseWasDown = true;
- GuiDrawingPanel_TileEditor.mouselock(0);
- temp.coords = GuiDrawingPanel_TileEditor.globaltolocalcoord({temp.xMouse, temp.yMouse});
- GuiWindow_TileEditor.tileSelectStart =
- GuiWindow_TileEditor.tileSelectEnd = {temp.coords[0] - temp.coords[0] % 16, temp.coords[1] - temp.coords[1] % 16};
- drawGuiSelect();
- }
- function GuiDrawingPanel_TileEditor.onMouseUp(temp.keyMod, temp.xMouse, temp.yMouse, temp.clickCount) {
- if (!GuiDrawingPanel_TileEditor.mouseWasDown)
- return;
- // ending of gui tile selection
- GuiDrawingPanel_TileEditor.mouseWasDown = false;
- if (Gui_TileEditor_Select != NULL)
- Gui_TileEditor_Select.destroy();
- setClipboardFromGui();
- GraalControl.makefirstresponder(true);
- }
- function GuiDrawingPanel_TileEditor.onMouseDragged(temp.keyMod, temp.xMouse, temp.yMouse, temp.clickCount) {
- // update gui tile selection with new coordinates after drag
- temp.coords = GuiDrawingPanel_TileEditor.globaltolocalcoord({temp.xMouse, temp.yMouse});
- temp.scrollcoords = GuiWindow_TileEditor.globaltolocalcoord({temp.xMouse, temp.yMouse});
- if (temp.scrollcoords[0] < GuiScroll_TileEditor.x + 32)
- temp.scrollx = temp.scrollcoords[0] - GuiScroll_TileEditor.x - 32;
- elseif (temp.scrollcoords[0] > GuiScroll_TileEditor.x + GuiScroll_TileEditor.width - 64)
- temp.scrollx = temp.scrollcoords[0] - GuiScroll_TileEditor.x - GuiScroll_TileEditor.width + 64;
- if (temp.scrollcoords[1] < GuiScroll_TileEditor.y + 32)
- temp.scrolly = temp.scrollcoords[1] - GuiScroll_TileEditor.y - 32;
- elseif (temp.scrollcoords[1] > GuiScroll_TileEditor.y + GuiScroll_TileEditor.height - 64)
- temp.scrolly = temp.scrollcoords[1] - GuiScroll_TileEditor.y - GuiScroll_TileEditor.height + 64;
- if (temp.scrollx != NULL || temp.scrolly != NULL)
- GuiScroll_TileEditor.scrolldelta(int(temp.scrollx / 8.0), int(temp.scrolly / 8.0));
- GuiWindow_TileEditor.tileSelectEnd = {temp.coords[0] - temp.coords[0] % 16, temp.coords[1] - temp.coords[1] % 16};
- drawGuiSelect();
- }
- function GuiTreeView_TileEditor_FileOpen.onSelect(temp.node, temp.nodeSlashPath, temp.nodeDotPath) {
- // if the selection ends in .txt, request to load the clipboard file
- if (!temp.node.ends(".txt"))
- return;
- triggerserver("gui", this.name, RPL.LOADCLIPBOARDFILE, temp.nodeSlashPath);
- GuiTreeView_TileEditor_FileOpen.selectedSlashPath = temp.nodeSlashPath;
- }
- function GuiButton_TileEditor_FileOpen_Delete.onAction() {
- // if the filepath is something, trigger server to delete it
- // i might add a confirmation box option eventually
- temp.filePath = GuiTreeView_TileEditor_FileOpen.selectedSlashPath;
- if (temp.filePath != NULL)
- triggerserver("gui", this.name, RPL.DELETECLIPBOARDFILE, temp.filePath);
- }
- function GuiButton_TileEditor_FileOpen_Open.onAction() {
- // load the clipboard file data into the clipboard
- if (GuiWindow_TileEditor_FileOpen.clipboard == NULL)
- return;
- GuiWindow_TileEditor.clipboard = GuiWindow_TileEditor_FileOpen.clipboard;
- drawClipboardPreview();
- GuiWindow_TileEditor_FileOpen.destroy();
- }
- function GuiButton_TileEditor_FileOpen_Cancel.onAction() {
- GuiWindow_TileEditor_FileOpen.destroy();
- }
- function GuiTreeView_TileEditor_FileSave.onSelect(temp.node, temp.nodeSlashPath, temp.nodeDotPath) {
- // if the path ends with .txt, trigger the server
- // to load the file
- if (!temp.node.ends(".txt"))
- return;
- triggerserver("gui", this.name, RPL.LOADCLIPBOARDFILE, temp.nodeSlashPath);
- GuiTextEdit_TileEditor_FileSave_FilePath.text = temp.nodeSlashPath;
- }
- function GuiButton_TileEditor_FileSave_Delete.onAction() {
- // if the filepath is something, triggerserver to delete it
- temp.filePath = GuiTextEdit_TileEditor_FileSave_FilePath.text;
- if (temp.filePath != NULL)
- triggerserver("gui", this.name, RPL.DELETECLIPBOARDFILE, temp.filePath);
- }
- function GuiButton_TileEditor_FileSave_Save.onAction() {
- // if the filepath is something, triggerserver to save
- // the clipboard file
- temp.filePath = GuiTextEdit_TileEditor_FileSave_FilePath.text;
- if (temp.filePath.length() == 0)
- return;
- triggerserver("gui", this.name, RPL.SAVECLIPBOARDFILE, GuiWindow_TileEditor.clipboard, temp.filePath);
- GuiWindow_TileEditor_FileSave.destroy();
- }
- function GuiButton_TileEditor_FileSave_Cancel.onAction() {
- GuiWindow_TileEditor_FileSave.destroy();
- }
- function GraalControl.onMouseDown(temp.keyMod, temp.xMouse, temp.yMouse, temp.clickCount) {
- // if the preview gui exists, destroy it
- // because either the program is dead or
- // we are selecting new tiles from the level
- if (GuiShowImg_TileEditor_ClipboardPreview != NULL)
- GuiShowImg_TileEditor_ClipboardPreview.destroy();
- // if the program isn't open, forget it
- if (GuiWindow_TileEditor == NULL)
- return;
- // beginning of tile selection from level
- GuiWindow_TileEditor.tileSelectStart =
- GuiWindow_TileEditor.tileSelectEnd = {int(mousex), int(mousey)};
- drawSelect();
- if (!GuiWindow_TileEditor.isexternal)
- GuiWindow_TileEditor.visible = false;
- }
- function GraalControl.onRightMouseDown(temp.keyMod, temp.xMouse, temp.yMouse, temp.clickCount) {
- // if the program isn't open or
- // no tiles are in the clipboard, forget it
- if (GuiWindow_TileEditor == NULL
- || GuiShowImg_TileEditor_ClipboardPreview == NULL
- || GuiWindow_TileEditor.clipboard == NULL)
- return;
- // make the preview bluey so there's some visual
- // indication that the paste is happening
- GuiShowImg_TileEditor_ClipboardPreview.blue = 1.0;
- // disable flickering while pasting too
- GuiDrawingPanel_TileEditor_ClipboardPreview.flickering = false;
- temp.mx = int(mousex);
- temp.my = int(mousey);
- // pastemode normal is just what you expect from your standard
- // tile editor. the tiles you see in the clipboard preview
- // are pushed to the stack of undo/redo and the clipboard
- // data is sent to the server as a request to paste tiles
- if (GuiWindow_TileEditor.pasteMode == PASTEMODE.NORMAL) {
- temp.historyObject = {
- temp.mx,
- temp.my,
- GuiWindow_TileEditor.editingLayer,
- NULL,
- GuiWindow_TileEditor.clipboard
- };
- for (temp.y = 0; temp.y < GuiWindow_TileEditor.clipboard.size(); temp.y++) {
- temp.row = {};
- for (temp.x = 0; temp.x < GuiWindow_TileEditor.clipboard[0].size(); temp.x++) {
- if (GuiWindow_TileEditor.editingLayer == 0)
- temp.tile = tiles[temp.x + temp.mx, temp.y + temp.my];
- else
- temp.tile = tilelayers[GuiWindow_TileEditor.editingLayer].tiles[temp.x + temp.mx, temp.y + temp.my];
- temp.row.add(temp.tile);
- }
- temp.historyObject[3].add(temp.row);
- }
- if (GuiWindow_TileEditor.history == NULL)
- GuiWindow_TileEditor.history = {};
- GuiWindow_TileEditor.history = GuiWindow_TileEditor.history.subarray(GuiWindow_TileEditor.historyIndex);
- GuiWindow_TileEditor.historyIndex = 0;
- GuiWindow_TileEditor.history.insert(0, temp.historyObject);
- triggerserver("gui", this.name, RPL.PLACETILES, GuiWindow_TileEditor.clipboard, temp.mx, temp.my, GuiWindow_TileEditor.editingLayer);
- // pastemode fill implements a flood fill algorithm
- // the computations are done on the clientside, here,
- // then a standard tile paste request is sent to the
- // server with the rectangle which contains the flooded
- // tiles
- } elseif (GuiWindow_TileEditor.pasteMode == PASTEMODE.FILL) {
- if (GuiWindow_TileEditor.editingLayer == 0) {
- temp.floodedArea = getFloodedAreaZero(temp.mx, temp.my);
- } else {
- temp.tileLayer = tilelayers[GuiWindow_TileEditor.editingLayer];
- temp.floodedArea = getFloodedAreaLayer(temp.tileLayer, temp.mx, temp.my);
- }
- temp.pasteX = temp.floodedArea[0];
- temp.pasteY = temp.floodedArea[1];
- temp.sizeY = temp.floodedArea[3] - temp.pasteY + 1;
- temp.sizeX = temp.floodedArea[2] - temp.pasteX + 1;
- temp.pasteData = new [temp.sizeY][temp.sizeX];
- temp.historyData = {};
- maxlooplimit = 100000;
- for (temp.y = 0; temp.y < temp.sizeY; temp.y++) {
- temp.row = {};
- for (temp.x = 0; temp.x < temp.sizeX; temp.x++) {
- if ((@{temp.pasteX + temp.x, temp.pasteY + temp.y}) in temp.floodedArea) {
- temp.pasteData[temp.y][temp.x] = GuiWindow_TileEditor.clipboard[(temp.pasteY - temp.my + temp.y) % GuiWindow_TileEditor.clipboard.size()][(temp.pasteX - temp.mx + temp.x) % GuiWindow_TileEditor.clipboard[0].size()];
- } else {
- temp.pasteData[temp.y][temp.x] = -2;
- }
- if (GuiWindow_TileEditor.editingLayer == 0)
- temp.row.add(tiles[temp.pasteX + temp.x, temp.pasteY + temp.y]);
- else
- temp.row.add(temp.tileLayer.tiles[temp.pasteX + temp.x, temp.pasteY + temp.y]);
- }
- temp.historyData.add(temp.row);
- }
- temp.historyObject = {
- temp.pasteX,
- temp.pasteY,
- GuiWindow_TileEditor.editingLayer,
- temp.historyData,
- temp.pasteData
- };
- if (GuiWindow_TileEditor.history == NULL)
- GuiWindow_TileEditor.history = {};
- GuiWindow_TileEditor.history = GuiWindow_TileEditor.history.subarray(GuiWindow_TileEditor.historyIndex);
- GuiWindow_TileEditor.historyIndex = 0;
- GuiWindow_TileEditor.history.insert(0, temp.historyObject);
- triggerserver("gui", this.name, RPL.PLACETILES, temp.pasteData, temp.pasteX, temp.pasteY, GuiWindow_TileEditor.editingLayer);
- }
- }
- function GraalControl.onRightMouseUp(temp.keyMod, temp.xMouse, temp.yMouse, temp.clickCount) {
- // if the program isn't open or the preview isn't existing
- // we don't care
- if (GuiWindow_TileEditor == NULL
- || GuiShowImg_TileEditor_ClipboardPreview == NULL)
- return;
- // reset the preview back to black to indicate that
- // you are no longer pasting tiles
- GuiShowImg_TileEditor_ClipboardPreview.blue = 0.0;
- // reenable flickering as well
- GuiDrawingPanel_TileEditor_ClipboardPreview.flickering = true;
- // set the preview position to the mouse position
- GuiShowImg_TileEditor_ClipboardPreview.x = screenx(int(mousex), 0) - 2;
- GuiShowImg_TileEditor_ClipboardPreview.y = screeny(0, int(mousey)) - 2;
- }
- function GraalControl.onMouseDragged(temp.keyMod, temp.xMouse, temp.yMouse, temp.clickCount) {
- // if the program isn't open we don't care
- if (GuiWindow_TileEditor == NULL)
- return;
- // level selection drag here
- // set the ending selection position to the mouse position
- GuiWindow_TileEditor.tileSelectEnd = {int(mousex), int(mousey)};
- drawSelect();
- }
- function GraalControl.onMouseUp(temp.keyMod, temp.xMouse, temp.yMouse, temp.clickCount) {
- hideimgs(200, 204);
- // if the program isn't open forget it
- if (GuiWindow_TileEditor == NULL)
- return;
- // create the clipboard data from the level data
- setClipboardFromLevel();
- GuiWindow_TileEditor.visible = true;
- }
- function GraalControl.onMouseMove(temp.keyMod, temp.xMouse, temp.yMouse, temp.clickCount) {
- // if the preview doesn't exist we don't care
- if (GuiShowImg_TileEditor_ClipboardPreview == NULL)
- return;
- temp.mx = int(mousex);
- temp.my = int(mousey);
- // the preview follows the mouse
- GuiShowImg_TileEditor_ClipboardPreview.x = screenx(temp.mx, 0) - 2;
- GuiShowImg_TileEditor_ClipboardPreview.y = screeny(0, temp.my) - 2;
- // display the pastemode icon a little bit above
- with (findimg(201)) {
- layer = 0;
- image = GuiWindow_TileEditor.pasteMode == PASTEMODE.FILL ? "tileeditor_bucket_1-1.png" : "tileeditor_pencil_1-1.png";
- x = temp.mx;
- y = temp.my - 1.5;
- }
- // if the extra cursor information is disabled
- // there's no need to continue
- if (!GuiWindow_TileEditor.extraCursorInfo)
- return;
- // display the top left corner's x , y
- with (findimg(202)) {
- layer = 0;
- text = temp.mx @ ", " @ temp.my;
- zoom = 0.6;
- x = temp.mx - 1.5 - gettextwidth(zoom, "", "", text) / 32;
- y = temp.my;
- }
- temp.tw = GuiWindow_TileEditor.clipboard[0].size();
- temp.th = GuiWindow_TileEditor.clipboard.size();
- temp.tex = temp.mx + tw;
- temp.tey = temp.my + th;
- // display the bottom right corner's x , y
- with (findimg(203)) {
- layer = 0;
- text = (temp.tex - 1) @ ", " @ (temp.tey - 1);
- x = temp.tex + 0.5;
- y = temp.tey - 1;
- zoom = 0.6;
- }
- // display the clipboard's (width , height)
- with (findimg(204)) {
- layer = 0;
- text = "(" @ temp.tw @ ", " @ temp.th @ ")";
- zoom = 0.6;
- x = temp.mx + temp.tw / 2 - gettextwidth(zoom, "", "", text) / 32;
- y = temp.tey + 0.5;
- }
- }
- function GraalControl.onKeyDown(temp.keyCode, temp.keyText, temp.scanCode) {
- // if the program is closed we dont care
- if (GuiWindow_TileEditor == NULL)
- return;
- // prevent the program from doing 4 billion undo/redo's
- // when the user only wants to do one
- if (timevar2 - GuiWindow_TileEditor.lastUndoOrRedoTime < 0.2)
- return;
- switch (temp.keyCode) {
- case 602: { // undo
- editorUndo();
- break;
- }
- case 601: { // redo
- editorRedo();
- break;
- }
- default: {
- return;
- }
- }
- GuiWindow_TileEditor.lastUndoOrRedoTime = timevar2;
- }
- function GuiTextEdit_TileEditor_Tileset.onLoseFirstResponder() {
- // sleep for a moment for some reason
- // some weird bug otherwise
- sleep(0.1);
- GuiTextEdit_TileEditor_Tileset.destroy();
- }
- function GuiTextEdit_TileEditor_NewLevel.onLoseFirstResponder() {
- // sleep for a moment for some reason
- // some weird bug otherwise
- sleep(0.1);
- GuiTextEdit_TileEditor_NewLevel.destroy();
- }
- function onCloseEditor() {
- // change the cursor from crosshair to default
- GraalControl.cursor = "default";
- // disable fading effect
- GuiWindow_TileEditor.fadeLayers = false;
- updateFadeEffect();
- // disable grid effect
- GuiWindow_TileEditor.grid = false;
- updateGridEffect();
- // destroy the program
- if (GuiShowImg_TileEditor_ClipboardPreview != NULL)
- GuiShowImg_TileEditor_ClipboardPreview.destroy();
- if (GuiWindow_TileEditor_FileOpen != NULL)
- GuiWindow_TileEditor_FileOpen.destroy();
- if (GuiWindow_TileEditor_FileSave != NULL)
- GuiWindow_TileEditor_FileSave.destroy();
- GuiWindow_TileEditor.destroy();
- // hide cursor information
- hideimgs(200, 204);
- }
- function onRequestUse() {
- // send a request to use the editor in this level
- triggerserver("gui", this.name, RPL.REQUESTUSE);
- do {
- temp.time = timevar2;
- waitfor(this, "onActionClientSide", 15.0);
- if (timevar2 - temp.time > 15.0) {
- shared.adminmessage("Your request to use the editor timed out");
- return;
- }
- } while (params[0] != RPL.REQUESTUSE);
- // fix tilelayercount
- tilelayercount = params[3];
- // params is set once onActionClientSide event is triggered
- // params[1] is either "1" or "0"
- // that indicates whether the player is allowed to use
- // the editor in this level or not
- if (params[1])
- showGui(params[2]);
- else
- shared.adminmessage("You do not have rights to view this level");
- }
- /**
- * functions
- */
- function showGui(temp.version) {
- // if the program is already existing
- // destroy it, so we can replace it
- if (GuiWindow_TileEditor != NULL)
- GuiWindow_TileEditor.destroy();
- new GuiWindowCtrl("GuiWindow_TileEditor") {
- profile = GuiBlueWindowProfile;
- canminimize =
- canmaximize = false;
- closequery = true;
- width = 304;
- height = 304;
- x = screenwidth - width;
- text = " Tile Editor v" @ temp.version SPC "(Layer 1)";
- // initialize the program with the defaults
- this.version = temp.version;
- this.tilesetImage = "TILES";
- this.editingLayer = 0;
- this.editingLevel = isonmap ? player.gmap.name : player.level.name;
- this.pasteMode = PASTEMODE.NORMAL;
- new GuiShowImgCtrl("GuiShowImg_TileEditor_Icon") {
- useownprofile = true;
- profile.modal = false;
- x = 8;
- y = 4;
- width = 16;
- height = 16;
- image = "tileeditor_icon_1-1.png";
- }
- new GuiMenuCtrl("GuiMenu_TileEditor") {
- profile = GuiBlueTextEditProfile;
- x = 6;
- y = 24;
- width = 304 - x * 2;
- height = 20;
- clearmenus();
- with (addmenu("File")) {
- profile = GuiBluePopUpMenuProfile;
- textprofile = GuiBlueTextListProfile;
- addrow(0, "New Level").hint = "Create a new Graal level at the specified filepath";
- addrow(1, "Update Level").hint = "Save the tile changes to the level file now";
- addrow(2, "Edit Links").hint = "Modify Level Links";
- addrow(3, "Open Clipboard").hint = "Open a clipboard file saved on the server";
- addrow(4, "Save Clipboard").hint = "Save the current selection as a clipboard file on the server";
- addrow(5, "Exit");
- }
- with (addmenu("Edit")) {
- profile = GuiBluePopUpMenuProfile;
- textprofile = GuiBlueTextListProfile;
- temp.ctrlKey = getplatform() == "mac" ? "CMD" : "CTRL";
- addrow(0, "Undo").hint = "Undo the previous tile paste (" @ temp.ctrlKey @ "+Z)";
- addrow(1, "Redo").hint = "Redo the previous undone paste (" @ temp.ctrlKey @ "+Y)";
- }
- with (addmenu("View")) {
- profile = GuiBluePopUpMenuProfile;
- textprofile = GuiBlueTextListProfile;
- addrow(0, "Fade inactive layers").hint = "Fades the inactive tilelayers, so you can focus on the layer you need to edit";
- addrow(1, "Grid").hint = "Forms a grid to measure and be more precise with tile placement";
- addrow(2, "Extra cursor info").hint = "Displays coordinates and selection size at the cursor";
- }
- with (addmenu("Tileset")) {
- profile = GuiBluePopUpMenuProfile;
- textprofile = GuiBlueTextListProfile;
- addrow(0, "Use image").hint = "Show an image to select from, rather than tiledefs";
- addrow(1, "Use tiledefs").hint = "Show the current tiledefs to select from";
- }
- with (addmenu("Layer")) {
- profile = GuiBluePopUpMenuProfile;
- textprofile = GuiBlueTextListProfile;
- addrow(0, "Add").hint = "Add an additional tilelayer to the top of the current level";
- addrow(1, "Remove").hint = "Remove the top tilelayer of the current level";
- for (temp.i = 0; temp.i < tilelayercount; temp.i++)
- addrow(temp.i + 2, temp.i + 1).hint = "Change the current editing layer to" SPC (temp.i + 1);
- setrowbyid(2, "*1");
- }
- with (addmenu("Options")) {
- profile = GuiBluePopUpMenuProfile;
- textprofile = GuiBlueTextListProfile;
- temp.obj = addrow(0, "External");
- temp.obj.hint = "Toggle between using an internal window and an external window";
- GuiWindow_TileEditor.externalToggleMenuRowObj = temp.obj;
- addrow(1, "Help").hint = "Open an internet browser window/tab to the graalonline forum thread";
- addrow(2, "Check for update").hint = "Checks online if there is an updated version";
- }
- new GuiButtonCtrl("GuiButton_TileEditor_PasteMode") {
- profile = GuiBlueButtonProfile;
- x = 248;
- y = 0;
- width = 40;
- height = 20;
- text = "";
- new GuiShowImgCtrl("GuiShowImg_TileEditor_PasteMode") {
- useownprofile = true;
- profile.modal = false;
- image = "tileeditor_bucket_1-1.png";
- x = 12;
- y = 2;
- }
- }
- }
- new GuiScrollCtrl("GuiScroll_TileEditor") {
- profile = GuiBlueScrollProfile;
- x = 6;
- y = 44;
- width = 304 - x * 2;
- height = 304 - y - 6;
- hScrollBar = "alwaysOn";
- vScrollBar = "alwaysOn";
- new GuiDrawingPanel("GuiDrawingPanel_TileEditor") {
- width = 2048;
- height = 512;
- clearall();
- drawimage(0, 0, GuiWindow_TileEditor.tilesetImage);
- cursor = "crosshair";
- }
- }
- }
- // the cursor is changed to a crosshair while the
- // program is open
- GraalControl.cursor = "crosshair";
- }
- function drawGuiSelect() {
- // draws the tile selection box on the gui
- if (GuiWindow_TileEditor.tileSelectStart[0] <= GuiWindow_TileEditor.tileSelectEnd[0]) {
- temp.tsx = GuiWindow_TileEditor.tileSelectStart[0];
- temp.tex = GuiWindow_TileEditor.tileSelectEnd[0] + 16;
- } else {
- temp.tsx = GuiWindow_TileEditor.tileSelectEnd[0];
- temp.tex = GuiWindow_TileEditor.tileSelectStart[0] + 16;
- }
- if (GuiWindow_TileEditor.tileSelectStart[1] <= GuiWindow_TileEditor.tileSelectEnd[1]) {
- temp.tsy = GuiWindow_TileEditor.tileSelectStart[1];
- temp.tey = GuiWindow_TileEditor.tileSelectEnd[1] + 16;
- } else {
- temp.tsy = GuiWindow_TileEditor.tileSelectEnd[1];
- temp.tey = GuiWindow_TileEditor.tileSelectStart[1] + 16;
- }
- if (Gui_TileEditor_Select != NULL) {
- Gui_TileEditor_Select.x = temp.tsx;
- Gui_TileEditor_Select.y = temp.tsy;
- Gui_TileEditor_Select.width = temp.tex - temp.tsx;
- Gui_TileEditor_Select.height = temp.tey - temp.tsy;
- return;
- }
- with (GuiDrawingPanel_TileEditor) {
- new GuiControl("Gui_TileEditor_Select") {
- useownprofile = true;
- profile.cankeyfocus =
- profile.modal = false;
- profile.border = 3;
- x = temp.tsx;
- y = temp.tsy;
- width = temp.tex - temp.tsx;
- height = temp.tey - temp.tsy;
- red =
- green =
- blue = 0.0;
- }
- }
- }
- function drawSelect() {
- // draws the tile selection box on the level
- if (GuiWindow_TileEditor.tileSelectStart[0] <= GuiWindow_TileEditor.tileSelectEnd[0]) {
- temp.tsx = GuiWindow_TileEditor.tileSelectStart[0];
- temp.tex = GuiWindow_TileEditor.tileSelectEnd[0] + 1.0;
- } else {
- temp.tsx = GuiWindow_TileEditor.tileSelectEnd[0];
- temp.tex = GuiWindow_TileEditor.tileSelectStart[0] + 1.0;
- }
- if (GuiWindow_TileEditor.tileSelectStart[1] <= GuiWindow_TileEditor.tileSelectEnd[1]) {
- temp.tsy = GuiWindow_TileEditor.tileSelectStart[1];
- temp.tey = GuiWindow_TileEditor.tileSelectEnd[1] + 1.0;
- } else {
- temp.tsy = GuiWindow_TileEditor.tileSelectEnd[1];
- temp.tey = GuiWindow_TileEditor.tileSelectStart[1] + 1.0;
- }
- with (findimg(200)) {
- layer = 0;
- polygon = {
- temp.tsx, temp.tsy,
- temp.tex, temp.tsy,
- temp.tex, temp.tey,
- temp.tsx, temp.tey
- };
- red = 0.0;
- green = 0.0;
- blue = 0.0;
- alpha = 0.6;
- }
- // display the pastemode icon
- with (findimg(201)) {
- layer = 0;
- image = GuiWindow_TileEditor.pasteMode == PASTEMODE.FILL ? "tileeditor_bucket_1-1.png" : "tileeditor_pencil_1-1.png";
- x = temp.tsx;
- y = temp.tsy - 1.5;
- }
- // display the top left corner x , y
- with (findimg(202)) {
- layer = 0;
- text = temp.tsx @ ", " @ temp.tsy;
- zoom = 0.6;
- x = temp.tsx - 1.5 - gettextwidth(zoom, "", "", text) / 32;
- y = temp.tsy;
- }
- // display the bottom right corner x , y
- with (findimg(203)) {
- layer = 0;
- text = (temp.tex - 1) @ ", " @ (temp.tey - 1);
- x = temp.tex + 0.5;
- y = temp.tey - 1;
- zoom = 0.6;
- }
- // display the (width , height)
- with (findimg(204)) {
- layer = 0;
- text = "(" @ (temp.tex - temp.tsx) @ ", " @ (temp.tey - temp.tsy) @ ")";
- zoom = 0.6;
- x = temp.tsx + (temp.tex - temp.tsx) / 2 - gettextwidth(zoom, "", "", text) / 32;
- y = temp.tey + 0.5;
- }
- }
- function showFileOpenGui() {
- // if the Open or Save window already exists
- // destroy it to be replaced
- if (GuiWindow_TileEditor_FileSave != NULL)
- GuiWindow_TileEditor_FileSave.destroy();
- if (GuiWindow_TileEditor_FileOpen != NULL)
- GuiWindow_TileEditor_FileOpen.destroy();
- new GuiWindowCtrl("GuiWindow_TileEditor_FileOpen") {
- profile = GuiBlueWindowProfile;
- destroyonhide = true;
- canresize =
- canminimize =
- canmaximize = false;
- width = 304;
- height = 304;
- x = screenwidth / 2 - width / 2;
- y = screenheight / 2 - height / 2;
- text = "Open";
- new GuiScrollCtrl("GuiScroll_TileEditor_FileOpen_Preview_Image") {
- x = 6;
- y = 24;
- profile = GuiBlueScrollProfile;
- width = 88;
- height = 88;
- hScrollBar = "alwaysOff";
- vScrollBar = "alwaysOff";
- new GuiStretchCtrl("GuiStretch_TileEditor_FileOpen") {
- width = 84;
- height = 84;
- new GuiDrawingPanel("GuiDrawingPanel_TileEditor_FileOpen_Preview") {
- clearall();
- }
- }
- }
- new GuiScrollCtrl("GuiScroll_TileEditor_FileOpen_Preview_Text") {
- profile = GuiBlueScrollProfile;
- x = 92;
- y = 24;
- width = 304 - x - 6;
- height = 88;
- hScrollBar = "dynamic";
- vScrollBar = "dynamic";
- new GuiTextCtrl("GuiText_TileEditor_FileOpen_Title") {
- profile = GuiBlueTextProfile;
- x = 4;
- height = 20;
- text = "Title:";
- }
- new GuiTextCtrl("GuiText_TileEditor_FileOpen_Title_Value") {
- profile = GuiBlueTextProfile;
- x = 56;
- height = 20;
- text = "N / A";
- }
- new GuiTextCtrl("GuiText_TileEditor_FileOpen_Extent") {
- profile = GuiBlueTextProfile;
- x = 4;
- y = 18;
- height = 20;
- text = "Extent:";
- }
- new GuiTextCtrl("GuiText_TileEditor_FileOpen_Extent_Value") {
- profile = GuiBlueTextProfile;
- x = 56;
- y = 18;
- height = 20;
- text = @{"N / A", "N / A"};
- }
- new GuiTextCtrl("GuiText_TileEditor_FileOpen_Created") {
- profile = GuiBlueTextProfile;
- x = 4;
- y = 36;
- height = 20;
- text = "Created:";
- }
- new GuiTextCtrl("GuiText_TileEditor_FileOpen_Created_Value") {
- profile = GuiBlueTextProfile;
- x = 56;
- y = 36;
- height = 20;
- text = "N / A";
- }
- }
- new GuiScrollCtrl("GuiScroll_TileEditor_FileOpen_Browse") {
- profile = GuiBlueScrollProfile;
- x = 6;
- y = 112;
- width = 304 - x * 2;
- height = 160;
- hScrollBar = "dynamic";
- vScrollBar = "dynamic";
- new GuiTreeViewCtrl("GuiTreeView_TileEditor_FileOpen") {
- profile = GuiBlueTreeViewProfile;
- width = 132;
- fitparentwidth = true;
- }
- }
- new GuiButtonCtrl("GuiButton_TileEditor_FileOpen_Delete") {
- profile = GuiBlueButtonProfile;
- x = 6;
- y = 273;
- width = 70;
- height = 24;
- text = "Delete";
- }
- new GuiButtonCtrl("GuiButton_TileEditor_FileOpen_Open") {
- profile = GuiBlueButtonProfile;
- x = 98;
- y = 273;
- width = 100;
- height = 24;
- text = "Open";
- }
- new GuiButtonCtrl("GuiButton_TileEditor_FileOpen_Cancel") {
- profile = GuiBlueButtonProfile;
- x = 198;
- y = 273;
- width = 100;
- height = 24;
- text = "Cancel";
- }
- }
- // once the gui is created, let's request a list of
- // clipboard files which the player can use
- triggerserver("gui", this.name, RPL.LISTCLIPBOARDFOLDER);
- }
- function showFileSaveGui() {
- // if the Open or Save window already exists
- // destroy it to be replaced
- if (GuiWindow_TileEditor_FileOpen != NULL)
- GuiWindow_TileEditor_FileOpen.destroy();
- if (GuiWindow_TileEditor_FileSave != NULL)
- GuiWindow_TileEditor_FileSave.destroy();
- new GuiWindowCtrl("GuiWindow_TileEditor_FileSave") {
- profile = GuiBlueWindowProfile;
- destroyonhide = true;
- canresize =
- canminimize =
- canmaximize = false;
- width = 304;
- height = 304;
- x = screenwidth / 2 - width / 2;
- y = screenheight / 2 - height / 2;
- text = "Save";
- new GuiScrollCtrl("GuiScroll_TileEditor_FileSave_Preview_Image") {
- x = 6;
- y = 24;
- profile = GuiBlueScrollProfile;
- width = 88;
- height = 88;
- hScrollBar = "alwaysOff";
- vScrollBar = "alwaysOff";
- new GuiStretchCtrl("GuiStretch_TileEditor_FileSave") {
- width = 84;
- height = 84;
- new GuiDrawingPanel("GuiDrawingPanel_TileEditor_FileSave_Preview") {
- clearall();
- }
- }
- }
- new GuiScrollCtrl("GuiScroll_TileEditor_FileSave_Preview_Text") {
- profile = GuiBlueScrollProfile;
- x = 92;
- y = 24;
- width = 304 - x - 6;
- height = 88;
- hScrollBar = "dynamic";
- vScrollBar = "dynamic";
- new GuiTextCtrl("GuiText_TileEditor_FileSave_Title") {
- profile = GuiBlueTextProfile;
- x = 4;
- height = 20;
- text = "Title:";
- }
- new GuiTextCtrl("GuiText_TileEditor_FileSave_Title_Value") {
- profile = GuiBlueTextProfile;
- x = 56;
- height = 20;
- text = "N / A";
- }
- new GuiTextCtrl("GuiText_TileEditor_FileSave_Extent") {
- profile = GuiBlueTextProfile;
- x = 4;
- y = 18;
- height = 20;
- text = "Extent:";
- }
- new GuiTextCtrl("GuiText_TileEditor_FileSave_Extent_Value") {
- profile = GuiBlueTextProfile;
- x = 56;
- y = 18;
- height = 20;
- text = @{"N / A", "N / A"};
- }
- new GuiTextCtrl("GuiText_TileEditor_FileSave_Created") {
- profile = GuiBlueTextProfile;
- x = 4;
- y = 36;
- height = 20;
- text = "Created:";
- }
- new GuiTextCtrl("GuiText_TileEditor_FileSave_Created_Value") {
- profile = GuiBlueTextProfile;
- x = 56;
- y = 36;
- height = 20;
- text = "N / A";
- }
- }
- new GuiScrollCtrl("GuiScroll_TileEditor_FileSave_Browse") {
- profile = GuiBlueScrollProfile;
- x = 6;
- y = 112;
- width = 304 - x * 2;
- height = 141;
- hScrollBar = "dynamic";
- vScrollBar = "dynamic";
- new GuiTreeViewCtrl("GuiTreeView_TileEditor_FileSave") {
- profile = GuiBlueTreeViewProfile;
- width = 132;
- fitparentwidth = true;
- }
- }
- new GuiTextEditCtrl("GuiTextEdit_TileEditor_FileSave_FilePath") {
- profile = GuiBlueTextEditProfile;
- x = 6;
- y = 253;
- width = 304 - x * 2;
- height = 20;
- }
- new GuiButtonCtrl("GuiButton_TileEditor_FileSave_Delete") {
- profile = GuiBlueButtonProfile;
- x = 6;
- y = 273;
- width = 70;
- height = 24;
- text = "Delete";
- }
- new GuiButtonCtrl("GuiButton_TileEditor_FileSave_Save") {
- profile = GuiBlueButtonProfile;
- x = 98;
- y = 273;
- width = 100;
- height = 24;
- text = "Save";
- }
- new GuiButtonCtrl("GuiButton_TileEditor_FileSave_Cancel") {
- profile = GuiBlueButtonProfile;
- x = 198;
- y = 273;
- width = 100;
- height = 24;
- text = "Cancel";
- }
- }
- // once the gui is created, let's request a list of
- // clipboard files which the player can use
- triggerserver("gui", this.name, RPL.LISTCLIPBOARDFOLDER);
- }
- function setClipboardFromLevel() {
- // set the clipboard to data from the level selection
- if (GuiWindow_TileEditor.tileSelectStart[0] <= GuiWindow_TileEditor.tileSelectEnd[0]) {
- temp.tsx = GuiWindow_TileEditor.tileSelectStart[0];
- temp.tex = GuiWindow_TileEditor.tileSelectEnd[0] + 1;
- } else {
- temp.tsx = GuiWindow_TileEditor.tileSelectEnd[0];
- temp.tex = GuiWindow_TileEditor.tileSelectStart[0] + 1;
- }
- if (GuiWindow_TileEditor.tileSelectStart[1] <= GuiWindow_TileEditor.tileSelectEnd[1]) {
- temp.tsy = GuiWindow_TileEditor.tileSelectStart[1];
- temp.tey = GuiWindow_TileEditor.tileSelectEnd[1] + 1;
- } else {
- temp.tsy = GuiWindow_TileEditor.tileSelectEnd[1];
- temp.tey = GuiWindow_TileEditor.tileSelectStart[1] + 1;
- }
- GuiWindow_TileEditor.clipboard = {};
- for (temp.y = temp.tsy; temp.y < temp.tey; temp.y++) {
- temp.arr = {};
- for (temp.x = temp.tsx; temp.x < temp.tex; temp.x++) {
- if (GuiWindow_TileEditor.editingLayer == 0)
- temp.tile = tiles[temp.x, temp.y];
- else
- temp.tile = tilelayers[GuiWindow_TileEditor.editingLayer].tiles[temp.x, temp.y];
- temp.arr.add(temp.tile);
- }
- GuiWindow_TileEditor.clipboard.add(temp.arr);
- }
- drawClipboardPreview();
- }
- function setClipboardFromGui() {
- // set the clipboard to data from the gui selection
- if (GuiWindow_TileEditor.tileSelectStart[0] < 0)
- GuiWindow_TileEditor.tileSelectStart[0] = 0;
- elseif(GuiWindow_TileEditor.tileSelectStart[0] >= GuiDrawingPanel_TileEditor.width)
- GuiWindow_TileEditor.tileSelectStart[0] = GuiDrawingPanel_TileEditor.width - 16;
- if (GuiWindow_TileEditor.tileSelectStart[1] < 0)
- GuiWindow_TileEditor.tileSelectStart[1] = 0;
- elseif(GuiWindow_TileEditor.tileSelectStart[1] >= GuiDrawingPanel_TileEditor.height)
- GuiWindow_TileEditor.tileSelectStart[1] = GuiDrawingPanel_TileEditor.height - 16;
- if (GuiWindow_TileEditor.tileSelectEnd[0] < 0)
- GuiWindow_TileEditor.tileSelectEnd[0] = 0;
- elseif(GuiWindow_TileEditor.tileSelectEnd[0] >= GuiDrawingPanel_TileEditor.width)
- GuiWindow_TileEditor.tileSelectEnd[0] = GuiDrawingPanel_TileEditor.width - 16;
- if (GuiWindow_TileEditor.tileSelectEnd[1] < 0)
- GuiWindow_TileEditor.tileSelectEnd[1] = 0;
- elseif(GuiWindow_TileEditor.tileSelectEnd[1] >= GuiDrawingPanel_TileEditor.height)
- GuiWindow_TileEditor.tileSelectEnd[1] = GuiDrawingPanel_TileEditor.height - 16;
- if (GuiWindow_TileEditor.tileSelectStart[0] <= GuiWindow_TileEditor.tileSelectEnd[0]) {
- temp.tsx = GuiWindow_TileEditor.tileSelectStart[0];
- temp.tex = GuiWindow_TileEditor.tileSelectEnd[0] + 16;
- } else {
- temp.tsx = GuiWindow_TileEditor.tileSelectEnd[0];
- temp.tex = GuiWindow_TileEditor.tileSelectStart[0] + 16;
- }
- if (GuiWindow_TileEditor.tileSelectStart[1] <= GuiWindow_TileEditor.tileSelectEnd[1]) {
- temp.tsy = GuiWindow_TileEditor.tileSelectStart[1];
- temp.tey = GuiWindow_TileEditor.tileSelectEnd[1] + 16;
- } else {
- temp.tsy = GuiWindow_TileEditor.tileSelectEnd[1];
- temp.tey = GuiWindow_TileEditor.tileSelectStart[1] + 16;
- }
- GuiWindow_TileEditor.clipboard = {};
- for (temp.y = temp.tsy; temp.y < temp.tey; temp.y += 16) {
- temp.arr = {};
- for (temp.x = temp.tsx; temp.x < temp.tex; temp.x += 16)
- temp.arr.add(getXYTile(temp.x, temp.y));
- GuiWindow_TileEditor.clipboard.add(temp.arr);
- }
- drawClipboardPreview();
- }
- function drawClipboardPreview() {
- // draw the clipboard preview gui which follows the mouse
- // if it already exists, destroy it to be replaced
- if (GuiShowImg_TileEditor_ClipboardPreview != NULL)
- GuiShowImg_TileEditor_ClipboardPreview.destroy();
- new GuiShowImgCtrl("GuiShowImg_TileEditor_ClipboardPreview") {
- useownprofile = true;
- profile.cankeyfocus =
- profile.modal = false;
- x = screenx(int(mousex), 0) - 2;
- y = screeny(0, int(mousey)) - 2;
- width = GuiWindow_TileEditor.clipboard[0].size() * 16 + 4;
- height = GuiWindow_TileEditor.clipboard.size() * 16 + 4;
- polygon = {
- 0, 0,
- width, 0,
- width, height,
- 0, height
- };
- red =
- green =
- blue = 0.0;
- alpha = 0.6;
- new GuiDrawingPanel("GuiDrawingPanel_TileEditor_ClipboardPreview") {
- useownprofile = true;
- profile.cankeyfocus =
- profile.modal = false;
- x =
- y = 2;
- width = GuiWindow_TileEditor.clipboard[0].size() * 16;
- height = GuiWindow_TileEditor.clipboard.size() * 16;
- clearall();
- // draw the tiles to the preview based on
- // the currently selected tileset image
- for (temp.y = 0; temp.y < GuiWindow_TileEditor.clipboard.size(); temp.y++) {
- for (temp.x = 0; temp.x < GuiWindow_TileEditor.clipboard[0].size(); temp.x++) {
- temp.xy = getTileXY(GuiWindow_TileEditor.clipboard[temp.y][temp.x]);
- drawimagerectangle(temp.x * 16, temp.y * 16, GuiWindow_TileEditor.tilesetImage, temp.xy[0], temp.xy[1], 16, 16);
- }
- }
- flickering = true;
- alpha = 0.5;
- }
- }
- // push the preview gui behind all gui's inside of GraalControl
- GuiShowImg_TileEditor_ClipboardPreview.pushtoback();
- }
- function getFloodedAreaZero(temp.x, temp.y) {
- // the flood fill algorithm for tiles on layer zero
- // it uses a non-recursive, stack based approach
- temp.tile = tiles[temp.x, temp.y];
- temp.a = {temp.x, temp.y, temp.x, temp.y};
- temp.q = {{temp.x, temp.y}};
- temp.tileMap = new [height][width];
- maxlooplimit = 100000;
- temp.minX = temp.x - 64;
- if (temp.minX < 0)
- temp.minX = 0;
- temp.minY = temp.y - 64;
- if (temp.minY < 0)
- temp.minY = 0;
- temp.maxX = temp.x + 64;
- if (temp.maxX >= width)
- temp.maxX = width - 1;
- temp.maxY = temp.y + 64;
- if (temp.maxY >= height)
- temp.maxY = height - 1;
- while (temp.q.size() != 0) {
- temp.n = temp.q[0];
- temp.q.delete(0);
- temp.x = temp.n[0];
- temp.y = temp.n[1];
- if (tiles[temp.x, temp.y] == temp.tile
- && !temp.tileMap[temp.y][temp.x]) {
- temp.tileMap[temp.y][temp.x] = true;
- temp.a.add(temp.n);
- if (temp.a.size() == 4100)
- break;
- if (temp.x < temp.a[0])
- temp.a[0] = temp.x;
- elseif (temp.x > temp.a[2])
- temp.a[2] = temp.x;
- if (temp.y < temp.a[1])
- temp.a[1] = temp.y;
- elseif (temp.y > temp.a[3])
- temp.a[3] = temp.y;
- if (temp.y > temp.minY)
- temp.q.add({temp.x, temp.y - 1});
- if (temp.x > temp.minX)
- temp.q.add({temp.x - 1, temp.y});
- if (temp.y < temp.maxY)
- temp.q.add({temp.x, temp.y + 1});
- if (temp.x < temp.maxX)
- temp.q.add({temp.x + 1, temp.y});
- }
- }
- return temp.a;
- }
- function getFloodedAreaLayer(temp.tileLayer, temp.x, temp.y) {
- // the flood fill algorithm for tiles on layers 1+
- // it uses a non-recursive, stack based approach
- temp.tile = temp.tileLayer.tiles[temp.x, temp.y];
- temp.a = {temp.x, temp.y, temp.x, temp.y};
- temp.q = {{temp.x, temp.y}};
- temp.tileMap = new [height][width];
- maxlooplimit = 100000;
- temp.minX = temp.x - 64;
- if (temp.minX < 0)
- temp.minX = 0;
- temp.minY = temp.y - 64;
- if (temp.minY < 0)
- temp.minY = 0;
- temp.maxX = temp.x + 64;
- if (temp.maxX >= width)
- temp.maxX = width - 1;
- temp.maxY = temp.y + 64;
- if (temp.maxY >= height)
- temp.maxY = height - 1;
- while (temp.q.size() != 0) {
- temp.n = temp.q[0];
- temp.q.delete(0);
- temp.x = temp.n[0];
- temp.y = temp.n[1];
- if (temp.tileLayer.tiles[temp.x, temp.y] == temp.tile
- && !temp.tileMap[temp.y][temp.x]) {
- temp.tileMap[temp.y][temp.x] = true;
- temp.a.add(temp.n);
- if (temp.a.size() == 4100)
- break;
- if (temp.x < temp.a[0])
- temp.a[0] = temp.x;
- elseif (temp.x > temp.a[2])
- temp.a[2] = temp.x;
- if (temp.y < temp.a[1])
- temp.a[1] = temp.y;
- elseif (temp.y > temp.a[3])
- temp.a[3] = temp.y;
- if (temp.y > temp.minY)
- temp.q.add({temp.x, temp.y - 1});
- if (temp.x > temp.minX)
- temp.q.add({temp.x - 1, temp.y});
- if (temp.y < temp.maxY)
- temp.q.add({temp.x, temp.y + 1});
- if (temp.x < temp.maxX)
- temp.q.add({temp.x + 1, temp.y});
- }
- }
- return temp.a;
- }
- function editorUndo() {
- // if the program isn't open, ignore it
- if (GuiWindow_TileEditor == NULL)
- return;
- // if you've reached the end of history
- // there's nothing to undo
- if (GuiWindow_TileEditor.historyIndex == GuiWindow_TileEditor.history.size()) {
- shared.adminmessage("nothing to undo");
- return;
- }
- // send a standard paste request to the server
- // providing the data from the history
- triggerserver(
- "gui",
- this.name,
- RPL.PLACETILES,
- GuiWindow_TileEditor.history[GuiWindow_TileEditor.historyIndex][3],
- GuiWindow_TileEditor.history[GuiWindow_TileEditor.historyIndex][0],
- GuiWindow_TileEditor.history[GuiWindow_TileEditor.historyIndex][1],
- GuiWindow_TileEditor.history[GuiWindow_TileEditor.historyIndex][2]
- );
- // increase stack position
- GuiWindow_TileEditor.historyIndex++;
- }
- function editorRedo() {
- // if the program is closed, ignore
- if (GuiWindow_TileEditor == NULL)
- return;
- // if you've reached the beginning of history
- // there is nothing to redo
- if (GuiWindow_TileEditor.historyIndex == 0) {
- shared.adminmessage("nothing to redo");
- return;
- }
- // decrease the stack position
- GuiWindow_TileEditor.historyIndex--;
- // send a standard paste request to the server
- // providing the data from the history
- triggerserver(
- "gui",
- this.name,
- RPL.PLACETILES,
- GuiWindow_TileEditor.history[GuiWindow_TileEditor.historyIndex][4],
- GuiWindow_TileEditor.history[GuiWindow_TileEditor.historyIndex][0],
- GuiWindow_TileEditor.history[GuiWindow_TileEditor.historyIndex][1],
- GuiWindow_TileEditor.history[GuiWindow_TileEditor.historyIndex][2]
- );
- }
- function updateFadeEffect() {
- // enables or disables the fading effect of
- // all inactive tilelayers
- if (GuiWindow_TileEditor.fadeLayers) {
- for (temp.i = 0; temp.i < tilelayercount; temp.i++) {
- if (temp.i == GuiWindow_TileEditor.editingLayer) {
- tilelayers[temp.i].red =
- tilelayers[temp.i].green =
- tilelayers[temp.i].blue =
- tilelayers[temp.i].alpha = 1.0;
- } else {
- tilelayers[temp.i].red =
- tilelayers[temp.i].green =
- tilelayers[temp.i].blue = 0.25;
- if (temp.i != 0)
- tilelayers[temp.i].alpha = 0.25;
- }
- }
- } else {
- for (temp.i = 0; temp.i < tilelayercount; temp.i++) {
- tilelayers[temp.i].red =
- tilelayers[temp.i].green =
- tilelayers[temp.i].blue =
- tilelayers[temp.i].alpha = 1.0;
- }
- }
- }
- function updateGridEffect() {
- // enables or disables the grid effect
- if (this.gridImageCount != NULL) {
- hideimgs(300, 300 + this.gridImageCount);
- this.gridImageCount = NULL;
- }
- if (GuiWindow_TileEditor.grid) {
- temp.w = width;
- temp.h = height;
- for (temp.y = 0; temp.y < temp.h; temp.y++) {
- with (findimg(300 + temp.i++)) {
- layer = 3;
- if (temp.y % 64 == 0) {
- red = 1.0;
- green = 0.0;
- blue = 0.0;
- polygon = {
- 0, temp.y,
- temp.w, temp.y,
- temp.w, temp.y + 1/4,
- 0, temp.y + 1/4
- };
- } elseif (temp.y % 32 == 0) {
- red = 0.0;
- green = 1.0;
- blue = 0.0;
- polygon = {
- 0, temp.y,
- temp.w, temp.y,
- temp.w, temp.y + 3/16,
- 0, temp.y + 3/16
- };
- } elseif (temp.y % 16 == 0) {
- red = 1.0;
- green = 0.0;
- blue = 1.0;
- polygon = {
- 0, temp.y,
- temp.w, temp.y,
- temp.w, temp.y + 1/8,
- 0, temp.y + 1/8
- };
- } elseif (temp.y % 8 == 0) {
- red = 0.0;
- green = 1.0;
- blue = 1.0;
- polygon = {
- 0, temp.y,
- temp.w, temp.y,
- temp.w, temp.y + 1/16,
- 0, temp.y + 1/16
- };
- } else {
- polygon = {
- 0, temp.y,
- temp.w, temp.y,
- temp.w, temp.y + 1/16,
- 0, temp.y + 1/16
- };
- }
- alpha = 0.5;
- }
- }
- for (temp.x = 0; temp.x < temp.w; temp.x++) {
- with (findimg(300 + temp.i++)) {
- layer = 3;
- if (temp.x % 64 == 0) {
- red = 1.0;
- green = 0.0;
- blue = 0.0;
- polygon = {
- temp.x, 0,
- temp.x, temp.h,
- temp.x + 1/4, temp.h,
- temp.x + 1/4, 0
- };
- } elseif (temp.x % 32 == 0) {
- red = 0.0;
- green = 1.0;
- blue = 0.0;
- polygon = {
- temp.x, 0,
- temp.x, temp.h,
- temp.x + 3/16, temp.h,
- temp.x + 3/16, 0
- };
- } elseif (temp.x % 16 == 0) {
- red = 1.0;
- green = 0.0;
- blue = 1.0;
- polygon = {
- temp.x, 0,
- temp.x, temp.h,
- temp.x + 1/8, temp.h,
- temp.x + 1/8, 0
- };
- } elseif (temp.x % 8 == 0) {
- red = 0.0;
- green = 1.0;
- blue = 1.0;
- polygon = {
- temp.x, 0,
- temp.x, temp.h,
- temp.x + 1/16, temp.h,
- temp.x + 1/16, 0
- };
- } else {
- polygon = {
- temp.x, 0,
- temp.x, temp.h,
- temp.x + 1/16, temp.h,
- temp.x + 1/16, 0
- };
- }
- alpha = 0.5;
- }
- }
- this.gridImageCount = temp.i;
- }
- }
- function getTileXY(temp.tile) {
- // returns the position of the tile on the tileset image
- // useful for rendering tiles on a drawing panel
- return {
- int(temp.tile % 16.0) * 16 + int(temp.tile / 512.0) * 256,
- (int(temp.tile / 16.0) * 16) % 512
- };
- }
- function getXYTile(temp.x, temp.y) {
- // returns the tile from the position at the tileset image
- // useful for getting tile data from a gui selection
- return int(temp.x / 16.0) % 16 + int(temp.x / 256.0) * 512 + int(temp.y / 16.0) * 16 % 512;
- }
- /**
- * the following are provided for public script interfacing
- * in an effort to make it easier to integrate this tool
- * into a staff tool manager
- */
- public function close() {
- // asynchronous close operation
- trigger("onCloseEditor");
- }
- public function open() {
- // asynchronous open request operation
- trigger("onRequestUse");
- }
- public function isOpen() {
- // returns a boolean telling if the program
- // is open or not
- return (GuiWindow_TileEditor != NULL);
- }
Add Comment
Please, Sign In to add comment