z Baldur's Gate 3

Upload your cheat tables here (No requests)
EvenLess
Expert Cheater
Expert Cheater
Posts: 181
Joined: Fri Aug 04, 2023 10:59 pm
Reputation: 209

Re: z Baldur's Gate 3

Post by EvenLess »

redjohn wrote:
Tue Oct 24, 2023 10:29 am
EvenLess wrote:
Tue Oct 24, 2023 9:58 am
Go to the first post, click the link Zanzer added to my additions. From that post, find the linke where I mention having added a version of Zanzer with autoloading. Just make sure my table is loaded before you start the game, then it will automatically ensure the items are activated as soon as they are ready, so you don't have to hit the activate just the right time.
Thanks, got it working. For some reason using the autoloader version started the game up without it seeing my data, i.e. I had to accept EULA and do some configuration and then had no saves available to load. Quitting the game and cheat engine, starting cheat engine and loading the non-autoloader table, starting the game, and then attaching cheat engine worked for me after this and also correctly loaded my profile data. Everything worked fine after this.

I think my problem was that I initally tried loading the table in the middle of a session with the game already loaded. I either didn't know or forgot that I should attach Cheat Engine before loading a save. Hope this might be helpful to someone.
This happens when BG3 have crashed X number of times, then it creates a debug game that it will load. You can just delete that from the savesgames folder, then it won't happen (until the next time the game creates the debug game).
They are normally stored in the Local AppData folder. Just copy paste this and paste into the address/path field of your Windows Explorer.
%localappdata%\Larian Studios\Baldur's Gate 3\PlayerProfiles
If I remember correctly the Debug Profiles will be stored directly in this folder. Maybe I remember wrong and it was stored in the Public subfolder.

How to use this cheat table?
  1. Install Cheat Engine
  2. Double-click the .CT file in order to open it.
  3. Click the PC icon in Cheat Engine in order to select the game process.
  4. Keep the list.
  5. Activate the trainer options by checking boxes or setting values from 0 to 1

User avatar
AkimboDK
Expert Cheater
Expert Cheater
Posts: 170
Joined: Tue Jan 23, 2018 7:57 pm
Reputation: 24

Re: z Baldur's Gate 3

Post by AkimboDK »

EvenLess wrote:
Tue Oct 24, 2023 9:28 am
Good to see :)
Only thing to note is that you might want to add a semicolon after the lone parenthesis, i.e. boost = boost .. ")" to boost = boost .. ");". I'm not sure if I got the right term, so bear with me. The semicolon is a termination marker, i.e. it specifies the termination/end of a line/command, so the interpreter (the engine that reads the commands and converts it to machine code) can see where one line/command ends and a new one begins, so it doesn't try to mix two commands together as one command. So here it would indicate that the UnlockSpellVariant(); is completed before trying to mix ActionResourcePreventReduction(Movement); in as if those 2 commands/lines/functions was 1 command.
In some languages (such as PHP as I recall) the termination marker is required, even if the commands are on separate lines. Most other languages that I know (such as PowerShell, JavaScript, Lua) the termination marker is only really required if you are adding multiple commands one the same line. With the above approach that's exactly what we're doing.
If you want to see what is happening when you execute the script, you could try adding print(boost) after every boost = boost .. line, then you would see how Lua is just combining the next line to the previous line, making them one single line.

So you would do something like this? Since I have added some more stuff to this code right now it looks like this:

Code: Select all

{$lua}
if syntaxcheck then return end

local movementMeters    = 1000       -- The amount of movement.
local rollBonus         = 50         -- Bonus added to all dice rolls.
local resistanceLevel   = "Immune"   -- Resistant or Immune.
local damageType        = {
  "Bludgeoning",
  "Piercing",
  "Slashing",
  "Acid",
  "Cold",
  "Fire",
  "Force",
  "Lightning",
  "Necrotic",
  "Poison",
  "Psychic",
  "Radiant",
  "Thunder",
}

boost = ''
boost = boost .. "UnlockSpellVariant("
boost = boost .. "IsSpell() or not IsSpell(),"
boost = boost .. "ModifySpellRoll('not SavingThrow','SpellAutoResolveOnAlly'),"
boost = boost .. "ModifyTargetRadius(AdditiveBase,10),"
--boost = boost .. "ModifyNumberOfTargets(AdditiveBase,2),"
boost = boost .. "ModifyMaximumTargets(AdditiveBase,10),"
--boost = boost .. "ModifySpellFlags(Verbal,0),"
boost = boost .. "ModifySpellFlags(Stealth,1),"
boost = boost .. "ModifySpellFlags(Melee,0),"
boost = boost .. "ModifySavingThrowDisadvantage(),"
boost = boost .. "ModifyUseCosts(Override,ActionPoint,0,0),"
boost = boost .. "ModifyUseCosts(Override,BonusActionPoint,0,0),"
boost = boost .. "ModifyUseCosts(Override,ReactionActionPoint,0,0),"
boost = boost .. "ModifyTooltipDescription()"
boost = boost .. "ActionResourcePreventReduction(Movement);"
boost = boost .. ");"
boost = boost .. string.format("ActionResourceOverride(Movement,%s,0);", movementMeters)
boost = boost .. string.format("RollBonus(SkillCheck,%s);", rollBonus)
boost = boost .. string.format("RollBonus(RawAbility,%s);", rollBonus)
boost = boost .. string.format("RollBonus(SavingThrow,%s);", rollBonus)
for i = 1, #damageType do
--boost = boost .. string.format("Resistance(%s, %s);", damageType[i], resistanceLevel)
end

[ENABLE]
AddBoostsToPlayer(boost)

[DISABLE]
RemoveBoostsFromPlayer(boost)
Or would you move the ");" below the string.format ?

