Jump to content

[Tutorial] Adding New Abilities to a Class (v4.1.0+)


Recommended Posts

You should be familiar with the Modding Basic Concepts tutorial before following this one.
 
In this tutorial, I'm going to show you how to use a BaseProgressionTableAppendGameData object to add a new ability to a class progression table (ClassProgressionTableGameData) in the game.  You can also use this object to modify character progression tables (CharacterProgressionTableGameData).
 
BaseProgressionTableAppendGameData is a new game data type that was added in v4.1.0.  It simply contains a list of abilities that can be unlocked (along with the requirements needed to unlock them), and a reference to an existing progression table where you want to insert those abilities.
 
Here's an example game data object I created for this tutorial. This object adds the talent Fast Runner as an eligible talent for Priests at Power Level 1.

{
	"GameDataObjects": [
		{
			"$type": "Game.GameData.BaseProgressionTableAppendGameData, Assembly-CSharp",
			"DebugName": "Priest_FastRunner",
			"ID": "5ec6e46a-4e3f-4f78-affe-0d7477d3b97f",
			"Components": [
				{
					"$type": "Game.GameData.BaseProgressionTableAppendComponent, Assembly-CSharp",
					"BaseTableID": "a52e8b61-9343-4716-8a55-3168be143cc4",
					"AbilityUnlocks": [
						{
							"Note": "",
							"Category": "General",
							"UnlockStyle": "Unlock",
							"ActivationObject": "Self",
							"AddAbilityID": "935b1a37-6f38-4ccc-bbc7-296f0f76790f",
							"RemoveAbilityID": "00000000-0000-0000-0000-000000000000",
							"Prerequisites": {
								"MinimumCharacterLevel": 1,
								"PowerLevelRequirement": {
									"ClassID": "f7cb46af-a719-41c0-9a53-107eefdbce2b",
									"MinimumPowerLevel": 1
								},
								"RequiresAbilityID": "00000000-0000-0000-0000-000000000000",
								"Conditional": {
									"Operator": 0,
									"Components": []
								},
								"VisibilityConditional": {
									"Operator": 0,
									"Components": []
								},
								"IsMutuallyExclusiveUpgrade": "true"
							}
						}
					]
				}
			]
		}
	]
}

priest_table_modded.png
 
This object only has two properties:

  • BaseTableID - the GUID of the existing table to modify. For example, "a52e8b61-9343-4716-8a55-3168be143cc4" represents the PT_Priest table.
  • AbilityUnlocks - a list of UnlockableAbility entries to add to the specified table.

You can find detailed information about the various properties of UnlockableAbility by clicking the link.
 
By adding abilities to progression tables this way, you will avoid conflicts with other mods and compatibility problems with updated versions of the game.

  • Like 5
  • Thanks 1
Link to comment
Share on other sites

Wow, finally! Now maybe I can go back to my subclass mods. Progression table updating has been a major drag that's why I've been lazy updating them. Thanks for this update!

 

Now if there is a way for us to override existing progression table entries (for example, I have a subclass that disables soul whip so I have to modify the conditions of soul whip) that would be even more awesome.

Link to comment
Share on other sites

 

 


Now if there is a way for us to override existing progression table entries (for example, I have a subclass that disables soul whip so I have to modify the conditions of soul whip) that would be even more awesome.

 

Yeah, it would be good to support that as well. If there is time I'll take another look at that.

 

 

 


Am i right that the old progression tables we are using for our mods so far will still work with 4.1.0? I am just a lazy guy in that aspect... :biggrin:

 

Yes, you can still override the tables the old way, and they will continue to "work" as they did before (i.e. they won't contain any changes we made to them in 4.1 and won't work with other mods on the same table).

Link to comment
Share on other sites

Huzzah on this addition!  Makes my home modding of PTs so much easier.

 

I do have one question though.  If I wanted to add an ability to ALL progression tables, could I put in a "0000" UUID into the BaseTableID field?  I ask because I have a couple of talents I'm adding to all of the base classes of the game and I didn't want to have to create 11 separate entries if I didn't have to (Yes, I'm lazy  :lol: ).

 

No big deal if I can't, and truth be told I expect I have to manually create an additional Append for each table I want changed.  But I thought I'd ask, if only for future reference. 

 

Thanks again for this addition!

 

edited

 

As a related question, if the standard null 0 UUID can't be put in a BaseTableID, can multiple UUIDs be put in it?  And if so, is there a limit.  Might be interesting to do something like BaseTableID [uUID1, UUID2, ..., UUIDX].

 

Probably a long shot, but no harm in asking, I reckon. :)

Edited by Zap Gun For Hire
  • Like 1
