Option to disable auto-assigning of talents at birth

All new ideas for the upcoming releases of ToME 4.x.x should be discussed here

Moderator: Moderator

Post Reply
Message
Author
magelike
Halfling
Posts: 109
Joined: Mon Sep 26, 2011 4:31 am

Option to disable auto-assigning of talents at birth

#1 Post by magelike »

Whenever I start a new character, I prefer to assign his talent points myself (unless I'm loading a premade character that I've already customized). It's kind of inconvenient for me to have to manually clear the talent points the game automatically assigns to new characters. The following patch adds an option to ToME4's "Game Options" menu that allows the player to disable the auto-assigning of points at birth (enabled by default, as it is currently). Like the bump attack toggle patch, this patch is for b34; however, it respects b35's change to talents like Cursed Item (the code checks the "no_unlearn_last" variable).

Uninteresting notes about what the patch changes after the code jump.

Code: Select all

diff -rupN original-tome-3.9.34/class/Actor.lua tome-3.9.34/class/Actor.lua
--- original-tome-3.9.34/class/Actor.lua	2011-09-17 17:04:16.000000000 -0700
+++ tome-3.9.34/class/Actor.lua	2011-10-14 21:51:30.161600000 -0700
@@ -1969,49 +1969,54 @@ function _M:learnTalent(t_id, force, nb)
 
 	if t.dont_provide_pool then return true end
 
-	if t.type[1]:find("^spell/") and not self:knowTalent(self.T_MANA_POOL) and t.mana or t.sustain_mana then
+	self:learnPool(t)
+	return true
+end
+
+--- Actor learns a resource pool
+-- @param talent a talent definition table
+function _M:learnPool(talent)
+	if talent.type[1]:find("^spell/") and not self:knowTalent(self.T_MANA_POOL) and talent.mana or talent.sustain_mana then
 		self:learnTalent(self.T_MANA_POOL, true)
 		self.resource_pool_refs[self.T_MANA_POOL] = (self.resource_pool_refs[self.T_MANA_POOL] or 0) + 1
 	end
-	if t.type[1]:find("^wild%-gift/") and not self:knowTalent(self.T_EQUILIBRIUM_POOL) and t.equilibrium or t.sustain_equilibrium then
+	if talent.type[1]:find("^wild%-gift/") and not self:knowTalent(self.T_EQUILIBRIUM_POOL) and talent.equilibrium or talent.sustain_equilibrium then
 		self:learnTalent(self.T_EQUILIBRIUM_POOL, true)
 		self.resource_pool_refs[self.T_EQUILIBRIUM_POOL] = (self.resource_pool_refs[self.T_EQUILIBRIUM_POOL] or 0) + 1
 	end
-	if t.type[1]:find("^technique/") and not self:knowTalent(self.T_STAMINA_POOL) and t.stamina or t.sustain_stamina then
+	if talent.type[1]:find("^technique/") and not self:knowTalent(self.T_STAMINA_POOL) and talent.stamina or talent.sustain_stamina then
 		self:learnTalent(self.T_STAMINA_POOL, true)
 		self.resource_pool_refs[self.T_STAMINA_POOL] = (self.resource_pool_refs[self.T_STAMINA_POOL] or 0) + 1
 	end
-	if t.type[1]:find("^corruption/") and not self:knowTalent(self.T_VIM_POOL) and t.vim or t.sustain_vim then
+	if talent.type[1]:find("^corruption/") and not self:knowTalent(self.T_VIM_POOL) and talent.vim or talent.sustain_vim then
 		self:learnTalent(self.T_VIM_POOL, true)
 		self.resource_pool_refs[self.T_VIM_POOL] = (self.resource_pool_refs[self.T_VIM_POOL] or 0) + 1
 	end
-	if t.type[1]:find("^celestial/") and (t.positive or t.sustain_positive) and not self:knowTalent(self.T_POSITIVE_POOL) then
+	if talent.type[1]:find("^celestial/") and (talent.positive or talent.sustain_positive) and not self:knowTalent(self.T_POSITIVE_POOL) then
 		self:learnTalent(self.T_POSITIVE_POOL, true)
 		self.resource_pool_refs[self.T_POSITIVE_POOL] = (self.resource_pool_refs[self.T_POSITIVE_POOL] or 0) + 1
 	end