Gray0ne
Noobzor
Noobzor
Posts: 14
Joined: Sun Aug 27, 2023 6:15 pm
Reputation: 0

Re: z Baldur's Gate 3

Post by Gray0ne »

This might be a bit of a noob question, I've been "generally" figuring things out just guessing and poking around but I still don't really understand what the different keys mean? I'll give an example

Code: Select all

 
        "MapKey": "475200ee-cc3c-4dbe-84b1-1820c02ea26a",
        "Name": "S_DEN_TieflingLeader",
        "Type": "character",
        "ParentTemplateName": "Tieflings_Male_Asmodeus_Civilian",
        "DisplayNameEnglish": "Zevlor",
        "DisplayNameFrench": "Zevlor",
        "AiHint": "f76e60e1-2957-470b-8a25-efdf32475ce0",
        "AnubisConfigName": "DEN_TieflingLeader",
        "Archetype": "melee_smart",
        "CharacterVisualResourceID": "6b49f80c-3ce2-cfe8-f569-5202f8f09f23",
        "CombatGroupID": "893da9dc-8adb-4cd6-ae5e-231628de205a",
        "DisplayName": "h5e06e255g785eg4c37g88bbgfc5eba6aa12d;1",
        "Equipment": "DEN_TieflingLeader",
        "Faction": "a3297c6f-87d1-37c4-a81d-d769d52c88a9",
        "Flag": "1",
        "GeneratePortrait": "Icon_Tiefling_Male",
        "Icon": "6b49f80c-3ce2-cfe8-f569-5202f8f09f23-DEN_TieflingLeader_(Icon_Tiefling_Male)",
        "IsGlobal": "True",
        "LevelName": "WLD_Main_A",
        "LevelOverride": "4",
        "Stats": "DEN_TieflingLeader",
        "TemplateName": "a5856190-08e3-4741-b697-8b1cbf03eaa1",
        "Title": "hb5935ce7ge1feg480dgb874gc960b57ff864;1",
        "TitleEnglish": "Hellrider Exile",
        "TitleFrench": "Cavalier des Enfers en exil",
        "VocalAttackResourceID": "5e7919ce-963f-295c-57cf-4cb9f3d2aa3f",
        "VocalBuffResourceID": "7257d609-cb62-4053-f5dc-ee9086f81a4c",
        "VocalDeathResourceID": "964f9875-32bc-8d2b-bb0f-6d05dd53e820",
        "VocalDodgeResourceID": "e5376d28-3e5b-afdb-fe27-f5f4817bcd16",
        "VocalEffortsResourceID": "f6629976-4569-c4af-de9a-7e366dbfa522",
        "VocalFallResourceID": "6d3bd2ec-8b6e-bb25-ded9-63fcbaf89910",
        "VocalInitiativeResourceID": "00000000-0000-0000-0000-000000000000",
        "VocalLaughterManiacalResourceID": "8f6a8a40-afbc-4e2a-9f56-d9ec36b103f8",
        "VocalLaughterResourceID": "ef25ce43-839f-2a7a-58ad-643c8f9da8b1",
        "VocalPainResourceID": "72d80e60-41ff-b578-07cb-369658fa5a57",
        "VocalRecoverResourceID": "d619827c-07c1-3e69-5804-05fa89e03830",
        "VocalShoutResourceID": "fc8e8647-a8eb-b875-2f6e-53de257a3ac7",
        "VocalSnoreResourceID": "b052669e-7d4a-82cf-c631-bb753d2d7802",
        "VocalVictoryResourceID": "81ab72d8-854a-b027-edf0-ae9e19ade926",
        "VocalWeakResourceID": "8e2be583-e04d-030a-9d77-d18926a9f304",
        "_OriginalFileVersion_": "144115209550692654",
        "RootFolder": "Patch3\\Mods\\Gustav\\Globals\\WLD_Main_A\\Characters",
        "RootFile": "_merged.lsf.lsx",
        "ParentTemplateId": "8170335b-d9ca-4fc3-a1fa-f3b520a1e4db"
That is Zevlor's Character. (Presumably the version you meet in the Grove)
  • "MapKey": "475200ee-cc3c-4dbe-84b1-1820c02ea26a"
  • "ParentTemplateId": "8170335b-d9ca-4fc3-a1fa-f3b520a1e4db"
  • "TemplateName": "a5856190-08e3-4741-b697-8b1cbf03eaa1"

    I have no idea what any of these actually mean other than MapKey sometimes it works to spawn things, is there a resource for this where I can learn what all these different variable labels actually mean?

Sungrey
Noobzor
Noobzor
Posts: 14
Joined: Wed Apr 19, 2017 5:44 am
Reputation: 0

Re: z Baldur's Gate 3

Post by Sungrey »

̶T̶h̶i̶s̶ ̶i̶s̶ ̶a̶ ̶v̶e̶r̶y̶ ̶b̶a̶s̶i̶c̶ ̶q̶u̶e̶s̶t̶i̶o̶n̶,̶ ̶b̶u̶t̶ ̶d̶o̶ ̶y̶o̶u̶ ̶a̶d̶d̶ ̶p̶a̶s̶s̶i̶v̶e̶s̶ ̶t̶o̶ ̶a̶n̶ ̶i̶t̶e̶m̶'̶s̶ ̶"̶B̶o̶o̶s̶t̶s̶"̶ ̶l̶i̶n̶e̶,̶ ̶o̶r̶ ̶d̶o̶ ̶y̶o̶u̶ ̶c̶r̶e̶a̶t̶e̶ ̶a̶ ̶n̶e̶w̶ ̶l̶i̶n̶e̶?̶ ̶I̶'̶v̶e̶ ̶s̶e̶e̶n̶ ̶a̶ ̶l̶i̶n̶e̶ ̶f̶o̶r̶ ̶"̶P̶a̶s̶s̶i̶v̶e̶s̶O̶n̶E̶q̶u̶i̶p̶"̶ ̶f̶o̶r̶ ̶s̶o̶m̶e̶ ̶i̶t̶e̶m̶s̶ ̶b̶u̶t̶ ̶n̶o̶t̶ ̶o̶t̶h̶e̶r̶s̶.̶

