Skip to content

Commit 3212a4e

Browse files
committed
Update: baldur's gate 3 project tutorial beta publish
1 parent 1d31d15 commit 3212a4e

File tree

1 file changed

+283
-0
lines changed

1 file changed

+283
-0
lines changed
Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
---
2+
title: Build a Baldur's Gate 3 Mod with Lua
3+
author: Julien Kris
4+
uid: Jps14SaCwqgdbbnYvoMpvMKv92P2
5+
datePublished: 2025-09-03
6+
description:
7+
published: beta
8+
header: https://raw.githubusercontent.com/codedex-io/projects/main/projects/50-terminal-project-ideas-using-python/header.png
9+
bannerImage: https://raw.githubusercontent.com/codedex-io/projects/main/projects/50-terminal-project-ideas-using-python/header.png
10+
tags:
11+
- intermediate
12+
- lua
13+
---
14+
15+
<BannerImage
16+
link="https://raw.githubusercontent.com/codedex-io/projects/main/projects/build-a-conversational-game-in-p5js/header.gif"
17+
description="Title Image"
18+
uid={true}
19+
cl="for-sidebar"
20+
/>
21+
22+
# Build a Baldur's Gate 3 Mod with Lua
23+
24+
<AuthorAvatar
25+
author_name=""
26+
author_avatar="/images/projects/authors/"
27+
username=""
28+
uid={true}
29+
/>
30+
31+
<BannerImage
32+
link="https://raw.githubusercontent.com/codedex-io/projects/main/projects/build-a-conversational-game-in-p5js/header.gif"
33+
description="Banner"
34+
uid={true}
35+
/>
36+
37+
**Prerequisites:** Lua basics, Baldur's Gate 3
38+
**Read Time:** 45 minutes
39+
40+
# Introduction: Frogify Your Enemies
41+
42+
Anyone who's played Baldur's Gate 3 knows it features some truly epic battles.
43+
44+
45+
46+
[Baldur’s Gate 3](https://en.wikipedia.org/wiki/Baldur%27s_Gate_3) (BG3) is a 2023 RPG by Larian Studios, adapted from the fifth edition of Dungeons & Dragons. It's earned over 10 million players due to its expansive worldbuilding, fleshed out characters, and stunning visuals.
47+
48+
But have you ever wanted to make Baldur’s Gate 3 *a little sillier*? 🐸 What if, every time combat started, your terrifying enemies suddenly transformed… into frogs?
49+
50+
51+
52+
We're going to do just that by making our own mods!
53+
54+
**Mods** (short for modifications) are a way of writing code to alter features, graphics, or gameplay of an existing game, even for huge titles like Baldur's Gate 3.
55+
56+
Since BG3 Lua modding is only supported on Windows, this tutorial is aimed at Windows users. If you're a Mac user, scroll down to our Resources section for some links!
57+
58+
<RoundedImage link="swap image before publishing" description="Image of enemies turning into frogs in combat" />
59+
60+
By the end of this tutorial, you’ll know how to:
61+
Set up a BG3 mod with Lua
62+
Apply polymorph statuses during combat
63+
Test your mod in-game
64+
65+
## Getting Started
66+
67+
Make sure you have Baldur's Gate 3 installed on your machine! If not, start [installing](https://store.steampowered.com/app/1086940/Baldurs_Gate_3) it in the background while you create your mod.
68+
69+
If you don't already have a code editor installed, download [Visual Studio Code](https://code.visualstudio.com). Otherwise, you can use another code editor of choice.
70+
71+
### BG3 Script Extender
72+
73+
**BG3 Script Extender (BG3SE)** is a program that adds Lua scripting and console support to Baldur's Gate 3. Download it from [GitHub](https://github.com/Norbyte/bg3se). Then, right click on the downloaded Zip file, select [Extract All], and extract the files to a separate
74+
75+
Inside this folder, create a folder called **FrogifyEnemies**. Here's the structure you'll be working with (you'll learn how to create the meta.lsx files and both .lua files in a bit!)
76+
77+
```
78+
FrogifyEnemies/Mods/FrogifyEnemies
79+
├── meta.lsx
80+
└── Public/
81+
└── FrogifyEnemies/
82+
└── Scripts/
83+
├── Init.lua
84+
└── Frogify.lua
85+
```
86+
87+
88+
## Set up the .lsx file
89+
An **.lsx** (XML) file tells Baldur’s Gate 3 about your mod, including its name, author, folder location, version, and unique ID, so the game can recognize and load it correctly.
90+
91+
Create a new plain text file in VS Code (or your favorite code editor) and save it as **meta.lsx** inside your **FrogifyEnemies** folder.
92+
93+
A **UUID (Universally Unique Identifier)** is a 128-bit value used to uniquely identify information across systems or databases without significant risk of duplication. It looks something like: `87654321-DCBA-4321-DCBA-0987654321AB`.
94+
95+
It'll make sure your mod is unique and doesn't interfere with another mod installed on the same system. Generate your own by using this [online UUID generator](https://www.uuidgenerator.net/version4).
96+
97+
```xml
98+
<save>
99+
<version>1</version>
100+
<region id="ModuleSettings">
101+
<node id="root">
102+
<children>
103+
<node id="ModuleShortDesc">
104+
<attribute id="UUID" value="87654321-DCBA-4321-DCBA-0987654321AB"/>
105+
<attribute id="Folder" value="FrogifyEnemies"/>
106+
<attribute id="Name" value="Frogify Enemies"/>
107+
<attribute id="Author" value="YourName"/>
108+
<attribute id="Description" value="Turns all enemies into frogs when combat starts."/>
109+
<attribute id="Version64" value="1"/>
110+
</node>
111+
</children>
112+
</node>
113+
</region>
114+
</save>
115+
```
116+
The **meta.lsx** file tells the game info about your mod, including what the mod is called, who made it, where its files live, and how to tell it apart from other mods.
117+
118+
It contains the following components:
119+
120+
- `UUID`: A unique ID number for your mod.
121+
- `Folder`: The name of the folder that holds your mod’s files (inside the **Mods/** directory).
122+
- `Name`: The display name of the mod. This is what shows up in BG3’s Mod Manager or in-game.
123+
- `Author`: The creator’s name (you!).
124+
- `Description`: A short blurb about what your mod does.
125+
- `Version`: A number you can bump up when you release updates so the game (and users) know it’s a new version.
126+
127+
Without this file, the game doesn’t know your mod exists.
128+
129+
## Write your Mod
130+
131+
The core logic: transform enemies into frogs when combat starts.
132+
133+
134+
As you saw in your file folder structure, you'll create two Lua scripts:
135+
136+
The first script is **Init.lua**:
137+
138+
```lua
139+
-- Init.lua
140+
141+
-- Require your main logic file
142+
Ext.Require("Frogify.lua")
143+
144+
-- Print when Init itself loads
145+
print("Init.lua loaded")
146+
147+
-- Hook into session start
148+
Ext.Events.SessionLoaded:Subscribe(function ()
149+
print("Frogify Enemies mod loaded!")
150+
end)
151+
152+
153+
```
154+
155+
Here, we are loading a save file, and once it's finished loading, we tell the game to run the code inside (in this case, a print message that says the mod has loaded!).
156+
157+
The second script is **Frogify.lua**.
158+
159+
```lua
160+
161+
-- Subscribe to session loaded to confirm mod is active
162+
Ext.Events.SessionLoaded:Subscribe(function()
163+
Print("Frogify Enemies mod loaded!")
164+
165+
-- Listen for combat starting
166+
Ext.Osiris.RegisterListener("EnteredCombat", 2, "after", function(combatGuid, characterGuid)
167+
-- Only affect enemies
168+
if Osi.IsEnemy(characterGuid) == 1 then
169+
-- Transform enemy into a frog
170+
Osi.ApplyStatus(characterGuid, "POLYMORPH_FROG", -1, 1)
171+
Print("Frogified enemy: " .. characterGuid)
172+
end
173+
end)
174+
end)
175+
176+
177+
```
178+
179+
Here, we are using `Ext.Osiris.RegisterListener("EnteredCombat", ...)` to listen for the event “a character has entered combat.”
180+
181+
`characterGuid` is the game’s internal ID for that specific character. Similar to UUID from before, **GUID** stands for Globally Unique Identifier. But unlike the UUID, this isn't a randomly generated string of numbers, but a predetermined identifier that the game automatically feeds into the function when the `EnteredCombat` event fires.
182+
183+
`if Osi.IsEnemy(characterGuid) == 1 then` checks: “Is this character an enemy?” (1 = yes, 0 = no).
184+
185+
`Osi.ApplyStatus(..., "POLYMORPH_FROG", -1, 1)` applies the “frog polymorph” effect. -1 means it lasts forever until combat ends. `POLYMORPH_FROG` is a built-in string ID that the game understands.
186+
Finally, `print("Frogified enemy: " .. characterGuid)` writes a debug message in the console so you can confirm the frogification was successful.
187+
188+
<RoundedImage link="swap image before publishing" description="Combat begins, enemies turn into frogs" />
189+
190+
## Export your Mod to a .pak
191+
Before your mod shows up in Baldur’s Gate 3, you’ll usually need to package it into a **.pak** file. This isn’t done in BG3 itself, you’ll use external tools made by the modding community.
192+
A **.pak** file is a type of “package” file, primarily used in video games, that bundles multiple game data files like graphics, textures, sounds, and other assets into a single file for easier management and distribution.
193+
### BG3 Modders Multitool
194+
Download [BG3 Modder’s Multitool](https://github.com/ShinyHobo/BG3-Modders-Multitool), which is a beginner-friendly open source tool that lets you unpack BG3’s files, browse models, and export your own mod into **.pak** format.
195+
Extract the contents of the .zip folder into a dedicated folder on your computer _outside_ the Mods folder, like `Documents\BG3ModdingTools\BG3ModdersMultitool` so you can run the tool separately from your mod files.
196+
Open BG3 Modder’s Multitool (installed outside the game).
197+
Select your project folder (like FrogifyEnemies/).
198+
Click Build Mod, which generates a .pak file.
199+
The **.pak** is usually saved here:
200+
201+
```
202+
Documents/Larian Studios/Baldur's Gate 3/Mods/
203+
```
204+
205+
## Load and Test Your Mod
206+
207+
Open BG3 Mod Manager, and drag your **.pak** mod from Inactive Mods → Active Mods.
208+
209+
Click [Save Load Order] and [Export].
210+
211+
Time to launch Baldur’s Gate 3 via Steam!! Start a new game or load an existing save. Then, enter combat! As soon as the battle begins, enemies should polymorph into frogs before your very eyes.
212+
213+
To debug, open the Script Extender console (<kbd>~</kbkd> key) to check for errors.
214+
Now you can go right into launching Baldur's Gate 3! Start a new game or load a save.
215+
Find an enemy whose model you swapped. It should now appear as a frog!
216+
217+
218+
## Bonus Challenge: Random Animal Mode
219+
Let's randomize between frogs, chickens, or sheep. 🐸🐔🐑
220+
221+
Open **Frogify.lua**, which contains the combat logic for polymorphing enemies, and adds randomization.
222+
223+
```lua
224+
local animals = {"POLYMORPH_FROG", "POLYMORPH_CHICKEN", "POLYMORPH_SHEEP"}
225+
local choice = animals[math.random(#animals)]
226+
227+
Osi.ApplyStatus(characterGuid, choice, -1, 1)
228+
print("Transformed enemy into: " .. choice)
229+
```
230+
231+
`local animals = {...}` creates a list of different polymorph status IDs. `POLYMORPH_FROG`, `POLYMORPH_CHICKEN`, `POLYMORPH_SHEEP` are all predefined effects in the game.
232+
233+
`local choice = animals[math.random(#animals)]` provides the number of items in the `animals` list (3 in this case). Then, it picks a random number between 1 and 3 (since Lua uses 1-based index) and selects the animal polymorph at that position in the `animals`list.
234+
235+
`Osi.ApplyStatus(characterGuid, choice, -1, 1)` applies the randomly selected polymorph effect to the enemy, to be applied indefinitely (`-1`) and immediately (`1`).
236+
237+
Finally, it prints a debug message showing which animal the enemy transformed into.
238+
239+
There are even more animals you can polymorph your enemies into! Search the word "POLYMORPH" in [Norbyte's BG3 Search Engine](https://bg3.norbyte.dev/search) to explore more options.
240+
241+
# Conclusion
242+
243+
Congrats! You just made your first Baldur’s Gate 3 mod! 🎉
244+
245+
246+
247+
We started by frogifying enemies, and extended it into a randomizer. For an even bigger challenge, you can explore more polymorphs ([cheese wheel](https://www.reddit.com/r/BG3/comments/1ceqelg/i_got_turned_into_a_cheese_wheel/), anyone?), or get wild with custom models.
248+
249+
Have fun breaking Faerûn!
250+
251+
# Additional Resources
252+
253+
Here are some more resources to explore:
254+
255+
- [accessibly named link to full source code on github](codedex/projects/etc)
256+
- [Norbyte's BG3 Search Engine](https://bg3.norbyte.dev/search)
257+
- [BG3 Modding Wiki](https://bg3.wiki/wiki/Modding:Modding_resources)
258+
- [BG3 Script Extender](https://github.com/Norbyte/bg3se)
259+
- [BG3 Modder’s Multitool](https://github.com/Norbyte/bg3se)
260+
- [LSLib](http://github.com/Norbyte/lslib)
261+
- Add some YouTube links
262+
- Resource for Mac users
263+
264+
Share your creations with us on IG or Twitter/X via [@codedex_io](https://x.com/codedex_io) and [@baldursgate3](https://x.com/baldursgate3)!
265+
266+
//
267+
268+
|---Julien's notes to self —--------------------------------------------------------|
269+
270+
Download it from [GitHub](https://github.com/Norbyte/bg3se). Then, right click on the downloaded Zip file, select [Extract All], and extract the files to your **Baldur’s Gate 3** bin folder (where **bg3.exe** is located):
271+
272+
```
273+
C:\Program Files (x86)\Steam\steamapps\common\Baldurs Gate 3\bin
274+
```
275+
276+
Create your project folder in your **Mods** folder inside your computer's AppData folder.
277+
278+
```
279+
C:\Users\<YourName>\AppData\Local\Larian Studios\Baldur's Gate 3\Mods\FrogifyEnemies\
280+
281+
```
282+
283+
Heads up: the AppData folder is hidden by default in Windows. Typing `%LocalAppData%` in the search bar is the easiest way to get there.

0 commit comments

Comments
 (0)