Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Scripted by iMagic
- function onActionServerside(temp.action) {
- switch (temp.action) {
- case "warpMe":
- temp.coords = params[1];
- player.setLevel2(temp.coords[0], temp.coords[1], temp.coords[2]);
- player.triggerClient("weapon", this.name, "finishedWarping");
- break;
- }
- }
- //#CLIENTSIDE
- function onActionClientside(temp.action) {
- this.trigger("onActionClientsideDone");
- }
- function onPlayerChats() {
- temp.tokens = player.chat.tokenize(" ");
- switch (temp.tokens[0]) {
- case "/sc":
- if (temp.tokens[1] && temp.tokens[2]) {
- temp.data = {temp.tokens[1], temp.tokens[2]};
- } else {
- temp.data = temp.tokens[1];
- }
- generateLevelScreenshot(temp.data);
- break;
- }
- }
- function generateLevelScreenshot(temp.data, temp.returnB64) {
- // The coordinates the player started at
- temp.coords = {player.x, player.y};
- temp.sc.level_width = player.level.width;
- temp.sc.level_height = player.level.height;
- // The amount of screenshots/steps it will take to
- // collect all images for the final render
- temp.sc.screenshots = {player.level.width / 32, player.level.height / 32};
- /* DETERMINE SCALE FROM DIMENSIONS */
- if (temp.data.size() == 2) {
- temp.sc.pixel_width = constrain(32, 2048, temp.data[0]);
- temp.sc.pixel_height = constrain(32, 2048, temp.data[1]);
- temp.sc.scale_width = 2048 / temp.sc.pixel_width;
- temp.sc.scale_height = 2048 / temp.sc.pixel_height;
- } else {
- /* DETERMINE DIMENSIONS FROM SCALE */
- // Ensure the scale is a valid decimal percentage
- temp.scale = temp.data == NULL || !(temp.data in |0.02, 1|) ? 1 : temp.data;
- // Calculate the width/height of the final render given the scale
- temp.sc.pixel_width = (temp.sc.level_width * 16) * temp.scale;
- temp.sc.pixel_height = (temp.sc.level_height * 16) * temp.scale;
- /* The script can only produce images smaller than 2048x2048
- We must ensure the final dimensions are not larger than this
- otherwise we will end up with an incomplete screenshot.
- We'll need to igure out how much we need to downscale the canvas
- so that both dimensions are under 2048px while still keeping the
- same aspect ratio.
- */
- temp.sc.scale_width = 2048 / temp.sc.pixel_width;
- temp.sc.scale_height = 2048 / temp.sc.pixel_height;
- // If either of these measurement is less than 1 it means
- // at least one of them needs to be shrinked...
- // and to keep aspect-ratio we should shrink both.
- if (temp.sc.scale_width < 1 || temp.sc.scale_height < 1) {
- temp.min = min(temp.sc.scale_width, temp.sc.scale_height);
- // Make the scale factor the same to preserve the aspect ratio
- temp.sc.scale_width = temp.sc.scale_height = temp.min;
- temp.sc.pixel_width *= temp.min;
- temp.sc.pixel_height *= temp.min;
- }
- }
- /* Recalculate the final dimensions again but ensure
- that the width and the height are integer values.
- Skipping this step may lead to weird 1px gaps
- on the final render.
- */
- temp.sc.pixel_width -= temp.sc.pixel_width % temp.sc.screenshots[0];
- temp.sc.pixel_height -= temp.sc.pixel_height % temp.sc.screenshots[1];
- // Recalculate the scales now that the width/height are integers
- temp.sc.scale_width = 2048 / temp.sc.pixel_width;
- temp.sc.scale_height = 2048 / temp.sc.pixel_height;
- // Create the GUI object that will generate the final image
- this.canvas = new GuiDrawingPanel();
- this.canvas.resize(0, 0, temp.sc.pixel_width, temp.sc.pixel_height);
- this.canvas.visible = true;
- this.screenshotsTaken = {};
- if (player.gmap != NULL) {
- /* This boolean signals to the script that the
- player should be warped serverside so that we
- ensure the tiles and npcs load properly. Without
- this there will be black patches on the final render
- that occur whenever the player warps from, say, x: 700
- back to 0.
- */
- temp.isLargeGmap = temp.sc.screenshots[0] >= 10;
- }
- for (temp.y = 0; temp.y < temp.sc.level_height; temp.y += 32) {
- for (temp.x = 0; temp.x < temp.sc.level_width; temp.x += 32) {
- /* If the client's screen were 1024x1024 pixels
- we could take one screenshot of the entire level
- and call it a day. However, this is not the case
- for most displays, so instead we go in increments
- of 32 tiles instead of 64 taking screenshots of
- 512x512, effectively half the level
- NOTE
- Using makeScreenshot2() for a resolution greater
- than the client's screen WILL crash the client.
- That is also another reason why we do 1 entire
- screenshot per level
- */
- onScreenshotLevel(temp.x, temp.y, {temp.sc.pixel_width, temp.sc.pixel_height}, temp.sc.screenshots, temp.isLargeGmap);
- // Wait for a signal to keep taking the other screenshots
- waitfor(this, "ContinueScreenshot", 10);
- }
- }
- /* The screenshots NEED to be saved on the
- * scriptfiles folder in order to be read
- * later on to extract the base64. Storing
- * the screenshot on the root graal
- * directory will make the file unreadable
- * by script.
- */
- temp.sc.fileName = extractFilebase(player.gmap == NULL ? player.level.name : player.gmap);
- temp.sc.fileName = "scriptfiles/" @ temp.sc.fileName @ ".png";
- // Save the final render
- this.canvas.saveimage(temp.sc.fileName);
- this.canvas.destroy();
- if (temp.returnB64) {
- // Load the raw image data string and extract the base64
- temp.data.loadstring(temp.sc.fileName);
- temp.b64 = base64encode(temp.data);
- this.screenshots.add(temp.sc.fileName);
- }
- // Let's delete the screenshots we generated earlier
- for (temp.screenshot : this.screenshotsTaken) {
- deletefile(temp.screenshot);
- }
- // Uncomment this for fun stats
- //echo(temp.sc.savejsontostring(1));
- this.screenshots = NULL;
- // Reset the player back to their original position
- player.x = temp.coords[0];
- player.y = temp.coords[1];
- return temp.b64 == NULL ? temp.sc.fileName : temp.b64;
- }
- function onScreenshotLevel(temp.x, temp.y, temp.finalDimensions, temp.screenshots, temp.gmapWarping) {
- if (temp.gmapWarping) {
- triggerServer("weapon", this.name, "warpMe", {player.gmap, temp.x, temp.y});
- waitfor(this, "onActionClientsideDone", 10);
- } else {
- // Make sure all of the NPCs are loaded in the sector being screenshotted by warping the player there.
- player.x = temp.x;
- player.y = temp.y;
- /* Give time for things to load around the player, removing this sleep
- * might cause the level not to load properly and chunks of it
- * might be missing on the final screenshot. It can also cause
- * the client to crash
- */
- waitfor(this, "Nothing", 0.1);
- }
- temp.resolution = {512, 512};
- temp.scale = {temp.finalDimensions[0] / (temp.resolution[0] * temp.screenshots[0]), temp.finalDimensions[1] / (temp.resolution[1] * temp.screenshots[1])};
- // Coordinates for this screenshot on the overall image
- temp.ss.x = (temp.x * 16) * temp.scale[0];
- temp.ss.y = (temp.y * 16) * temp.scale[1];
- temp.ss.width = temp.resolution[0] * temp.scale[0];
- temp.ss.height = temp.resolution[1] * temp.scale[1];
- // Create a unique temporal name for this screenshot.
- temp.fileName = format("temp_generate_%s_%s.png", temp.x, temp.y);
- // Take the screenshot of the level
- makeScreenshot2(temp.fileName, 0x4, temp.x, temp.y, 0, temp.resolution[0], temp.resolution[1]);
- // Add the screenshot we just took to the overall image being created
- this.canvas.drawimagestretched(
- // Insert the stretched-down image to a specific part of the overall image.
- temp.ss.x, // X coordinate this image is being inserted into the final image
- temp.ss.y, // Y coordinate this image is being inserted into the final image
- temp.ss.width, // Width of this image in the overall image
- temp.ss.height, // Height of this image in the overall image
- // Select which part of this screenshot we just took we want to add to the overall image (we want to add the whole screenshot)
- temp.fileName, 0, 0, temp.resolution[0], temp.resolution[1]
- );
- // Add the name of this screenshot to an array to be deleted later on.
- this.screenshotsTaken.add(temp.fileName);
- // Trigger the loop to keep going.
- this.trigger("ContinueScreenshot");
- }
- function constrain(temp.min, temp.max, temp.number) {
- return max(temp.min, min(temp.max, temp.number));
- }
Add Comment
Please, Sign In to add comment