Nvm I got it to work by adding a PassivesOnEquip line.

User avatar
sanitka
Expert Cheater
Expert Cheater
Posts: 493
Joined: Sat Aug 22, 2020 5:40 am
Reputation: 249

Re: z Baldur's Gate 3

Post by sanitka »

Little bit off-topic, anyone having or knowing a simple mod using script extender and a config file (external) ?
I'd like to create a mod using external config, but I do not want to waste time on config management if it has been already done.

EvenLess
Expert Cheater
Expert Cheater
Posts: 181
Joined: Fri Aug 04, 2023 10:59 pm
Reputation: 209

Re: z Baldur's Gate 3

Post by EvenLess »

PrinceRevivalDK wrote:
Tue Oct 24, 2023 1:28 pm
EvenLess wrote:
Tue Oct 24, 2023 9:28 am
...

So you would do something like this? Since I have added some more stuff to this code right now it looks like this:

Code: Select all

{$lua}
if syntaxcheck then return end

local movementMeters    = 1000       -- The amount of movement.
local rollBonus         = 50         -- Bonus added to all dice rolls.
local resistanceLevel   = "Immune"   -- Resistant or Immune.
local damageType        = {
  "Bludgeoning",
  "Piercing",
  "Slashing",
  "Acid",
  "Cold",
  "Fire",
  "Force",
  "Lightning",
  "Necrotic",
  "Poison",
  "Psychic",
  "Radiant",
  "Thunder",
}

boost = ''
boost = boost .. "UnlockSpellVariant("
boost = boost .. "IsSpell() or not IsSpell(),"
boost = boost .. "ModifySpellRoll('not SavingThrow','SpellAutoResolveOnAlly'),"
boost = boost .. "ModifyTargetRadius(AdditiveBase,10),"
--boost = boost .. "ModifyNumberOfTargets(AdditiveBase,2),"
boost = boost .. "ModifyMaximumTargets(AdditiveBase,10),"
--boost = boost .. "ModifySpellFlags(Verbal,0),"
boost = boost .. "ModifySpellFlags(Stealth,1),"
boost = boost .. "ModifySpellFlags(Melee,0),"
boost = boost .. "ModifySavingThrowDisadvantage(),"
boost = boost .. "ModifyUseCosts(Override,ActionPoint,0,0),"
boost = boost .. "ModifyUseCosts(Override,BonusActionPoint,0,0),"
boost = boost .. "ModifyUseCosts(Override,ReactionActionPoint,0,0),"
boost = boost .. "ModifyTooltipDescription()"
boost = boost .. "ActionResourcePreventReduction(Movement);"
boost = boost .. ");"
boost = boost .. string.format("ActionResourceOverride(Movement,%s,0);", movementMeters)
boost = boost .. string.format("RollBonus(SkillCheck,%s);", rollBonus)
boost = boost .. string.format("RollBonus(RawAbility,%s);", rollBonus)
boost = boost .. string.format("RollBonus(SavingThrow,%s);", rollBonus)
for i = 1, #damageType do
--boost = boost .. string.format("Resistance(%s, %s);", damageType[i], resistanceLevel)
end

[ENABLE]
AddBoostsToPlayer(boost)

[DISABLE]
RemoveBoostsFromPlayer(boost)
Or would you move the ");" below the string.format ?
I see you found one of my earlier scripts :)

Without having tested your code, I would imagine that it is failing/not working. Right now you're adding a separate ActionResourcePreventReduction() boost into your UnlockSpellVariant() boost, then terminating all lines up to that point (the semicolon), then adding a lonely end parenthesis that is then also terminated, followed by 4 more ActionResourceOverride() and RollBonus() boosts.

You need to keep track of when a opening and closing brackets, as the number must match. So UnlockSpellVariant() is a single function/command, which can contain several arguments inside its brackets/parenthesis. This is actually the main reason it is VERY good practice to always indent your code for better readability. Then you can follow your cursor down from the starting bracket (or command that precedes the starting bracket) down to the closing bracket. This section between is often called a "code block".

I've rewritten your code to how I would do it today, keeping it mind that I want it somewhat modular, so I can easily add or remove commands/boosts.

Code: Select all

{$lua}
if syntaxcheck then return end
local rollBonus = 50 -- Bonus added to all dice rolls.

-- Add all the wanted "ModifySpell" options to a table.
local spellMod = {
  "ModifySpellRoll('not SavingThrow','SpellAutoResolveOnAlly')",
  "ModifyTargetRadius(AdditiveBase,10)",
  --"ModifyNumberOfTargets(AdditiveBase,2)",
  "ModifyMaximumTargets(AdditiveBase,10)",
  --"ModifySpellFlags(Verbal,0)",
  "ModifySpellFlags(Stealth,1)",
  "ModifySpellFlags(Melee,0)",
  "ModifySavingThrowDisadvantage()",
  "ModifyUseCosts(Override,ActionPoint,0,0)", -- Set Action Point cost to 0.
  "ModifyUseCosts(Override,BonusActionPoint,0,0)", -- Set Bonus Action Point cost to 0.
  "ModifyUseCosts(Override,ReactionActionPoint,0,0)", -- Set Reaction Action Point cost to 0.
  "ModifyTooltipDescription()",
}
-- Concatenate all the spellMods, separated by a comma, into a single UnlockSpellVariant() boost string.
local spellVariant = string.format("UnlockSpellVariant(IsSpell() or not IsSpell(),%s)",table.concat(spellMod, ','))

