Guide:Cosmetics Screenshots

TODO
 * ezmo looks bad

This guide explains how to take pretty screenshots of Battlerite champion cosmetics. Last updated to work with v0.10.2

Editing Battlerite
To take pretty screenshots some modifications to Battlerite are needed. The idea is to hide all objects that are in the way of the champion model in the ingame menu. To edit Battlerite's source code use dnSpy. The file to edit is. To find the relevant methods click the magnifying glass in the menu bar (or use Ctrl+Shift+K) and search for the method name.

Unlocking All Cosmetics
When taking screenshots the champion details display can be in the way. The problem is that when closing the champion details display the equipped cosmetics are reset. If the account you're using doesn't own the selected cosmetic item it will reset to whatever cosmetics are actually equipped. To get around this modify the method that checks if a cosmetic item is owned to always return true: // Inventory // Token: 0x060020A4 RID: 8356 public int GetStackableValue(int stackableId) {	if (this._StackableState.ContainsKey(stackableId)) {		return this._StackableState[stackableId]; }	return 1; } Note: This does not enable using non owned cosmetics in online play.

Pausing champion animations
// ModelViewData // Token: 0x06000D0E RID: 3342 public static ModelViewData DefaultCharacter(Vector3 position, Vector3 aimDirection, AssetGUID attachment) {	return new ModelViewData {		Position = position, MousePosition = position + aimDirection * 10f, RotationSpeed = 1000f, AnimatorSpeed = 1E-32f, Attachment = attachment }; }

Hiding the Mount
Mounts don't usually show up on the final cropped screenshots but with some champions like Rook it would. To get around this hide mounts completely with: // BloodgateSceneManager // Token: 0x06001CDE RID: 7390 public void SetMount(BackdropNodeId position, AssetGUID guid, string backdropGuid, bool canRotate = false, bool interactable = true, bool rotateBack = false, bool usePortraitSettings = false) {	if (!canRotate) {		this.SetModel(position, backdropGuid, guid, AssetGUID.Empty, AssetGUID.Empty, AssetGUID.Empty, canRotate, false, interactable, rotateBack, usePortraitSettings); } } Note: Deleting the whole method body would work the same.

Hiding UI Elements
A lot of UI elements like the play button and the Info and Customize buttons are in the way. To hide them use: // UI_CharacterSelect // Token: 0x060017A2 RID: 6050 private void ToggleInfoClicked {	this._ReadyButton.gameObject.SetActive(false); this._ShowEquipButton.SetDefaultImageColor(new Color(0f, 0f, 0f, 0f)); this._ShowEquipButton.SetText(""); this._ShowInfoButton.SetDefaultImageColor(new Color(0f, 0f, 0f, 0f)); this._ShowInfoButton.SetText(""); UIHelper.SetActive(this._LocalCharacterArrow.gameObject, false); this._EquipArrow.color = new Color(0f, 0f, 0f, 0f); this.ChampionDetails.Hide; } Note: To actually hide stuff click on the Info button.

Hiding the Ready Button Holder
The one thing that is still left on the screen is the sprite that's right under the play button. That thing is super annoying. I haven't figured out how to hide it programatically yet so to hide it edit the game assets:
 * 1) Get UABE
 * 2) Open
 * 3) Find
 * 4) Export Raw
 * 5) Open the exported file with a hex editor
 * 6) Change both occurrences of float:345 and float:48 to 0 (use the search function in your editor) and save (v0.10.2)
 * 7) Back in UABE "Import Raw" with the previously exported file
 * 8) Close UABE and confirm the save dialog (change the name and then rename to   after closing UABE)