-	if t.type[1]:find("^celestial/") and (t.negative or t.sustain_negative) and not self:knowTalent(self.T_NEGATIVE_POOL) then
+	if talent.type[1]:find("^celestial/") and (talent.negative or talent.sustain_negative) and not self:knowTalent(self.T_NEGATIVE_POOL) then
 		self:learnTalent(self.T_NEGATIVE_POOL, true)
 		self.resource_pool_refs[self.T_NEGATIVE_POOL] = (self.resource_pool_refs[self.T_NEGATIVE_POOL] or 0) + 1
 	end
-	if t.type[1]:find("^cursed/") and not self:knowTalent(self.T_HATE_POOL) then
+	if talent.type[1]:find("^cursed/") and not self:knowTalent(self.T_HATE_POOL) then
 		self:learnTalent(self.T_HATE_POOL, true)
 		self.resource_pool_refs[self.T_HATE_POOL] = (self.resource_pool_refs[self.T_HATE_POOL] or 0) + 1
 	end
-	if t.type[1]:find("^chronomancy/") and not self:knowTalent(self.T_PARADOX_POOL) then
+	if talent.type[1]:find("^chronomancy/") and not self:knowTalent(self.T_PARADOX_POOL) then
 		self:learnTalent(self.T_PARADOX_POOL, true)
 		self.resource_pool_refs[self.T_PARADOX_POOL] = (self.resource_pool_refs[self.T_PARADOX_POOL] or 0) + 1
 	end
-	if t.type[1]:find("^psionic/") and not self:knowTalent(self.T_PSI_POOL) then
+	if talent.type[1]:find("^psionic/") and not self:knowTalent(self.T_PSI_POOL) then
 		self:learnTalent(self.T_PSI_POOL, true)
 		self.resource_pool_refs[self.T_PSI_POOL] = (self.resource_pool_refs[self.T_PSI_POOL] or 0) + 1
 	end
 	-- If we learn an archery talent, also learn to shoot
-	if t.type[1]:find("^technique/archery") and not self:knowTalent(self.T_SHOOT) then
+	if talent.type[1]:find("^technique/archery") and not self:knowTalent(self.T_SHOOT) then
 		self:learnTalent(self.T_SHOOT, true)
 		self.resource_pool_refs[self.T_SHOOT] = (self.resource_pool_refs[self.T_SHOOT] or 0) + 1
 	end
-
-	return true
 end
 
 --- Actor forgets a talent
diff -rupN original-tome-3.9.34/dialogs/Birther.lua tome-3.9.34/dialogs/Birther.lua
--- original-tome-3.9.34/dialogs/Birther.lua	2011-08-29 23:52:58.000000000 -0700
+++ tome-3.9.34/dialogs/Birther.lua	2011-10-14 21:43:17.158000000 -0700
@@ -206,6 +206,44 @@ function _M:atEnd(v)
 				self:setTile(self.has_custom_tile.f, self.has_custom_tile.w, self.has_custom_tile.h, true)
 				self.actor.has_custom_tile = self.has_custom_tile.f
 			end
+			-- Prevent the game from auto-assigning talents if necessary.
+			if (not config.settings.tome.autoassign_talents_on_birth) then
+				for _, d in pairs(self.descriptors) do
+					local unlearned_talents = { }
+
+					if (d.talents ~= nil and (d.type == "race" or d.type == "subrace" or d.type == "class" or d.type == "subclass")) then
+						for t_id, t_level in pairs(d.talents) do
+							local talent = self.actor:getTalentFromId(t_id)
+							if (talent ~= nil and not talent.no_unlearn_last) then
+								--[[ Award talent points based on the highest available level of the talent
+								     This is in the potential case of a player selecting a race with two points in phase door
+								     and Archmage as his class. Archmage starts with one point in phase door. Cases like this may
+									 result in a conflict of what the player might expect to get back in points. The highest 
+									 amount of points is always awarded to the player (two, in this case).
+								  ]]
+								if (unlearned_talents[talent] == nil) then
+									unlearned_talents[talent] = t_level
+								elseif (unlearned_talents[talent] < t_level) then
+									unlearned_talents[talent] = t_level
+								end
+
+								self.actor:learnPool(talent)
+								print("[BIRTHER] Ignoring auto-assign for " .. t_id .. " (from " .. d.type .. " descriptor \"" .. d.name .. "\")")
+								d.talents[t_id] = nil
+							end
+						end
+
+						-- Give the player the appropriate amount of talent points
+						for talent, t_level in pairs(unlearned_talents) do
+							if (talent.generic == true) then
+								self.actor.unused_generics = self.actor.unused_generics + t_level
+							else
+								self.actor.unused_talents = self.actor.unused_talents + t_level
+							end
+						end
+					end
+				end
+			end
 			self:apply()
 			if self.has_custom_tile then
 				self.actor.make_tile = nil