-- Add all the wanted boosts to a table.
local boost = {
  spellVariant,
  "ActionResourcePreventReduction(Movement)",
  "Resistance(All, Immune)",
  string.format("RollBonus(SkillCheck,%s)", rollBonus), -- Add bonus to skill checks.
  string.format("RollBonus(RawAbility,%s)", rollBonus), -- Add bonus to ability checks.
  string.format("RollBonus(SavingThrow,%s)", rollBonus), -- Add bonus to saving throws.
}
local boosts = table.concat(boost, ';')
print(boosts)
[ENABLE]
AddBoostsToPlayer(boosts)

[DISABLE]
RemoveBoostsFromPlayer(boosts)
So first I removed the code that you weren't actually using (i.e. the damageType table ActionResourceOverride() for movement, since you already have another boost that fully eliminates movement cost). I could have left the resistanceLevel variable in there, this again is a thing of preference. I tend to use variables if the same string/result is used multiple places in the following code, that way I only have to change it one place. Or I might use a variable at the top, just so I don't have to hunt through the code to find the one thing I might want to change ad-hoc.

Then I first created a table containg every ModifySpell*()" function that should be added to the UnlockSpellVariant() boost. I've ensured the commas were removed, as they will be added using the with comma as a delimiter table.concat(). This will be stored in the spellVariant variable.

Then I create a table with every single boost. Again, I don't add the semicolons, as I'll be adding those with the delimiter argument in the table.concat() function.

If in doubt what a function does, just Google the command along with "Lua", then you'll get results that will explain what the command/function does, and its syntax (i.e. how many and in which order any arguments are) and what the command/function returns as in this case you want it to return a string, and not a boolean (true/false) or nil (i.e. nothing) or a table etc. I usually use print() to verify the result is as I expect, and if print() doesn't output anything, enclose the variable you're trying to print in a tostring(), that way whatever type in the result will be converted to a string, so print() will at least give you a nice hint of what happened. So f.ex. print(tostring(boosts)) will always print something, even if it's just "nil" (meaning the variable contains no data whatsoever), or it might return something like "table" and you know you just tried sending a table where you wanted a string.

I can really recommend going through some of the "courses" on [Link]. They don't have Lua, but JavaScript is somewhat similar in the syntax, so you would easily could take the understanding gained from that course and apply it to many other coding/programming languages. While I don't really know Python, I would really recommend that one as well, as a first language, since you can find and create almost anything in Python. The syntax is a bit different though, but it's good at forcing people into the habit of indenting/formatting their code properly as Python requires proper indentation to work :)

EvenLess
Expert Cheater
Expert Cheater
Posts: 181
Joined: Fri Aug 04, 2023 10:59 pm
Reputation: 209

Re: z Baldur's Gate 3

Post by EvenLess »

sanitka wrote:
Tue Oct 24, 2023 7:31 pm
Little bit off-topic, anyone having or knowing a simple mod using script extender and a config file (external) ?
I'd like to create a mod using external config, but I do not want to waste time on config management if it has been already done.
I haven't looked into mods whatsoever. I did create a rough read/write settings file in my latest BG3Commander table. Don't know if that would help.

EvenLess
Expert Cheater
Expert Cheater
Posts: 181
Joined: Fri Aug 04, 2023 10:59 pm
Reputation: 209

Re: z Baldur's Gate 3

Post by EvenLess »

Gray0ne wrote:
Tue Oct 24, 2023 3:48 pm
This might be a bit of a noob question, I've been "generally" figuring things out just guessing and poking around but I still don't really understand what the different keys mean? I'll give an example

Code: Select all

 
        "MapKey": "475200ee-cc3c-4dbe-84b1-1820c02ea26a",
        "Name": "S_DEN_TieflingLeader",
        "Type": "character",
        "ParentTemplateName": "Tieflings_Male_Asmodeus_Civilian",
        "DisplayNameEnglish": "Zevlor",
        "DisplayNameFrench": "Zevlor",
        "AiHint": "f76e60e1-2957-470b-8a25-efdf32475ce0",
        "AnubisConfigName": "DEN_TieflingLeader",
        "Archetype": "melee_smart",
        "CharacterVisualResourceID": "6b49f80c-3ce2-cfe8-f569-5202f8f09f23",
        "CombatGroupID": "893da9dc-8adb-4cd6-ae5e-231628de205a",
        "DisplayName": "h5e06e255g785eg4c37g88bbgfc5eba6aa12d;1",
        "Equipment": "DEN_TieflingLeader",
        "Faction": "a3297c6f-87d1-37c4-a81d-d769d52c88a9",
        "Flag": "1",
        "GeneratePortrait": "Icon_Tiefling_Male",
        "Icon": "6b49f80c-3ce2-cfe8-f569-5202f8f09f23-DEN_TieflingLeader_(Icon_Tiefling_Male)",
        "IsGlobal": "True",
        "LevelName": "WLD_Main_A",
        "LevelOverride": "4",
        "Stats": "DEN_TieflingLeader",
        "TemplateName": "a5856190-08e3-4741-b697-8b1cbf03eaa1",
        "Title": "hb5935ce7ge1feg480dgb874gc960b57ff864;1",
        "TitleEnglish": "Hellrider Exile",
        "TitleFrench": "Cavalier des Enfers en exil",
        "VocalAttackResourceID": "5e7919ce-963f-295c-57cf-4cb9f3d2aa3f",
        "VocalBuffResourceID": "7257d609-cb62-4053-f5dc-ee9086f81a4c",
        "VocalDeathResourceID": "964f9875-32bc-8d2b-bb0f-6d05dd53e820",
        "VocalDodgeResourceID": "e5376d28-3e5b-afdb-fe27-f5f4817bcd16",
        "VocalEffortsResourceID": "f6629976-4569-c4af-de9a-7e366dbfa522",
        "VocalFallResourceID": "6d3bd2ec-8b6e-bb25-ded9-63fcbaf89910",
        "VocalInitiativeResourceID": "00000000-0000-0000-0000-000000000000",
        "VocalLaughterManiacalResourceID": "8f6a8a40-afbc-4e2a-9f56-d9ec36b103f8",
        "VocalLaughterResourceID": "ef25ce43-839f-2a7a-58ad-643c8f9da8b1",
        "VocalPainResourceID": "72d80e60-41ff-b578-07cb-369658fa5a57",
        "VocalRecoverResourceID": "d619827c-07c1-3e69-5804-05fa89e03830",
        "VocalShoutResourceID": "fc8e8647-a8eb-b875-2f6e-53de257a3ac7",
        "VocalSnoreResourceID": "b052669e-7d4a-82cf-c631-bb753d2d7802",
        "VocalVictoryResourceID": "81ab72d8-854a-b027-edf0-ae9e19ade926",
        "VocalWeakResourceID": "8e2be583-e04d-030a-9d77-d18926a9f304",
        "_OriginalFileVersion_": "144115209550692654",
        "RootFolder": "Patch3\\Mods\\Gustav\\Globals\\WLD_Main_A\\Characters",
        "RootFile": "_merged.lsf.lsx",
        "ParentTemplateId": "8170335b-d9ca-4fc3-a1fa-f3b520a1e4db"
