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 `steamapps\common\Battlerite\Battlerite_Data\Managed\MergedUnity.dll`. 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 `steamapps\common\Battlerite\Battlerite_Data\resources.assets`
3. Find `CharacterSelection_BottomButtonHolder_Short`
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 `resources.assets` 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 `steamapps\common\Battlerite\champs.txt`. 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 `UI_ChampionDetailsBindings` `public void SetSelectedItem(GameObjectTypeId id)`:

```
		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 `steamapps\common\Battlerite\screenshot magick.ps1` with this content:

```
$width  = 1920
$height = 1080

$savePath = "Screenshots\Cropped"

$testpath = test-path $savePath

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

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 `screenshot magick.ps1` (How to enable execution of PowerShell scripts). The cropped images will be in `steamapps\common\Battlerite\Screenshots\Cropped`.