Enabling Screenshot Functionality
Taking a screenshot will happen automatically after a set amount of time after selecting a cosmetic. The waiting is there so the cosmetic has time to load and also to settle (this is needed for Oldur's weapon for example). The amount of time that will be waited is champion specific. It is saved in. Create this file and paste: Igniter Ashka 1000 660 590 735 Seeker Jumong 1000 540 860 790 Inquisitor Pearl 2000 670 580 680 Gunner Jade 1300 635 645 790 Nomad Taya 1000 650 610 810 Astronomer Sirius 1000 540 870 800 Inhibitor Varesh 1000 580 765 960 Alchemist Lucie 1000 660 605 750 Harbinger Ruh_Kaan 5000 430 1100 875 Spearmaster Shifu 1000 485 900 760 Engineer Iva 1000 630 655 780 Psychopomp Poloma 1000 525 860 855 Ranid Croak 1000 545 865 755 Glutton Rook 1000 300 1285 960 Stormcaller Ezmo 1000 610 700 700 Vanguard Bakko 1000 500 925 960 Ravener Freya 1500 610 700 800 BloodPriest Pestilus 1000 450 975 960 Herald Oldur 7000 575 775 875 Values are spereated by a single space and the format is:
 * 1) Internal name (BLC name)
 * 2) Battlerite name
 * 3) Time to wait before taking the screenshot in millisecods
 * 4) Left padding of the cropped version in pixels
 * 5) Width of the cropped version in pixels
 * 6) Height of the cropped version in pixels

Add this at the end of   : System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(delegate {

ShopItem shopItem = this._Bg.Shop.GetShopItem(id); string text = ""; string champion = ""; int wait = 0;

string path = Application.dataPath; path += "/../";

string[] array = System.IO.File.ReadAllLines(path + "\\champs.txt"); for (int i = 0; i < array.Length; i++) {				string s = array[i]; if (s.StartsWith(this._GetFocusedCharacterFunc.Name)) {

champion = s.Split(new char[]					{						' '					})[1].Replace("_", ""); wait = Convert.ToInt32(s.Split(new char[] {						' '					})[2]);				}			}

this._ChampionDetails.gameObject.transform.position = new Vector3(-5f, -5f);

string a = shopItem.ItemType.ToString; if (!(a == "Attachment")) {				if (!(a == "Emote")) {					if (a == "Outfit") {						text = "Outfit"; }				}				else {					text = "Pose"; }			}			else {				text = "Weapon"; }			string name = System.Globalization.CultureInfo.InvariantCulture.TextInfo.ToTitleCase(shopItem.Name.ToString).Replace(" ", "").Replace("'", "").Replace("-", ""); if(name.StartsWith("Default")) {					text = "Outfit"; name = "Default"; }			System.Threading.Thread.Sleep(wait); Application.CaptureScreenshot(string.Concat(new object[] {				path, "\\Screenshots\\", text, " ",				champion, " ",				name, ".png" }));			System.Threading.Thread.Sleep(50); this._ChampionDetails.gameObject.transform.position = new Vector3(20f, 850f); }));

Taking Screenshots
After doing all of this now is the time to actually take some screenshots:
 * 1) Open Battlerite
 * 2) Go to the Playground tab
 * 3) Click the Info button
 * 4) Mouse over the location of the Customize button, the button shows itself when hovering it
 * 5) Equip all default items
 * 6) Select all cosmetics once so they are loaded
 * 7) Go through every cosmetic making sure to wait for the champion specific time (take care with Oldur, it's 2 seconds for him)

Cropping
Install ImageMagick and put it in your path. Create  with this content: $width = 1920 $height = 1080

$savePath = "Screenshots\Cropped"

$testpath = test-path $savePath

if(!$testpath){ new-item $savePath -itemtype directory }

Get-ChildItem "Screenshots" -Filter *.png | Foreach-Object { $screenshot = $_.BaseName $screenshot

$champion = $_.BaseName.Split(" ")[1]

$config = Select-String champs.txt -pattern $champion | Select-Object Line $config = $config.Line.Split(" ")

$screenshotWidth = $config[4] $screenshotHeight = $config[5]

$screenshotLeft  = $config[3] $screeshotTop    = $height - $screenshotHeight

$testpath = test-path ($savePath + "\" + $champion)

if(!$testpath){ new-item ($savePath + "\" + $champion) -itemtype directory }   Invoke-Expression -command ('magick convert "Screenshots/' + $screenshot + '.png" -crop ' +         $screenshotWidth + 'x' + $screenshotHeight +         '+' + $screenshotLeft + '+' + $screeshotTop +         ' "Screenshots/Cropped/' + $champion + '/' + $screenshot + '.png"') } Note: You might need to change the $width and $height variables at the top.

To crop all the images in the Screenshots folder run  (How to enable execution of PowerShell scripts). The cropped images will be in.