That is Zevlor's Character. (Presumably the version you meet in the Grove)
  • "MapKey": "475200ee-cc3c-4dbe-84b1-1820c02ea26a"
  • "ParentTemplateId": "8170335b-d9ca-4fc3-a1fa-f3b520a1e4db"
  • "TemplateName": "a5856190-08e3-4741-b697-8b1cbf03eaa1"

    I have no idea what any of these actually mean other than MapKey sometimes it works to spawn things, is there a resource for this where I can learn what all these different variable labels actually mean?
It is indeed a bit of guesswork (or looking at what others have figured out and accumulating their knowledge). When talking about templates, my experience is that the MapKey is the UUID used in most commands. The ParentTemplateId is a reference to (the MapKey in) another template, from where this template is inheriting any unspecified data/values from. I'm unsure what the TemplateName is for. My first thought was that it was a reference to the language file, but the syntax doesn't fit. You can see the syntax of those if you look at "DisplayName" or "TitleName" (which Noway3 have then fetched and added to his dumps as DisplayNameEnglish etc.).

I can only recommend digging into the rabbithole that is BG3-Modders-Multitool. If you follow the link from Zanzer's first post, to my post, there's a a bit dated guide I wrote on how to use it. The newer versions have changed a bit, so you don't need the LSLib anymore as it's included in the toolbox now. I actually think Noway3 have a newer/better guide than mine. I'm also certain that Noway3 have gained a better understanding of the properties than I have :)

Just search for the GUID in the toolbox, and you will see wherever it's reference. With enough time spend crawling around in the rabbithole you start getting a picture of how everything connects.

User avatar
AkimboDK
Expert Cheater
Expert Cheater
Posts: 170
Joined: Tue Jan 23, 2018 7:57 pm
Reputation: 24

Re: z Baldur's Gate 3

Post by AkimboDK »

EvenLess wrote:
Tue Oct 24, 2023 9:42 pm
PrinceRevivalDK wrote:
Tue Oct 24, 2023 1:28 pm
EvenLess wrote:
Tue Oct 24, 2023 9:28 am
...

So you would do something like this? Since I have added some more stuff to this code right now it looks like this:

Code: Select all

{$lua}
if syntaxcheck then return end

local movementMeters    = 1000       -- The amount of movement.
local rollBonus         = 50         -- Bonus added to all dice rolls.
local resistanceLevel   = "Immune"   -- Resistant or Immune.
local damageType        = {
  "Bludgeoning",
  "Piercing",
  "Slashing",
  "Acid",
  "Cold",
  "Fire",
  "Force",
  "Lightning",
  "Necrotic",
  "Poison",
  "Psychic",
  "Radiant",
  "Thunder",
}

boost = ''
boost = boost .. "UnlockSpellVariant("
boost = boost .. "IsSpell() or not IsSpell(),"
boost = boost .. "ModifySpellRoll('not SavingThrow','SpellAutoResolveOnAlly'),"
boost = boost .. "ModifyTargetRadius(AdditiveBase,10),"
--boost = boost .. "ModifyNumberOfTargets(AdditiveBase,2),"
boost = boost .. "ModifyMaximumTargets(AdditiveBase,10),"
--boost = boost .. "ModifySpellFlags(Verbal,0),"
boost = boost .. "ModifySpellFlags(Stealth,1),"
boost = boost .. "ModifySpellFlags(Melee,0),"
boost = boost .. "ModifySavingThrowDisadvantage(),"
boost = boost .. "ModifyUseCosts(Override,ActionPoint,0,0),"
boost = boost .. "ModifyUseCosts(Override,BonusActionPoint,0,0),"
boost = boost .. "ModifyUseCosts(Override,ReactionActionPoint,0,0),"
boost = boost .. "ModifyTooltipDescription()"
boost = boost .. "ActionResourcePreventReduction(Movement);"
boost = boost .. ");"
boost = boost .. string.format("ActionResourceOverride(Movement,%s,0);", movementMeters)
boost = boost .. string.format("RollBonus(SkillCheck,%s);", rollBonus)
boost = boost .. string.format("RollBonus(RawAbility,%s);", rollBonus)
boost = boost .. string.format("RollBonus(SavingThrow,%s);", rollBonus)
for i = 1, #damageType do
--boost = boost .. string.format("Resistance(%s, %s);", damageType[i], resistanceLevel)
end