Link to comment
Share on other sites

Wotcha @zapgunforhire

 

Are you only after modifying the "$type": "Game.GameData.CharacterProgressionTableGameData, Assembly-CSharp", ones?

 

I can automate this

 

I simply need an example and the specific $type to mess with

 

Did this for @Spherikal a few months ago for his enhanced UI

 

Our Slack is still alive so PM me there with specifics and I'll write it for you - it's only an hour or so's work (beats doing it manually)

 

This is simply a conversion job and I have the base code from Spherikal's on my system

  • Like 1

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Link to comment
Share on other sites

No, that won't work unfortunately, you can only put one GUID in there.  I could potentially add support for it if I have time.

 

Figured as much, but I thought I'd ask.  Not so much for the base classes, but all of the companion PT's out there which I'm also doing.

Wotcha @zapgunforhire

 

Are you only after modifying the "$type": "Game.GameData.CharacterProgressionTableGameData, Assembly-CSharp", ones?

 

I can automate this

 

I simply need an example and the specific $type to mess with

 

Did this for @Spherikal a few months ago for his enhanced UI

 

Our Slack is still alive so PM me there with specifics and I'll write it for you - it's only an hour or so's work (beats doing it manually)

 

This is simply a conversion job and I have the base code from Spherikal's on my system

 

Thanks for the offer, but no worries. :) I can do it pretty quickly on my own end as well.  Was more curious about the idea than anything else. 

Link to comment
Share on other sites

Just looked at my code

 

150 lines of PHP with expected directories

 

I'll upload it if you like with the assumptions I make if you want

 

Warning - you'll need about 25G on a Linux server or a VM running Ubuntu

 

Sod it - I'll write a howto to generealize the method

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Link to comment
Share on other sites

NP Zappy

 

If you've got it covered that's good enough for me

 

Your friend (always) Simon (well just about everyone knows my name <g>)

 

Note I didn't use your real name...

Edited by peardox

OK Fair warning has been applied

 

I'm gonna move the domain to https://perspak.com early Feb but will keep all content

 

There are reasons behind this move which basically boil down to unifying my release schedule

 

My friends are welcome to play (I'll set you up your own areas if you desire them)

 

Please note that this process is messy so may take a few weeks 

Link to comment
Share on other sites

Huzzah on this addition!  Makes my home modding of PTs so much easier.

 

I do have one question though.  If I wanted to add an ability to ALL progression tables, could I put in a "0000" UUID into the BaseTableID field?  I ask because I have a couple of talents I'm adding to all of the base classes of the game and I didn't want to have to create 11 separate entries if I didn't have to (Yes, I'm lazy  :lol: ).

 

No big deal if I can't, and truth be told I expect I have to manually create an additional Append for each table I want changed.  But I thought I'd ask, if only for future reference. 

 

Thanks again for this addition!

 

edited

 

As a related question, if the standard null 0 UUID can't be put in a BaseTableID, can multiple UUIDs be put in it?  And if so, is there a limit.  Might be interesting to do something like BaseTableID [uUID1, UUID2, ..., UUIDX].

 

Probably a long shot, but no harm in asking, I reckon. :)

 

 

No, that won't work unfortunately, you can only put one GUID in there.  I could potentially add support for it if I have time.

 

After a lot of trial and error, I actually figured out a way to have it so something can go into all classes at one time.  :thumbsup:   Instead of pointing the "BaseTableID": to a CLASS or COMPANION PT, I pointed it to  the RACIAL PT that defines what races get what  ("b2afaada-c140-42c3-9f02-2f919e45b49d") and followed the template of "Weapon Proficiency: Unarmed" (with a couple of further modifications).

 

Worked like a charm.   :dancing:

 

In fact, if I had thought of this before, I would have saved myself a ton of hassle (not to mention around a couple dozen UUIDs).  :facepalm:

 

Now the ability I am adding IS an Auto-Granted one, so I don't know what would happen if someone tried to use this back-door trick for a user selected one on level up.  But at least I'm happy.  :lol:

 

====

 

Fun fact though.  Only reason I even hit upon this is I was getting VERY annoyed trying to figure out how to stop the multi-class hired adventurers I was creating as an edge case from getting duplicate copies of my auto-granted ability.  I tried every last thing I could think of and kept seeing duplication.

 

Then I finally thought, "Hey... Wait a second.  Racial traits don't get duped on character creation.  Maybe I should figure out how they're put into characters."

 

Little while latter: SUCCESS!!  Even works for Imported Characters on hiring, which is even better than inserting into the class PTs, as they weren't getting the new Auto Generated trait until they leveled up.

 

