From Brotato Wiki
(INITIAL \o/) |
DarkTwinge (talk | contribs) m (→Item Costs: Mammoth / Baby with a Beard) |
||
(40 intermediate revisions by one other user not shown) | |||
Line 9: | Line 9: | ||
==Apps== | ==Apps== | ||
=== Decompile === | |||
To decompile Brotato for modding, use GDRETools, which can be downloaded [https://github.com/bruvzg/gdsdecomp here]. | To decompile Brotato for modding, use GDRETools, which can be downloaded [https://github.com/bruvzg/gdsdecomp here]. | ||
You'll need to download [https://godotengine.org/en Godot] to edit the decompiled project. Jonus has an excellent video [https://www.youtube.com/watch?v=hsMA6h7Rd4I here] that covers the basics of modding, and will show you how to customise weapons and characters, and change item appearances. | === Godot === | ||
You'll need to download [https://godotengine.org/en Godot] to edit the decompiled project. Jonus has an excellent video [https://www.youtube.com/watch?v=hsMA6h7Rd4I here] that covers the basics of modding, and will show you how to customise weapons and characters, and change item appearances. You can also read the documentation for Godot [https://docs.godotengine.org/en/stable/index.html here]. | |||
=== Steam Errors === | |||
The standard version of Godot will have lots of errors related to the Steam API when you try to run it via Godot, due to it lacking inbuilt support for Steam's SDK. Instead, you can use an alternate version of Godot that has been compiled to include Steam support, called [https://github.com/Gramps/GodotSteam GodotSteam]. Get the version you need for Brotato [https://github.com/Gramps/GodotSteam/releases/tag/g35-s155-gs3174 here] (Godot v3.5). | |||
Make sure you read GodotSteam's [https://gramps.github.io/GodotSteam/tutorials-exporting-shipping.html docs on exporting], because there are some limitations and caveats (eg. you can't use the "''Export with Debug''" option, and you need to set up your export templates manually). | |||
== Balancing == | |||
When balancing new items, referring to the vanilla [[Items]] can be very helpful. | |||
We also have a special [[Items/Items Grid|Items Grid]] page that shows all items in a grid, with buttons to filter by stat. This can help you identify gaps in vanilla's item pool that your mod might be able to fill, or see how much vanilla's stat increases differ by tier. | |||
=== Characters with Positive Stats === | |||
Some characters start with very high base stats, which have the potential to instantly make your modded items OP: | |||
{| class="wikitable sortable mw-collapsible mw-collapsed" | |||
!Character | |||
!Stat | |||
!Value | |||
|- | |||
|Ranger | |||
|Range | |||
| 50 | |||
|- | |||
|Sick | |||
|Life Steal | |||
| 25 | |||
|- | |||
|Speedy | |||
|Speed | |||
|30 | |||
|- | |||
|Ghost | |||
|Dodge | |||
|30 | |||
|- | |||
|Hunter | |||
|Range | |||
|100 | |||
|- | |||
|One Armed | |||
|Attack Speed | |||
|200 | |||
|} | |||
=== Characters with Negative Stats === | |||
If you're creating an effect that converts one negative stat to a different positive one, keep in mind that many [[Characters]] start with huge decreases to certain stats. | |||
The vanilla items that use this effect are: {{MiniIconbox|name=Esty's Couch}} (-''Speed''), and {{MiniIconbox|name=Retromation's Hoodie}} ''(-Dodge)''. | |||
{| class="wikitable sortable mw-collapsible mw-collapsed" | |||
!Character | |||
!Stats | |||
!Value | |||
!Notes | |||
|- | |||
| rowspan="2" |[[Brawler]] | |||
|Range | |||
| -50 | |||
| | |||
|- | |||
|Ranged Damage | |||
| -50 | |||
| | |||
|- | |||
|[[Crazy]] | |||
|Dodge | |||
| -30% | |||
| | |||
|- | |||
| rowspan="3" |[[Mage]] | |||
|Ranged Damage | |||
| -100 | |||
|''No longer the case since v0.8.0.0'' | |||
|- | |||
|Melee Damage | |||
| -100 | |||
|''No longer the case since v0.8.0.0'' | |||
|- | |||
|Engineering | |||
| -50 | |||
|''No longer the case since v0.8.0.0'' | |||
|- | |||
|[[Chunky]] | |||
|Life Steal | |||
| -100 | |||
| | |||
|- | |||
|[[Lucky]] | |||
|Attack Speed | |||
| -60% | |||
| | |||
|- | |||
|[[Mutant]] | |||
|Items Price | |||
| -50% | |||
| | |||
|- | |||
|[[Loud]] | |||
|Harvesting | |||
| -95% ''(-3 per wave)'' | |||
| | |||
|- | |||
| rowspan="2" |[[Pacifist]] | |||
|Damage | |||
| -100% | |||
| | |||
|- | |||
|Engineering | |||
| -100 | |||
| | |||
|- | |||
|[[Saver]] | |||
|Items Price | |||
| -50% | |||
| | |||
|- | |||
|[[Sick]] | |||
|HP Regeneration | |||
| -100 | |||
| | |||
|- | |||
|[[Ghost]] | |||
|Armor | |||
| -100 | |||
| | |||
|- | |||
|[[Speedy]] | |||
|Armor while standing still | |||
| -100 | |||
| | |||
|- | |||
|[[Doctor]] | |||
|Attack Speed | |||
| -100% | |||
| | |||
|- | |||
|[[Artificer]] | |||
|Damage | |||
| -100% | |||
| | |||
|- | |||
|[[Masochist]] | |||
|Damage | |||
| -100% | |||
| | |||
|} | |||
=== Item Costs === | |||
[[Items|Item]] costs for each tier in vanilla are as follows: | |||
{| class="wikitable" | |||
!Tier | |||
!Min | |||
!Max | |||
|- | |||
!{{Color|color=tier1|text=Tier 1}} | |||
|8 | |||
|30 | |||
|- | |||
!{{Color|color=tier2|text=Tier 2}} | |||
|35 | |||
|65 | |||
|- | |||
!{{Color|color=tier3|text=Tier 3}} | |||
|50 | |||
|100 | |||
|- | |||
!{{Color|color=tier4|text=Tier 4}} | |||
|80 | |||
|130 | |||
|} | |||
=== Weapon Costs === | |||
Weapon costs for each tier in vanilla. There are 3 different "Max" columns, because weapons that only start from tiers 2/3 have considerably higher max prices than weapons that start from tier 1. | |||
{| class="wikitable" | |||
!Tier | |||
!Min | |||
!Max | |||
!Max T2 | |||
!Max T3 | |||
|- | |||
!{{Color|color=tier1|text=Tier 1}} | |||
|10 | |||
|20 | |||
| | |||
| - | |||
|- | |||
!{{Color|color=tier2|text=Tier 2}} | |||
|22 | |||
|39 | |||
|56 | |||
| - | |||
|- | |||
!{{Color|color=tier3|text=Tier 3}} | |||
|45 | |||
|74 | |||
|103 | |||
|144 | |||
|- | |||
!{{Color|color=tier4|text=Tier 4}} | |||
|91 | |||
|149 | |||
|207 | |||
|289 | |||
|} | |||
=== Community Guide === | |||
Here's a guide written by a community member about balancing: [[Community/Modding Balance Guide|Modding Balance Guide]]. | |||
== DebugService == | |||
You can use DebugService to edit your items, weapons, starting materials, and much more. | |||
To access these options: | |||
* In the FileSystem tab, find {{Color|color=cream|text=singletons/debug_service.tscn}} and double-click it. | |||
* In the Scene tab, double-click {{Color|color=cream|text=DebugService}}. | |||
* The debug options will be shown in the Inspector tab. | |||
{| class="wikitable" | |||
!Option | |||
!Type | |||
!Default | |||
!Effect | |||
|- | |||
|Starting Wave | |||
|int | |||
|<code>1</code> | |||
|Sets initial wave. Supports <code>1</code> - <code>999</code> | |||
|- | |||
|Starting Gold | |||
|int | |||
|<code>30</code> | |||
|Sets initial materials. | |||
|- | |||
|Invulnerable | |||
|bool | |||
|<code>false</code> | |||
|Disables your hurtbox. Prevents things like [[Bull]]'s effect from triggering. | |||
|- | |||
|Invisible | |||
|bool | |||
|<code>false</code> | |||
|Player is invisible. | |||
|- | |||
|One Shot Enemies | |||
|bool | |||
|<code>false</code> | |||
|All enemies die in 1 hit. | |||
|- | |||
|Instant Waves | |||
|bool | |||
|<code>false</code> | |||
|Waves only last 1 second. Great for testing shops | |||
|- | |||
|No Fullscreen on Launch | |||
|bool | |||
|<code>false</code> | |||
|Prevents the game from launching into fullscreen. | |||
|- | |||
|Debug Weapons | |||
|array | |||
|<code>[]</code> | |||
|Weapons to add at the start of each wave. Can add multiple of the same weapon | |||
|- | |||
|Debug Items | |||
|array | |||
|<code>[]</code> | |||
|Items to add once, at the start of the next wave. Can add multiple of the same item | |||
|- | |||
|Remove Starting Weapons | |||
|bool | |||
|<code>false</code> | |||
|Removes your starting weapons. | |||
|- | |||
|Add All Weapons | |||
|bool | |||
|<code>false</code> | |||
|Adds every weapon. Can go over your character's weapon limit | |||
|- | |||
|Add All Items | |||
|bool | |||
|<code>false</code> | |||
|Adds every item to your character. Can be combined with debug_items to stack them | |||
|- | |||
|Unlock All Chars | |||
|bool | |||
|<code>false</code> | |||
|Unlocks all characters. Temporary | |||
|- | |||
|Unlock All Challenges | |||
|bool | |||
|<code>false</code> | |||
|{{Color|color=pastelred|text='''Permanent.'''}} Unlocks all challenges: | |||
* Completes every challenge | |||
* Unlocks their Steam achievements | |||
* Saves this data to your save file | |||
Make sure you enable the "Disable Saving" option before using this, otherwise it will affect your save file. | |||
|- | |||
|Unlock All Difficulties | |||
|bool | |||
|<code>false</code> | |||
|Unlocks all danger levels. Temporary | |||
|- | |||
|Generate Full Unlocked Save File | |||
|bool | |||
|<code>false</code> | |||
| | |||
|- | |||
|Reinitialize Save | |||
|bool | |||
|<code>false</code> | |||
| | |||
|- | |||
|Reinitialize Steam Data | |||
|bool | |||
|<code>false</code> | |||
| | |||
|- | |||
|Disabling Saving | |||
|bool | |||
|<code>false</code> | |||
|'''{{Color|color=pastelgreen|text=Highly recommended.}}''' | |||
Prevents the game from ever saving, which protects your save file. | |||
Always use if you also enable "''Unlock All Challenges''". | |||
|- | |||
|Randomize Equipment | |||
|bool | |||
|<code>false</code> | |||
| | |||
* Start with 6 of a random weapon. | |||
* Start with 10 - 500 materials. | |||
* Start at level 10 - 26. | |||
|- | |||
|Hide Wave Timer | |||
|bool | |||
|<code>false</code> | |||
| | |||
|- | |||
|Nullify Enemy Speed | |||
|bool | |||
|<code>false</code> | |||
| | |||
|- | |||
|No Enemies | |||
|bool | |||
|<code>false</code> | |||
| | |||
|- | |||
|Debug Enemies | |||
|bool | |||
|<code>false</code> | |||
| | |||
|- | |||
|Spawn Specific Elite | |||
|bool | |||
|<code>false</code> | |||
|Forces a specific [[Enemies#Elites (Danger 2+)|Elite]] to spawn during an Elite wave. Does nothing on regular waves. Details below. | |||
|} | |||
=== Spawn Specific Elite === | |||
To spawn a specific [[Enemies#Elites (Danger 2+)|Elite]], enter an elite string for <code>spawn_specific_elite</code>, as one of the following: | |||
*<code>elite_butcher</code> | |||
*<code>elite_colossus</code> | |||
*<code>elite_croco</code> | |||
*<code>elite_demon</code> | |||
*<code>elite_insect</code> | |||
*<code>elite_mom</code> | |||
* <code>elite_monk</code> | |||
*<code>elite_rhino</code> | |||
These names come from the resource (''.tres'') files in {{Color|color=cream|text=res://entities/units/enemies/elites/}} | |||
You need to start a new run after setting this variable, as elites/hordes etc. are determined at the start of a run. | |||
Note that this does not force an Elite to spawn on any wave. It only changes the Elite that will spawn on an [[Elite and Horde Waves|Elite wave.]] | |||
==Effects== | ==Effects== | ||
See [[Modding Effects]] for a list of all the effects available in vanilla. | See [[Modding Effects]] for a list of all the effects available in vanilla. | ||
==Text - BBCode== | |||
You can use some BBCode in your item descriptions. View the available options in the [https://docs.godotengine.org/en/stable/tutorials/ui/bbcode_in_richtextlabel.html Godot docs]. | |||
=== Related Files=== | |||
These files are related to text, and mostly apply colors: | |||
*{{Color|color=cream|text=singletons/text.gd}} | |||
*{{Color|color=cream|text=weapons/weapon_stats/weapon_stats.gd}} | |||
**In this file, <code><small>col_pos_a</small></code> means "color positive, part A", with part B being the closing <code><small>[/color]</small></code> | |||
*{{Color|color=cream|text=singletons/utils.gd}} | |||
**This file also sets the icon size (see ''Image Icons'' below) | |||
*{{Color|color=cream|text=ui/menus/shop/item_description.gd}} | |||
**Sets weapon and item descriptions. It's a good place to start if you're looking for the code that handles them. | |||
*{{Color|color=cream|text=items/global/effect.gd}} | |||
**Has the function <code><small>get_text</small></code>, which modifies stats used by effects | |||
===Color Options=== | |||
''For programming (ie. not BBCode), see also: [https://docs.godotengine.org/en/stable/classes/class_color.html Color class]; color constants [https://raw.githubusercontent.com/godotengine/godot-docs/master/img/color_constants.png cheatsheet].'' | |||
{| class="wikitable" | |||
!Code | |||
!Color | |||
!Example | |||
!Notes | |||
!Via | |||
|- | |||
|<code>[color=#00ff00]TEXT[/color]</code> | |||
|Green | |||
|{{Color|color=green|text=TEXT}} | |||
| | |||
|<code><small>Utils.POS_COLOR_STR</small></code> | |||
|- | |||
|<code>[color=red]TEXT[/color]</code> | |||
|Red | |||
|{{Color|color=red|text=TEXT}} | |||
| | |||
|<code><small>Utils.NEG_COLOR_STR</small></code> | |||
|- | |||
|<code>[color=white]TEXT[/color]</code> | |||
|White | |||
|<span color="white">TEXT</span> | |||
| | |||
|<code><small>Color.white</small></code> | |||
|- | |||
|<code>[color=#555555]TEXT[/color]</code> | |||
|Grey | |||
|<span style="color: #555555">TEXT</span> | |||
| | |||
|<code><small>Utils.GRAY_COLOR_STR</small></code> | |||
|- | |||
| <code>[color=#76FF76]TEXT[/color]</code> | |||
|Materials | |||
|<span style="color: #76FF76">TEXT</span> | |||
|Actually <code>rgb(118,255,118)</code> | |||
|<code><small>Utils.GOLD_COLOR</small></code> | |||
|- | |||
|<code>[color=#EAE2B0]TEXT[/color]</code> | |||
|Secondary | |||
|{{Color|color=cream|text=TEXT}} | |||
|Actually <code>rgb(234,226,176)</code> | |||
|<code><small>Utils.SECONDARY_FONT_COLOR</small></code> | |||
|- | |||
|<code>[color=#C8C8C8]TEXT[/color]</code> | |||
|Tier 1 | |||
|{{Color|tier1|TEXT}} | |||
| | |||
|<small>NA</small> <ref group="c">''Tier 1 uses <code><small>Color.white</small></code> in-game. This grey color is only used on the wiki, to differentiate this tier''</ref> | |||
|- | |||
|<code>[color=#4A9BD1]TEXT[/color]</code> | |||
|Tier 2 | |||
|{{Color|tier2|TEXT}} | |||
|Actually <code>rgb(74,155,209)</code> | |||
|<code><small>ItemService.TIER_UNCOMMON_COLOR</small></code> | |||
|- | |||
|<code>[color=#AD5AFF]TEXT[/color]</code> | |||
|Tier 3 | |||
|{{Color|tier3|TEXT}} | |||
|Actually <code>rgb(173,90,255)</code> | |||
|<code><small>ItemService.TIER_RARE_COLOR</small></code> | |||
|- | |||
|<code>[color=#FF3B3B]TEXT[/color]</code> | |||
|Tier 4 | |||
|{{Color|tier4|TEXT}} | |||
|Actually <code>rgb(255,59,59)</code> | |||
|<code><small>ItemService.TIER_LEGENDARY_COLOR</small></code> | |||
|} | |||
<references group="c" /> | |||
===Image Icons=== | |||
You can add an image with the code <code><small>[img=20x20]res://path_to_image/file.png[/img]</small></code>. | |||
* The size 20x20 applies to the default font size (100%). | |||
** At the minimum font size of 80%, the image size is 16x16. | |||
** At the maximum of 125%, the image size is 25x25. | |||
* If you want to show scaled stat icons, you can use <code><small>Utils.get_scaling_stat_text(stat_name)</small></code> ''(see {{Color|color=cream|text=singletons/utils.gd}}).'' | |||
** The code in this func also shows how to get a scaled size for a custom image (<code><small>var w = 20 * ProgressData.settings.font_size</small></code>) | |||
Here's the code for showing stat icons, when the Font Size option is set to its default 100%: | |||
{| class="wikitable mw-collapsible mw-collapsed" | |||
|+BBCode for stat icons | |||
! colspan="1" rowspan="1" |BBCode | |||
! colspan="1" rowspan="1" |Icon | |||
! colspan="1" rowspan="1" |Stat Name | |||
|- | |||
|<code>[img=20x20]res://items/stats/max_hp.png[/img]</code> | |||
|{{StatIcon|Max HP}} | |||
|[[Max HP]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/hp_regeneration.png[/img]</code> | |||
|{{StatIcon|Hp Regeneration}} | |||
|[[HP Regeneration]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/lifesteal.png[/img]</code> | |||
|{{StatIcon|Lifesteal}} | |||
|[[Life Steal]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/percent_damage.png[/img]</code> | |||
|{{StatIcon|Damage}} | |||
|[[Damage]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/melee_damage.png[/img]</code> | |||
|{{StatIcon|Melee Damage}} | |||
|[[Melee Damage]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/ranged_damage.png[/img]</code> | |||
|{{StatIcon|Ranged Damage}} | |||
|[[Ranged Damage]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/elemental_damage.png[/img]</code> | |||
|{{StatIcon|Elemental Damage}} | |||
|[[Elemental Damage]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/attack_speed.png[/img]</code> | |||
|{{StatIcon|Attack Speed}} | |||
|[[Attack Speed]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/crit_chance.png[/img]</code> | |||
|{{StatIcon|Crit Chance}} | |||
|[[Crit Chance]] | |||
|- | |||
| <code>[img=20x20]res://items/stats/engineering.png[/img]</code> | |||
|{{StatIcon|Engineering}} | |||
|[[Engineering]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/range.png[/img]</code> | |||
|{{StatIcon|Range}} | |||
|[[Range]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/armor.png[/img]</code> | |||
|{{StatIcon|Armor}} | |||
|[[Armor]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/dodge.png[/img]</code> | |||
|{{StatIcon|Dodge}} | |||
|[[Dodge]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/speed.png[/img]</code> | |||
|{{StatIcon|Speed}} | |||
|[[Speed]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/luck.png[/img]</code> | |||
|{{StatIcon|Luck}} | |||
|[[Luck]] | |||
|- | |||
|<code>[img=20x20]res://items/stats/harvesting.png[/img]</code> | |||
| {{StatIcon|Harvesting}} | |||
|[[Harvesting]] | |||
|} | |||
===Misc=== | |||
For line breaks, use <code><small>"\n"</small></code>. | |||
To hide an item description, set the effect key to <code><small>[EMPTY]</small></code>. | |||
===Limitations=== | |||
Bold (<code><small>[b]</small></code>) and italics (<code><small>[i]</small></code>) don't work, because the vanilla game doesn't have support for them. | |||
== Text - Stats == | |||
=== Dynamic Stats === | |||
Item descriptions in the shop are retrieved the first time it appears, so any dynamic stats will need to account for this. It might mean that the stats your item shows are different once the item is bought. | |||
They're also retrieved every time you hover over an item (via <code><small>get_args</small></code>), which gives you more freedom to use dynamic stats than the shop descriptions. | |||
=== get_args === | |||
Use <code><small>get_args</small></code> to pass variables to your item descriptions. They replace {0}, {1}, etc, with each item in the array that <code><small>get_args</small></code> returns acting as a replacement for the matching <code><small>{index}</small></code> string in your translation. | |||
The default effect ({{Color|color=cream|text=effect.gd}}) only passes 1 arg, value (0), which is converted from an int to string with <code><small>str(value)</small></code>. | |||
Most custom effects (eg. {{Color|color=cream|text=stat_effect.gd}}) pass 2 args: <code><small>value</small></code> (0) and <code><small>key</small></code> (1), with <code><small>key</small></code> being translated using <code><small>tr(key.to_upper())</small></code>. | |||
You can use <code><small>key_text</small></code> to apply a custom effect description. | |||
As mentioned above, you can also hide an item's description by setting the <code><small>key_text</small></code> to <code><small>[EMPTY]</small></code>. | |||
==Translations== | ==Translations== | ||
=== Guide === | |||
To add translations: | |||
#Create your CSV translation file | |||
#Drag it into your project's file system | |||
Here's how your CSV should look: | |||
[[File:Guide-Translations 1.png]] | |||
Godot will automatically generate ''.translation'' files for each of the languages you've specified. | |||
You can view the vanilla translation file: | |||
* On Discord's ''#modding-dev'' channel: Check the pinned messages to find it. Join the Brotato server here: https://discord.com/invite/j39jE6k | |||
* On the BrotatoMods GitHub, here: https://github.com/BrotatoMods/Brotato-Translations | |||
=== Translation Notes === | |||
See Godot's tutorial [https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html Internationalizing games] for more info on using translations. You may also find the docs on [https://docs.godotengine.org/en/stable/classes/class_translationserver.html TranslationServer] helpful. | |||
You can use <code>tr()</code> to access translated strings. It's a native [https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-method-tr function]. | |||
To use commas, wrap your string in quotes, eg: <code><small>"Potatoes are good, potatoes are cool"</small></code> | |||
== Item Tags == | |||
The following item tags are used in vanilla: | |||
{| class="wikitable" | |||
!Stats | |||
!Misc | |||
|- | |||
|<code>stat_armor</code> | |||
|<code>economy</code> | |||
|- | |||
|<code>stat_attack_speed</code> | |||
|<code>exploration</code> | |||
|- | |||
|<code>stat_crit_chance</code> | |||
|<code>explosive</code> | |||
|- | |||
|<code>stat_dodge</code> | |||
|<code>less_enemies</code> | |||
|- | |||
|<code>stat_elemental_damage</code> | |||
|<code>less_enemy_speed</code> | |||
|- | |||
|<code>stat_engineering</code> | |||
|<code>more_enemies</code> | |||
|- | |||
|<code>stat_harvesting</code> | |||
|<code>pickup</code> | |||
|- | |||
|<code>stat_hp_regeneration</code> | |||
|<code>saving</code> | |||
|- | |||
|<code>stat_lifesteal</code> | |||
|<code>stand_still</code> | |||
|- | |||
|<code>stat_luck</code> | |||
|<code>xp_gain</code> | |||
|- | |||
|<code>stat_max_hp</code> | |||
| | |||
|- | |||
|<code>stat_melee_damage</code> | |||
| | |||
|- | |||
|<code>stat_percent_damage</code> | |||
| | |||
|- | |||
|<code>stat_range</code> | |||
| | |||
|- | |||
|<code>stat_ranged_damage</code> | |||
| | |||
|- | |||
|<code>stat_speed</code> | |||
| | |||
|} | |||
==Multi Mod== | |||
If you're building a mod, creating it to work with [https://github.com/BrotatoMods/Brotato-damis-Multiple-Mod-Support dami's Multi Mod] might be worth considering. It lets you add your mod pack to any compatible mod (eg. [[Mod:Invasion|Invasion]]/[[Mod:Dami's Arsenal|dami's Arsenal]]). It lets you create custom characters, weapons, and items, and release your mod as a small standalone file (usually <3mb). | |||
The only caveat is that you can't touch vanilla code, and can't currently add new weapon classes or challenges. | |||
==Weapon Cooldowns== | |||
Calculating the displayed cooldown text is tricky. The formula for Ranged weapons is easy to calculate, but the Melee formula is complex and takes many things into consideration. For this reason, Darkly77 made an cooldown text calculator, here: | |||
{{ExternalLinkButton|https://brotato.codemuffin.com|Cooldown Calculator}} | |||
== Weapon Notes == | |||
Weapon stats have an option called <code>increase_projectile_speed_with_range</code>. In vanilla, this is only used by {{MiniIconbox|name=Flamethrower}} and {{MiniIconbox|name=Incendiary Turret}}, as their flame projectiles don't interact with Range in the usual way. So this option just makes their projectiles go further, because they're moving faster. Search for this var in ''weapon_service.gd'' to see the formula. | |||
==GitHub== | ==GitHub== | ||
Line 33: | Line 685: | ||
There's a GitHub organisation for Brotato repos [https://github.com/BrotatoMods here]. It is maintained by Darkly77, KANA, and dami, who are all active on the [https://discord.gg/j39jE6k Space Potatoes Discord]. | There's a GitHub organisation for Brotato repos [https://github.com/BrotatoMods here]. It is maintained by Darkly77, KANA, and dami, who are all active on the [https://discord.gg/j39jE6k Space Potatoes Discord]. | ||
It's not recommended to host a full Brotato project on GitHub, because you'd be making all of Brotato's source code public. But you can host just your modded files (eg Darkly77's https://github.com/BrotatoMods/Brotato-Invasion-Mod Invasion]), or even just host the downloads for your mod (eg. KANA's [https://github.com/KANAjetzt/brotato_mod_releases mod releases]) | It's not recommended to host a full Brotato project on GitHub, because you'd be making all of Brotato's source code public. But you can host just your modded files (eg Darkly77's [https://github.com/BrotatoMods/Brotato-Invasion-Mod Invasion]), or even just host the downloads for your mod (eg. KANA's [https://github.com/KANAjetzt/brotato_mod_releases mod releases]) | ||
Hosting your downloads on | Hosting your downloads on GitHub has a few advantages: | ||
* You can create versioned README and CHANGELOG files to track your mod's changes. | *You can create versioned README and CHANGELOG files to track your mod's changes. | ||
* You can create separate releases, which track the release date. | *You can create separate releases, which track the release date. | ||
* You can view download stats with [https://tooomm.github.io/github-release-stats/ this tool]. | *You can view download stats with [https://tooomm.github.io/github-release-stats/ this tool]. | ||
{{NavBoxModding}} |
Latest revision as of 17:06, 6 July 2023
This page has notes that modders may find useful.
Apps
Decompile
To decompile Brotato for modding, use GDRETools, which can be downloaded here.
Godot
You'll need to download Godot to edit the decompiled project. Jonus has an excellent video here that covers the basics of modding, and will show you how to customise weapons and characters, and change item appearances. You can also read the documentation for Godot here.
Steam Errors
The standard version of Godot will have lots of errors related to the Steam API when you try to run it via Godot, due to it lacking inbuilt support for Steam's SDK. Instead, you can use an alternate version of Godot that has been compiled to include Steam support, called GodotSteam. Get the version you need for Brotato here (Godot v3.5).
Make sure you read GodotSteam's docs on exporting, because there are some limitations and caveats (eg. you can't use the "Export with Debug" option, and you need to set up your export templates manually).
Balancing
When balancing new items, referring to the vanilla Items can be very helpful.
We also have a special Items Grid page that shows all items in a grid, with buttons to filter by stat. This can help you identify gaps in vanilla's item pool that your mod might be able to fill, or see how much vanilla's stat increases differ by tier.
Characters with Positive Stats
Some characters start with very high base stats, which have the potential to instantly make your modded items OP:
Character | Stat | Value |
---|---|---|
Ranger | Range | 50 |
Sick | Life Steal | 25 |
Speedy | Speed | 30 |
Ghost | Dodge | 30 |
Hunter | Range | 100 |
One Armed | Attack Speed | 200 |
Characters with Negative Stats
If you're creating an effect that converts one negative stat to a different positive one, keep in mind that many Characters start with huge decreases to certain stats.
The vanilla items that use this effect are: Esty's Couch (-Speed), and Retromation's Hoodie (-Dodge).
Character | Stats | Value | Notes |
---|---|---|---|
Brawler | Range | -50 | |
Ranged Damage | -50 | ||
Crazy | Dodge | -30% | |
Mage | Ranged Damage | -100 | No longer the case since v0.8.0.0 |
Melee Damage | -100 | No longer the case since v0.8.0.0 | |
Engineering | -50 | No longer the case since v0.8.0.0 | |
Chunky | Life Steal | -100 | |
Lucky | Attack Speed | -60% | |
Mutant | Items Price | -50% | |
Loud | Harvesting | -95% (-3 per wave) | |
Pacifist | Damage | -100% | |
Engineering | -100 | ||
Saver | Items Price | -50% | |
Sick | HP Regeneration | -100 | |
Ghost | Armor | -100 | |
Speedy | Armor while standing still | -100 | |
Doctor | Attack Speed | -100% | |
Artificer | Damage | -100% | |
Masochist | Damage | -100% |
Item Costs
Item costs for each tier in vanilla are as follows:
Tier | Min | Max |
---|---|---|
Tier 1 | 8 | 30 |
Tier 2 | 35 | 65 |
Tier 3 | 50 | 100 |
Tier 4 | 80 | 130 |
Weapon Costs
Weapon costs for each tier in vanilla. There are 3 different "Max" columns, because weapons that only start from tiers 2/3 have considerably higher max prices than weapons that start from tier 1.
Tier | Min | Max | Max T2 | Max T3 |
---|---|---|---|---|
Tier 1 | 10 | 20 | - | |
Tier 2 | 22 | 39 | 56 | - |
Tier 3 | 45 | 74 | 103 | 144 |
Tier 4 | 91 | 149 | 207 | 289 |
Community Guide
Here's a guide written by a community member about balancing: Modding Balance Guide.
DebugService
You can use DebugService to edit your items, weapons, starting materials, and much more.
To access these options:
- In the FileSystem tab, find singletons/debug_service.tscn and double-click it.
- In the Scene tab, double-click DebugService.
- The debug options will be shown in the Inspector tab.
Option | Type | Default | Effect |
---|---|---|---|
Starting Wave | int | 1
|
Sets initial wave. Supports 1 - 999
|
Starting Gold | int | 30
|
Sets initial materials. |
Invulnerable | bool | false
|
Disables your hurtbox. Prevents things like Bull's effect from triggering. |
Invisible | bool | false
|
Player is invisible. |
One Shot Enemies | bool | false
|
All enemies die in 1 hit. |
Instant Waves | bool | false
|
Waves only last 1 second. Great for testing shops |
No Fullscreen on Launch | bool | false
|
Prevents the game from launching into fullscreen. |
Debug Weapons | array | []
|
Weapons to add at the start of each wave. Can add multiple of the same weapon |
Debug Items | array | []
|
Items to add once, at the start of the next wave. Can add multiple of the same item |
Remove Starting Weapons | bool | false
|
Removes your starting weapons. |
Add All Weapons | bool | false
|
Adds every weapon. Can go over your character's weapon limit |
Add All Items | bool | false
|
Adds every item to your character. Can be combined with debug_items to stack them |
Unlock All Chars | bool | false
|
Unlocks all characters. Temporary |
Unlock All Challenges | bool | false
|
Permanent. Unlocks all challenges:
Make sure you enable the "Disable Saving" option before using this, otherwise it will affect your save file. |
Unlock All Difficulties | bool | false
|
Unlocks all danger levels. Temporary |
Generate Full Unlocked Save File | bool | false
|
|
Reinitialize Save | bool | false
|
|
Reinitialize Steam Data | bool | false
|
|
Disabling Saving | bool | false
|
Highly recommended.
Prevents the game from ever saving, which protects your save file. Always use if you also enable "Unlock All Challenges". |
Randomize Equipment | bool | false
|
|
Hide Wave Timer | bool | false
|
|
Nullify Enemy Speed | bool | false
|
|
No Enemies | bool | false
|
|
Debug Enemies | bool | false
|
|
Spawn Specific Elite | bool | false
|
Forces a specific Elite to spawn during an Elite wave. Does nothing on regular waves. Details below. |
Spawn Specific Elite
To spawn a specific Elite, enter an elite string for spawn_specific_elite
, as one of the following:
elite_butcher
elite_colossus
elite_croco
elite_demon
elite_insect
elite_mom
elite_monk
elite_rhino
These names come from the resource (.tres) files in res://entities/units/enemies/elites/
You need to start a new run after setting this variable, as elites/hordes etc. are determined at the start of a run.
Note that this does not force an Elite to spawn on any wave. It only changes the Elite that will spawn on an Elite wave.
Effects
See Modding Effects for a list of all the effects available in vanilla.
Text - BBCode
You can use some BBCode in your item descriptions. View the available options in the Godot docs.
Related Files
These files are related to text, and mostly apply colors:
- singletons/text.gd
- weapons/weapon_stats/weapon_stats.gd
- In this file,
col_pos_a
means "color positive, part A", with part B being the closing[/color]
- In this file,
- singletons/utils.gd
- This file also sets the icon size (see Image Icons below)
- ui/menus/shop/item_description.gd
- Sets weapon and item descriptions. It's a good place to start if you're looking for the code that handles them.
- items/global/effect.gd
- Has the function
get_text
, which modifies stats used by effects
- Has the function
Color Options
For programming (ie. not BBCode), see also: Color class; color constants cheatsheet.
Code | Color | Example | Notes | Via |
---|---|---|---|---|
[color=#00ff00]TEXT[/color]
|
Green | TEXT | Utils.POS_COLOR_STR
| |
[color=red]TEXT[/color]
|
Red | TEXT | Utils.NEG_COLOR_STR
| |
[color=white]TEXT[/color]
|
White | TEXT | Color.white
| |
[color=#555555]TEXT[/color]
|
Grey | TEXT | Utils.GRAY_COLOR_STR
| |
[color=#76FF76]TEXT[/color]
|
Materials | TEXT | Actually rgb(118,255,118)
|
Utils.GOLD_COLOR
|
[color=#EAE2B0]TEXT[/color]
|
Secondary | TEXT | Actually rgb(234,226,176)
|
Utils.SECONDARY_FONT_COLOR
|
[color=#C8C8C8]TEXT[/color]
|
Tier 1 | TEXT | NA [c 1] | |
[color=#4A9BD1]TEXT[/color]
|
Tier 2 | TEXT | Actually rgb(74,155,209)
|
ItemService.TIER_UNCOMMON_COLOR
|
[color=#AD5AFF]TEXT[/color]
|
Tier 3 | TEXT | Actually rgb(173,90,255)
|
ItemService.TIER_RARE_COLOR
|
[color=#FF3B3B]TEXT[/color]
|
Tier 4 | TEXT | Actually rgb(255,59,59)
|
ItemService.TIER_LEGENDARY_COLOR
|
- ↑ Tier 1 uses
Color.white
in-game. This grey color is only used on the wiki, to differentiate this tier
Image Icons
You can add an image with the code [img=20x20]res://path_to_image/file.png[/img]
.
- The size 20x20 applies to the default font size (100%).
- At the minimum font size of 80%, the image size is 16x16.
- At the maximum of 125%, the image size is 25x25.
- If you want to show scaled stat icons, you can use
Utils.get_scaling_stat_text(stat_name)
(see singletons/utils.gd).- The code in this func also shows how to get a scaled size for a custom image (
var w = 20 * ProgressData.settings.font_size
)
- The code in this func also shows how to get a scaled size for a custom image (
Here's the code for showing stat icons, when the Font Size option is set to its default 100%:
BBCode | Icon | Stat Name |
---|---|---|
[img=20x20]res://items/stats/max_hp.png[/img]
|
Max HP | |
[img=20x20]res://items/stats/hp_regeneration.png[/img]
|
HP Regeneration | |
[img=20x20]res://items/stats/lifesteal.png[/img]
|
Life Steal | |
[img=20x20]res://items/stats/percent_damage.png[/img]
|
Damage | |
[img=20x20]res://items/stats/melee_damage.png[/img]
|
Melee Damage | |
[img=20x20]res://items/stats/ranged_damage.png[/img]
|
Ranged Damage | |
[img=20x20]res://items/stats/elemental_damage.png[/img]
|
Elemental Damage | |
[img=20x20]res://items/stats/attack_speed.png[/img]
|
Attack Speed | |
[img=20x20]res://items/stats/crit_chance.png[/img]
|
Crit Chance | |
[img=20x20]res://items/stats/engineering.png[/img]
|
Engineering | |
[img=20x20]res://items/stats/range.png[/img]
|
Range | |
[img=20x20]res://items/stats/armor.png[/img]
|
Armor | |
[img=20x20]res://items/stats/dodge.png[/img]
|
Dodge | |
[img=20x20]res://items/stats/speed.png[/img]
|
Speed | |
[img=20x20]res://items/stats/luck.png[/img]
|
Luck | |
[img=20x20]res://items/stats/harvesting.png[/img]
|
Harvesting |
Misc
For line breaks, use "\n"
.
To hide an item description, set the effect key to [EMPTY]
.
Limitations
Bold ([b]
) and italics ([i]
) don't work, because the vanilla game doesn't have support for them.
Text - Stats
Dynamic Stats
Item descriptions in the shop are retrieved the first time it appears, so any dynamic stats will need to account for this. It might mean that the stats your item shows are different once the item is bought.
They're also retrieved every time you hover over an item (via get_args
), which gives you more freedom to use dynamic stats than the shop descriptions.
get_args
Use get_args
to pass variables to your item descriptions. They replace {0}, {1}, etc, with each item in the array that get_args
returns acting as a replacement for the matching {index}
string in your translation.
The default effect (effect.gd) only passes 1 arg, value (0), which is converted from an int to string with str(value)
.
Most custom effects (eg. stat_effect.gd) pass 2 args: value
(0) and key
(1), with key
being translated using tr(key.to_upper())
.
You can use key_text
to apply a custom effect description.
As mentioned above, you can also hide an item's description by setting the key_text
to [EMPTY]
.
Translations
Guide
To add translations:
- Create your CSV translation file
- Drag it into your project's file system
Here's how your CSV should look:
Godot will automatically generate .translation files for each of the languages you've specified.
You can view the vanilla translation file:
- On Discord's #modding-dev channel: Check the pinned messages to find it. Join the Brotato server here: https://discord.com/invite/j39jE6k
- On the BrotatoMods GitHub, here: https://github.com/BrotatoMods/Brotato-Translations
Translation Notes
See Godot's tutorial Internationalizing games for more info on using translations. You may also find the docs on TranslationServer helpful.
You can use tr()
to access translated strings. It's a native function.
To use commas, wrap your string in quotes, eg: "Potatoes are good, potatoes are cool"
Item Tags
The following item tags are used in vanilla:
Stats | Misc |
---|---|
stat_armor
|
economy
|
stat_attack_speed
|
exploration
|
stat_crit_chance
|
explosive
|
stat_dodge
|
less_enemies
|
stat_elemental_damage
|
less_enemy_speed
|
stat_engineering
|
more_enemies
|
stat_harvesting
|
pickup
|
stat_hp_regeneration
|
saving
|
stat_lifesteal
|
stand_still
|
stat_luck
|
xp_gain
|
stat_max_hp
|
|
stat_melee_damage
|
|
stat_percent_damage
|
|
stat_range
|
|
stat_ranged_damage
|
|
stat_speed
|
Multi Mod
If you're building a mod, creating it to work with dami's Multi Mod might be worth considering. It lets you add your mod pack to any compatible mod (eg. Invasion/dami's Arsenal). It lets you create custom characters, weapons, and items, and release your mod as a small standalone file (usually <3mb).
The only caveat is that you can't touch vanilla code, and can't currently add new weapon classes or challenges.
Weapon Cooldowns
Calculating the displayed cooldown text is tricky. The formula for Ranged weapons is easy to calculate, but the Melee formula is complex and takes many things into consideration. For this reason, Darkly77 made an cooldown text calculator, here:
Weapon Notes
Weapon stats have an option called increase_projectile_speed_with_range
. In vanilla, this is only used by Flamethrower and Incendiary Turret, as their flame projectiles don't interact with Range in the usual way. So this option just makes their projectiles go further, because they're moving faster. Search for this var in weapon_service.gd to see the formula.
GitHub
There's a GitHub organisation for Brotato repos here. It is maintained by Darkly77, KANA, and dami, who are all active on the Space Potatoes Discord.
It's not recommended to host a full Brotato project on GitHub, because you'd be making all of Brotato's source code public. But you can host just your modded files (eg Darkly77's Invasion), or even just host the downloads for your mod (eg. KANA's mod releases)
Hosting your downloads on GitHub has a few advantages:
- You can create versioned README and CHANGELOG files to track your mod's changes.
- You can create separate releases, which track the release date.
- You can view download stats with this tool.
Modding [T] | |
---|---|
Wiki | Modding • Notes • Effects • Vanilla Items |
Godot | Download • Docs • GDRETools • GodotSteam • Jonus' Tutorial |
Misc | BrotatoMods • Cooldown Calculator |