[ENABLE]
AddBoostsToPlayer(boost)

[DISABLE]
RemoveBoostsFromPlayer(boost)
Or would you move the ");" below the string.format ?
I see you found one of my earlier scripts :)

Without having tested your code, I would imagine that it is failing/not working. Right now you're adding a separate ActionResourcePreventReduction() boost into your UnlockSpellVariant() boost, then terminating all lines up to that point (the semicolon), then adding a lonely end parenthesis that is then also terminated, followed by 4 more ActionResourceOverride() and RollBonus() boosts.

You need to keep track of when a opening and closing brackets, as the number must match. So UnlockSpellVariant() is a single function/command, which can contain several arguments inside its brackets/parenthesis. This is actually the main reason it is VERY good practice to always indent your code for better readability. Then you can follow your cursor down from the starting bracket (or command that precedes the starting bracket) down to the closing bracket. This section between is often called a "code block".

I've rewritten your code to how I would do it today, keeping it mind that I want it somewhat modular, so I can easily add or remove commands/boosts.

Code: Select all

{$lua}
if syntaxcheck then return end
local rollBonus = 50 -- Bonus added to all dice rolls.

-- Add all the wanted "ModifySpell" options to a table.
local spellMod = {
  "ModifySpellRoll('not SavingThrow','SpellAutoResolveOnAlly')",
  "ModifyTargetRadius(AdditiveBase,10)",
  --"ModifyNumberOfTargets(AdditiveBase,2)",
  "ModifyMaximumTargets(AdditiveBase,10)",
  --"ModifySpellFlags(Verbal,0)",
  "ModifySpellFlags(Stealth,1)",
  "ModifySpellFlags(Melee,0)",
  "ModifySavingThrowDisadvantage()",
  "ModifyUseCosts(Override,ActionPoint,0,0)", -- Set Action Point cost to 0.
  "ModifyUseCosts(Override,BonusActionPoint,0,0)", -- Set Bonus Action Point cost to 0.
  "ModifyUseCosts(Override,ReactionActionPoint,0,0)", -- Set Reaction Action Point cost to 0.
  "ModifyTooltipDescription()",
}
-- Concatenate all the spellMods, separated by a comma, into a single UnlockSpellVariant() boost string.
local spellVariant = string.format("UnlockSpellVariant(IsSpell() or not IsSpell(),%s)",table.concat(spellMod, ','))

-- Add all the wanted boosts to a table.
local boost = {
  spellVariant,
  "ActionResourcePreventReduction(Movement)",
  "Resistance(All, Immune)",
  string.format("RollBonus(SkillCheck,%s)", rollBonus), -- Add bonus to skill checks.
  string.format("RollBonus(RawAbility,%s)", rollBonus), -- Add bonus to ability checks.
  string.format("RollBonus(SavingThrow,%s)", rollBonus), -- Add bonus to saving throws.
}
local boosts = table.concat(boost, ';')
print(boosts)
[ENABLE]
AddBoostsToPlayer(boosts)

[DISABLE]
RemoveBoostsFromPlayer(boosts)
So first I removed the code that you weren't actually using (i.e. the damageType table ActionResourceOverride() for movement, since you already have another boost that fully eliminates movement cost). I could have left the resistanceLevel variable in there, this again is a thing of preference. I tend to use variables if the same string/result is used multiple places in the following code, that way I only have to change it one place. Or I might use a variable at the top, just so I don't have to hunt through the code to find the one thing I might want to change ad-hoc.

Then I first created a table containg every ModifySpell*()" function that should be added to the UnlockSpellVariant() boost. I've ensured the commas were removed, as they will be added using the with comma as a delimiter table.concat(). This will be stored in the spellVariant variable.

Then I create a table with every single boost. Again, I don't add the semicolons, as I'll be adding those with the delimiter argument in the table.concat() function.

If in doubt what a function does, just Google the command along with "Lua", then you'll get results that will explain what the command/function does, and its syntax (i.e. how many and in which order any arguments are) and what the command/function returns as in this case you want it to return a string, and not a boolean (true/false) or nil (i.e. nothing) or a table etc. I usually use print() to verify the result is as I expect, and if print() doesn't output anything, enclose the variable you're trying to print in a tostring(), that way whatever type in the result will be converted to a string, so print() will at least give you a nice hint of what happened. So f.ex. print(tostring(boosts)) will always print something, even if it's just "nil" (meaning the variable contains no data whatsoever), or it might return something like "table" and you know you just tried sending a table where you wanted a string.

I can really recommend going through some of the "courses" on [Link]. They don't have Lua, but JavaScript is somewhat similar in the syntax, so you would easily could take the understanding gained from that course and apply it to many other coding/programming languages. While I don't really know Python, I would really recommend that one as well, as a first language, since you can find and create almost anything in Python. The syntax is a bit different though, but it's good at forcing people into the habit of indenting/formatting their code properly as Python requires proper indentation to work :)
Well, this new code you added here looks simpler and better, I modified one duplicated script into the table I am using, and everything seemed to have worked just fine.
The only problem is that the movement is being reduced even with the line "ActionResourcePreventReduction(Movement)",
and adding back the movemeter code just breaks the whole script. haha I'm so confused right now xD

EDIT: nevermind, I added this instead:
"ActionResourceConsumeMultiplier(Movement,0,0)", and it works.

Gray0ne
Noobzor
Noobzor
Posts: 14
Joined: Sun Aug 27, 2023 6:15 pm
Reputation: 0

Re: z Baldur's Gate 3

Post by Gray0ne »