Still need to clean up my code a little, but it seems to be working as I want now. :)

Edited by Zap Gun For Hire
  • Like 1
Link to comment
Share on other sites

You know how recipes have a line to add an itemmod and a line to remove one? Would it be possible to have something similar with this? RemoveAbilitiesFromProgressionTable or something? Or maybe make them invisible rather than removing them? If that could be done then in addition to adding abilities to progression tables we could also replace abilities, which would be very exciting

Link to comment
Share on other sites

You know how recipes have a line to add an itemmod and a line to remove one? Would it be possible to have something similar with this? RemoveAbilitiesFromProgressionTable or something? Or maybe make them invisible rather than removing them? If that could be done then in addition to adding abilities to progression tables we could also replace abilities, which would be very exciting

{
							"Note": "PL 5 Unlock - Weapon Training",
							"Category": "General",
							"UnlockStyle": "Unlock",
							"ActivationObject": "Self",
							"AddAbilityID": "c6649642-7729-4386-ae1c-6980351fe8c6",
							"RemoveAbilityID": "00000000-0000-0000-0000-000000000000",
							"Prerequisites": {
								"MinimumCharacterLevel": 1,
								"PowerLevelRequirement": {
									"ClassID": "ccdc9675-e2a7-46fa-83e9-7a5368b56265",
									"MinimumPowerLevel": 5
								},
								"RequiresAbilityID": "00000000-0000-0000-0000-000000000000",
								"Conditional": {
									"Operator": 0,
									"Components": []
								},
								"VisibilityConditional": {
									"Operator": 0,
									"Components": []
								},
								"IsMutuallyExclusiveUpgrade": "true"
							}
						}

This is one of the custom abilities I have on my home mods (it lets a class select an additional Weapon Set at level up starting at Power Level 5) that is part of a larger set of abilities I am adding to a PT (so I'm not posting the entire code block here). I know for a fact that VisibilityConditional can remove something from view on a PT, in both standard and append.  I haven't played around with RemoveAbilityID or RequiresAbilityID, but just at a glance it looks like it should be able to remove an ability and replace it with a different one.

 

Or have you tried that and it didn't do what you wanted?

Edited by Zap Gun For Hire
Link to comment
Share on other sites

It looks to me like removing an ability from a progression table is actually just making it invisible via the VisibilityConditional. I've started using the conditional "Boolean AlwaysFalse()" as a means for making something invisible.

 

When you upgrade an ability you're actually training a new ability and removing the old, hence the RemoveAbilityID. This would not function to remove an ability from the PT completely though. Interestingly (in previous version; untested in 4.1), I could RemoveAbilityID while having a "0000-" in the AddAbilityID without causing problems.

 

RequiresAbilityID is mostly, but not entirely, the aesthetic for connecting two abilities with a line. I say not entirely because it does have some functionality beyond the connecting line but I've never tried to track down exactly what that functionality is.

  • Like 1
Link to comment
Share on other sites

So, it looks like this new capability does not allow us to modify existing entries on a class progression table (ClassProgressionTableGameData). I have not researched the "modify" potential of the CharacterProgressionTableGameData but I'm assuming it is the same.

 

I guess I just misread and assumed that that was the new capability. So, if we want to remove, rearrange, or reconnect existing abilities we have to still override the entire progression table.

 

Can anyone else confirm?

Link to comment
Share on other sites

So, it looks like this new capability does not allow us to modify existing entries on a class progression table (ClassProgressionTableGameData). I have not researched the "modify" potential of the CharacterProgressionTableGameData but I'm assuming it is the same.

 

I guess I just misread and assumed that that was the new capability. So, if we want to remove, rearrange, or reconnect existing abilities we have to still override the entire progression table.

 

Can anyone else confirm?

Unfortunately, yes, that's correct.

 

BMac,can you use this method to add multiple abilities to the same table?  If so could you show another example?  Thanks.

Yes, you just need to duplicate the object in the AbilityUnlocks array. This example redundantly adds the same ability twice, just to show the syntax:

 

{
	"GameDataObjects": [
		{
			"$type": "Game.GameData.BaseProgressionTableAppendGameData, Assembly-CSharp",
			"DebugName": "Priest_FastRunner",
			"ID": "5ec6e46a-4e3f-4f78-affe-0d7477d3b97f",
			"Components": [
				{
					"$type": "Game.GameData.BaseProgressionTableAppendComponent, Assembly-CSharp",
					"BaseTableID": "a52e8b61-9343-4716-8a55-3168be143cc4",
					"AbilityUnlocks": [
						{
							"Note": "",
							"Category": "General",
							"UnlockStyle": "Unlock",
							"ActivationObject": "Self",
							"AddAbilityID": "935b1a37-6f38-4ccc-bbc7-296f0f76790f",
							"RemoveAbilityID": "00000000-0000-0000-0000-000000000000",
							"Prerequisites": {
								"MinimumCharacterLevel": 1,
								"PowerLevelRequirement": {
									"ClassID": "f7cb46af-a719-41c0-9a53-107eefdbce2b",
									"MinimumPowerLevel": 1
								},
								"RequiresAbilityID": "00000000-0000-0000-0000-000000000000",
								"Conditional": {
									"Operator": 0,
									"Components": []
								},
								"VisibilityConditional": {
									"Operator": 0,
									"Components": []
								},
								"IsMutuallyExclusiveUpgrade": "true"
							}
						},
						{
							"Note": "",
							"Category": "General",
							"UnlockStyle": "Unlock",
							"ActivationObject": "Self",
							"AddAbilityID": "935b1a37-6f38-4ccc-bbc7-296f0f76790f",
							"RemoveAbilityID": "00000000-0000-0000-0000-000000000000",
							"Prerequisites": {
								"MinimumCharacterLevel": 1,
								"PowerLevelRequirement": {
									"ClassID": "f7cb46af-a719-41c0-9a53-107eefdbce2b",
									"MinimumPowerLevel": 1
								},
								"RequiresAbilityID": "00000000-0000-0000-0000-000000000000",
								"Conditional": {
									"Operator": 0,
									"Components": []
								},
								"VisibilityConditional": {
									"Operator": 0,
									"Components": []
								},
								"IsMutuallyExclusiveUpgrade": "true"
							}
						}
					]
				}
			]
		}
	]
}
Link to comment
Share on other sites

@BMac: Do you have any idea why our modded abilities are completly broken in turn-based-mode so there is "shaken" everywhere in the decriptions?

 

Would be really cool if we could fix this! :)

 