diff -rupN original-tome-3.9.34/dialogs/GameOptions.lua tome-3.9.34/dialogs/GameOptions.lua
--- original-tome-3.9.34/dialogs/GameOptions.lua	2011-09-07 01:30:18.000000000 -0700
+++ tome-3.9.34/dialogs/GameOptions.lua	2011-10-13 23:30:41.570000000 -0700
@@ -226,6 +226,14 @@ function _M:generateList()
 		self.c_list:drawItem(item)
 	end,}
 
+	local zone = Textzone.new{width=self.c_desc.w, height=self.c_desc.h, text=string.toTString"New games begin with some talent points auto-assigned.#WHITE#"}
+	list[#list+1] = { zone=zone, name=string.toTString"#GOLD##{bold}#Auto-assign talent points at birth#WHITE##{normal}#", status=function(item)
+		return tostring(config.settings.tome.autoassign_talents_on_birth and "enabled" or "disabled")
+	end, fct=function(item)
+		config.settings.tome.autoassign_talents_on_birth = not config.settings.tome.autoassign_talents_on_birth
+		game:saveSettings("tome.autoassign_talents_on_birth", ("tome.autoassign_talents_on_birth = %s\n"):format(tostring(config.settings.tome.autoassign_talents_on_birth)))
+		self.c_list:drawItem(item)
+	end,}
 
 	self.list = list
 end
diff -rupN original-tome-3.9.34/load.lua tome-3.9.34/load.lua
--- original-tome-3.9.34/load.lua	2011-09-07 01:30:18.000000000 -0700
+++ tome-3.9.34/load.lua	2011-10-13 23:36:24.758000000 -0700
@@ -62,6 +62,7 @@ if type(config.settings.tome.weather_eff
 if type(config.settings.tome.smooth_fov) == "nil" then config.settings.tome.smooth_fov = true end
 if type(config.settings.tome.daynight) == "nil" then config.settings.tome.daynight = true end
 if type(config.settings.tome.hotkey_icons) == "nil" then config.settings.tome.hotkey_icons = true end
+if type(config.settings.tome.autoassign_talents_on_birth) == "nil" then config.settings.tome.autoassign_talents_on_birth = true end
 if type(config.settings.tome.chat_log) == "nil" then config.settings.tome.chat_log = true end
 if not config.settings.tome.fonts then config.settings.tome.fonts = {type="fantasy", size="normal"} end
 if not config.settings.tome.ui_theme2 then config.settings.tome.ui_theme2 = "metal" end
Because of the way resource pools are gained, I had to modify the mod.class.Actor:learnTalent() function. I moved most everything resource pool-related to the new function mod.class.Actor:learnPool(). The alternative seemed hacky (adding a talent that makes use of the appropriate pool and then removing that talent from the player). When the autoassign_talents_at_birth option is disabled, my changes to mod.dialogs.Birther:atEnd() remove talents from any race/class/subrace/subclass descriptors before applying those descriptors to the player and giving him the appropriate amount of talent points. Some of the code is commented and all of it should be easy enough to understand. The rest of the patch consists of only the minor changes necessary to implement the toggling of the option.
Last edited by magelike on Sat Oct 15, 2011 6:24 pm, edited 7 times in total.

magelike
Halfling
Posts: 109
Joined: Mon Sep 26, 2011 4:31 am

Re: Option to disable auto-assigning of talents at birth

#2 Post by magelike »

I tested this fairly well, but it's the kind of thing that may require some more testing to ensure that there are no bugs. Any talents that are intrinsic features of a race/class/subrace/subclass (especially those that aren't meant to appear on the level up dialog) should always have no_unlearn_last set to true to avoid problems with them being unassigned if that's not supposed to be possible.

Post Reply