EvenLess wrote:
Tue Oct 24, 2023 9:57 pm
Gray0ne wrote:
Tue Oct 24, 2023 3:48 pm
This might be a bit of a noob question, I've been "generally" figuring things out just guessing and poking around but I still don't really understand what the different keys mean? I'll give an example

Code: Select all

 
-snip-
It is indeed a bit of guesswork (or looking at what others have figured out and accumulating their knowledge). When talking about templates, my experience is that the MapKey is the UUID used in most commands. The ParentTemplateId is a reference to (the MapKey in) another template, from where this template is inheriting any unspecified data/values from. I'm unsure what the TemplateName is for. My first thought was that it was a reference to the language file, but the syntax doesn't fit. You can see the syntax of those if you look at "DisplayName" or "TitleName" (which Noway3 have then fetched and added to his dumps as DisplayNameEnglish etc.).

I can only recommend digging into the rabbithole that is BG3-Modders-Multitool. If you follow the link from Zanzer's first post, to my post, there's a a bit dated guide I wrote on how to use it. The newer versions have changed a bit, so you don't need the LSLib anymore as it's included in the toolbox now. I actually think Noway3 have a newer/better guide than mine. I'm also certain that Noway3 have gained a better understanding of the properties than I have :)

Just search for the GUID in the toolbox, and you will see wherever it's reference. With enough time spend crawling around in the rabbithole you start getting a picture of how everything connects.
I appreciate that thank you. I've been having difficulty getting modders multitool to actually work. I ended up doing it the legacy way first not realizing it wasnt necessary so I pulled all the files with export tool and then unpacked, decompressed, and indexed them. Object Explorer had zero models or model data and most fields were empty on everything. I deleted it all and am starting over without using lslib this time though. hopefully it works out better.

Gray0ne
Noobzor
Noobzor
Posts: 14
Joined: Sun Aug 27, 2023 6:15 pm
Reputation: 0

Re: z Baldur's Gate 3

Post by Gray0ne »

Anyone know what the TimelineTemplate_ on a bunch of these characters means?

User avatar
AkimboDK
Expert Cheater
Expert Cheater
Posts: 170
Joined: Tue Jan 23, 2018 7:57 pm
Reputation: 24

Re: z Baldur's Gate 3

Post by AkimboDK »

EvenLess wrote:
Tue Oct 24, 2023 9:42 pm

Code: Select all

{$lua}
if syntaxcheck then return end
local rollBonus = 50 -- Bonus added to all dice rolls.

-- Add all the wanted "ModifySpell" options to a table.
local spellMod = {
  "ModifySpellRoll('not SavingThrow','SpellAutoResolveOnAlly')",
  "ModifyTargetRadius(AdditiveBase,10)",
  --"ModifyNumberOfTargets(AdditiveBase,2)",
  "ModifyMaximumTargets(AdditiveBase,10)",
  --"ModifySpellFlags(Verbal,0)",
  "ModifySpellFlags(Stealth,1)",
  "ModifySpellFlags(Melee,0)",
  "ModifySavingThrowDisadvantage()",
  "ModifyUseCosts(Override,ActionPoint,0,0)", -- Set Action Point cost to 0.
  "ModifyUseCosts(Override,BonusActionPoint,0,0)", -- Set Bonus Action Point cost to 0.
  "ModifyUseCosts(Override,ReactionActionPoint,0,0)", -- Set Reaction Action Point cost to 0.
  "ModifyTooltipDescription()",
}
-- Concatenate all the spellMods, separated by a comma, into a single UnlockSpellVariant() boost string.
local spellVariant = string.format("UnlockSpellVariant(IsSpell() or not IsSpell(),%s)",table.concat(spellMod, ','))

-- Add all the wanted boosts to a table.
local boost = {
  spellVariant,
  "ActionResourcePreventReduction(Movement)",
  "Resistance(All, Immune)",
  string.format("RollBonus(SkillCheck,%s)", rollBonus), -- Add bonus to skill checks.
  string.format("RollBonus(RawAbility,%s)", rollBonus), -- Add bonus to ability checks.
  string.format("RollBonus(SavingThrow,%s)", rollBonus), -- Add bonus to saving throws.
}
local boosts = table.concat(boost, ';')
print(boosts)
[ENABLE]
AddBoostsToPlayer(boosts)

[DISABLE]
RemoveBoostsFromPlayer(boosts)
Okay, Now I am really confused about this script, I want to keep this list as it is. but, I am trying to have one that still uses Action points and Bonus Action points, so I will change the 0,0 to 1,0 for each and that works.
But for some reason this SpellMod code changes all actions into actions, (I mean if a melee spell or normal spell originally used a Bonus Action, that will be converted into using an action and says that in the description of it. Hell, even "Jump" now uses an Action instead of Bonus Actions)
which is a bummer, because in this case I just want it to spend the Action and Bonus action but not spend any spell level slots.
and I am guessing it is something to do with
local spellVariant = string.format("UnlockSpellVariant(IsSpell() or not IsSpell(),%s)",table.concat(spellMod, ','))
that changes all spells into actions instead of what they used to be.
I have no idea how to fix tat s:

User avatar
sanitka
Expert Cheater
Expert Cheater
Posts: 493
Joined: Sat Aug 22, 2020 5:40 am
Reputation: 249

Re: z Baldur's Gate 3

Post by sanitka »

PrinceRevivalDK wrote:
Thu Oct 26, 2023 1:45 am
Okay, Now I am really confused about this script, I want to keep this list as it is. but, I am trying to have one that still uses Action points and Bonus Action points, so I will change the 0,0 to 1,0 for each and that works.
But for some reason this SpellMod code changes all actions into actions, (I mean if a melee spell or normal spell originally used a Bonus Action, that will be converted into using an action and says that in the description of it. Hell, even "Jump" now uses an Action instead of Bonus Actions)
which is a bummer, because in this case I just want it to spend the Action and Bonus action but not spend any spell level slots.
and I am guessing it is something to do with
local spellVariant = string.format("UnlockSpellVariant(IsSpell() or not IsSpell(),%s)",table.concat(spellMod, ','))
that changes all spells into actions instead of what they used to be.
I have no idea how to fix tat s:
It is kind of simple, if you are converting an apple to a cucumber, do not be surprised with the result ;).
ie. if you applying one set of "improvements" to everything, do not be surprised with the result.