https://forums.obsidian.net/topic/105780-mod-the-class-project/?p=2136867

 

I think I know what's up there. You can probably fix it by adding "OverrideDescriptionStringTactical": -1 to your status effects. Unfortunately it sounds like that's defaulting to 0 when omitted, which indicates string ID 0, whereas -1 indicates "don't use this".  I'll see if I can do something about that on my end for 4.1.1. 

"As the murderhobo mantra goes: 'If you can't kill it, steal it.'" - Prince of Lies

Link to comment
Share on other sites

Unsure if this is the right place to ask, but what about adding completely new spells to the game?

 

I'm considering making a Paladin pack that adds a handful of spells and strikes to the various kits to enhance the strengths and weaknesses of a given Order. For some spells I can just give access via the method in the OP, but I'm less sure about adding in new spells.

Link to comment
Share on other sites

  • 1 month later...
  • 1 year later...

ive been reviewing this thread and going over an existing subclass mod for wizards, and while parsing through,

I want to basically do the following:
1.create a subclass
1.1  within that subclass and only that subclass, do the following
1.11. knock out/erase access to a banned spell list (in this case necromantic themed spells)

"AddAbilityID": "935ce6a1-9e28-4ec4-abdf-e84058a717a8",
"RemoveAbilityID": "00000000-0000-0000-0000-000000000000",

i saw these two lines. They look promising, but append/add is not the same thing as "lock/erase from display icon list" which is my goal.
1.12. add a few custom passive abilities to the far right columns
1.13. delete some passive abilities from the list
1.14. MOVE some existing abilities up/down the level availability tier on the Progression table.

analysis:
1. creating the subclass is basically just making a mod folder with its custom icon and tossing it in over ride. Already did this.✅
1.11 - i have no idea how to do this ❌
1.12 - i can do this ✅❔
1.13 - i have no idea how to do this either ❌
1.14 - maybe can move tiers of abilities ❔✖️

im wondering if the "Note": "PL 0 Auto Grant..." section of  
 

"$type": "Game.GameData.ClassProgressionTableGameData, Assembly-CSharp"

is where to start.

Link to comment
Share on other sites

Unfortunately moving or removing existing abilities from the progression table will probably require overriding the entire table. Certainly doable, but might have compatibility problems with other mods that use that table.

You would copy the entire progression table object PT_Wizard into your mod bundle and add Conditional checks to the spells and passives your new subclass should not be allowed. This is how the normal wizard subclasses are done and you should be able to find samples using the IsSubclass script.  To move abilities to new power levels, I would guess you would have to duplicate the table entry for that ability and change it, conditionalizing the new entry for your subclass and the old one for the inverse ("Not" your subclass) and using the VisibilityConditional instead of the normal one to entirely hide the duplicates rather than disabling them.

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...