try to think, why usually UnlockSpellVariant is cast over a specific spell or an action ? ;)

User avatar
AkimboDK
Expert Cheater
Expert Cheater
Posts: 170
Joined: Tue Jan 23, 2018 7:57 pm
Reputation: 24

Re: z Baldur's Gate 3

Post by AkimboDK »

sanitka wrote:
Thu Oct 26, 2023 5:10 am
PrinceRevivalDK wrote:
Thu Oct 26, 2023 1:45 am
Okay, Now I am really confused about this script, I want to keep this list as it is. but, I am trying to have one that still uses Action points and Bonus Action points, so I will change the 0,0 to 1,0 for each and that works.
But for some reason this SpellMod code changes all actions into actions, (I mean if a melee spell or normal spell originally used a Bonus Action, that will be converted into using an action and says that in the description of it. Hell, even "Jump" now uses an Action instead of Bonus Actions)
which is a bummer, because in this case I just want it to spend the Action and Bonus action but not spend any spell level slots.
and I am guessing it is something to do with
local spellVariant = string.format("UnlockSpellVariant(IsSpell() or not IsSpell(),%s)",table.concat(spellMod, ','))
that changes all spells into actions instead of what they used to be.
I have no idea how to fix tat s:
It is kind of simple, if you are converting an apple to a cucumber, do not be surprised with the result ;).
ie. if you applying one set of "improvements" to everything, do not be surprised with the result.

try to think, why usually UnlockSpellVariant is cast over a specific spell or an action ? ;)
Yeah, well the best I could do was to change this

Code: Select all

local spellVariant = string.format("UnlockSpellVariant(IsSpell() or not IsSpell(),%s)",table.concat(spellMod, ','))
into this

Code: Select all

local spellVariant = string.format("UnlockSpellVariant(IsSpell(),%s)",table.concat(spellMod, ','))
That way, at least Jump, fly, or similar actions still uses bonus actions, one of the other thing was it also turned the Illithid powers into actions, those of using Bonus actions at least, and as soon you get the Awakened from the Giths, so at least that is working agian. But as far as for the spells, they are all using Actions, a shame because I can't use Quickened Spell since everything uses actions so that is a bummer, un less I have the action set to 0,0 but that just makes things to easy, oh well.

EvenLess
Expert Cheater
Expert Cheater
Posts: 181
Joined: Fri Aug 04, 2023 10:59 pm
Reputation: 209

Re: z Baldur's Gate 3

Post by EvenLess »

PrinceRevivalDK wrote:
Thu Oct 26, 2023 6:39 am
sanitka wrote:
Thu Oct 26, 2023 5:10 am
PrinceRevivalDK wrote:
Thu Oct 26, 2023 1:45 am
Okay, Now I am really confused about this script, I want to keep this list as it is. but, I am trying to have one that still uses Action points and Bonus Action points, so I will change the 0,0 to 1,0 for each and that works.
But for some reason this SpellMod code changes all actions into actions, (I mean if a melee spell or normal spell originally used a Bonus Action, that will be converted into using an action and says that in the description of it. Hell, even "Jump" now uses an Action instead of Bonus Actions)
which is a bummer, because in this case I just want it to spend the Action and Bonus action but not spend any spell level slots.
and I am guessing it is something to do with
local spellVariant = string.format("UnlockSpellVariant(IsSpell() or not IsSpell(),%s)",table.concat(spellMod, ','))
that changes all spells into actions instead of what they used to be.
I have no idea how to fix tat s:
It is kind of simple, if you are converting an apple to a cucumber, do not be surprised with the result ;).
ie. if you applying one set of "improvements" to everything, do not be surprised with the result.

try to think, why usually UnlockSpellVariant is cast over a specific spell or an action ? ;)
Yeah, well the best I could do was to change this

Code: Select all

local spellVariant = string.format("UnlockSpellVariant(IsSpell() or not IsSpell(),%s)",table.concat(spellMod, ','))
into this

Code: Select all

local spellVariant = string.format("UnlockSpellVariant(IsSpell(),%s)",table.concat(spellMod, ','))
That way, at least Jump, fly, or similar actions still uses bonus actions, one of the other thing was it also turned the Illithid powers into actions, those of using Bonus actions at least, and as soon you get the Awakened from the Giths, so at least that is working agian. But as far as for the spells, they are all using Actions, a shame because I can't use Quickened Spell since everything uses actions so that is a bummer, un less I have the action set to 0,0 but that just makes things to easy, oh well.
As mentioned previously, the first argument seems to be a condition. This means that before all the modifications are done, the "condition" must be true. So right now the condition is IsSpell(). The function name is rather self-explanatory, so it basically returns true every time what you're trying to do is a spell, which in turn means that all your spells will have all the modifications added. So you need to figure out what conditions the modifications should be added to.
A quick search for UnlockSpellVariant gives several posts with examples, or you could start digging into the game files. I'd start with Noway3's Passives dump and look a the Boosts entries, and see how the various UnlockSpellVariant() boosts are structured, and try to understand what is possible from that. I'm sure someone on the Internet already have done the grunt work on this, but it's nothing I've looked into.
search.php?keywords=UnlockSpellVariant& ... sf=msgonly

Post Reply

Who is online

Users browsing this forum: 5545ggdgdf, comodo234, Emitter, Google Adsense [Bot]